diff options
author | Matt Fleming <matt.fleming@intel.com> | 2013-07-05 12:51:12 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2013-08-02 20:11:09 +0100 |
commit | 4f2d3e62b61ebe21498844c0ca346482aca118c9 (patch) | |
tree | 0a2b37b1453c25e1d758a853d8b7a91ce072c303 | |
parent | 9e33f739bcf8455a083ffeb1d8f941d4cd9796b9 (diff) | |
download | syslinux-4f2d3e62b61ebe21498844c0ca346482aca118c9.tar.gz syslinux-4f2d3e62b61ebe21498844c0ca346482aca118c9.tar.xz syslinux-4f2d3e62b61ebe21498844c0ca346482aca118c9.zip |
efi: implement LOCALBOOTsyslinux-6.02-pre16
Booting the next device is in fact fairly trivial under EFI. We simply
need to return control to the firmware with an error code that indicates
we couldn't execute our OS loader properly.
Unlike under BIOS, we don't take any notice of any integer arguments
passed to LOCALBOOT for EFI, since there is no variation for "boot next
entry".
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r-- | efi/main.c | 11 |
1 files changed, 10 insertions, 1 deletions
@@ -6,6 +6,7 @@ #include <syslinux/firmware.h> #include <syslinux/linux.h> #include <sys/ansi.h> +#include <setjmp.h> #include "efi.h" #include "fio.h" @@ -24,6 +25,8 @@ uint32_t timer_irq; __export uint8_t KbdMap[256]; char aux_seg[256]; +static jmp_buf load_error_buf; + static inline EFI_STATUS efi_close_protocol(EFI_HANDLE handle, EFI_GUID *guid, EFI_HANDLE agent, EFI_HANDLE controller) @@ -119,6 +122,11 @@ void printf_init(void) __export void local_boot(uint16_t ax) { + /* + * Inform the firmware that we failed to execute correctly, which + * will trigger the next entry in the EFI Boot Manager list. + */ + longjmp(load_error_buf, 1); } void bios_timer_cleanup(void) @@ -1320,7 +1328,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *table) status = uefi_call_wrapper(in->ReadKeyStroke, 2, in, &key); } while (status != EFI_NOT_READY); - load_env32(NULL); + if (!setjmp(load_error_buf)) + load_env32(NULL); /* load_env32() failed.. cancel timer and bailout */ status = cancel_timer(timer_ev); |