git: c796ba5824d8 - stable/13 - loader.efi: fix panic() after BS off

From: Toomas Soome <tsoome_at_FreeBSD.org>
Date: Sun, 26 Jun 2022 08:46:15 UTC
The branch stable/13 has been updated by tsoome:

URL: https://cgit.FreeBSD.org/src/commit/?id=c796ba5824d8809f087058d55929b1496f9e52b3

commit c796ba5824d8809f087058d55929b1496f9e52b3
Author:     Toomas Soome <tsoome@FreeBSD.org>
AuthorDate: 2021-09-08 00:14:51 +0000
Commit:     Toomas Soome <tsoome@FreeBSD.org>
CommitDate: 2022-06-26 05:18:13 +0000

    loader.efi: fix panic() after BS off
    
    panic() is using multiple services - attempting to read
    keyboard, accessing time functions and finally, exiting the loader.
    
    Protect all the accessed listed above. Note, when BS are off,
    we really can not just exit the loader, we only can reboot.
    
    (cherry-picked from commit a2e02d9d8e100bc41cf99b8fd04738954e48a94e)
---
 stand/efi/include/efiapi.h     | 2 +-
 stand/efi/libefi/delay.c       | 3 ++-
 stand/efi/libefi/efi_console.c | 6 ++++++
 stand/efi/loader/efi_main.c    | 8 ++++++--
 4 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/stand/efi/include/efiapi.h b/stand/efi/include/efiapi.h
index 0118027d4b3c..2347a4d9cf73 100644
--- a/stand/efi/include/efiapi.h
+++ b/stand/efi/include/efiapi.h
@@ -438,7 +438,7 @@ VOID
     IN EFI_STATUS               ResetStatus,
     IN UINTN                    DataSize,
     IN CHAR16                   *ResetData OPTIONAL
-    );
+    ) __dead2;
 
 typedef
 EFI_STATUS
diff --git a/stand/efi/libefi/delay.c b/stand/efi/libefi/delay.c
index 9eb123096636..9bf40d28f96b 100644
--- a/stand/efi/libefi/delay.c
+++ b/stand/efi/libefi/delay.c
@@ -33,5 +33,6 @@ __FBSDID("$FreeBSD$");
 void
 delay(int usecs)
 {
-	BS->Stall(usecs);
+	if (boot_services_active)
+		BS->Stall(usecs);
 }
diff --git a/stand/efi/libefi/efi_console.c b/stand/efi/libefi/efi_console.c
index 7166b7a3cfbe..1aeb94344c58 100644
--- a/stand/efi/libefi/efi_console.c
+++ b/stand/efi/libefi/efi_console.c
@@ -1362,6 +1362,9 @@ efi_cons_getchar(void)
 	if ((c = keybuf_getchar()) != 0)
 		return (c);
 
+	if (!boot_services_active)
+		return (-1);
+
 	key_pending = 0;
 
 	if (coninex == NULL) {
@@ -1383,6 +1386,9 @@ efi_cons_poll(void)
 	if (keybuf_ischar() || key_pending)
 		return (1);
 
+	if (!boot_services_active)
+		return (0);
+
 	/*
 	 * Some EFI implementation (u-boot for example) do not support
 	 * WaitForKey().
diff --git a/stand/efi/loader/efi_main.c b/stand/efi/loader/efi_main.c
index 736c1aa56c99..3e1fa06638e9 100644
--- a/stand/efi/loader/efi_main.c
+++ b/stand/efi/loader/efi_main.c
@@ -40,8 +40,12 @@ void
 efi_exit(EFI_STATUS exit_code)
 {
 
-	BS->FreePages(heap, EFI_SIZE_TO_PAGES(heapsize));
-	BS->Exit(IH, exit_code, 0, NULL);
+	if (boot_services_active) {
+		BS->FreePages(heap, EFI_SIZE_TO_PAGES(heapsize));
+		BS->Exit(IH, exit_code, 0, NULL);
+	} else {
+		RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+	}
 }
 
 void