summaryrefslogtreecommitdiff
path: root/replacements.c
diff options
context:
space:
mode:
Diffstat (limited to 'replacements.c')
-rw-r--r--replacements.c131
1 files changed, 62 insertions, 69 deletions
diff --git a/replacements.c b/replacements.c
index 01eda0e3..944c779d 100644
--- a/replacements.c
+++ b/replacements.c
@@ -50,16 +50,19 @@
#include <efi.h>
#include <efiapi.h>
#include <efilib.h>
-#include "shim.h"
-#include "replacements.h"
-/* oh for fuck's sakes.*/
-#ifndef EFI_SECURITY_VIOLATION
-#define EFI_SECURITY_VIOLATION 26
-#endif
+#include "shim.h"
static EFI_SYSTEM_TABLE *systab;
+EFI_SYSTEM_TABLE *
+get_active_systab(void)
+{
+ if (systab)
+ return systab;
+ return ST;
+}
+
static typeof(systab->BootServices->LoadImage) system_load_image;
static typeof(systab->BootServices->StartImage) system_start_image;
static typeof(systab->BootServices->Exit) system_exit;
@@ -76,6 +79,7 @@ unhook_system_services(void)
systab->BootServices->LoadImage = system_load_image;
systab->BootServices->StartImage = system_start_image;
systab->BootServices->ExitBootServices = system_exit_boot_services;
+ gBS = systab->BootServices;
}
static EFI_STATUS EFIAPI
@@ -83,80 +87,67 @@ load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle,
EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer,
UINTN SourceSize, EFI_HANDLE *ImageHandle)
{
- EFI_STATUS status;
- unhook_system_services();
+ EFI_STATUS efi_status;
- status = systab->BootServices->LoadImage(BootPolicy,
- ParentImageHandle, DevicePath,
- SourceBuffer, SourceSize, ImageHandle);
+ unhook_system_services();
+ efi_status = gBS->LoadImage(BootPolicy, ParentImageHandle, DevicePath,
+ SourceBuffer, SourceSize, ImageHandle);
hook_system_services(systab);
- if (EFI_ERROR(status))
+ if (EFI_ERROR(efi_status))
last_loaded_image = NULL;
else
last_loaded_image = *ImageHandle;
- return status;
+ return efi_status;
}
static EFI_STATUS EFIAPI
-start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
+replacement_start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
{
- EFI_STATUS status;
+ EFI_STATUS efi_status;
unhook_system_services();
- /* We have to uninstall shim's protocol here, because if we're
- * On the fallback.efi path, then our call pathway is:
- *
- * shim->fallback->shim->grub
- * ^ ^ ^
- * | | \- gets protocol #0
- * | \- installs its protocol (#1)
- * \- installs its protocol (#0)
- * and if we haven't removed this, then grub will get the *first*
- * shim's protocol, but it'll get the second shim's systab
- * replacements. So even though it will participate and verify
- * the kernel, the systab never finds out.
- */
if (image_handle == last_loaded_image) {
loader_is_participating = 1;
uninstall_shim_protocols();
}
- status = systab->BootServices->StartImage(image_handle, exit_data_size, exit_data);
- if (EFI_ERROR(status)) {
+ efi_status = gBS->StartImage(image_handle, exit_data_size, exit_data);
+ if (EFI_ERROR(efi_status)) {
if (image_handle == last_loaded_image) {
- EFI_STATUS status2 = install_shim_protocols();
-
- if (EFI_ERROR(status2)) {
- Print(L"Something has gone seriously wrong: %d\n",
- status2);
- Print(L"shim cannot continue, sorry.\n");
- systab->BootServices->Stall(5000000);
- systab->RuntimeServices->ResetSystem(
- EfiResetShutdown,
- EFI_SECURITY_VIOLATION, 0, NULL);
+ EFI_STATUS efi_status2 = install_shim_protocols();
+
+ if (EFI_ERROR(efi_status2)) {
+ console_print(L"Something has gone seriously wrong: %r\n",
+ efi_status2);
+ console_print(L"shim cannot continue, sorry.\n");
+ msleep(5000000);
+ gRT->ResetSystem(EfiResetShutdown,
+ EFI_SECURITY_VIOLATION,
+ 0, NULL);
}
}
hook_system_services(systab);
loader_is_participating = 0;
}
- return status;
+ return efi_status;
}
static EFI_STATUS EFIAPI
exit_boot_services(EFI_HANDLE image_key, UINTN map_key)
{
- if (loader_is_participating || verification_method == VERIFIED_BY_HASH) {
+ if (loader_is_participating ||
+ verification_method == VERIFIED_BY_HASH) {
unhook_system_services();
- EFI_STATUS status;
- status = systab->BootServices->ExitBootServices(image_key, map_key);
- if (status != EFI_SUCCESS)
+ EFI_STATUS efi_status;
+ efi_status = gBS->ExitBootServices(image_key, map_key);
+ if (EFI_ERROR(efi_status))
hook_system_services(systab);
- return status;
+ return efi_status;
}
- Print(L"Bootloader has not verified loaded image.\n");
- Print(L"System is compromised. halting.\n");
- systab->BootServices->Stall(5000000);
- systab->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL);
+ console_print(L"Bootloader has not verified loaded image.\n");
+ console_print(L"System is compromised. halting.\n");
+ msleep(5000000);
+ gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL);
return EFI_SECURITY_VIOLATION;
}
@@ -164,41 +155,41 @@ static EFI_STATUS EFIAPI
do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus,
UINTN ExitDataSize, CHAR16 *ExitData)
{
- EFI_STATUS status;
+ EFI_STATUS efi_status;
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);
+ efi_status = gBS->Exit(ImageHandle, ExitStatus,
+ ExitDataSize, ExitData);
+ if (EFI_ERROR(efi_status)) {
+ EFI_STATUS efi_status2 = shim_init();
+
+ if (EFI_ERROR(efi_status2)) {
+ console_print(L"Something has gone seriously wrong: %r\n",
+ efi_status2);
+ console_print(L"shim cannot continue, sorry.\n");
+ msleep(5000000);
+ gRT->ResetSystem(EfiResetShutdown,
+ EFI_SECURITY_VIOLATION, 0, NULL);
}
}
- return status;
+ return efi_status;
}
void
hook_system_services(EFI_SYSTEM_TABLE *local_systab)
{
systab = local_systab;
+ gBS = systab->BootServices;
/* We need to hook various calls to make this work... */
/* We need LoadImage() hooked so that fallback.c can load shim
* without having to fake LoadImage as well. This allows it
* to call the system LoadImage(), and have us track the output
- * and mark loader_is_participating in start_image. This means
- * anything added by fallback has to be verified by the system db,
- * which we want to preserve anyway, since that's all launching
+ * and mark loader_is_participating in replacement_start_image. This
+ * means anything added by fallback has to be verified by the system
+ * db, which we want to preserve anyway, since that's all launching
* through BDS gives us. */
system_load_image = systab->BootServices->LoadImage;
systab->BootServices->LoadImage = load_image;
@@ -206,7 +197,7 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab)
/* we need StartImage() so that we can allow chain booting to an
* image trusted by the firmware */
system_start_image = systab->BootServices->StartImage;
- systab->BootServices->StartImage = start_image;
+ systab->BootServices->StartImage = replacement_start_image;
/* we need to hook ExitBootServices() so a) we can enforce the policy
* and b) we can unwrap when we're done. */
@@ -218,12 +209,14 @@ void
unhook_exit(void)
{
systab->BootServices->Exit = system_exit;
+ gBS = systab->BootServices;
}
void
hook_exit(EFI_SYSTEM_TABLE *local_systab)
{
systab = local_systab;
+ gBS = local_systab->BootServices;
/* 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