diff options
| author | Peter Jones <pjones@redhat.com> | 2013-04-26 12:14:51 -0400 |
|---|---|---|
| committer | Peter Jones <pjones@redhat.com> | 2013-04-30 09:46:22 -0400 |
| commit | a24d3ba3bd05223e94156a81a10f196facade4dc (patch) | |
| tree | 075d543f5d9a547638dc9c6710f751750d4187b4 | |
| parent | 3ce517fdbb4eb895060e99bc86e63e223091faab (diff) | |
| download | efi-boot-shim-a24d3ba3bd05223e94156a81a10f196facade4dc.tar.gz efi-boot-shim-a24d3ba3bd05223e94156a81a10f196facade4dc.zip | |
Make shim use fallback when appropriate.
If we're called as /BOOT/EFI/BOOT*.EFI, and /BOOT/EFI/FALLBACK.EFI exists,
give it a shot.
Signed-off-by: Peter Jones <pjones@redhat.com>
| -rw-r--r-- | shim.c | 69 |
1 files changed, 68 insertions, 1 deletions
@@ -44,6 +44,7 @@ #include "ucs2.h" #define DEFAULT_LOADER L"\\grub.efi" +#define FALLBACK L"\\fallback.efi" #define MOK_MANAGER L"\\MokManager.efi" static EFI_SYSTEM_TABLE *systab; @@ -899,6 +900,69 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, return EFI_SUCCESS; } +static int +should_use_fallback(EFI_HANDLE image_handle) +{ + EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL; + EFI_LOADED_IMAGE *li; + EFI_DEVICE_PATH *devpath; + int i; + unsigned int pathlen = 0; + CHAR16 *bootpath; + EFI_FILE_IO_INTERFACE *fio = NULL; + EFI_FILE_HANDLE vh; + EFI_FILE_HANDLE fh; + EFI_STATUS rc; + + rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, + &loaded_image_protocol, (void **)&li); + if (EFI_ERROR(rc)) + return 0; + + devpath = li->FilePath; + + bootpath = DevicePathToStr(devpath); + + /* Check the beginning of the string and the end, to avoid + * caring about which arch this is. */ + /* I really don't know why, but sometimes bootpath gives us + * L"\\EFI\\BOOT\\/BOOTX64.EFI". So just handle that here... + */ + if (StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\BOOT", 14) && + StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\/BOOT", 15)) + return 0; + pathlen = StrLen(bootpath); + if (pathlen < 5 || StrCaseCmp(bootpath + pathlen - 4, L".EFI")) + return 0; + + for (i=pathlen; i>0; i--) { + if (bootpath[i] == '\\') + break; + } + + bootpath[i+1] = '\0'; + + rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle, + &FileSystemProtocol, &fio); + if (EFI_ERROR(rc)) + return 0; + + rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh); + if (EFI_ERROR(rc)) + return 0; + + rc = uefi_call_wrapper(vh->Open, 5, vh, &fh, L"\\EFI\\BOOT" FALLBACK, + EFI_FILE_READ_ONLY, 0); + if (EFI_ERROR(rc)) { + uefi_call_wrapper(vh->Close, 1, vh); + return 0; + } + uefi_call_wrapper(fh->Close, 1, fh); + uefi_call_wrapper(vh->Close, 1, vh); + + return 1; +} + /* * Generate the path of an executable given shim's path and the name * of the executable @@ -1202,7 +1266,10 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) { EFI_STATUS efi_status; - efi_status = start_image(image_handle, second_stage); + if (should_use_fallback(image_handle)) + efi_status = start_image(image_handle, FALLBACK); + else + efi_status = start_image(image_handle, second_stage); if (efi_status != EFI_SUCCESS) efi_status = start_image(image_handle, MOK_MANAGER); |
