summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--replacements.c37
-rw-r--r--replacements.h3
-rw-r--r--shim.c116
-rw-r--r--shim.h3
4 files changed, 109 insertions, 50 deletions
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
diff --git a/replacements.h b/replacements.h
index bd094240..e38cded1 100644
--- a/replacements.h
+++ b/replacements.h
@@ -41,6 +41,9 @@ extern int loader_is_participating;
extern void hook_system_services(EFI_SYSTEM_TABLE *local_systab);
extern void unhook_system_services(void);
+extern void hook_exit(EFI_SYSTEM_TABLE *local_systab);
+extern void unhook_exit(void);
+
extern EFI_STATUS install_shim_protocols(void);
extern void uninstall_shim_protocols(void);
diff --git a/shim.c b/shim.c
index 99b0d0e2..67d723a5 100644
--- a/shim.c
+++ b/shim.c
@@ -54,6 +54,7 @@
#define MOK_MANAGER L"\\MokManager.efi"
static EFI_SYSTEM_TABLE *systab;
+static EFI_HANDLE image_handle;
static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
static CHAR16 *second_stage;
@@ -1809,7 +1810,6 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
/*
* Verify that MokSBState is valid, and if appropriate set insecure mode
*/
-
static EFI_STATUS check_mok_sb (void)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
@@ -2042,7 +2042,62 @@ uninstall_shim_protocols(void)
&shim_lock_guid, &shim_lock_interface);
}
-EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
+EFI_STATUS
+shim_init(void)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ setup_console(1);
+ setup_verbosity();
+ dprinta(shim_version);
+
+ /* Set the second stage loader */
+ set_second_stage (image_handle);
+
+ if (secure_mode()) {
+ if (vendor_cert_size || vendor_dbx_size) {
+ /*
+ * If shim includes its own certificates then ensure
+ * that anything it boots has performed some
+ * validation of the next image.
+ */
+ hook_system_services(systab);
+ loader_is_participating = 0;
+ }
+
+ hook_exit(systab);
+
+ status = install_shim_protocols();
+ }
+ return status;
+}
+
+void
+shim_fini(void)
+{
+ if (secure_mode()) {
+ /*
+ * Remove our protocols
+ */
+ uninstall_shim_protocols();
+
+ /*
+ * Remove our hooks from system services.
+ */
+ unhook_system_services();
+ unhook_exit();
+ }
+
+ /*
+ * Free the space allocated for the alternative 2nd stage loader
+ */
+ if (load_options_size > 0 && second_stage)
+ FreePool(second_stage);
+
+ setup_console(0);
+}
+
+EFI_STATUS efi_main (EFI_HANDLE passed_image_handle,
+ EFI_SYSTEM_TABLE *passed_systab)
{
EFI_STATUS efi_status;
@@ -2062,84 +2117,59 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
shim_lock_interface.Context = shim_read_header;
systab = passed_systab;
+ image_handle = passed_image_handle;
/*
* Ensure that gnu-efi functions are available
*/
InitializeLib(image_handle, systab);
- setup_console(1);
- setup_verbosity();
-
- dprinta(shim_version);
-
- /* Set the second stage loader */
- set_second_stage (image_handle);
-
/*
* Check whether the user has configured the system to run in
* insecure mode
*/
check_mok_sb();
+ efi_status = shim_init();
+ if (EFI_ERROR(efi_status)) {
+ Print(L"Something has gone seriously wrong: %r\n", efi_status);
+ Print(L"shim cannot continue, sorry.\n");
+ systab->BootServices->Stall(5000000);
+ systab->RuntimeServices->ResetSystem(EfiResetShutdown,
+ EFI_SECURITY_VIOLATION,
+ 0, NULL);
+ }
+
/*
* Tell the user that we're in insecure mode if necessary
*/
if (user_insecure_mode) {
Print(L"Booting in insecure mode\n");
uefi_call_wrapper(BS->Stall, 1, 2000000);
- } else if (secure_mode()) {
- if (vendor_cert_size || vendor_dbx_size) {
- /*
- * If shim includes its own certificates then ensure
- * that anything it boots has performed some
- * validation of the next image.
- */
- hook_system_services(systab);
- loader_is_participating = 0;
- }
}
- efi_status = install_shim_protocols();
- if (EFI_ERROR(efi_status))
- return efi_status;
-
/*
* Enter MokManager if necessary
*/
efi_status = check_mok_request(image_handle);
/*
- * Copy the MOK list to a runtime variable so the kernel can make
- * use of it
+ * Copy the MOK list to a runtime variable so the kernel can
+ * make use of it
*/
efi_status = mirror_mok_list();
/*
- * Create the runtime MokIgnoreDB variable so the kernel can make
- * use of it
+ * Create the runtime MokIgnoreDB variable so the kernel can
+ * make use of it
*/
efi_status = mok_ignore_db();
/*
* Hand over control to the second stage bootloader
*/
-
efi_status = init_grub(image_handle);
- uninstall_shim_protocols();
- /*
- * Remove our hooks from system services.
- */
- unhook_system_services();
-
- /*
- * Free the space allocated for the alternative 2nd stage loader
- */
- if (load_options_size > 0)
- FreePool(second_stage);
-
- setup_console(0);
-
+ shim_fini();
return efi_status;
}
diff --git a/shim.h b/shim.h
index f7a766a2..52cbfeb9 100644
--- a/shim.h
+++ b/shim.h
@@ -34,3 +34,6 @@ typedef struct _SHIM_LOCK {
EFI_SHIM_LOCK_HASH Hash;
EFI_SHIM_LOCK_CONTEXT Context;
} SHIM_LOCK;
+
+extern EFI_STATUS shim_init(void);
+extern void shim_fini(void);