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/pc/pxe.c | |
parent | 0cb5b3181cfe3d545860bcb8bbf1d0031a29cb21 (diff) |
9boot: disable nmi, reload idt, load segments twice, check sequence number of pxe packets
Diffstat (limited to 'sys/src/boot/pc/pxe.c')
-rw-r--r-- | sys/src/boot/pc/pxe.c | 21 |
1 files changed, 14 insertions, 7 deletions
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)) |