9boot: DHCPv6 support for efi
This commit is contained in:
parent
c83a6f9c00
commit
5c2b4dfc81
1 changed files with 98 additions and 12 deletions
|
@ -118,8 +118,9 @@ EFI_GUID EFI_PXE_BASE_CODE_PROTOCOL_GUID = {
|
|||
static
|
||||
EFI_PXE_BASE_CODE_PROTOCOL *pxe;
|
||||
|
||||
static
|
||||
EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp;
|
||||
static uchar mymac[6];
|
||||
static uchar myip[16];
|
||||
static uchar serverip[16];
|
||||
|
||||
typedef struct Tftp Tftp;
|
||||
struct Tftp
|
||||
|
@ -310,25 +311,109 @@ pxeopen(char *name)
|
|||
Tftp *t = (Tftp*)((uintptr)(buf+7)&~7);
|
||||
|
||||
memset(t, 0, sizeof(Tftp));
|
||||
|
||||
memmove(&t->dip, dhcp->BootpSiAddr, 4);
|
||||
memmove(&t->sip, pxe->Mode->StationIp, 4);
|
||||
|
||||
memmove(&t->sip, myip, sizeof(myip));
|
||||
memmove(&t->dip, serverip, sizeof(serverip));
|
||||
if(tftpopen(t, name))
|
||||
return nil;
|
||||
return t;
|
||||
}
|
||||
|
||||
static int
|
||||
parseipv6(uchar to[16], char *from)
|
||||
{
|
||||
int i, dig, elipsis;
|
||||
char *p;
|
||||
|
||||
elipsis = 0;
|
||||
memset(to, 0, 16);
|
||||
for(i = 0; i < 16; i += 2){
|
||||
dig = 0;
|
||||
for(p = from;; p++){
|
||||
if(*p >= '0' && *p <= '9')
|
||||
dig = (dig << 4) | (*p - '0');
|
||||
else if(*p >= 'a' && *p <= 'f')
|
||||
dig = (dig << 4) | (*p - 'a'+10);
|
||||
else if(*p >= 'A' && *p <= 'F')
|
||||
dig = (dig << 4) | (*p - 'A'+10);
|
||||
else
|
||||
break;
|
||||
if(dig > 0xFFFF)
|
||||
return -1;
|
||||
}
|
||||
to[i] = dig>>8;
|
||||
to[i+1] = dig;
|
||||
if(*p == ':'){
|
||||
if(*++p == ':'){ /* :: is elided zero short(s) */
|
||||
if (elipsis)
|
||||
return -1; /* second :: */
|
||||
elipsis = i+2;
|
||||
p++;
|
||||
}
|
||||
} else if (p == from)
|
||||
break;
|
||||
from = p;
|
||||
}
|
||||
if(i < 16){
|
||||
memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis);
|
||||
memset(&to[elipsis], 0, 16-i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
parsedhcp(EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp)
|
||||
{
|
||||
uchar *p, *e;
|
||||
char *x;
|
||||
int opt;
|
||||
int len;
|
||||
|
||||
memset(mymac, 0, sizeof(mymac));
|
||||
memset(serverip, 0, sizeof(serverip));
|
||||
|
||||
/* DHCPv4 */
|
||||
if(pxe->Mode->UsingIpv6 == 0){
|
||||
memmove(mymac, dhcp->BootpHwAddr, 6);
|
||||
memmove(serverip, dhcp->BootpSiAddr, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
/* DHCPv6 */
|
||||
e = (uchar*)dhcp + sizeof(*dhcp);
|
||||
p = (uchar*)dhcp + 4;
|
||||
while(p+4 <= e){
|
||||
opt = p[0]<<8 | p[1];
|
||||
len = p[2]<<8 | p[3];
|
||||
p += 4;
|
||||
if(p + len > e)
|
||||
break;
|
||||
switch(opt){
|
||||
case 1: /* Client DUID */
|
||||
memmove(mymac, p+len-6, 6);
|
||||
break;
|
||||
case 59: /* Boot File URL */
|
||||
for(x = (char*)p; x < (char*)p+len; x++){
|
||||
if(*x == '['){
|
||||
parseipv6(serverip, x+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pxeinit(void **pf)
|
||||
{
|
||||
EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp;
|
||||
EFI_PXE_BASE_CODE_MODE *mode;
|
||||
EFI_HANDLE *Handles;
|
||||
UINTN Count;
|
||||
int i;
|
||||
|
||||
pxe = nil;
|
||||
dhcp = nil;
|
||||
Count = 0;
|
||||
Handles = nil;
|
||||
if(eficall(ST->BootServices->LocateHandleBuffer,
|
||||
|
@ -341,7 +426,7 @@ pxeinit(void **pf)
|
|||
Handles[i], &EFI_PXE_BASE_CODE_PROTOCOL_GUID, &pxe))
|
||||
continue;
|
||||
mode = pxe->Mode;
|
||||
if(mode == nil || mode->UsingIpv6 || mode->Started == 0)
|
||||
if(mode == nil || mode->Started == 0)
|
||||
continue;
|
||||
if(mode->DhcpAckReceived){
|
||||
dhcp = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)mode->DhcpAck;
|
||||
|
@ -355,19 +440,20 @@ pxeinit(void **pf)
|
|||
return -1;
|
||||
|
||||
Found:
|
||||
parsedhcp(dhcp);
|
||||
memmove(myip, mode->StationIp, 16);
|
||||
|
||||
open = pxeopen;
|
||||
read = pxeread;
|
||||
close = pxeclose;
|
||||
|
||||
if(pf != nil){
|
||||
char ini[24];
|
||||
uchar *mac;
|
||||
|
||||
mac = dhcp->BootpHwAddr;
|
||||
memmove(ini, "/cfg/pxe/", 9);
|
||||
for(i=0; i<6; i++){
|
||||
ini[9+i*2+0] = hex[mac[i] >> 4];
|
||||
ini[9+i*2+1] = hex[mac[i] & 0xF];
|
||||
ini[9+i*2+0] = hex[mymac[i] >> 4];
|
||||
ini[9+i*2+1] = hex[mymac[i] & 0xF];
|
||||
}
|
||||
ini[9+12] = '\0';
|
||||
if((*pf = pxeopen(ini)) == nil)
|
||||
|
|
Loading…
Reference in a new issue