20 typedef struct Tftp Tftp;
21 typedef struct Dhcp Dhcp;
37 char pkt[2+2+Segsize];
59 int pxecall(int op, void *buf);
62 unfar(ulong seg, ulong off)
64 return (void*)((off & 0xFFFF) + (seg & 0xFFFF)*16);
68 puts(void *x, ushort v)
81 return p[1]<<8 | p[0];
85 hnputs(void *x, ushort v)
98 return p[0]<<8 | p[1];
104 memmove(d, s, sizeof(d));
108 getip(IP4 yip, IP4 sip, IP4 gip, char mac[16])
121 memset(&buf, 0, sizeof(buf));
122 puts(buf.pkttype, 3);
124 if(r = pxecall(0x71, &buf))
126 if((p = unfar(gets(buf.seg), gets(buf.off))) == 0)
133 mac[i*2] = hex[p->mac[i]>>4];
134 mac[i*2+1] = hex[p->mac[i]&15];
148 moveip(buf.sip, sip);
149 return pxecall(0x30, &buf);
157 return pxecall(0x31, status);
161 udpread(IP4 sip, IP4 dip, int *sport, int dport, int *len, void *data)
176 moveip(buf.sip, sip);
177 moveip(buf.dip, dip);
178 hnputs(buf.sport, *sport);
179 hnputs(buf.dport, dport);
181 puts(buf.off, (long)data);
183 if(r = pxecall(0x32, &buf))
185 moveip(sip, buf.sip);
186 *sport = nhgets(buf.sport);
187 *len = gets(buf.len);
192 udpwrite(IP4 ip, IP4 gw, int sport, int dport, int len, void *data)
208 hnputs(buf.sport, sport);
209 hnputs(buf.dport, dport);
211 puts(buf.off, (long)data);
213 return pxecall(0x33, &buf);
217 read(void *f, void *data, int len)
222 if(!t->eof && t->rp >= t->ep){
224 hnputs(t->pkt, Tftp_ACK);
225 udpwrite(t->dip, t->gip, t->sport, t->dport, 4, t->pkt);
230 if(udpread(t->dip, t->sip, &t->dport, t->sport, &n, t->pkt))
235 switch(nhgets(t->pkt)){
239 t->eof = n < Segsize;
252 memmove(data, t->rp, len);
266 tftpopen(Tftp *t, char *path, IP4 sip, IP4 dip, IP4 gip)
268 static ushort xport = 6666;
274 memset(t->dip, 0, sizeof(t->dip));
280 if(r = udpopen(t->sip))
283 hnputs(p, Tftp_READ); p += 2;
285 memmove(p, path, n); p += n;
286 memmove(p, "octet", 6); p += 6;
289 if(r = udpwrite(dip, t->gip, t->sport, TftpPort, n, t->pkt))
291 if(r = read(t, 0, 0))
302 char mac[16], path[Maxpath], *kern;
307 if(getip(yip, sip, gip, mac)){
308 print("bad dhcp\r\n");
311 memmove(path, "/cfg/pxe/", 9);
312 memmove(path+9, mac, 13);
313 if(tftpopen(f = &t, path, yip, sip, gip)){
314 print("no config\r\n");
318 kern = configure(f, path); f = 0;
319 if(tftpopen(&t, kern, yip, sip, gip)){
320 print("not found\r\n");