From 3e48cb37712f34a158ea6b0f491c6ba37aab4c10 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 5 Feb 2010 17:20:49 -0800 Subject: [PATCH] PXE: fix the EFI localboot hack Make the EFI localboot hack work again, by properly detecting the EFI signature and adjusting the stack properly. Signed-off-by: H. Peter Anvin --- core/fs/pxe/pxe.c | 38 +++++++++++++++++++++----------------- core/pxelinux.asm | 5 +++++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index d48473f..ea26ef6 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -1277,7 +1277,7 @@ static int pxe_init(void) uint16_t seg, off; uint16_t code_seg, code_len; uint16_t data_seg, data_len; - char *base = GET_PTR(InitStack); + const char *base = GET_PTR(InitStack); com32sys_t regs; const char *type; const struct pxenv_t *pxenv; @@ -1287,16 +1287,16 @@ static int pxe_init(void) APIVer = 0x201; /* Plan A: !PXE structure as SS:[SP + 4] */ - off = *(uint16_t *)(base + 48); - seg = *(uint16_t *)(base + 50); + off = *(const uint16_t *)(base + 48); + seg = *(const uint16_t *)(base + 50); pxe = MK_PTR(seg, off); if (is_pxe(pxe)) goto have_pxe; /* Plan B: PXENV+ structure at [ES:BX] */ plan++; - off = *(uint16_t *)(base + 24); /* Original BX */ - seg = *(uint16_t *)(base + 4); /* Original ES */ + off = *(const uint16_t *)(base + 24); /* Original BX */ + seg = *(const uint16_t *)(base + 4); /* Original ES */ pxenv = MK_PTR(seg, off); if (is_pxenv(pxenv)) goto have_pxenv; @@ -1522,11 +1522,12 @@ extern far_ptr_t InitStack; struct efi_struct { uint32_t magic; + uint8_t csum; uint8_t len; -}; -#define EFI_MAGIC 0x24454649 /* $EFI, but bigendian... */ +} __attribute__((packed)); +#define EFI_MAGIC (('$' << 24)+('E' << 16)+('F' << 8)+'I') -static inline int is_efi(const struct efi_struct *efi) +static inline bool is_efi(const struct efi_struct *efi) { /* * We don't verify the checksum, because it seems some CSMs leave @@ -1540,15 +1541,12 @@ static void install_efi_csm_hack(void) static const uint8_t efi_csm_hack[] = { 0xcd, 0x18, /* int $0x18 */ - 0xea, 0xf0, 0xff, 0x00, 0xf0, /* ljmpw $0xf000,$0xffff */ + 0xea, 0xf0, 0xff, 0x00, 0xf0, /* ljmpw $0xf000,$0xfff0 */ 0xf4 /* hlt */ }; - far_ptr_t retptr; uint16_t *retcode; - retptr = *(far_ptr_t *)GET_PTR(InitStack); - retptr.offs += 44; - retcode = GET_PTR(retptr); + retcode = GET_PTR(*(far_ptr_t *)((char *)GET_PTR(InitStack) + 44)); /* Don't do this if the return already points to int $0x18 */ if (*retcode != 0x18cd) { @@ -1565,12 +1563,14 @@ static void install_efi_csm_hack(void) if (efi) { uint8_t *src = GET_PTR(InitStack); uint8_t *dst = src - sizeof efi_csm_hack; + memmove(dst, src, 52); memcpy(dst+52, efi_csm_hack, sizeof efi_csm_hack); - InitStack.offs -= 52; + InitStack.offs -= sizeof efi_csm_hack; /* Clobber the return address */ - *(far_ptr_t *)(dst+44) = FAR_PTR(dst+52); + *(uint16_t *)(dst+44) = OFFS_WRT(dst+52, InitStack.seg); + *(uint16_t *)(dst+46) = InitStack.seg; } } } @@ -1580,6 +1580,10 @@ void reset_pxe(void) static __lowmem struct s_PXENV_UDP_CLOSE udp_close; extern void gpxe_unload(void); + pxe_idle_cleanup(); + + printf("reset_pxe\n"); + pxe_call(PXENV_UDP_CLOSE, &udp_close); if (gpxe_funcs & 0x80) { @@ -1603,8 +1607,6 @@ void unload_pxe(void) int int_addr; static __lowmem struct s_PXENV_UNLOAD_STACK unload_stack; - pxe_idle_cleanup(); - if (KeepPXE) { /* * We want to keep PXE around, but still we should reset @@ -1614,6 +1616,8 @@ void unload_pxe(void) return; } + pxe_idle_cleanup(); + api_ptr = major_ver(APIVer) >= 2 ? new_api_unload : old_api_unload; while((api = *api_ptr++)) { memset(&unload_stack, 0, sizeof unload_stack); diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 6f78623..58f76ce 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -300,6 +300,7 @@ local_boot: mov si,localboot_msg call writestr_early ; Restore the environment we were called with + pm_call reset_pxe call cleanup_hardware lss sp,[InitStack] pop gs @@ -442,6 +443,8 @@ gpxe_unload: ; Now we actually need to exit back to gPXE, which will ; give control back to us on the *new* "original stack"... pushfd + push ds + push es mov [PXEStack],sp mov [PXEStack+2],ss lss sp,[InitStack] @@ -471,6 +474,8 @@ gpxe_unload: mov [cs:InitStack],sp mov [cs:InitStack+2],ss lss sp,[cs:PXEStack] + pop es + pop ds popfd .plain: -- 2.7.4