char *rp;
char *ep;
+ int seq;
int eof;
char pkt[2+2+Segsize];
char bootfile[128];
};
+int pxeinit(void);
int pxecall(int op, void *buf);
static void*
memmove(d, s, sizeof(d));
}
+void
+unload(void)
+{
+ struct {
+ uchar status[2];
+ uchar junk[10];
+ } buf;
+ static uchar shutdown[] = { 0x05, 0x070, 0x02, 0 };
+ uchar *o;
+
+ for(o = shutdown; *o; o++){
+ memset(&buf, 0, sizeof(buf));
+ if(pxecall(*o, &buf))
+ break;
+ }
+}
+
static int
getip(IP4 yip, IP4 sip, IP4 gip, char mac[16])
{
static int
udpclose(void)
{
- char status[2];
+ uchar status[2];
puts(status, 0);
return pxecall(0x31, status);
}
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))
}
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;
t->eof = 1;
return -1;
}
+ break;
}
n = t->ep - t->rp;
if(len > n)
udpclose();
}
+
static int
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))
void *f;
Tftp t;
+ if(pxeinit()){
+ print("pxe init\r\n");
+ halt();
+ }
if(getip(yip, sip, gip, mac)){
print("bad dhcp\r\n");
halt();