diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-04-20 07:00:15 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-04-20 07:00:15 +0000 |
commit | 02e7e8da1dafcdc32bc28a62931de28317ca758c (patch) | |
tree | e9f48356a592bb025f50d136842a52c463c34ec0 /sys/src/boot | |
parent | 0cb5b3181cfe3d545860bcb8bbf1d0031a29cb21 (diff) |
9boot: disable nmi, reload idt, load segments twice, check sequence number of pxe packets
Diffstat (limited to 'sys/src/boot')
-rw-r--r-- | sys/src/boot/pc/l.s | 118 | ||||
-rw-r--r-- | sys/src/boot/pc/pxe.c | 21 | ||||
-rw-r--r-- | sys/src/boot/pc/x16.h | 3 |
3 files changed, 106 insertions, 36 deletions
diff --git a/sys/src/boot/pc/l.s b/sys/src/boot/pc/l.s index ecc9d9e57..347f403e5 100644 --- 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 @@ TEXT origin(SB), $0 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 @@ TEXT tgdt(SB), $0 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 $((0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) + + /* exec segment descriptor for (PL 0) 16-bit */ LONG $(0xFFFF) - LONG $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) + 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,20 +136,31 @@ TEXT halt(SB), $0 _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 TEXT gotc(SB), $0 CALL rmode16(SB) - STI + CALL16(spllo(SB)) MOVB $0x01, AH BIOSCALL(0x16) JNZ _getcret @@ -102,11 +170,10 @@ TEXT gotc(SB), $0 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 @@ TEXT pxecall(SB), $0 MOVL op+4(SP),AX MOVL buf+8(SP),SI CALL rmode16(SB) - CLI CLR(rCX) PUSHR(rCX) @@ -130,6 +196,7 @@ TEXT pxecall(SB), $0 /* opcode */ PUSHR(rAX) + /* farcall */ PUSHR(rCX) PUSHI(pxecallret(SB)) @@ -155,7 +222,8 @@ _getentry: SEGES; LXW(0x10, xBX, rAX) PUSHR(rAX) -_pxecall: + CALL16(spllo(SB)) + CLR(rAX) CLR(rBX) CLR(rCX) @@ -165,13 +233,6 @@ _pxecall: _farret: FARRET -_pxeplus: - CMPI((('P'<<0)|('X'<<8)), rAX) - JNE _farret - - PUSHR(rAX) - JMP _pxecall - #else /* PXE */ /* @@ -218,9 +279,8 @@ TEXT readsect(SB), $0 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 diff --git a/sys/src/boot/pc/pxe.c b/sys/src/boot/pc/pxe.c index 13a1a413d..c624e4825 100644 --- a/sys/src/boot/pc/pxe.c +++ b/sys/src/boot/pc/pxe.c @@ -32,6 +32,7 @@ struct Tftp char *rp; char *ep; + int seq; int eof; char pkt[2+2+Segsize]; @@ -217,14 +218,9 @@ int 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 @@ read(void *f, void *data, int len) } 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 @@ read(void *f, void *data, int len) t->eof = 1; return -1; } + break; } n = t->ep - t->rp; if(len > n) @@ -275,6 +281,7 @@ tftpopen(Tftp *t, char *path, IP4 sip, IP4 dip, IP4 gip) 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)) diff --git a/sys/src/boot/pc/x16.h b/sys/src/boot/pc/x16.h index 36fa40fc7..f0c9376dc 100644 --- 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 |