Skip to content

Commit

Permalink
efi/chainloader: support Secure Launch
Browse files Browse the repository at this point in the history
Signed-off-by: Sergii Dmytruk <[email protected]>
  • Loading branch information
SergiiDmytruk committed Jan 15, 2025
1 parent 3d75b8f commit 54debcb
Showing 1 changed file with 56 additions and 15 deletions.
71 changes: 56 additions & 15 deletions grub-core/loader/efi/chainloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/net.h>
#include <grub/slaunch.h>
#if defined (__i386__) || defined (__x86_64__)
#include <grub/macho.h>
#include <grub/i386/macho.h>
Expand All @@ -45,13 +46,35 @@ GRUB_MOD_LICENSE ("GPLv3+");

static grub_dl_t my_mod;

static void *image_mem;
static grub_efi_physical_address_t image_address;
static grub_efi_uintn_t image_pages;

static struct grub_slaunch_params slparams = {0};

static void
free_image (void)
{
if (image_address)
{
grub_efi_system_table->boot_services->free_pages (image_address,
image_pages);

image_mem = NULL;
image_address = 0;
image_pages = 0;
}
}

static grub_err_t
grub_chainloader_unload (void *context)
{
grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
grub_efi_loaded_image_t *loaded_image;
grub_efi_boot_services_t *b;

free_image ();

loaded_image = grub_efi_get_loaded_image (image_handle);
if (loaded_image != NULL)
grub_free (loaded_image->load_options);
Expand All @@ -71,6 +94,25 @@ grub_chainloader_boot (void *context)
grub_efi_status_t status;
grub_efi_uintn_t exit_data_size;
grub_efi_char16_t *exit_data = NULL;
grub_err_t err;
grub_efi_loaded_image_t *loaded_image;

loaded_image = grub_efi_get_loaded_image (image_handle);
if (loaded_image == NULL)
return grub_error (GRUB_ERR_BUG, "Couldn't query EFI loaded image");

if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
{
err = grub_sl_efi_txt_setup (&slparams, image_mem, loaded_image, /*is_linux=*/false);
if (err != GRUB_ERR_NONE)
return grub_error (err, "Secure Launch setup TXT failed");
}
else if (grub_slaunch_platform_type () == SLP_AMD_SKINIT)
{
err = grub_sl_efi_skinit_setup (&slparams, image_mem, loaded_image, /*is_linux=*/false);
if (err != GRUB_ERR_NONE)
return grub_error (err, "Secure Launch setup SKINIT failed");
}

b = grub_efi_system_table->boot_services;
status = b->start_image (image_handle, &exit_data_size, &exit_data);
Expand Down Expand Up @@ -220,17 +262,16 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_efi_device_path_t *dp = NULL, *file_path = NULL;
grub_efi_loaded_image_t *loaded_image;
char *filename;
void *boot_image = 0;
grub_efi_handle_t dev_handle = 0;
grub_efi_physical_address_t address = 0;
grub_efi_uintn_t pages = 0;
grub_efi_char16_t *cmdline = NULL;
grub_efi_handle_t image_handle = NULL;

if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
filename = argv[0];

free_image ();

grub_dl_ref (my_mod);

b = grub_efi_system_table->boot_services;
Expand Down Expand Up @@ -280,21 +321,21 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
filename);
goto fail;
}
pages = (grub_efi_uintn_t) GRUB_EFI_BYTES_TO_PAGES (size);
image_pages = (grub_efi_uintn_t) GRUB_EFI_BYTES_TO_PAGES (size);

status = b->allocate_pages (GRUB_EFI_ALLOCATE_ANY_PAGES,
GRUB_EFI_LOADER_CODE,
pages, &address);
image_pages, &image_address);
if (status != GRUB_EFI_SUCCESS)
{
grub_dprintf ("chain", "Failed to allocate %u pages\n",
(unsigned int) pages);
(unsigned int) image_pages);
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto fail;
}

boot_image = (void *) ((grub_addr_t) address);
if (grub_file_read (file, boot_image, size) != size)
image_mem = (void *) ((grub_addr_t) image_address);
if (grub_file_read (file, image_mem, size) != size)
{
if (grub_errno == GRUB_ERR_NONE)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
Expand All @@ -306,7 +347,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
#if defined (__i386__) || defined (__x86_64__)
if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
{
struct grub_macho_fat_header *head = boot_image;
struct grub_macho_fat_header *head = image_mem;
if (head->magic
== grub_cpu_to_le32_compile_time (GRUB_MACHO_FAT_EFI_MAGIC))
{
Expand All @@ -333,14 +374,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
filename);
goto fail;
}
boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset);
image_mem = (char *) image_mem + grub_cpu_to_le32 (archs[i].offset);
size = grub_cpu_to_le32 (archs[i].size);
}
}
#endif

status = b->load_image (0, grub_efi_image_handle, file_path,
boot_image, size,
image_mem, size,
&image_handle);
if (status != GRUB_EFI_SUCCESS)
{
Expand Down Expand Up @@ -396,8 +437,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_file_close (file);
grub_device_close (dev);

/* We're finished with the source image buffer and file path now. */
b->free_pages (address, pages);
/* We're typically finished with the source image buffer and file path here. */
if (grub_slaunch_platform_type () == SLP_NONE)
free_image ();
grub_free (file_path);

grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0);
Expand All @@ -414,8 +456,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_free (cmdline);
grub_free (file_path);

if (address)
b->free_pages (address, pages);
free_image ();

if (image_handle != NULL)
b->unload_image (image_handle);
Expand Down

0 comments on commit 54debcb

Please sign in to comment.