shithub: riscv

Download patch

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