File shim-fix-loadoptions.patch of Package shim

commit f23f6b726bd12b28befd5a064c47a8a249d80a59
Author: Gary Ching-Pang Lin <glin@suse.com>
Date:   Mon Jan 14 16:53:19 2013 +0800

    Adopt the UEFI shell style LoadOptions
    
    The previous commit, 14d4b8e, caused shim failed to parse the name
    of the 2nd stage loader in UEFI shell. Amend parsing of the name the
    2nd stage loader to be compatible with UEFI shell.
    
    To create an boot entry for elilo.efi:
    
     # efibootmgr -c -L "shim elilo" -l "efi\\shim.efi" -u "shim.efi elilo.efi"

diff --git a/shim.c b/shim.c
index dcf1c51..37a5898 100644
--- a/shim.c
+++ b/shim.c
@@ -1330,6 +1330,8 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
 	EFI_LOADED_IMAGE *li;
 	CHAR16 *start = NULL, *c;
 	int i, remaining_size = 0;
+	CHAR16 *loader_str = NULL;
+	int loader_len = 0;
 
 	second_stage = DEFAULT_LOADER;
 	load_options = NULL;
@@ -1351,6 +1353,11 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
 		return EFI_BAD_BUFFER_SIZE;
 	}
 
+	/*
+	 * UEFI shell copies the whole line of the command into LoadOptions.
+	 * We ignore the string before the first L' ', i.e. the name of this
+	 * program.
+	 */
 	for (i = 0; i < li->LoadOptionsSize; i += 2) {
 		c = (CHAR16 *)(li->LoadOptions + i);
 		if (*c == L' ') {
@@ -1360,9 +1367,30 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
 			break;
 		}
 	}
+	if (!start || remaining_size <= 0)
+		return EFI_SUCCESS;
 
-	second_stage = (CHAR16 *)li->LoadOptions;
-	if (start && remaining_size > 0) {
+	for (i = 0; start[i] != '\0'; i++) {
+		if (start[i] == L' ' || start[i] == L'\0')
+			break;
+		loader_len++;
+	}
+
+	/*
+	 * Setup the name of the alternative loader and the LoadOptions for
+	 * the loader
+	 */
+	if (loader_len > 0) {
+		loader_str = AllocatePool((loader_len + 1) * sizeof(CHAR16));
+		if (!loader_str) {
+			Print(L"Failed to allocate loader string\n");
+			return EFI_OUT_OF_RESOURCES;
+		}
+		for (i = 0; i < loader_len; i++)
+			loader_str[i] = start[i];
+		loader_str[loader_len] = L'\0';
+
+		second_stage = loader_str;
 		load_options = start;
 		load_options_size = remaining_size;
 	}
@@ -1439,5 +1467,11 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
 	uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle,
 			  &shim_lock_guid, &shim_lock_interface);
 
+	/*
+	 * Free the space allocated for the alternative 2nd stage loader
+	 */
+	if (load_options_size > 0)
+		FreePool(second_stage);
+
 	return efi_status;
 }
openSUSE Build Service is sponsored by