]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
efi: Provide wrappers for load_image, start_image and unload_image
authorJulian Andres Klode <julian.klode@canonical.com>
Tue, 8 Jul 2025 20:21:13 +0000 (21:21 +0100)
committerDaniel Kiper <daniel.kiper@oracle.com>
Fri, 11 Jul 2025 15:12:24 +0000 (17:12 +0200)
These can be used to register a different implementation later,
for example, when shim provides a protocol with those functions.

Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/kern/efi/efi.c
grub-core/loader/efi/chainloader.c
grub-core/loader/efi/linux.c
include/grub/efi/efi.h

index b93ae3aba12db0337e5713634456f448e602f4bd..77456835e4b941ef291677a2d073128977f61767 100644 (file)
@@ -1049,3 +1049,60 @@ grub_efi_find_configuration_table (const grub_guid_t *target_guid)
 
   return 0;
 }
+
+static const grub_efi_loader_t *override_loader = NULL;
+
+grub_err_t
+grub_efi_register_loader (const grub_efi_loader_t *loader)
+{
+  if (override_loader != NULL)
+    return grub_error (GRUB_ERR_BUG, "trying to register different loader");
+  override_loader = loader;
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efi_unregister_loader (const grub_efi_loader_t *loader)
+{
+  if (loader != override_loader)
+    return grub_error (GRUB_ERR_BUG, "trying to unregister different loader");
+
+  override_loader = NULL;
+  return GRUB_ERR_NONE;
+}
+
+grub_efi_status_t
+grub_efi_load_image (grub_efi_boolean_t boot_policy,
+                    grub_efi_handle_t parent_image_handle,
+                    grub_efi_device_path_t *file_path, void *source_buffer,
+                    grub_efi_uintn_t source_size,
+                    grub_efi_handle_t *image_handle)
+{
+  if (override_loader != NULL)
+    return override_loader->load_image (boot_policy, parent_image_handle,
+                                       file_path, source_buffer, source_size,
+                                       image_handle);
+  return grub_efi_system_table->boot_services->load_image (
+      boot_policy, parent_image_handle, file_path, source_buffer, source_size,
+      image_handle);
+}
+
+grub_efi_status_t
+grub_efi_start_image (grub_efi_handle_t image_handle,
+                     grub_efi_uintn_t *exit_data_size,
+                     grub_efi_char16_t **exit_data)
+{
+  if (override_loader != NULL)
+    return override_loader->start_image (image_handle, exit_data_size,
+                                        exit_data);
+  return grub_efi_system_table->boot_services->start_image (
+      image_handle, exit_data_size, exit_data);
+}
+
+grub_efi_status_t
+grub_efi_unload_image (grub_efi_handle_t image_handle)
+{
+  if (override_loader != NULL)
+    return override_loader->unload_image (image_handle);
+  return grub_efi_system_table->boot_services->unload_image (image_handle);
+}
index 869307bf3f02813e25824b364a1668770f93a7f7..11b64ac1b688fc3d61701045e31ff6a8fc07b63e 100644 (file)
@@ -50,14 +50,12 @@ 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;
 
   loaded_image = grub_efi_get_loaded_image (image_handle);
   if (loaded_image != NULL)
     grub_free (loaded_image->load_options);
 
-  b = grub_efi_system_table->boot_services;
-  b->unload_image (image_handle);
+  grub_efi_unload_image (image_handle);
 
   grub_dl_unref (my_mod);
   return GRUB_ERR_NONE;
@@ -73,7 +71,7 @@ grub_chainloader_boot (void *context)
   grub_efi_char16_t *exit_data = NULL;
 
   b = grub_efi_system_table->boot_services;
-  status = b->start_image (image_handle, &exit_data_size, &exit_data);
+  status = grub_efi_start_image (image_handle, &exit_data_size, &exit_data);
   if (status != GRUB_EFI_SUCCESS)
     {
       if (exit_data)
@@ -339,9 +337,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
     }
 #endif
 
-  status = b->load_image (0, grub_efi_image_handle, file_path,
-                         boot_image, size,
-                         &image_handle);
+  status = grub_efi_load_image (0, grub_efi_image_handle, file_path,
+                               boot_image, size, &image_handle);
   if (status != GRUB_EFI_SUCCESS)
     {
       if (status == GRUB_EFI_OUT_OF_RESOURCES)
@@ -418,7 +415,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
     b->free_pages (address, pages);
 
   if (image_handle != NULL)
-    b->unload_image (image_handle);
+    grub_efi_unload_image (image_handle);
 
   grub_dl_unref (my_mod);
 
index 36dea2931b146c64282e3fb729973a19e048250c..918884ef3b6f3ec678cc7ee85228c4470a2c01f9 100644 (file)
@@ -187,7 +187,6 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
 {
   grub_efi_memory_mapped_device_path_t *mempath;
   grub_efi_handle_t image_handle;
-  grub_efi_boot_services_t *b;
   grub_efi_status_t status;
   grub_efi_loaded_image_t *loaded_image;
   grub_size_t len;
@@ -208,10 +207,9 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
   mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
   mempath[1].header.length = sizeof (grub_efi_device_path_t);
 
-  b = grub_efi_system_table->boot_services;
-  status = b->load_image (0, grub_efi_image_handle,
-                         (grub_efi_device_path_t *) mempath,
-                         (void *) addr, size, &image_handle);
+  status = grub_efi_load_image (0, grub_efi_image_handle,
+                               (grub_efi_device_path_t *)mempath,
+                               (void *)addr, size, &image_handle);
   if (status != GRUB_EFI_SUCCESS)
     return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
 
@@ -238,7 +236,7 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
   loaded_image->load_options_size = len * sizeof (grub_efi_char16_t);
 
   grub_dprintf ("linux", "starting image %p\n", image_handle);
-  status = b->start_image (image_handle, 0, NULL);
+  status = grub_efi_start_image (image_handle, 0, NULL);
 
   /* When successful, not reached */
   grub_error (GRUB_ERR_BAD_OS, "start_image() returned 0x%" PRIxGRUB_EFI_UINTN_T, status);
@@ -246,7 +244,7 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
                       GRUB_EFI_BYTES_TO_PAGES (len));
   loaded_image->load_options = NULL;
 unload:
-  b->unload_image (image_handle);
+  grub_efi_unload_image (image_handle);
 
   return grub_errno;
 }
index a5cd99e5afa931d981c99881644ebc5f4142d27c..b4d2f2d46d0c2b95494bb7c4a0ac482795f83f6e 100644 (file)
@@ -132,6 +132,48 @@ grub_err_t grub_arch_efi_linux_load_image_header(grub_file_t file,
 grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
                                            char *args);
 
+grub_efi_status_t
+EXPORT_FUNC (grub_efi_load_image) (grub_efi_boolean_t boot_policy,
+                                  grub_efi_handle_t parent_image_handle,
+                                  grub_efi_device_path_t *file_path,
+                                  void *source_buffer, grub_efi_uintn_t source_size,
+                                  grub_efi_handle_t *image_handle);
+
+grub_efi_status_t
+EXPORT_FUNC (grub_efi_start_image) (grub_efi_handle_t image_handle,
+                                   grub_efi_uintn_t *exit_data_size,
+                                   grub_efi_char16_t **exit_data);
+
+grub_efi_status_t
+EXPORT_FUNC (grub_efi_unload_image) (grub_efi_handle_t image_handle);
+
+typedef struct grub_efi_loader
+{
+  grub_efi_status_t (__grub_efi_api *load_image) (grub_efi_boolean_t boot_policy,
+                                                 grub_efi_handle_t parent_image_handle,
+                                                 grub_efi_device_path_t *file_path,
+                                                 void *source_buffer,
+                                                 grub_efi_uintn_t source_size,
+                                                 grub_efi_handle_t *image_handle);
+
+  grub_efi_status_t (__grub_efi_api *start_image) (grub_efi_handle_t image_handle,
+                                                  grub_efi_uintn_t *exit_data_size,
+                                                  grub_efi_char16_t **exit_data);
+
+  grub_efi_status_t (__grub_efi_api *exit) (grub_efi_handle_t image_handle,
+                                           grub_efi_status_t exit_status,
+                                           grub_efi_uintn_t exit_data_size,
+                                           grub_efi_char16_t *exit_data);
+
+  grub_efi_status_t (__grub_efi_api *unload_image) (grub_efi_handle_t image_handle);
+} grub_efi_loader_t;
+
+grub_err_t
+EXPORT_FUNC (grub_efi_register_loader) (const grub_efi_loader_t *loader);
+
+grub_err_t
+EXPORT_FUNC (grub_efi_unregister_loader) (const grub_efi_loader_t *loader);
+
 grub_addr_t grub_efi_section_addr (const char *section);
 
 void grub_efi_mm_init (void);