5 typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT;
37 UINT8 BootpHwAddr[16];
38 UINT8 BootpSrvName[64];
39 UINT8 BootpBootFile[128];
41 UINT8 DhcpOptions[56];
42 } EFI_PXE_BASE_CODE_DHCPV4_PACKET;
46 BOOLEAN Ipv6Available;
47 BOOLEAN Ipv6Supported;
53 BOOLEAN DhcpDiscoverValid;
54 BOOLEAN DhcpAckReceived;
55 BOOLEAN ProxyOfferReceived;
56 BOOLEAN PxeDiscoverValid;
57 BOOLEAN PxeReplyReceived;
58 BOOLEAN PxeBisReplyReceived;
59 BOOLEAN IcmpErrorReceived;
60 BOOLEAN TftpErrorReceived;
61 BOOLEAN MakeCallbacks;
71 UINT8 DhcpDiscover[1472];
73 UINT8 ProxyOffer[1472];
74 UINT8 PxeDiscover[1472];
76 UINT8 PxeBisReply[1472];
78 } EFI_PXE_BASE_CODE_MODE;
94 EFI_PXE_BASE_CODE_MODE *Mode;
95 } EFI_PXE_BASE_CODE_PROTOCOL;
112 EFI_GUID EFI_PXE_BASE_CODE_PROTOCOL_GUID = {
113 0x03C4E603, 0xAC28, 0x11D3,
114 0x9A, 0x2D, 0x00, 0x90,
115 0x27, 0x3F, 0xC1, 0x4D,
119 EFI_PXE_BASE_CODE_PROTOCOL *pxe;
121 static uchar mymac[6];
122 static uchar myip[16];
123 static uchar serverip[16];
125 typedef struct Tftp Tftp;
131 EFI_PXE_BASE_CODE_UDP_PORT sport;
132 EFI_PXE_BASE_CODE_UDP_PORT dport;
140 char pkt[2+2+Segsize];
145 puts(void *x, ushort v)
149 p[1] = (v>>8) & 0xFF;
158 return p[1]<<8 | p[0];
162 hnputs(void *x, ushort v)
166 p[0] = (v>>8) & 0xFF;
175 return p[0]<<8 | p[1];
180 ANY_SRC_PORT = 0x0002,
181 ANY_DEST_IP = 0x0004,
182 ANY_DEST_PORT = 0x0008,
184 MAY_FRAGMENT = 0x0020,
188 udpread(EFI_IP_ADDRESS *sip, EFI_IP_ADDRESS *dip,
189 EFI_PXE_BASE_CODE_UDP_PORT *sport,
190 EFI_PXE_BASE_CODE_UDP_PORT dport,
191 int *len, void *data)
196 if(eficall(pxe->UdpRead, pxe, (UINTN)ANY_SRC_PORT, dip, &dport, sip, sport, nil, nil, &size, data))
204 udpwrite(EFI_IP_ADDRESS *dip,
205 EFI_PXE_BASE_CODE_UDP_PORT sport,
206 EFI_PXE_BASE_CODE_UDP_PORT dport,
212 if(eficall(pxe->UdpWrite, pxe, (UINTN)MAY_FRAGMENT, dip, &dport, nil, nil, &sport, nil, nil, &size, data))
219 pxeread(void *f, void *data, int len)
224 while(!t->eof && t->rp >= t->ep){
227 if(udpread(&t->dip, &t->sip, &t->dport, t->sport, &n, t->pkt))
232 switch(nhgets(t->pkt)){
234 seq = nhgets(t->pkt+2);
239 hnputs(t->pkt, Tftp_ACK);
240 while(udpwrite(&t->dip, t->sport, t->dport, 4, t->pkt))
250 t->eof = n < Segsize;
264 memmove(data, t->rp, len);
278 tftpopen(Tftp *t, char *path)
280 static EFI_PXE_BASE_CODE_UDP_PORT xport = 6666;
291 hnputs(p, Tftp_READ); p += 2;
293 memmove(p, path, n); p += n;
294 memmove(p, "octet", 6); p += 6;
297 if(r = udpwrite(&t->dip, t->sport, TftpPort, n, t->pkt))
299 if(r = pxeread(t, 0, 0))
310 static uchar buf[sizeof(Tftp)+8];
311 Tftp *t = (Tftp*)((uintptr)(buf+7)&~7);
313 memset(t, 0, sizeof(Tftp));
314 memmove(&t->sip, myip, sizeof(myip));
315 memmove(&t->dip, serverip, sizeof(serverip));
316 if(tftpopen(t, name))
322 parseipv6(uchar to[16], char *from)
329 for(i = 0; i < 16; i += 2){
332 if(*p >= '0' && *p <= '9')
333 dig = (dig << 4) | (*p - '0');
334 else if(*p >= 'a' && *p <= 'f')
335 dig = (dig << 4) | (*p - 'a'+10);
336 else if(*p >= 'A' && *p <= 'F')
337 dig = (dig << 4) | (*p - 'A'+10);
346 if(*++p == ':'){ /* :: is elided zero short(s) */
348 return -1; /* second :: */
352 } else if (p == from)
357 memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis);
358 memset(&to[elipsis], 0, 16-i);
364 parsedhcp(EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp)
371 memset(mymac, 0, sizeof(mymac));
372 memset(serverip, 0, sizeof(serverip));
375 if(pxe->Mode->UsingIpv6 == 0){
376 memmove(mymac, dhcp->BootpHwAddr, 6);
377 memmove(serverip, dhcp->BootpSiAddr, 4);
382 e = (uchar*)dhcp + sizeof(*dhcp);
383 p = (uchar*)dhcp + 4;
385 opt = p[0]<<8 | p[1];
386 len = p[2]<<8 | p[3];
391 case 1: /* Client DUID */
392 memmove(mymac, p+len-6, 6);
394 case 59: /* Boot File URL */
395 for(x = (char*)p; x < (char*)p+len; x++){
397 parseipv6(serverip, x+1);
410 EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp;
411 EFI_PXE_BASE_CODE_MODE *mode;
419 if(eficall(ST->BootServices->LocateHandleBuffer,
420 ByProtocol, &EFI_PXE_BASE_CODE_PROTOCOL_GUID, nil, &Count, &Handles))
423 for(i=0; i<Count; i++){
425 if(eficall(ST->BootServices->HandleProtocol,
426 Handles[i], &EFI_PXE_BASE_CODE_PROTOCOL_GUID, &pxe))
429 if(mode == nil || mode->Started == 0)
431 if(mode->DhcpAckReceived){
432 dhcp = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)mode->DhcpAck;
435 if(mode->PxeReplyReceived){
436 dhcp = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)mode->PxeReply;
444 memmove(myip, mode->StationIp, 16);
453 memmove(ini, "/cfg/pxe/", 9);
455 ini[9+i*2+0] = hex[mymac[i] >> 4];
456 ini[9+i*2+1] = hex[mymac[i] & 0xF];
459 if((*pf = pxeopen(ini)) == nil)
460 *pf = pxeopen("/cfg/pxe/default");