efi: Properly propagate exits after loading an image using chainloading; do not try to return from panics if boot services were exited
diff --git a/stage23/lib/panic.s2.c b/stage23/lib/panic.s2.c
index 7acec053..f2fae794 100644
--- a/stage23/lib/panic.s2.c
+++ b/stage23/lib/panic.s2.c
@@ -26,13 +26,20 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) {
print("System halted.");
rm_hcf();
#elif defined (uefi)
- print("Press [ENTER] to return to firmware.");
- while (getchar() != '\n');
- fb_clear(&fbinfo);
+ if (efi_boot_services_exited == false) {
+ print("Press [ENTER] to return to firmware.");
+ while (getchar() != '\n');
+ fb_clear(&fbinfo);
- // release all uefi memory and return to firmware
- pmm_release_uefi_mem();
- uefi_call_wrapper(gBS->Exit, 4, efi_image_handle, EFI_ABORTED, 0, NULL);
- __builtin_unreachable();
+ // release all uefi memory and return to firmware
+ pmm_release_uefi_mem();
+ uefi_call_wrapper(gBS->Exit, 4, efi_image_handle, EFI_ABORTED, 0, NULL);
+ __builtin_unreachable();
+ } else {
+ print("System halted.");
+ for (;;) {
+ asm ("hlt");
+ }
+ }
#endif
}
diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c
index eae87b3e..f03f2027 100644
--- a/stage23/protos/chainload.c
+++ b/stage23/protos/chainload.c
@@ -189,9 +189,15 @@ void chainload(char *config) {
new_handle_loaded_image->DeviceHandle = loader_loaded_image->DeviceHandle;
- status = uefi_call_wrapper(gBS->StartImage, 3, new_handle, NULL, NULL);
+ UINTN exit_data_size = 0;
+ CHAR16 *exit_data = NULL;
+ EFI_STATUS exit_status = uefi_call_wrapper(gBS->StartImage, 3,
+ new_handle, &exit_data_size, &exit_data);
+
+ status = uefi_call_wrapper(gBS->Exit, 4,
+ efi_image_handle, exit_status, exit_data_size, exit_data);
if (status) {
- panic("chainload: StartImage failure (%x)", status);
+ panic("chainload: Exit failure (%x)", status);
}
__builtin_unreachable();
