ref: 02e7e8da1dafcdc32bc28a62931de28317ca758c
parent: 0cb5b3181cfe3d545860bcb8bbf1d0031a29cb21
author: cinap_lenrek <cinap_lenrek@localhost>
date: Wed Apr 20 03:00:15 EDT 2011
9boot: disable nmi, reload idt, load segments twice, check sequence number of pxe packets
--- a/sys/src/boot/pc/l.s
+++ b/sys/src/boot/pc/l.s
@@ -5,7 +5,9 @@
#define DATA32SEL SELECTOR(1, SELGDT, 0)
#define EXEC32SEL SELECTOR(2, SELGDT, 0)
-#define EXEC16SEL SELECTOR(3, SELGDT, 0)
+#define DATA16SEL SELECTOR(3, SELGDT, 0)
+#define EXEC16SEL SELECTOR(4, SELGDT, 0)
+
#define SEGSS BYTE $0x36
#define SEGES BYTE $0x26
#define FARRET BYTE $0xCB
@@ -21,33 +23,80 @@
PUSHI(start(SB))
TEXT pmode32(SB), $0
+ CLI
+
+ /* disable nmi */
+ PUSHA
+ LWI(0x70, rDX)
+ INB
+ ANDB $0x7F, AL
+ OUTB
+ POPA
+
+ /* get return pc */
POPR(rDI)
+
+ /* make sure stack is at 0000: */
+ CLR(rCX)
+ MTSR(rCX, rSS)
+ OPSIZE; ANDL $0xFFFF, SP
+
+ /* convert 16-bit return pc to far pointer */
+ PUSHI(EXEC32SEL)
+ PUSHR(rDI)
+
+ /* load gdt */
SEGSS; LGDT(tgdtptr(SB))
+
+ /* enable protected mode */
MFCR(rCR0, rCX)
ORB $1, CL
MTCR(rCX, rCR0)
- PUSHI(EXEC32SEL)
- PUSHR(rDI)
+
+ /* flush */
+ FARJUMP16(EXEC16SEL, pmode32flush(SB));
+TEXT pmode32flush(SB), $0
+
+ /* load 32-bit protected mode data selector */
LWI(DATA32SEL, rCX)
+
_segret:
+ /* load all data segments */
MTSR(rCX, rDS)
MTSR(rCX, rES)
+ MTSR(rCX, rFS)
+ MTSR(rCX, rGS)
MTSR(rCX, rSS)
FARRET
TEXT rmode16(SB), $0
- POPL DI
- OPSIZE; BYTE $0xEA
- WORD $unreal(SB)
- WORD $EXEC16SEL
+ /* setup farret to rmode16x */
+ PUSHL $EXEC16SEL
+ PUSHL $rmode16x(SB)
-TEXT unreal(SB), $0
+ /* load 16-bit protected mode data selector */
+ MOVL $DATA16SEL, CX
+ JMP _segret
+
+TEXT rmode16x(SB), $0
+ /* reload idt */
+ SEGSS; LIDT(tidtptr(SB))
+
+ /* disable protected mode */
MFCR(rCR0, rCX)
ANDB $0xfe, CL
MTCR(rCX, rCR0)
+
+ /* flush */
+ FARJUMP16(0, rmode16flush(SB));
+TEXT rmode16flush(SB), $0
+
+ /*
+ * load 16-bit realmode data segment 0000: and
+ * return to 32 bit return pc interpreted
+ * as 16 bit far pointer.
+ */
CLR(rCX)
- PUSHR(rCX)
- PUSHR(rDI)
JMP _segret
TEXT tgdt(SB), $0
@@ -63,14 +112,22 @@
LONG $(0xFFFF)
LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
- /* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */
+ /* data segment descriptor for (PL 0) 16-bit */
LONG $(0xFFFF)
- LONG $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+ LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
+ /* exec segment descriptor for (PL 0) 16-bit */
+ LONG $(0xFFFF)
+ LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+
TEXT tgdtptr(SB), $0
- WORD $(4*8)
+ WORD $(5*8)
LONG $tgdt(SB)
+TEXT tidtptr(SB), $0
+ WORD $0x3ff
+ LONG $0
+
TEXT jump(SB), $0
MOVL 4(SP), AX
JMP *AX
@@ -79,13 +136,24 @@
_halt:
JMP _halt
+TEXT spllo(SB), $0
+ /* enable nmi */
+ PUSHA
+ LWI(0x70, rDX)
+ INB
+ ORB $0x80, AL
+ OUTB
+ POPA
+
+ STI
+ RET
+
TEXT getc(SB), $0
CALL rmode16(SB)
- STI
+ CALL16(spllo(SB))
MOVB $0x00, AH
BIOSCALL(0x16)
_getcret:
- CLI
CALL16(pmode32(SB))
ANDL $0xFF, AX
RET
@@ -92,7 +160,7 @@
TEXT gotc(SB), $0
CALL rmode16(SB)
- STI
+ CALL16(spllo(SB))
MOVB $0x01, AH
BIOSCALL(0x16)
JNZ _getcret
@@ -102,11 +170,10 @@
TEXT putc(SB), $0
MOVL 4(SP),AX
CALL rmode16(SB)
- STI
+ CALL16(spllo(SB))
MOVB $0x0E, AH
BIOSCALL(0x10)
_pret32:
- CLI
CALL16(pmode32(SB))
ANDL $0xFFFF, AX
RET
@@ -121,7 +188,6 @@
MOVL op+4(SP),AX
MOVL buf+8(SP),SI
CALL rmode16(SB)
- CLI
CLR(rCX)
PUSHR(rCX)
@@ -130,6 +196,7 @@
/* opcode */
PUSHR(rAX)
+ /* farcall */
PUSHR(rCX)
PUSHI(pxecallret(SB))
@@ -155,7 +222,8 @@
SEGES; LXW(0x10, xBX, rAX)
PUSHR(rAX)
-_pxecall:
+ CALL16(spllo(SB))
+
CLR(rAX)
CLR(rBX)
CLR(rCX)
@@ -165,13 +233,6 @@
_farret:
FARRET
-_pxeplus:
- CMPI((('P'<<0)|('X'<<8)), rAX)
- JNE _farret
-
- PUSHR(rAX)
- JMP _pxecall
-
#else /* PXE */
/*
@@ -218,9 +279,8 @@
MOVW 10(SP), BX
MOVL 12(SP), SI
CALL rmode16(SB)
- STI
+ CALL16(spllo(SB))
CALL16(readsect16(SB))
- CLI
CALL16(pmode32(SB))
ANDL $0xFFFF, AX
RET
--- a/sys/src/boot/pc/pxe.c
+++ b/sys/src/boot/pc/pxe.c
@@ -32,6 +32,7 @@
char *rp;
char *ep;
+ int seq;
int eof;
char pkt[2+2+Segsize];
@@ -217,14 +218,9 @@
read(void *f, void *data, int len)
{
Tftp *t = f;
- int n;
+ int seq, n;
- if(!t->eof && t->rp >= t->ep){
- if(t->rp){
- hnputs(t->pkt, Tftp_ACK);
- udpwrite(t->dip, t->gip, t->sport, t->dport, 4, t->pkt);
- t->rp = t->ep = 0;
- }
+ while(!t->eof && t->rp >= t->ep){
for(;;){
n = sizeof(t->pkt);
if(udpread(t->dip, t->sip, &t->dport, t->sport, &n, t->pkt))
@@ -234,6 +230,15 @@
}
switch(nhgets(t->pkt)){
case Tftp_DATA:
+ seq = nhgets(t->pkt+2);
+ if(seq <= t->seq){
+ putc('@');
+ continue;
+ }
+ hnputs(t->pkt, Tftp_ACK);
+ while(udpwrite(t->dip, t->gip, t->sport, t->dport, 4, t->pkt))
+ putc('!');
+ t->seq = seq;
t->rp = t->pkt + 4;
t->ep = t->pkt + n;
t->eof = n < Segsize;
@@ -245,6 +250,7 @@
t->eof = 1;
return -1;
}
+ break;
}
n = t->ep - t->rp;
if(len > n)
@@ -275,6 +281,7 @@
t->sport = xport++;
t->dport = 0;
t->rp = t->ep = 0;
+ t->seq = -1;
t->eof = 0;
t->nul = 0;
if(r = udpopen(t->sip))
--- a/sys/src/boot/pc/x16.h
+++ b/sys/src/boot/pc/x16.h
@@ -153,6 +153,9 @@
#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \
BYTE $0x01; BYTE $0x16; \
WORD $gdtptr
+#define LIDT(idtptr) BYTE $0x0F; /* LIDT */ \
+ BYTE $0x01; BYTE $0x1e; \
+ WORD $idtptr
/* operand size switch. */
#define OPSIZE BYTE $0x66