b28e5aa
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
b28e5aa
From: Javier Martinez Canillas <javierm@redhat.com>
b28e5aa
Date: Thu, 23 Apr 2020 15:06:46 +0200
b28e5aa
Subject: [PATCH] efi: Set image base address before jumping to the PE/COFF
b28e5aa
 entry point
b28e5aa
b28e5aa
Upstream GRUB uses the EFI LoadImage() and StartImage() to boot the Linux
b28e5aa
kernel. But our custom EFI loader that supports Secure Boot instead uses
b28e5aa
the EFI handover protocol (for x86) or jumping directly to the PE/COFF
b28e5aa
entry point (for aarch64).
b28e5aa
b28e5aa
This is done to allow the bootloader to verify the images using the shim
b28e5aa
lock protocol to avoid booting untrusted binaries.
b28e5aa
b28e5aa
Since the bootloader loads the kernel from the boot media instead of using
b28e5aa
LoadImage(), it is responsible to set the Loaded Image base address before
b28e5aa
booting the kernel.
b28e5aa
b28e5aa
Otherwise the kernel EFI stub will complain that it was not set correctly
b28e5aa
and print the following warning message:
b28e5aa
b28e5aa
EFI stub: ERROR: FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value
b28e5aa
46968b6
Resolves: rhbz#1814690
b28e5aa
b28e5aa
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
b28e5aa
---
46968b6
 grub-core/loader/efi/linux.c | 14 ++++++++++++++
46968b6
 1 file changed, 14 insertions(+)
b28e5aa
b28e5aa
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
46968b6
index 0622dfa48d4..e8b9ecb17f6 100644
b28e5aa
--- a/grub-core/loader/efi/linux.c
b28e5aa
+++ b/grub-core/loader/efi/linux.c
b28e5aa
@@ -72,6 +72,7 @@ grub_err_t
b28e5aa
 grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
b28e5aa
 		     void *kernel_params)
b28e5aa
 {
b28e5aa
+  grub_efi_loaded_image_t *loaded_image = NULL;
b28e5aa
   handover_func hf;
b28e5aa
   int offset = 0;
b28e5aa
 
46968b6
@@ -79,6 +80,19 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
b28e5aa
   offset = 512;
b28e5aa
 #endif
b28e5aa
 
b28e5aa
+  /*
b28e5aa
+   * Since the EFI loader is not calling the LoadImage() and StartImage()
b28e5aa
+   * services for loading the kernel and booting respectively, it has to
b28e5aa
+   * set the Loaded Image base address.
b28e5aa
+   */
b28e5aa
+  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
b28e5aa
+  if (loaded_image)
b28e5aa
+    loaded_image->image_base = kernel_addr;
b28e5aa
+  else
b28e5aa
+    grub_dprintf ("linux", "Loaded Image base address could not be set\n");
b28e5aa
+
46968b6
+  grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
46968b6
+		kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
b28e5aa
   hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
46968b6
   hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
46968b6