From 16e08adb32778864035cc582c3a9163d3032ca4b Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Thu, 23 Oct 2014 23:11:49 +0200 Subject: [PATCH] efi: add initial pxe support (v4 only) --- sys/src/boot/efi/efi.c | 110 ++++-------- sys/src/boot/efi/efi.h | 52 +----- sys/src/boot/efi/fns.h | 15 +- sys/src/boot/efi/fs.c | 106 ++++++++++++ sys/src/boot/efi/mkfile | 16 +- sys/src/boot/efi/pe32.s | 24 ++- sys/src/boot/efi/pe64.s | 21 ++- sys/src/boot/efi/pxe.c | 359 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 555 insertions(+), 148 deletions(-) create mode 100644 sys/src/boot/efi/fs.c create mode 100644 sys/src/boot/efi/pxe.c diff --git a/sys/src/boot/efi/efi.c b/sys/src/boot/efi/efi.c index a16260d6f..38df155de 100644 --- a/sys/src/boot/efi/efi.c +++ b/sys/src/boot/efi/efi.c @@ -2,14 +2,13 @@ #include "fns.h" #include "efi.h" -enum { - MAXPATH = 128, -}; - UINTN MK; EFI_HANDLE IH; EFI_SYSTEM_TABLE *ST; -EFI_FILE_PROTOCOL *root; + +void* (*open)(char *name); +int (*read)(void *f, void *data, int len); +void (*close)(void *f); void putc(int c) @@ -18,7 +17,7 @@ putc(int c) w[0] = c; w[1] = 0; - eficall(2, ST->ConOut->OutputString, ST->ConOut, w); + eficall(ST->ConOut->OutputString, ST->ConOut, w); } int @@ -26,7 +25,7 @@ getc(void) { EFI_INPUT_KEY k; - if(eficall(2, ST->ConIn->ReadKeyStroke, ST->ConIn, &k)) + if(eficall(ST->ConIn->ReadKeyStroke, ST->ConIn, &k)) return 0; return k.UnicodeChar; } @@ -34,78 +33,15 @@ getc(void) void usleep(int us) { - eficall(1, ST->BootServices->Stall, (UINTN)us); + eficall(ST->BootServices->Stall, (UINTN)us); } void unload(void) { - eficall(2, ST->BootServices->ExitBootServices, IH, MK); + eficall(ST->BootServices->ExitBootServices, IH, MK); } -void -fsinit(void) -{ - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs; - - fs = nil; - root = nil; - if(eficall(3, ST->BootServices->LocateProtocol, - &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &fs)) - return; - if(eficall(2, fs->OpenVolume, fs, &root)){ - root = nil; - return; - } -} - -static void -towpath(CHAR16 *w, int nw, char *s) -{ - int i; - - for(i=0; *s && iOpen, dir, &fp, wname, (UINT64)1, (UINT64)1)) - return nil; - return fp; -} - - -int -read(void *f, void *data, int len) -{ - UINTN size; - - size = len; - if(eficall(3, ((EFI_FILE_PROTOCOL*)f)->Read, f, &size, data)) - return 0; - return (int)size; -} - -void -close(void *f) -{ - eficall(1, ((EFI_FILE_PROTOCOL*)f)->Close, f); -} - - static void memconf(char **cfg) { @@ -134,7 +70,7 @@ memconf(char **cfg) mapsize = sizeof(mapbuf); entsize = sizeof(EFI_MEMORY_DESCRIPTOR); entvers = 1; - if(eficall(5, ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers)) + if(eficall(ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers)) return; s = *cfg; @@ -165,6 +101,16 @@ memconf(char **cfg) static void acpiconf(char **cfg) { + static EFI_GUID ACPI_20_TABLE_GUID = { + 0x8868e871, 0xe4f1, 0x11d3, + 0xbc, 0x22, 0x00, 0x80, + 0xc7, 0x3c, 0x88, 0x81, + }; + static EFI_GUID ACPI_10_TABLE_GUID = { + 0xeb9d2d30, 0x2d88, 0x11d3, + 0x9a, 0x16, 0x00, 0x90, + 0x27, 0x3f, 0xc1, 0x4d, + }; EFI_CONFIGURATION_TABLE *t; uintptr pa; char *s; @@ -220,6 +166,11 @@ lowbit(ulong mask) static void screenconf(char **cfg) { + static EFI_GUID EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID = { + 0x9042a9de, 0x23dc, 0x4a38, + 0x96, 0xfb, 0x7a, 0xde, + 0xd0, 0x80, 0x51, 0x6a, + }; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; EFI_HANDLE *Handles; UINTN Count; @@ -231,13 +182,13 @@ screenconf(char **cfg) Count = 0; Handles = nil; - if(eficall(5, ST->BootServices->LocateHandleBuffer, + if(eficall(ST->BootServices->LocateHandleBuffer, ByProtocol, &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &Count, &Handles)) return; for(i=0; iBootServices->HandleProtocol, + if(eficall(ST->BootServices->HandleProtocol, Handles[i], &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, &gop)) continue; @@ -331,7 +282,7 @@ eficonfig(char **cfg) } EFI_STATUS -main(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) +efimain(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) { char path[MAXPATH], *kern; void *f; @@ -339,12 +290,13 @@ main(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) IH = ih; ST = st; - fsinit(); + f = pxeinit(); + if(f == nil) + f = fsinit(); - f = fswalk(root, "/plan9.ini"); for(;;){ kern = configure(f, path); - f = fswalk(root, kern); + f = open(kern); if(f == nil){ print("not found\n"); continue; diff --git a/sys/src/boot/efi/efi.h b/sys/src/boot/efi/efi.h index 142385af3..b78040f3d 100644 --- a/sys/src/boot/efi/efi.h +++ b/sys/src/boot/efi/efi.h @@ -4,6 +4,7 @@ typedef uchar UINT8; typedef ushort UINT16; typedef ulong UINT32; typedef uvlong UINT64; +typedef UINT8 BOOLEAN; typedef uintptr UINTN; @@ -87,41 +88,6 @@ typedef struct { EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; } EFI_GRAPHICS_OUTPUT_PROTOCOL; -EFI_GUID EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID = { - 0x9042a9de, 0x23dc, 0x4a38, - 0x96, 0xfb, 0x7a, 0xde, - 0xd0, 0x80, 0x51, 0x6a, -}; - -typedef struct { - UINT64 Revision; - void *Open; - void *Close; - void *Delete; - void *Read; - void *Write; - void *GetPosition; - void *SetPosition; - void *GetInfo; - void *SetInfo; - void *Flush; - void *OpenEx; - void *ReadEx; - void *WriteEx; - void *FlushEx; -} EFI_FILE_PROTOCOL; - -typedef struct { - UINT64 Revision; - void *OpenVolume; -} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; - -EFI_GUID EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID = { - 0x0964e5b22, 0x6459, 0x11d2, - 0x8e, 0x39, 0x00, 0xa0, - 0xc9, 0x69, 0x72, 0x3b, -}; - enum { EfiReservedMemoryType, EfiLoaderCode, @@ -243,19 +209,6 @@ typedef struct { void *QueryVariableInfo; } EFI_RUNTIME_SERVICES; - -EFI_GUID ACPI_20_TABLE_GUID = { - 0x8868e871, 0xe4f1, 0x11d3, - 0xbc, 0x22, 0x00, 0x80, - 0xc7, 0x3c, 0x88, 0x81, -}; - -EFI_GUID ACPI_10_TABLE_GUID = { - 0xeb9d2d30, 0x2d88, 0x11d3, - 0x9a, 0x16, 0x00, 0x90, - 0x27, 0x3f, 0xc1, 0x4d, -}; - typedef struct { EFI_GUID VendorGuid; void *VendorTable; @@ -282,3 +235,6 @@ typedef struct { UINTN NumberOfTableEntries; EFI_CONFIGURATION_TABLE *ConfigurationTable; } EFI_SYSTEM_TABLE; + +extern EFI_SYSTEM_TABLE *ST; +extern EFI_HANDLE IH; diff --git a/sys/src/boot/efi/fns.h b/sys/src/boot/efi/fns.h index 3d1770562..c249dd5ce 100644 --- a/sys/src/boot/efi/fns.h +++ b/sys/src/boot/efi/fns.h @@ -1,11 +1,20 @@ +enum { + MAXPATH = 128, +}; + extern char hex[]; void usleep(int t); void jump(void *pc); -int read(void *f, void *data, int len); +void* pxeinit(void); +void* fsinit(void); + +void* (*open)(char *name); +int (*read)(void *f, void *data, int len); +void (*close)(void *f); + int readn(void *f, void *data, int len); -void close(void *f); void unload(void); int getc(void); @@ -25,5 +34,5 @@ char *bootkern(void *f); char *hexfmt(char *s, int i, uvlong a); char *decfmt(char *s, int i, ulong a); -long eficall(long narg, void *proc, ...); +uintptr eficall(void *proc, ...); void eficonfig(char **cfg); diff --git a/sys/src/boot/efi/fs.c b/sys/src/boot/efi/fs.c new file mode 100644 index 000000000..04d9114a0 --- /dev/null +++ b/sys/src/boot/efi/fs.c @@ -0,0 +1,106 @@ +#include +#include "fns.h" +#include "efi.h" + +typedef struct { + UINT64 Revision; + void *Open; + void *Close; + void *Delete; + void *Read; + void *Write; + void *GetPosition; + void *SetPosition; + void *GetInfo; + void *SetInfo; + void *Flush; + void *OpenEx; + void *ReadEx; + void *WriteEx; + void *FlushEx; +} EFI_FILE_PROTOCOL; + +typedef struct { + UINT64 Revision; + void *OpenVolume; +} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +static +EFI_GUID EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID = { + 0x0964e5b22, 0x6459, 0x11d2, + 0x8e, 0x39, 0x00, 0xa0, + 0xc9, 0x69, 0x72, 0x3b, +}; + +static +EFI_FILE_PROTOCOL *fsroot; + +static void +towpath(CHAR16 *w, int nw, char *s) +{ + int i; + + for(i=0; *s && iOpen, fsroot, &fp, wname, (UINT64)1, (UINT64)1)) + return nil; + return fp; +} + +static int +fsread(void *f, void *data, int len) +{ + UINTN size; + + size = len; + if(eficall(((EFI_FILE_PROTOCOL*)f)->Read, f, &size, data)) + return 0; + return (int)size; +} + +static void +fsclose(void *f) +{ + eficall(((EFI_FILE_PROTOCOL*)f)->Close, f); +} + +void* +fsinit(void) +{ + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs; + + fs = nil; + fsroot = nil; + if(eficall(ST->BootServices->LocateProtocol, + &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &fs)) + return nil; + if(eficall(fs->OpenVolume, fs, &fsroot)){ + fsroot = nil; + return nil; + } + + read = fsread; + close = fsclose; + open = fsopen; + + return fsopen("/plan9.ini"); +} diff --git a/sys/src/boot/efi/mkfile b/sys/src/boot/efi/mkfile index fa5292ce2..c68fa0fb4 100644 --- a/sys/src/boot/efi/mkfile +++ b/sys/src/boot/efi/mkfile @@ -13,7 +13,7 @@ install:V: $TARG clean:V: rm -f *.[68] *.out $TARG -bootia32.efi: pe32.8 efi.8 sub.8 +bootia32.efi: pe32.8 efi.8 fs.8 pxe.8 sub.8 8l -l -H3 -T$IMAGEBASE -o $target $prereq pe32.8: pe32.s @@ -22,13 +22,19 @@ pe32.8: pe32.s efi.8: efi.c efi.h 8c $CFLAGS efi.c +fs.8: fs.c efi.h + 8c $CFLAGS fs.c + +pxe.8: pxe.c efi.h + 8c $CFLAGS pxe.c + sub.8: sub.c 8c $CFLAGS sub.c %.8: $HFILES -bootx64.efi: pe64.6 efi.6 sub.6 +bootx64.efi: pe64.6 efi.6 fs.6 pxe.6 sub.6 6l -l -s -R1 -T$IMAGEBASE -o bootx64.out $prereq dd -if bootx64.out -bs 1 -iseek 40 >$target @@ -38,6 +44,12 @@ pe64.6: pe64.s efi.6: efi.c efi.h 6c $CFLAGS efi.c +fs.6: fs.c efi.h + 6c $CFLAGS fs.c + +pxe.6: pxe.c efi.h + 6c $CFLAGS pxe.c + sub.6: sub.c 6c $CFLAGS sub.c diff --git a/sys/src/boot/efi/pe32.s b/sys/src/boot/efi/pe32.s index 46abc0009..35891db1b 100644 --- a/sys/src/boot/efi/pe32.s +++ b/sys/src/boot/efi/pe32.s @@ -129,7 +129,7 @@ TEXT reloc(SB), 1, $0 MOVL $edata-IMAGEBASE(SB), CX CLD REP; MOVSB - MOVL $main(SB), DI + MOVL $efimain(SB), DI MOVL DI, (SP) RET @@ -138,12 +138,22 @@ TEXT jump(SB), $0 MOVL 4(SP), AX JMP *AX - TEXT eficall(SB), 1, $0 - MOVL 0(SP), DI /* saved by callee */ - MOVL 8(SP), AX - ADDL $12, SP + MOVL SP, SI + MOVL SP, DI + MOVL $(4*16), CX + SUBL CX, DI + ANDL $~15ULL, DI + SUBL $8, DI + + MOVL 4(SI), AX + LEAL 8(DI), SP + + CLD + REP; MOVSB + SUBL $(4*16), SI + CALL AX - SUBL $12, SP - MOVL DI, 0(SP) + + MOVL SI, SP RET diff --git a/sys/src/boot/efi/pe64.s b/sys/src/boot/efi/pe64.s index a9c00aa39..a2a3d1239 100644 --- a/sys/src/boot/efi/pe64.s +++ b/sys/src/boot/efi/pe64.s @@ -136,25 +136,28 @@ TEXT reloc(SB), 1, $-4 REP; MOVSB MOVQ 16(SP), BP - MOVQ $main(SB), DI + MOVQ $efimain(SB), DI MOVQ DI, (SP) RET TEXT eficall(SB), 1, $-4 - MOVQ 0(SP), DI /* saved by callee */ - MOVQ 16(SP), AX - ADDQ $24, SP + MOVQ SP, SI + MOVQ SP, DI + MOVL $(8*16), CX + SUBQ CX, DI + ANDQ $~15ULL, DI + LEAQ 16(DI), SP + CLD + REP; MOVSB + SUBQ $(8*16), SI - /* arguments in regisyers */ MOVQ 0(SP), CX MOVQ 8(SP), DX MOVQ 16(SP), R8 MOVQ 24(SP), R9 + CALL BP - CALL AX - - SUBQ $24, SP - MOVQ DI, 0(SP) + MOVQ SI, SP RET #include "mem.h" diff --git a/sys/src/boot/efi/pxe.c b/sys/src/boot/efi/pxe.c new file mode 100644 index 000000000..9c7af88bc --- /dev/null +++ b/sys/src/boot/efi/pxe.c @@ -0,0 +1,359 @@ +#include +#include "fns.h" +#include "efi.h" + +typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT; + +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +typedef struct { + UINT8 BootpOpcode; + UINT8 BootpHwType; + UINT8 BootpHwAddrLen; + UINT8 BootpGateHops; + UINT32 BootpIdent; + UINT16 BootpSeconds; + UINT16 BootpFlags; + UINT8 BootpCiAddr[4]; + UINT8 BootpYiAddr[4]; + UINT8 BootpSiAddr[4]; + UINT8 BootpGiAddr[4]; + UINT8 BootpHwAddr[16]; + UINT8 BootpSrvName[64]; + UINT8 BootpBootFile[128]; + UINT32 DhcpMagik; + UINT8 DhcpOptions[56]; +} EFI_PXE_BASE_CODE_DHCPV4_PACKET; + +typedef struct { + BOOLEAN Started; + BOOLEAN Ipv6Available; + BOOLEAN Ipv6Supported; + BOOLEAN UsingIpv6; + BOOLEAN BisSupported; + BOOLEAN BisDetected; + BOOLEAN AutoArp; + BOOLEAN SendGUID; + BOOLEAN DhcpDiscoverValid; + BOOLEAN DhcpAckReceived; + BOOLEAN ProxyOfferReceived; + BOOLEAN PxeDiscoverValid; + BOOLEAN PxeReplyReceived; + BOOLEAN PxeBisReplyReceived; + BOOLEAN IcmpErrorReceived; + BOOLEAN TftpErrorReceived; + BOOLEAN MakeCallbacks; + + UINT8 TTL; + UINT8 ToS; + + UINT8 Reserved; + + UINT8 StationIp[16]; + UINT8 SubnetMask[16]; + + UINT8 DhcpDiscover[1472]; + UINT8 DhcpAck[1472]; +} EFI_PXE_BASE_CODE_MODE; + +typedef struct { + UINT64 Revision; + void *Start; + void *Stop; + void *Dhcp; + void *Discover; + void *Mtftp; + void *UdpWrite; + void *UdpRead; + void *SetIpFilter; + void *Arp; + void *SetParameters; + void *SetStationIp; + void *SetPackets; + EFI_PXE_BASE_CODE_MODE *Mode; +} EFI_PXE_BASE_CODE_PROTOCOL; + + +enum { + Tftp_READ = 1, + Tftp_WRITE = 2, + Tftp_DATA = 3, + Tftp_ACK = 4, + Tftp_ERROR = 5, + Tftp_OACK = 6, + + TftpPort = 69, + + Segsize = 512, +}; + +static +EFI_GUID EFI_PXE_BASE_CODE_PROTOCOL_GUID = { + 0x03C4E603, 0xAC28, 0x11D3, + 0x9A, 0x2D, 0x00, 0x90, + 0x27, 0x3F, 0xC1, 0x4D, +}; + +static +EFI_PXE_BASE_CODE_PROTOCOL *pxe; + +static +EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp; + +typedef struct Tftp Tftp; +struct Tftp +{ + EFI_IP_ADDRESS sip; + EFI_IP_ADDRESS dip; + + EFI_PXE_BASE_CODE_UDP_PORT sport; + EFI_PXE_BASE_CODE_UDP_PORT dport; + + char *rp; + char *ep; + + int seq; + int eof; + + char pkt[2+2+Segsize]; + char nul; +}; + +static void +puts(void *x, ushort v) +{ + uchar *p = x; + + p[1] = (v>>8) & 0xFF; + p[0] = v & 0xFF; +} + +static ushort +gets(void *x) +{ + uchar *p = x; + + return p[1]<<8 | p[0]; +} + +static void +hnputs(void *x, ushort v) +{ + uchar *p = x; + + p[0] = (v>>8) & 0xFF; + p[1] = v & 0xFF; +} + +static ushort +nhgets(void *x) +{ + uchar *p = x; + + return p[0]<<8 | p[1]; +} + +enum { + ANY_SRC_IP = 0x0001, + ANY_SRC_PORT = 0x0002, + ANY_DEST_IP = 0x0004, + ANY_DEST_PORT = 0x0008, + USE_FILTER = 0x0010, + MAY_FRAGMENT = 0x0020, +}; + +static int +udpread(EFI_IP_ADDRESS *sip, EFI_IP_ADDRESS *dip, + EFI_PXE_BASE_CODE_UDP_PORT *sport, + EFI_PXE_BASE_CODE_UDP_PORT dport, + int *len, void *data) +{ + UINTN size; + + size = *len; + if(eficall(pxe->UdpRead, pxe, (UINTN)ANY_SRC_PORT, dip, &dport, sip, sport, nil, nil, &size, data)) + return -1; + + *len = size; + return 0; +} + +static int +udpwrite(EFI_IP_ADDRESS *dip, + EFI_PXE_BASE_CODE_UDP_PORT sport, + EFI_PXE_BASE_CODE_UDP_PORT dport, + int len, void *data) +{ + UINTN size; + + size = len; + if(eficall(pxe->UdpWrite, pxe, (UINTN)MAY_FRAGMENT, dip, &dport, nil, nil, &sport, nil, nil, &size, data)) + return -1; + + return 0; +} + +static int +pxeread(void *f, void *data, int len) +{ + Tftp *t = f; + int seq, n; + + 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)) + continue; + if(n >= 4) + break; + } + 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->sport, t->dport, 4, t->pkt)) + putc('!'); + if(seq < t->seq){ + putc('@'); + continue; + } + t->seq = seq+1; + n -= 4; + t->rp = t->pkt + 4; + t->ep = t->rp + n; + t->eof = n < Segsize; + break; + case Tftp_ERROR: + print(t->pkt+4); + print("\n"); + default: + t->eof = 1; + return -1; + } + break; + } + n = t->ep - t->rp; + if(len > n) + len = n; + memmove(data, t->rp, len); + t->rp += len; + return len; +} + +static void +pxeclose(void *f) +{ + Tftp *t = f; + t->eof = 1; +} + + +static int +tftpopen(Tftp *t, char *path) +{ + static EFI_PXE_BASE_CODE_UDP_PORT xport = 6666; + int r, n; + char *p; + + t->sport = xport++; + t->dport = 0; + t->rp = t->ep = 0; + t->seq = 1; + t->eof = 0; + t->nul = 0; + p = t->pkt; + hnputs(p, Tftp_READ); p += 2; + n = strlen(path)+1; + memmove(p, path, n); p += n; + memmove(p, "octet", 6); p += 6; + n = p - t->pkt; + for(;;){ + if(r = udpwrite(&t->dip, t->sport, TftpPort, n, t->pkt)) + break; + if(r = pxeread(t, 0, 0)) + break; + return 0; + } + pxeclose(t); + return r; +} + +static void* +pxeopen(char *name) +{ + static Tftp t[1]; + + memset(t, 0, sizeof(Tftp)); + + memmove(&t->dip, dhcp->BootpSiAddr, 4); + memmove(&t->sip, pxe->Mode->StationIp, 4); + + if(tftpopen(t, name) == 0) + return t; + return nil; +} + +void* +pxeinit(void) +{ + EFI_HANDLE *Handles; + UINTN Count; + char ini[24]; + uchar *mac; + void *f; + int i; + + pxe = nil; + dhcp = nil; + Count = 0; + Handles = nil; + if(eficall(ST->BootServices->LocateHandleBuffer, + ByProtocol, &EFI_PXE_BASE_CODE_PROTOCOL_GUID, nil, &Count, &Handles)) + return nil; + + for(i=0; iBootServices->HandleProtocol, + Handles[i], &EFI_PXE_BASE_CODE_PROTOCOL_GUID, &pxe)) + continue; + if(pxe->Mode != nil && pxe->Mode->Started) + break; + } + dhcp = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)pxe->Mode->DhcpAck; + + 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+12] = '\0'; + + open = pxeopen; + read = pxeread; + close = pxeclose; + + if((f = pxeopen(ini)) != nil) + return f; + return pxeopen("/cfg/pxe/default"); +}