File shim-get-2nd-stage-loader.patch of Package shim
commit 940425a8bce6bf1b556dc48189884b4a82d8d420
Author: Gary Ching-Pang Lin <glin@suse.com>
Date: Thu Dec 6 17:47:26 2012 +0800
Get the second stage loader from the Load Options
This commit replaces the 2nd stage loader path with the first
argument in the Load Options and moves the rest arguments (if any)
to the Load Options for the 2nd stage loader.
For example, to make shim to load elilo.efi, just create a new
boot entry with efibootmgr:
# efibootmgr -c -L "shim elilo" -l "efi\\shim.efi" -u "elilo.efi"
diff --git a/shim.c b/shim.c
index c3aae9e..44301dd 100644
--- a/shim.c
+++ b/shim.c
@@ -42,12 +42,16 @@
#include "netboot.h"
#include "shim_cert.h"
-#define SECOND_STAGE L"\\grub.efi"
+#define DEFAULT_LOADER L"\\grub.efi"
#define MOK_MANAGER L"\\MokManager.efi"
static EFI_SYSTEM_TABLE *systab;
static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
+static CHAR16 *second_stage;
+static void *load_options;
+static UINT32 load_options_size;
+
/*
* The vendor certificate used for validating the second stage loader
*/
@@ -881,6 +885,10 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
li->ImageBase = buffer;
li->ImageSize = context.ImageSize;
+ /* Pass the load options to the second stage loader */
+ li->LoadOptions = load_options;
+ li->LoadOptionsSize = load_options_size;
+
if (!entry_point) {
Print(L"Invalid entry point\n");
FreePool(buffer);
@@ -1192,7 +1200,7 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle)
{
EFI_STATUS efi_status;
- efi_status = start_image(image_handle, SECOND_STAGE);
+ efi_status = start_image(image_handle, second_stage);
if (efi_status != EFI_SUCCESS)
efi_status = start_image(image_handle, MOK_MANAGER);
@@ -1312,6 +1320,55 @@ static EFI_STATUS check_mok_sb (void)
return status;
}
+/*
+ * Check the load options to specify the second stage loader
+ */
+EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
+{
+ EFI_STATUS status;
+ EFI_LOADED_IMAGE *li;
+ CHAR16 *start = NULL, *c;
+ int i, remaining_size = 0;
+
+ second_stage = DEFAULT_LOADER;
+ load_options = NULL;
+ load_options_size = 0;
+
+ status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
+ &LoadedImageProtocol, (void **) &li);
+ if (status != EFI_SUCCESS) {
+ Print (L"Failed to get load options\n");
+ return status;
+ }
+
+ /* Expect a CHAR16 string with at least one CHAR16 */
+ if (li->LoadOptionsSize < 4 || li->LoadOptionsSize % 2 != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ c = (CHAR16 *)(li->LoadOptions + (li->LoadOptionsSize - 2));
+ if (*c != L'\0') {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ for (i = 0; i < li->LoadOptionsSize; i += 2) {
+ c = (CHAR16 *)(li->LoadOptions + i);
+ if (*c == L' ') {
+ *c = L'\0';
+ start = c + 1;
+ remaining_size = li->LoadOptionsSize - i - 2;
+ break;
+ }
+ }
+
+ second_stage = (CHAR16 *)li->LoadOptions;
+ if (start && remaining_size > 0) {
+ load_options = start;
+ load_options_size = remaining_size;
+ }
+
+ return EFI_SUCCESS;
+}
+
EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
@@ -1334,6 +1391,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
*/
InitializeLib(image_handle, systab);
+ /* Set the second stage loader */
+ set_second_stage (image_handle);
+
/*
* Check whether the user has configured the system to run in
* insecure mode