From cdcbabe549e69c8b65cac8405bbdbd9c16544d83d17dc7ef6958eece9d1ed7f3 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 30 May 2018 03:26:13 +0000 Subject: [PATCH] Accepting request 612951 from home:gary_lin:branches:devel:openSUSE:Factory Add shim-bsc1092000-fallback-menu.patch to show a menu before system reset ((bsc#1092000)) OBS-URL: https://build.opensuse.org/request/show/612951 OBS-URL: https://build.opensuse.org/package/show/devel:openSUSE:Factory/shim?expand=0&rev=141 --- shim-bsc1092000-fallback-menu.patch | 194 ++++++++++++++++++++++++++++ shim.changes | 6 + shim.spec | 3 + 3 files changed, 203 insertions(+) create mode 100644 shim-bsc1092000-fallback-menu.patch diff --git a/shim-bsc1092000-fallback-menu.patch b/shim-bsc1092000-fallback-menu.patch new file mode 100644 index 0000000..389f269 --- /dev/null +++ b/shim-bsc1092000-fallback-menu.patch @@ -0,0 +1,194 @@ +From 22269728415432718e7757842086785d7daf0cc3 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Mon, 28 May 2018 10:57:06 +0800 +Subject: [PATCH] fallback: show a countdown menu before reset + +Some machines with the faulty firmware may keep booting the default boot +path instead of the boot option we create. To avoid the infinite reset +loop, this commit introduce a countdown screen before fallback resets the +system, so the user can interrupt the system reset and choose to boot +the restored boot option. The "Always continue boot" option creates a +BS+RT+NV variable, FB_NO_REBOOT, to make fallback boot the first boot +option afterward without asking. The user can revert the behavior by +removing the variable. + +https://github.com/rhboot/shim/issues/128 +https://bugzilla.opensuse.org/show_bug.cgi?id=1092000 + +Signed-off-by: Gary Lin +--- + fallback.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 144 insertions(+) + +diff --git a/fallback.c b/fallback.c +index 886e052..1f3eb78 100644 +--- a/fallback.c ++++ b/fallback.c +@@ -13,6 +13,9 @@ + #include "ucs2.h" + #include "variables.h" + #include "tpm.h" ++#include "console.h" ++ ++#define NO_REBOOT L"FB_NO_REBOOT" + + EFI_LOADED_IMAGE *this_image = NULL; + +@@ -953,6 +956,127 @@ try_start_first_option(EFI_HANDLE parent_image_handle) + return rc; + } + ++static UINT32 ++get_fallback_no_reboot(void) ++{ ++ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; ++ EFI_STATUS efi_status; ++ UINT32 no_reboot; ++ UINTN size = sizeof(UINT32); ++ ++ efi_status = uefi_call_wrapper(RT->GetVariable, 5, ++ 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_GUID shim_lock_guid = SHIM_LOCK_GUID; ++ EFI_STATUS efi_status; ++ UINT32 no_reboot = 1; ++ efi_status = uefi_call_wrapper(RT->SetVariable, 5, ++ 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 void console_save_and_set_mode (SIMPLE_TEXT_OUTPUT_MODE *SavedMode) ++{ ++ if (!SavedMode) { ++ Print(L"Invalid parameter: SavedMode\n"); ++ return; ++ } ++ ++ CopyMem(SavedMode, ST->ConOut->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE)); ++ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); ++ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, ++ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); ++} ++ ++static void console_restore_mode (SIMPLE_TEXT_OUTPUT_MODE *SavedMode) ++{ ++ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, ++ SavedMode->CursorVisible); ++ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, ++ SavedMode->CursorColumn, SavedMode->CursorRow); ++ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, ++ SavedMode->Attribute); ++} ++ ++static int ++draw_countdown(void) ++{ ++ SIMPLE_TEXT_OUTPUT_MODE SavedMode; ++ EFI_INPUT_KEY key; ++ EFI_STATUS status; ++ UINTN cols, rows; ++ CHAR16 *title[2]; ++ CHAR16 *message = L"Press any key to stop system reset"; ++ int timeout = 5, wait = 10000000; ++ ++ console_save_and_set_mode (&SavedMode); ++ ++ title[0] = L"Boot Option Restoration"; ++ title[1] = NULL; ++ ++ console_print_box_at(title, -1, 0, 0, -1, -1, 1, 1); ++ ++ uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ++ ST->ConOut->Mode->Mode, &cols, &rows); ++ ++ PrintAt((cols - StrLen(message))/2, rows/2, message); ++ while (1) { ++ if (timeout > 1) ++ PrintAt(2, rows - 3, L"Booting in %d seconds ", timeout); ++ else if (timeout) ++ PrintAt(2, rows - 3, L"Booting in %d second ", timeout); ++ ++ status = WaitForSingleEvent(ST->ConIn->WaitForKey, wait); ++ ++ if (status != EFI_TIMEOUT) { ++ /* Clear the key in the queue */ ++ uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ++ ST->ConIn, &key); ++ break; ++ } ++ ++ timeout--; ++ if (!timeout) ++ break; ++ } ++ ++ console_restore_mode(&SavedMode); ++ ++ 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); + +@@ -1014,6 +1138,26 @@ 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) { ++ rc = set_fallback_no_reboot(); ++ if (EFI_ERROR(rc)) ++ goto reset; ++ } ++ VerbosePrint(L"tpm present, starting the first image\n"); ++ try_start_first_option(image); ++reset: + VerbosePrint(L"tpm present, resetting system\n"); + } + +-- +2.16.3 + diff --git a/shim.changes b/shim.changes index f001cdc..94481c8 100644 --- a/shim.changes +++ b/shim.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue May 29 06:41:59 UTC 2018 - glin@suse.com + +- Add shim-bsc1092000-fallback-menu.patch to show a menu before + system reset ((bsc#1092000)) + ------------------------------------------------------------------- Tue Apr 10 03:45:39 UTC 2018 - glin@suse.com diff --git a/shim.spec b/shim.spec index 07ab662..14bc611 100644 --- a/shim.spec +++ b/shim.spec @@ -56,6 +56,8 @@ Patch4: shim-remove-cryptpem.patch Patch5: shim-httpboot-amend-device-path.patch # PATCH-FIX-UPSTREAM shim-bsc1088585-handle-mok-allocations-better.patch bsc#1088585 glin@suse.com -- Handle the mok parameter allocations better Patch6: shim-bsc1088585-handle-mok-allocations-better.patch +# PATCH-FIX-UPSTREAM shim-bsc1092000-fallback-menu.patch bsc#1092000 glin@suse.com -- Show a menu before reset +Patch7: shim-bsc1092000-fallback-menu.patch # PATCH-FIX-OPENSUSE shim-change-debug-file-path.patch glin@suse.com -- Change the default debug file path Patch50: shim-change-debug-file-path.patch # PATCH-FIX-OPENSUSE shim-opensuse-cert-prompt.patch glin@suse.com -- Show the prompt to ask whether the user trusts openSUSE certificate or not @@ -106,6 +108,7 @@ The source code of UEFI shim loader %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 %patch50 -p1 %if 0%{?is_opensuse} == 1 %patch100 -p1