|
|
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
|
|
|
f2fa6b |
Subject: [PATCH 19/19] [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 |
--
|
|
|
f2fa6b |
1.8.5.3
|
|
|
f2fa6b |
|