arrfab / rpms / shim

Forked from rpms/shim 4 years ago
Clone

Blame SOURCES/0018-fallback-For-HD-device-paths-use-just-the-media-node.patch

f2fa6b
From dfd6c73a212f8cf6b32ce74807de9a08a87f0b79 Mon Sep 17 00:00:00 2001
f2fa6b
From: Peter Jones <pjones@redhat.com>
f2fa6b
Date: Fri, 31 Jan 2014 10:30:24 -0500
f2fa6b
Subject: [PATCH 18/19] [fallback] For HD() device paths, use just the media
f2fa6b
 node and later.
f2fa6b
f2fa6b
UEFI 2.x section 3.1.2 provides for "short-form device path", where the
f2fa6b
first element specified is a "hard drive media device path", so that you
f2fa6b
can move a disk around on different buses without invalidating your
f2fa6b
device path.  Fallback has not been using this option, though in most
f2fa6b
cases efibootmgr has.
f2fa6b
f2fa6b
Note that we still keep the full device path, because LoadImage()
f2fa6b
isn't necessarily the layer where HD() works - one some systems BDS is
f2fa6b
responsible for resolving the full path and passes that to LoadImage()
f2fa6b
instead.  So we have to do LoadImage() with the full path.
f2fa6b
---
f2fa6b
 fallback.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++---------------
f2fa6b
 1 file changed, 78 insertions(+), 25 deletions(-)
f2fa6b
f2fa6b
diff --git a/fallback.c b/fallback.c
f2fa6b
index ba864ee..a12bb74 100644
f2fa6b
--- a/fallback.c
f2fa6b
+++ b/fallback.c
f2fa6b
@@ -15,6 +15,27 @@
f2fa6b
 EFI_LOADED_IMAGE *this_image = NULL;
f2fa6b
 
f2fa6b
 static EFI_STATUS
f2fa6b
+FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType,
f2fa6b
+		  EFI_DEVICE_PATH **Out)
f2fa6b
+{
f2fa6b
+	EFI_DEVICE_PATH *dp = In;
f2fa6b
+	if (!In || !Out)
f2fa6b
+		return EFI_INVALID_PARAMETER;
f2fa6b
+
f2fa6b
+	for (dp = In; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) {
f2fa6b
+		if (DevicePathType(dp) == Type &&
f2fa6b
+				DevicePathSubType(dp) == SubType) {
f2fa6b
+			*Out = DuplicateDevicePath(dp);
f2fa6b
+			if (!*Out)
f2fa6b
+				return EFI_OUT_OF_RESOURCES;
f2fa6b
+			return EFI_SUCCESS;
f2fa6b
+		}
f2fa6b
+	}
f2fa6b
+	*Out = NULL;
f2fa6b
+	return EFI_NOT_FOUND;
f2fa6b
+}
f2fa6b
+
f2fa6b
+static EFI_STATUS
f2fa6b
 get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize)
f2fa6b
 {
f2fa6b
 	EFI_STATUS rc;
f2fa6b
@@ -93,7 +114,9 @@ make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen)
f2fa6b
 {
f2fa6b
 	UINT64 len;
f2fa6b
 	
f2fa6b
-	len = StrLen(dirname) + StrLen(filename) + StrLen(L"\\EFI\\\\") + 2;
f2fa6b
+	len = StrLen(L"\\EFI\\") + StrLen(dirname)
f2fa6b
+	    + StrLen(L"\\") + StrLen(filename)
f2fa6b
+	    + 2;
f2fa6b
 
f2fa6b
 	CHAR16 *fullpath = AllocateZeroPool(len*sizeof(CHAR16));
f2fa6b
 	if (!fullpath) {
f2fa6b
@@ -119,7 +142,8 @@ VOID *first_new_option_args = NULL;
f2fa6b
 UINTN first_new_option_size = 0;
f2fa6b
 
f2fa6b
 EFI_STATUS
f2fa6b
-add_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
f2fa6b
+add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
f2fa6b
+		CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
f2fa6b
 {
f2fa6b
 	static int i = 0;
f2fa6b
 	CHAR16 varname[] = L"Boot0000";
f2fa6b
@@ -136,24 +160,31 @@ add_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, CHAR16 *ar
f2fa6b
 		void *var = LibGetVariable(varname, &global);
f2fa6b
 		if (!var) {
f2fa6b
 			int size = sizeof(UINT32) + sizeof (UINT16) +
f2fa6b
-				StrLen(label)*2 + 2 + DevicePathSize(dp) +
f2fa6b
-				StrLen(arguments) * 2 + 2;
f2fa6b
+				StrLen(label)*2 + 2 + DevicePathSize(hddp) +
f2fa6b
+				StrLen(arguments) * 2;
f2fa6b
 
f2fa6b
 			CHAR8 *data = AllocateZeroPool(size);
f2fa6b
 			CHAR8 *cursor = data;
f2fa6b
 			*(UINT32 *)cursor = LOAD_OPTION_ACTIVE;
f2fa6b
 			cursor += sizeof (UINT32);
f2fa6b
-			*(UINT16 *)cursor = DevicePathSize(dp);
f2fa6b
+			*(UINT16 *)cursor = DevicePathSize(hddp);
f2fa6b
 			cursor += sizeof (UINT16);
f2fa6b
 			StrCpy((CHAR16 *)cursor, label);
f2fa6b
 			cursor += StrLen(label)*2 + 2;
f2fa6b
-			CopyMem(cursor, dp, DevicePathSize(dp));
f2fa6b
-			cursor += DevicePathSize(dp);
f2fa6b
+			CopyMem(cursor, hddp, DevicePathSize(hddp));
f2fa6b
+			cursor += DevicePathSize(hddp);
f2fa6b
 			StrCpy((CHAR16 *)cursor, arguments);
f2fa6b
 
f2fa6b
 			Print(L"Creating boot entry \"%s\" with label \"%s\" "
f2fa6b
 					L"for file \"%s\"\n",
f2fa6b
 				varname, label, filename);
f2fa6b
+
f2fa6b
+			if (!first_new_option) {
f2fa6b
+				first_new_option = DuplicateDevicePath(fulldp);
f2fa6b
+				first_new_option_args = arguments;
f2fa6b
+				first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
f2fa6b
+			}
f2fa6b
+
f2fa6b
 			rc = uefi_call_wrapper(RT->SetVariable, 5, varname,
f2fa6b
 				&global, EFI_VARIABLE_NON_VOLATILE |
f2fa6b
 					 EFI_VARIABLE_BOOTSERVICE_ACCESS |
f2fa6b
@@ -254,7 +285,10 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *
f2fa6b
 	if (EFI_ERROR(rc))
f2fa6b
 		return rc;
f2fa6b
 	
f2fa6b
-	EFI_DEVICE_PATH *dph = NULL, *dpf = NULL, *dp = NULL;
f2fa6b
+	EFI_DEVICE_PATH *dph = NULL;
f2fa6b
+	EFI_DEVICE_PATH *file = NULL;
f2fa6b
+	EFI_DEVICE_PATH *full_device_path = NULL;
f2fa6b
+	EFI_DEVICE_PATH *dp = NULL;
f2fa6b
 	
f2fa6b
 	dph = DevicePathFromHandle(this_image->DeviceHandle);
f2fa6b
 	if (!dph) {
f2fa6b
@@ -262,19 +296,31 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *
f2fa6b
 		goto err;
f2fa6b
 	}
f2fa6b
 
f2fa6b
-	dpf = FileDevicePath(fh, fullpath);
f2fa6b
-	if (!dpf) {
f2fa6b
+	file = FileDevicePath(fh, fullpath);
f2fa6b
+	if (!file) {
f2fa6b
 		rc = EFI_OUT_OF_RESOURCES;
f2fa6b
 		goto err;
f2fa6b
 	}
f2fa6b
 
f2fa6b
-	dp = AppendDevicePath(dph, dpf);
f2fa6b
-	if (!dp) {
f2fa6b
+	full_device_path = AppendDevicePath(dph, file);
f2fa6b
+	if (!full_device_path) {
f2fa6b
 		rc = EFI_OUT_OF_RESOURCES;
f2fa6b
 		goto err;
f2fa6b
 	}
f2fa6b
 
f2fa6b
+	rc = FindSubDevicePath(full_device_path,
f2fa6b
+				MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp;;
f2fa6b
+	if (EFI_ERROR(rc)) {
f2fa6b
+		if (rc == EFI_NOT_FOUND) {
f2fa6b
+			dp = full_device_path;
f2fa6b
+		} else {
f2fa6b
+			rc = EFI_OUT_OF_RESOURCES;
f2fa6b
+			goto err;
f2fa6b
+		}
f2fa6b
+	}
f2fa6b
+
f2fa6b
 #ifdef DEBUG_FALLBACK
f2fa6b
+	{
f2fa6b
 	UINTN s = DevicePathSize(dp);
f2fa6b
 	int i;
f2fa6b
 	UINT8 *dpv = (void *)dp;
f2fa6b
@@ -287,20 +333,16 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *
f2fa6b
 
f2fa6b
 	CHAR16 *dps = DevicePathToStr(dp);
f2fa6b
 	Print(L"device path: \"%s\"\n", dps);
f2fa6b
-#endif
f2fa6b
-	if (!first_new_option) {
f2fa6b
-		CHAR16 *dps = DevicePathToStr(dp);
f2fa6b
-		Print(L"device path: \"%s\"\n", dps);
f2fa6b
-		first_new_option = DuplicateDevicePath(dp);
f2fa6b
-		first_new_option_args = arguments;
f2fa6b
-		first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
f2fa6b
 	}
f2fa6b
+#endif
f2fa6b
 
f2fa6b
-	add_boot_option(dp, fullpath, label, arguments);
f2fa6b
+	add_boot_option(dp, full_device_path, fullpath, label, arguments);
f2fa6b
 
f2fa6b
 err:
f2fa6b
-	if (dpf)
f2fa6b
-		FreePool(dpf);
f2fa6b
+	if (file)
f2fa6b
+		FreePool(file);
f2fa6b
+	if (full_device_path)
f2fa6b
+		FreePool(full_device_path);
f2fa6b
 	if (dp)
f2fa6b
 		FreePool(dp);
f2fa6b
 	if (fullpath)
f2fa6b
@@ -629,8 +671,19 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
f2fa6b
 			       first_new_option, NULL, 0,
f2fa6b
 			       &image_handle);
f2fa6b
 	if (EFI_ERROR(rc)) {
f2fa6b
-		Print(L"LoadImage failed: %d\n", rc);
f2fa6b
-		uefi_call_wrapper(BS->Stall, 1, 2000000);
f2fa6b
+		CHAR16 *dps = DevicePathToStr(first_new_option);
f2fa6b
+		UINTN s = DevicePathSize(first_new_option);
f2fa6b
+		int i;
f2fa6b
+		UINT8 *dpv = (void *)first_new_option;
f2fa6b
+		Print(L"LoadImage failed: %d\nDevice path: \"%s\"\n", rc, dps);
f2fa6b
+		for (i = 0; i < s; i++) {
f2fa6b
+			if (i > 0 && i % 16 == 0)
f2fa6b
+				Print(L"\n");
f2fa6b
+			Print(L"%02x ", dpv[i]);
f2fa6b
+		}
f2fa6b
+		Print(L"\n");
f2fa6b
+
f2fa6b
+		uefi_call_wrapper(BS->Stall, 1, 500000000);
f2fa6b
 		return rc;
f2fa6b
 	}
f2fa6b
 
f2fa6b
@@ -644,7 +697,7 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
f2fa6b
 	rc = uefi_call_wrapper(BS->StartImage, 3, image_handle, NULL, NULL);
f2fa6b
 	if (EFI_ERROR(rc)) {
f2fa6b
 		Print(L"StartImage failed: %d\n", rc);
f2fa6b
-		uefi_call_wrapper(BS->Stall, 1, 2000000);
f2fa6b
+		uefi_call_wrapper(BS->Stall, 1, 500000000);
f2fa6b
 	}
f2fa6b
 	return rc;
f2fa6b
 }
f2fa6b
-- 
f2fa6b
1.8.5.3
f2fa6b