arrfab / rpms / shim

Forked from rpms/shim 4 years ago
Clone

Blame SOURCES/0019-fallback-Attempt-to-re-use-existing-entries-when-pos.patch

f2fa6b
From 894a2738d6c843a7b51245fb92bb2f835901e613 Mon Sep 17 00:00:00 2001
f2fa6b
From: Peter Jones <pjones@redhat.com>
f2fa6b
Date: Fri, 31 Jan 2014 10:31:10 -0500
e97c83
Subject: [PATCH 19/74] [fallback] Attempt to re-use existing entries when
f2fa6b
 possible.
f2fa6b
f2fa6b
Some firmwares seem to ignore our boot entries and put their fallback
f2fa6b
entries back on top.  Right now that results in a lot of boot entries
f2fa6b
for our stuff, a la https://bugzilla.redhat.com/show_bug.cgi?id=995834 .
f2fa6b
f2fa6b
Instead of that happening, if we simply find existing entries that match
f2fa6b
the entry we would create and move them to the top of the boot order,
f2fa6b
the machine will continue to operate in failure mode (which we can't
f2fa6b
avoid), but at least we won't create thousands of extra entries.
f2fa6b
f2fa6b
Signed-off-by: Peter Jones <pjones@redhat.com>
f2fa6b
---
f2fa6b
 fallback.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
f2fa6b
 1 file changed, 98 insertions(+), 1 deletion(-)
f2fa6b
f2fa6b
diff --git a/fallback.c b/fallback.c
f2fa6b
index a12bb74..44638ec 100644
f2fa6b
--- a/fallback.c
f2fa6b
+++ b/fallback.c
f2fa6b
@@ -226,6 +226,85 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
f2fa6b
 }
f2fa6b
 
f2fa6b
 EFI_STATUS
f2fa6b
+find_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label,
f2fa6b
+		CHAR16 *arguments, UINT16 *optnum)
f2fa6b
+{
f2fa6b
+	int size = sizeof(UINT32) + sizeof (UINT16) +
f2fa6b
+		StrLen(label)*2 + 2 + DevicePathSize(dp) +
f2fa6b
+		StrLen(arguments) * 2 + 2;
f2fa6b
+
f2fa6b
+	CHAR8 *data = AllocateZeroPool(size);
f2fa6b
+	if (!data)
f2fa6b
+		return EFI_OUT_OF_RESOURCES;
f2fa6b
+	CHAR8 *cursor = data;
f2fa6b
+	*(UINT32 *)cursor = LOAD_OPTION_ACTIVE;
f2fa6b
+	cursor += sizeof (UINT32);
f2fa6b
+	*(UINT16 *)cursor = DevicePathSize(dp);
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
+	StrCpy((CHAR16 *)cursor, arguments);
f2fa6b
+
f2fa6b
+	int i = 0;
f2fa6b
+	CHAR16 varname[] = L"Boot0000";
f2fa6b
+	CHAR16 hexmap[] = L"0123456789ABCDEF";
f2fa6b
+	EFI_GUID global = EFI_GLOBAL_VARIABLE;
f2fa6b
+	EFI_STATUS rc;
f2fa6b
+
f2fa6b
+	CHAR8 *candidate = AllocateZeroPool(size);
f2fa6b
+	if (!candidate) {
f2fa6b
+		FreePool(data);
f2fa6b
+		return EFI_OUT_OF_RESOURCES;
f2fa6b
+	}
f2fa6b
+
f2fa6b
+	for(i = 0; i < nbootorder && i < 0x10000; i++) {
f2fa6b
+		varname[4] = hexmap[(bootorder[i] & 0xf000) >> 12];
f2fa6b
+		varname[5] = hexmap[(bootorder[i] & 0x0f00) >> 8];
f2fa6b
+		varname[6] = hexmap[(bootorder[i] & 0x00f0) >> 4];
f2fa6b
+		varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0];
f2fa6b
+
f2fa6b
+		UINTN candidate_size = size;
f2fa6b
+		rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global,
f2fa6b
+					NULL, &candidate_size, candidate);
f2fa6b
+		if (EFI_ERROR(rc))
f2fa6b
+			continue;
f2fa6b
+
f2fa6b
+		if (candidate_size != size)
f2fa6b
+			continue;
f2fa6b
+
f2fa6b
+		if (CompareMem(candidate, data, size))
f2fa6b
+			continue;
f2fa6b
+
f2fa6b
+		/* at this point, we have duplicate data. */
f2fa6b
+		*optnum = i;
f2fa6b
+		FreePool(candidate);
f2fa6b
+		FreePool(data);
f2fa6b
+		return EFI_SUCCESS;
f2fa6b
+	}
f2fa6b
+	FreePool(candidate);
f2fa6b
+	FreePool(data);
f2fa6b
+	return EFI_NOT_FOUND;
f2fa6b
+}
f2fa6b
+
f2fa6b
+EFI_STATUS
f2fa6b
+set_boot_order(void)
f2fa6b
+{
f2fa6b
+	CHAR16 *oldbootorder;
f2fa6b
+	UINTN size;
f2fa6b
+	EFI_GUID global = EFI_GLOBAL_VARIABLE;
f2fa6b
+
f2fa6b
+	oldbootorder = LibGetVariableAndSize(L"BootOrder", &global, &size);
f2fa6b
+	if (oldbootorder) {
f2fa6b
+		nbootorder = size / sizeof (CHAR16);
f2fa6b
+		bootorder = oldbootorder;
f2fa6b
+	}
f2fa6b
+	return EFI_SUCCESS;
f2fa6b
+
f2fa6b
+}
f2fa6b
+
f2fa6b
+EFI_STATUS
f2fa6b
 update_boot_order(void)
f2fa6b
 {
f2fa6b
 	CHAR16 *oldbootorder;
f2fa6b
@@ -336,7 +415,23 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *
f2fa6b
 	}
f2fa6b
 #endif
f2fa6b
 
f2fa6b
-	add_boot_option(dp, full_device_path, fullpath, label, arguments);
f2fa6b
+	UINT16 option;
f2fa6b
+	rc = find_boot_option(dp, fullpath, label, arguments, &option);
f2fa6b
+	if (EFI_ERROR(rc)) {
f2fa6b
+		add_boot_option(dp, full_device_path, fullpath, label, arguments);
f2fa6b
+	} else if (option != 0) {
f2fa6b
+		CHAR16 *newbootorder;
f2fa6b
+		newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder);
f2fa6b
+		if (!newbootorder)
f2fa6b
+			return EFI_OUT_OF_RESOURCES;
f2fa6b
+
f2fa6b
+		newbootorder[0] = bootorder[option];
f2fa6b
+		CopyMem(newbootorder + 1, bootorder, sizeof (CHAR16) * option);
f2fa6b
+		CopyMem(newbootorder + option + 1, bootorder + option + 1,
f2fa6b
+			sizeof (CHAR16) * (nbootorder - option - 1));
f2fa6b
+		FreePool(bootorder);
f2fa6b
+		bootorder = newbootorder;
f2fa6b
+	}
f2fa6b
 
f2fa6b
 err:
f2fa6b
 	if (file)
f2fa6b
@@ -717,6 +812,8 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
f2fa6b
 
f2fa6b
 	Print(L"System BootOrder not found.  Initializing defaults.\n");
f2fa6b
 
f2fa6b
+	set_boot_order();
f2fa6b
+
f2fa6b
 	rc = find_boot_options(this_image->DeviceHandle);
f2fa6b
 	if (EFI_ERROR(rc)) {
f2fa6b
 		Print(L"Error: could not find boot options: %d\n", rc);
f2fa6b
-- 
e97c83
1.9.3
f2fa6b