arrfab / rpms / shim

Forked from rpms/shim 4 years ago
Clone

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

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