6e9b303231
- Print the debug messages in fallback.efi dynamically - Refresh shim-fallback-workaround-masked-ami-variables.patch - Measure more components and support TPM better OBS-URL: https://build.opensuse.org/request/show/519292 OBS-URL: https://build.opensuse.org/package/show/devel:openSUSE:Factory/shim?expand=0&rev=132
199 lines
7.1 KiB
Diff
199 lines
7.1 KiB
Diff
From 38744a099187401f2f5e382c2ce8869e1e9b22a0 Mon Sep 17 00:00:00 2001
|
|
From: Lans Zhang <jia.zhang@windriver.com>
|
|
Date: Fri, 11 Aug 2017 13:42:20 +0800
|
|
Subject: [PATCH] fallback: work around the issue of boot option creation with
|
|
AMI BIOS
|
|
|
|
AMI BIOS (e.g, Intel NUC5i3MYHE) may automatically hide and patch BootXXXX
|
|
variables with ami_masked_device_path_guid.
|
|
|
|
Initially, the normal boot option created by fallback looks like this:
|
|
00000000 01 00 00 00 5e 00 42 00 6f 00 6f 00 74 00 6c 00 |....^.B.o.o.t.l.|
|
|
00000010 6f 00 61 00 64 00 65 00 72 00 20 00 54 00 65 00 |o.a.d.e.r. .T.e.|
|
|
00000020 73 00 74 00 20 00 28 00 36 00 34 00 2d 00 62 00 |s.t. .(.6.4.-.b.|
|
|
00000030 69 00 74 00 29 00 00 00 04 01 2a 00 01 00 00 00 |i.t.).....*.....|
|
|
00000040 00 08 00 00 00 00 00 00 00 00 08 00 00 00 00 00 |................|
|
|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
00000060 01 01 04 04 30 00 5c 00 45 00 46 00 49 00 5c 00 |....0.\.E.F.I.\.|
|
|
00000070 42 00 4f 00 4f 00 54 00 5c 00 74 00 65 00 73 00 |B.O.O.T.\.t.e.s.|
|
|
00000080 74 00 78 00 36 00 34 00 2e 00 65 00 66 00 69 00 |t.x.6.4...e.f.i.|
|
|
00000090 00 00 7f ff 04 00 |......|
|
|
00000096
|
|
|
|
after reboot, fallback has to create a new one due to the previous boot
|
|
option is hidden and masked by AMI BIOS:
|
|
00000000 09 00 00 00 76 00 42 00 6f 00 6f 00 74 00 6c 00 |....v.B.o.o.t.l.|
|
|
00000010 6f 00 61 00 64 00 65 00 72 00 20 00 54 00 65 00 |o.a.d.e.r. .T.e.|
|
|
00000020 73 00 74 00 20 00 28 00 36 00 34 00 2d 00 62 00 |s.t. .(.6.4.-.b.|
|
|
00000030 69 00 74 00 29 00 00 00 01 04 14 00 e7 75 e2 99 |i.t.)........u..|
|
|
00000040 a0 75 37 4b a2 e6 c5 38 5e 6c 00 cb 7f ff 04 00 |.u7K...8^l......|
|
|
00000050 04 01 2a 00 01 00 00 00 00 08 00 00 00 00 00 00 |..*.............|
|
|
00000060 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
00000070 00 00 00 00 00 00 00 00 01 01 04 04 30 00 5c 00 |............0.\.|
|
|
00000080 45 00 46 00 49 00 5c 00 42 00 4f 00 4f 00 54 00 |E.F.I.\.B.O.O.T.|
|
|
00000090 5c 00 74 00 65 00 73 00 74 00 78 00 36 00 34 00 |\.t.e.s.t.x.6.4.|
|
|
000000a0 2e 00 65 00 66 00 69 00 00 00 7f ff 04 00 |..e.f.i.......|
|
|
000000ae
|
|
|
|
And after several reboot, fallback will have to create more boot options
|
|
because AMI BIOS corrupts the previous ones.
|
|
|
|
We can get the valid device path if just skipping the masked device path and
|
|
its next end path.
|
|
|
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
|
(cherry picked from commit 0cc030c2f2fba53b74fb09466a07b8e6297a52d3)
|
|
---
|
|
fallback.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 109 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/fallback.c b/fallback.c
|
|
index 5602a88..8c0369f 100644
|
|
--- a/fallback.c
|
|
+++ b/fallback.c
|
|
@@ -286,6 +286,105 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
+/*
|
|
+ * AMI BIOS (e.g, Intel NUC5i3MYHE) may automatically hide and patch BootXXXX
|
|
+ * variables with ami_masked_device_path_guid. We can get the valid device path
|
|
+ * if just skipping it and its next end path.
|
|
+ */
|
|
+
|
|
+static EFI_GUID ami_masked_device_path_guid = {
|
|
+ 0x99e275e7, 0x75a0, 0x4b37,
|
|
+ { 0xa2, 0xe6, 0xc5, 0x38, 0x5e, 0x6c, 0x0, 0xcb }
|
|
+};
|
|
+
|
|
+static unsigned int
|
|
+calc_masked_boot_option_size(unsigned int size)
|
|
+{
|
|
+ return size + sizeof(EFI_DEVICE_PATH) +
|
|
+ sizeof(ami_masked_device_path_guid) + sizeof(EFI_DEVICE_PATH);
|
|
+}
|
|
+
|
|
+static int
|
|
+check_masked_boot_option(CHAR8 *candidate, unsigned int candidate_size,
|
|
+ CHAR8 *data, unsigned int data_size)
|
|
+{
|
|
+ /*
|
|
+ * The patched BootXXXX variables contain a hardware device path and
|
|
+ * an end path, preceding the real device path.
|
|
+ */
|
|
+ if (calc_masked_boot_option_size(data_size) != candidate_size)
|
|
+ return 1;
|
|
+
|
|
+ CHAR8 *cursor = candidate;
|
|
+
|
|
+ /* Check whether the BootXXXX is patched */
|
|
+ cursor += sizeof(UINT32) + sizeof(UINT16);
|
|
+ cursor += StrSize((CHAR16 *)cursor);
|
|
+
|
|
+ unsigned int min_valid_size = cursor - candidate + sizeof(EFI_DEVICE_PATH);
|
|
+
|
|
+ if (candidate_size <= min_valid_size)
|
|
+ return 1;
|
|
+
|
|
+ EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)cursor;
|
|
+ unsigned int node_size = DevicePathNodeLength(dp) - sizeof(EFI_DEVICE_PATH);
|
|
+
|
|
+ min_valid_size += node_size;
|
|
+ if (candidate_size <= min_valid_size ||
|
|
+ DevicePathType(dp) != HARDWARE_DEVICE_PATH ||
|
|
+ DevicePathSubType(dp) != HW_VENDOR_DP ||
|
|
+ node_size != sizeof(ami_masked_device_path_guid) ||
|
|
+ CompareGuid((EFI_GUID *)(cursor + sizeof(EFI_DEVICE_PATH)),
|
|
+ &ami_masked_device_path_guid))
|
|
+ return 1;
|
|
+
|
|
+ /* Check whether the patched guid is followed by an end path */
|
|
+ min_valid_size += sizeof(EFI_DEVICE_PATH);
|
|
+ if (candidate_size <= min_valid_size)
|
|
+ return 1;
|
|
+
|
|
+ dp = NextDevicePathNode(dp);
|
|
+ if (!IsDevicePathEnd(dp))
|
|
+ return 1;
|
|
+
|
|
+ /*
|
|
+ * OK. We may really get a masked BootXXXX variable. The next
|
|
+ * step is to test whether it is hidden.
|
|
+ */
|
|
+ UINT32 attrs = *(UINT32 *)candidate;
|
|
+#ifndef LOAD_OPTION_HIDDEN
|
|
+# define LOAD_OPTION_HIDDEN 0x00000008
|
|
+#endif
|
|
+ if (!(attrs & LOAD_OPTION_HIDDEN))
|
|
+ return 1;
|
|
+
|
|
+ attrs &= ~LOAD_OPTION_HIDDEN;
|
|
+
|
|
+ /* Compare the field Attributes */
|
|
+ if (attrs != *(UINT32 *)data)
|
|
+ return 1;
|
|
+
|
|
+ /* Compare the field FilePathListLength */
|
|
+ data += sizeof(UINT32);
|
|
+ candidate += sizeof(UINT32);
|
|
+ if (calc_masked_boot_option_size(*(UINT16 *)data) !=
|
|
+ *(UINT16 *)candidate)
|
|
+ return 1;
|
|
+
|
|
+ /* Compare the field Description */
|
|
+ data += sizeof(UINT16);
|
|
+ candidate += sizeof(UINT16);
|
|
+ if (CompareMem(candidate, data, cursor - candidate))
|
|
+ return 1;
|
|
+
|
|
+ /* Compare the filed FilePathList */
|
|
+ cursor = (CHAR8 *)NextDevicePathNode(dp);
|
|
+ data += sizeof(UINT16);
|
|
+ data += StrSize((CHAR16 *)data);
|
|
+
|
|
+ return CompareMem(cursor, data, candidate_size - min_valid_size);
|
|
+}
|
|
+
|
|
EFI_STATUS
|
|
find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp,
|
|
CHAR16 *filename, CHAR16 *label, CHAR16 *arguments,
|
|
@@ -315,7 +414,8 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp,
|
|
EFI_GUID global = EFI_GLOBAL_VARIABLE;
|
|
EFI_STATUS rc;
|
|
|
|
- CHAR8 *candidate = AllocateZeroPool(size);
|
|
+ UINTN max_candidate_size = calc_masked_boot_option_size(size);
|
|
+ CHAR8 *candidate = AllocateZeroPool(max_candidate_size);
|
|
if (!candidate) {
|
|
FreePool(data);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
@@ -327,17 +427,21 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp,
|
|
varname[6] = hexmap[(bootorder[i] & 0x00f0) >> 4];
|
|
varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0];
|
|
|
|
- UINTN candidate_size = size;
|
|
+ UINTN candidate_size = max_candidate_size;
|
|
rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global,
|
|
NULL, &candidate_size, candidate);
|
|
if (EFI_ERROR(rc))
|
|
continue;
|
|
|
|
- if (candidate_size != size)
|
|
+ if (candidate_size != size) {
|
|
+ if (check_masked_boot_option(candidate, candidate_size,
|
|
+ data, size))
|
|
+ continue;
|
|
+ } else if (CompareMem(candidate, data, size))
|
|
continue;
|
|
|
|
- if (CompareMem(candidate, data, size))
|
|
- continue;
|
|
+ VerbosePrint(L"Found boot entry \"%s\" with label \"%s\" "
|
|
+ L"for file \"%s\"\n", varname, label, filename);
|
|
|
|
/* at this point, we have duplicate data. */
|
|
if (!first_new_option) {
|
|
--
|
|
2.14.1
|
|
|