From 031e5cce385d3f96b1caa1d53495332a7eb03749 Mon Sep 17 00:00:00 2001 From: Steve McIntyre Date: Tue, 23 Mar 2021 23:49:46 +0000 Subject: New upstream version 15.3 --- fallback.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 151 insertions(+), 43 deletions(-) (limited to 'fallback.c') diff --git a/fallback.c b/fallback.c index c3f5583c..8d89917a 100644 --- a/fallback.c +++ b/fallback.c @@ -1,22 +1,20 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* - * Copyright 2012-2013 Red Hat, Inc. - * All rights reserved. - * - * See "COPYING" for license terms. - * - * Author(s): Peter Jones + * Copyright Red Hat, Inc. + * Copyright Peter Jones */ - -#include -#include - #include "shim.h" +#define NO_REBOOT L"FB_NO_REBOOT" + EFI_LOADED_IMAGE *this_image = NULL; int get_fallback_verbose(void) { +#ifdef FALLBACK_VERBOSE + return 1; +#else UINT8 *data = NULL; UINTN dataSize = 0; EFI_STATUS efi_status; @@ -44,6 +42,7 @@ get_fallback_verbose(void) if (data) FreePool(data); return state; +#endif } #define VerbosePrintUnprefixed(fmt, ...) \ @@ -54,14 +53,15 @@ get_fallback_verbose(void) ret_; \ }) -#define VerbosePrint(fmt, ...) \ - ({ UINTN line_ = __LINE__; \ - UINTN ret_ = 0; \ - if (get_fallback_verbose()) { \ - console_print(L"%a:%d: ", __func__, line_); \ - ret_ = console_print((fmt), ##__VA_ARGS__); \ - } \ - ret_; \ +#define VerbosePrint(fmt, ...) \ + ({ \ + UINTN line_ = __LINE__ - 2; \ + UINTN ret_ = 0; \ + if (get_fallback_verbose()) { \ + console_print(L"%a:%d: ", __func__, line_); \ + ret_ = console_print((fmt), ##__VA_ARGS__); \ + } \ + ret_; \ }) static EFI_STATUS @@ -242,9 +242,9 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, cursor += DevicePathSize(hddp); StrCpy((CHAR16 *)cursor, arguments); - console_print(L"Creating boot entry \"%s\" with label \"%s\" " - L"for file \"%s\"\n", - varname, label, filename); + VerbosePrint(L"Creating boot entry \"%s\" with label \"%s\" " + L"for file \"%s\"\n", + varname, label, filename); if (!first_new_option) { first_new_option = DuplicateDevicePath(fulldp); @@ -280,13 +280,11 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, } bootorder = newbootorder; nbootorder += 1; -#ifdef DEBUG_FALLBACK - console_print(L"nbootorder: %d\nBootOrder: ", + VerbosePrint(L"nbootorder: %d\nBootOrder: ", nbootorder); for (j = 0 ; j < nbootorder ; j++) - console_print(L"%04x ", bootorder[j]); - console_print(L"\n"); -#endif + VerbosePrintUnprefixed(L"%04x ", bootorder[j]); + VerbosePrintUnprefixed(L"\n"); return EFI_SUCCESS; } @@ -398,8 +396,9 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments, UINT16 *optnum) { + unsigned int label_size = StrLen(label)*2 + 2; unsigned int size = sizeof(UINT32) + sizeof (UINT16) + - StrLen(label)*2 + 2 + DevicePathSize(dp) + + label_size + DevicePathSize(dp) + StrLen(arguments) * 2; CHAR8 *data = AllocateZeroPool(size + 2); @@ -411,15 +410,14 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, *(UINT16 *)cursor = DevicePathSize(dp); cursor += sizeof (UINT16); StrCpy((CHAR16 *)cursor, label); - cursor += StrLen(label)*2 + 2; + cursor += label_size; CopyMem(cursor, dp, DevicePathSize(dp)); cursor += DevicePathSize(dp); StrCpy((CHAR16 *)cursor, arguments); - int i = 0; - CHAR16 varname[] = L"Boot0000"; - CHAR16 hexmap[] = L"0123456789ABCDEF"; + CHAR16 varname[256]; EFI_STATUS efi_status; + EFI_GUID vendor_guid = NullGuid; UINTN max_candidate_size = calc_masked_boot_option_size(size); CHAR8 *candidate = AllocateZeroPool(max_candidate_size); @@ -428,11 +426,18 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, return EFI_OUT_OF_RESOURCES; } - 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]; + varname[0] = 0; + while (1) { + UINTN varname_size = sizeof(varname); + efi_status = gRT->GetNextVariableName(&varname_size, varname, + &vendor_guid); + if (EFI_ERROR(efi_status)) + 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 = max_candidate_size; efi_status = gRT->GetVariable(varname, &GV_GUID, NULL, @@ -457,7 +462,7 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, first_new_option_size = StrLen(arguments) * sizeof (CHAR16); } - *optnum = i; + *optnum = xtoi(varname + 4); FreePool(candidate); FreePool(data); return EFI_SUCCESS; @@ -475,8 +480,15 @@ set_boot_order(void) oldbootorder = LibGetVariableAndSize(L"BootOrder", &GV_GUID, &size); if (oldbootorder) { + int i; nbootorder = size / sizeof (CHAR16); bootorder = oldbootorder; + + VerbosePrint(L"Original nbootorder: %d\nOriginal BootOrder: ", + nbootorder); + for (i = 0 ; i < nbootorder ; i++) + VerbosePrintUnprefixed(L"%04x ", bootorder[i]); + VerbosePrintUnprefixed(L"\n"); } return EFI_SUCCESS; @@ -500,7 +512,7 @@ update_boot_order(void) UINTN j; for (j = 0 ; j < size / sizeof (CHAR16); j++) VerbosePrintUnprefixed(L"%04x ", newbootorder[j]); - console_print(L"\n"); + VerbosePrintUnprefixed(L"\n"); efi_status = gRT->GetVariable(L"BootOrder", &GV_GUID, NULL, &len, NULL); if (efi_status == EFI_BUFFER_TOO_SMALL) LibDeleteVariable(L"BootOrder", &GV_GUID); @@ -600,7 +612,7 @@ err: } EFI_STATUS -populate_stanza(CHAR16 *dirname, CHAR16 *filename, CHAR16 *csv) +populate_stanza(CHAR16 *dirname, CHAR16 *filename UNUSED, CHAR16 *csv) { CHAR16 *file = csv; VerbosePrint(L"CSV data: \"%s\"\n", csv); @@ -933,6 +945,17 @@ try_start_first_option(EFI_HANDLE parent_image_handle) EFI_STATUS efi_status; EFI_HANDLE image_handle; + if (get_fallback_verbose()) { + int fallback_verbose_wait = 500000; /* default to 0.5s */ +#ifdef FALLBACK_VERBOSE_WAIT + fallback_verbose_wait = FALLBACK_VERBOSE_WAIT; +#endif + console_print(L"Verbose enabled, sleeping for %d mseconds... " + L"Press the Pause key now to hold for longer.\n", + fallback_verbose_wait); + msleep(fallback_verbose_wait); + } + if (!first_new_option) { return EFI_SUCCESS; } @@ -973,6 +996,65 @@ try_start_first_option(EFI_HANDLE parent_image_handle) return efi_status; } +static UINT32 +get_fallback_no_reboot(void) +{ + EFI_STATUS efi_status; + UINT32 no_reboot; + UINTN size = sizeof(UINT32); + + efi_status = gRT->GetVariable(NO_REBOOT, &SHIM_LOCK_GUID, + NULL, &size, &no_reboot); + if (!EFI_ERROR(efi_status)) { + return no_reboot; + } + return 0; +} + +static EFI_STATUS +set_fallback_no_reboot(void) +{ + EFI_STATUS efi_status; + UINT32 no_reboot = 1; + efi_status = gRT->SetVariable(NO_REBOOT, &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(UINT32), &no_reboot); + return efi_status; +} + +static int +draw_countdown(void) +{ + CHAR16 *title = L"Boot Option Restoration"; + CHAR16 *message = L"Press any key to stop system reset"; + int timeout; + + timeout = console_countdown(title, message, 5); + + return timeout; +} + +static int +get_user_choice(void) +{ + int choice; + CHAR16 *title[] = {L"Boot Option Restored", NULL}; + CHAR16 *menu_strings[] = { + L"Reset system", + L"Continue boot", + L"Always continue boot", + NULL + }; + + do { + choice = console_select(title, menu_strings, 0); + } while (choice < 0 || choice > 2); + + return choice; +} + extern EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab); @@ -983,7 +1065,7 @@ debug_hook(void) UINT8 *data = NULL; UINTN dataSize = 0; EFI_STATUS efi_status; - volatile register int x = 0; + register volatile int x = 0; extern char _etext, _edata; efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, @@ -1023,7 +1105,7 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) return efi_status; } - console_print(L"System BootOrder not found. Initializing defaults.\n"); + VerbosePrint(L"System BootOrder not found. Initializing defaults.\n"); set_boot_order(); @@ -1039,14 +1121,40 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) VerbosePrint(L"tpm not present, starting the first image\n"); try_start_first_option(image); } else { + if (get_fallback_no_reboot() == 1) { + VerbosePrint(L"NO_REBOOT is set, starting the first image\n"); + try_start_first_option(image); + } + + int timeout = draw_countdown(); + if (timeout == 0) + goto reset; + + int choice = get_user_choice(); + if (choice == 0) { + goto reset; + } else if (choice == 2) { + efi_status = set_fallback_no_reboot(); + if (EFI_ERROR(efi_status)) + goto reset; + } + VerbosePrint(L"tpm present, starting the first image\n"); + try_start_first_option(image); +reset: VerbosePrint(L"tpm present, resetting system\n"); } console_print(L"Reset System\n"); if (get_fallback_verbose()) { - console_print(L"Verbose enabled, sleeping for half a second\n"); - msleep(500000); + int fallback_verbose_wait = 500000; /* default to 0.5s */ +#ifdef FALLBACK_VERBOSE_WAIT + fallback_verbose_wait = FALLBACK_VERBOSE_WAIT; +#endif + console_print(L"Verbose enabled, sleeping for %d mseconds... " + L"Press the Pause key now to hold for longer.\n", + fallback_verbose_wait); + msleep(fallback_verbose_wait); } gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); -- cgit v1.2.3