summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Jones <pjones@redhat.com>2013-04-26 12:14:51 -0400
committerPeter Jones <pjones@redhat.com>2013-04-30 09:46:22 -0400
commita24d3ba3bd05223e94156a81a10f196facade4dc (patch)
tree075d543f5d9a547638dc9c6710f751750d4187b4
parent3ce517fdbb4eb895060e99bc86e63e223091faab (diff)
downloadefi-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.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/shim.c b/shim.c
index 0113ed5e..f2b8f1d1 100644
--- a/shim.c
+++ b/shim.c
@@ -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);