9boot: disable nmi, reload idt, load segments twice, check sequence number of pxe packets
This commit is contained in:
parent
0cb5b3181c
commit
02e7e8da1d
3 changed files with 106 additions and 36 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue