diff options
| author | João Paulo Rechi Vita <jprvita@endlessm.com> | 2017-02-13 14:03:11 -0500 |
|---|---|---|
| committer | João Paulo Rechi Vita <jprvita@endlessm.com> | 2017-02-21 11:36:13 -0500 |
| commit | b45652aba2d797b64516ba2867d756c39a6735d1 (patch) | |
| tree | 0de861d9dea84adf6c4596101f1755fbeca13678 | |
| parent | 692218f58d37b415bc7e92dd82c2b8211b84795f (diff) | |
| download | efi-boot-shim-b45652aba2d797b64516ba2867d756c39a6735d1.tar.gz efi-boot-shim-b45652aba2d797b64516ba2867d756c39a6735d1.zip | |
fallback: Consider all Boot* vars when checking for duplicates
Some firmware implementations like the one on the Acer TravelMate
P449-G2-MG completely ignore the contents of BootOrder on boot, and
overwrite it with a value of its own. On this particular machine, the
boot entry that was just created by fallback on the previous boot is not
included by the firmware on this new BootOrder, so it is not considered
when checking for duplicates.
This problem is agravated by the fact that the aformentioned firmware
does not give the user the possibility to boot from the entry created by
fallback (or any other entry created by the OS). The only way to boot
a distro that deploys the fallback setup (no grub inside \EFI\BOOT) with
this firmware is to select the entry pointing to \EFI\BOOT\bootx64.efi,
leading to a new boot entry being created by fallback on every boot.
This commit makes fallback try every Boot* variable when checking for
duplicates, working around this problem.
Signed-off-by: João Paulo Rechi Vita <jprvita@endlessm.com>
https://phabricator.endlessm.com/T15481
| -rw-r--r-- | fallback.c | 44 |
1 files changed, 32 insertions, 12 deletions
@@ -246,21 +246,39 @@ add_new_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, } int +isxdigit(CHAR16 c) +{ + return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f')); +} + +int find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) { - int i = 0; - CHAR16 varname[] = L"Boot0000"; - CHAR16 hexmap[] = L"0123456789ABCDEF"; - EFI_GUID global = EFI_GLOBAL_VARIABLE; + EFI_STATUS status; + EFI_GUID global; + int ret = -1; - for(i = 0; i < nbootorder && i < 0x10000; i++) { - varname[4] = hexmap[(bootorder[i] & 0xf000) >> 12]; - varname[5] = hexmap[(bootorder[i] & 0x0f00) >> 8]; - varname[6] = hexmap[(bootorder[i] & 0x00f0) >> 4]; - varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0]; + UINTN CANDIDATE_SIZE = 256; + CHAR16 *varname = AllocateZeroPool(CANDIDATE_SIZE * sizeof(CHAR16)); + if (!varname) { + Print(L"Could not allocate memory\n"); + return ret; + } + + while (1) { + UINTN candidate_size = CANDIDATE_SIZE; + status = uefi_call_wrapper(RT->GetNextVariableName, 3, + &candidate_size, varname, &global); + if (status != EFI_SUCCESS) + break; + + if (StrLen(varname) != 8 || StrnCmp(varname, L"Boot", 4) || + !isxdigit(varname[4]) || !isxdigit(varname[5]) || + !isxdigit(varname[6]) || !isxdigit(varname[7])) + continue; - UINTN candidate_size; CHAR8 *candidate = LibGetVariableAndSize(varname, &global, &candidate_size); if (!candidate) @@ -280,9 +298,11 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, /* at this point, we have duplicate data. */ FreePool(candidate); - return i; + ret = xtoi(varname + 4); + break; } - return -1; + FreePool(varname); + return ret; } EFI_STATUS |
