9boot: disable nmi, reload idt, load segments twice, check sequence number of pxe packets

This commit is contained in:
cinap_lenrek 2011-04-20 07:00:15 +00:00
parent 0cb5b3181c
commit 02e7e8da1d
3 changed files with 106 additions and 36 deletions

View file

@ -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 $(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,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

View file

@ -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))

View file

@ -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