From 0a7003faec146ff1db829cc2d896ab093da7def0 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 11 Jun 2015 13:25:56 -0400 Subject: Ensure that apps launched by shim get correct BS->Exit() behavior Right now applications run by shim get our wrapper for Exit(), but it doesn't do as much cleanup as it should - shim itself also exits, but currently is not doing all the cleanup it should be doing. This changes it so all of shim's cleanup is also performed. Based on a patch and lots of review from Gary Lin. Signed-off-by: Peter Jones --- replacements.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'replacements.c') diff --git a/replacements.c b/replacements.c index f7623d9d..01eda0e3 100644 --- a/replacements.c +++ b/replacements.c @@ -73,7 +73,6 @@ unhook_system_services(void) if (!systab) return; - systab->BootServices->Exit = system_exit; systab->BootServices->LoadImage = system_load_image; systab->BootServices->StartImage = system_start_image; systab->BootServices->ExitBootServices = system_exit_boot_services; @@ -163,18 +162,30 @@ exit_boot_services(EFI_HANDLE image_key, UINTN map_key) static EFI_STATUS EFIAPI do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus, - UINTN ExitDataSize, CHAR16 *ExitData) + UINTN ExitDataSize, CHAR16 *ExitData) { EFI_STATUS status; - unhook_system_services(); - status = systab->BootServices->Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData); - if (EFI_ERROR(status)) - hook_system_services(systab); + shim_fini(); + + status = systab->BootServices->Exit(ImageHandle, ExitStatus, + ExitDataSize, ExitData); + if (EFI_ERROR(status)) { + EFI_STATUS status2 = shim_init(); + + if (EFI_ERROR(status2)) { + Print(L"Something has gone seriously wrong: %r\n", + status2); + Print(L"shim cannot continue, sorry.\n"); + systab->BootServices->Stall(5000000); + systab->RuntimeServices->ResetSystem( + EfiResetShutdown, + EFI_SECURITY_VIOLATION, 0, NULL); + } + } return status; } - void hook_system_services(EFI_SYSTEM_TABLE *local_systab) { @@ -201,6 +212,18 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab) * and b) we can unwrap when we're done. */ system_exit_boot_services = systab->BootServices->ExitBootServices; systab->BootServices->ExitBootServices = exit_boot_services; +} + +void +unhook_exit(void) +{ + systab->BootServices->Exit = system_exit; +} + +void +hook_exit(EFI_SYSTEM_TABLE *local_systab) +{ + systab = local_systab; /* we need to hook Exit() so that we can allow users to quit the * bootloader and still e.g. start a new one or run an internal -- cgit v1.2.3