summaryrefslogtreecommitdiff
path: root/sys/src/boot
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-04-20 07:00:15 +0000
committercinap_lenrek <cinap_lenrek@localhost>2011-04-20 07:00:15 +0000
commit02e7e8da1dafcdc32bc28a62931de28317ca758c (patch)
treee9f48356a592bb025f50d136842a52c463c34ec0 /sys/src/boot
parent0cb5b3181cfe3d545860bcb8bbf1d0031a29cb21 (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.s118
-rw-r--r--sys/src/boot/pc/pxe.c21
-rw-r--r--sys/src/boot/pc/x16.h3
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