[PATCH 08/16] efi/libstub: Add generic arch callbacks for DRTM
Jason Gunthorpe
jgg at nvidia.com
Thu Sep 24 06:53:11 PDT 2026
If the architecture supports an EFI stub launched version of DRTM, it
can select the kconfig and provide the hooks under its architecture
build.
Have the common code parse a drtm=enforce|auto|off kernel command line
parameter to set the boot behavior. Support commas in the args list since
there will be more options here down the road.
efi_drtm_prepare() is called before doing any decompression or image
relocation. It should figure out if DRTM is supported, policy-permitted,
and how much memory efi_drtm_get_extra_size() should return.
The image handling is revised to allocate extra_size at the end of
the normal image. The architecture can use this to store any
information needed for the DRTM flow. It is always contiguous with
Image, which is a requirement of ARM's specification.
efi_drtm_prepare_launch() is called while still in EFI boot services after
Image is fully prepared in its final location.
efi_drtm_launch() is called after exiting boot services and must
jump into the kernel through the DRTM flow. If it returns, then the
normal launch is tried (auto mode).
The extra_size is allocated directly after the Image. Handle the
trivial zboot flow now, and vmlinux in the following patch.
Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
---
.../admin-guide/kernel-parameters.txt | 12 +++++++
drivers/firmware/efi/Kconfig | 30 ++++++++++++++++
drivers/firmware/efi/libstub/efi-stub-entry.c | 4 +++
.../firmware/efi/libstub/efi-stub-helper.c | 34 ++++++++++++++++++
drivers/firmware/efi/libstub/efistub.h | 36 +++++++++++++++++++
drivers/firmware/efi/libstub/fdt.c | 8 ++++-
drivers/firmware/efi/libstub/zboot.c | 19 +++++++---
7 files changed, 137 insertions(+), 6 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 68647ff4bdd24b..a576e06bd43584 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1373,6 +1373,18 @@ Kernel parameters
data set with no connector name will be used for
any connectors not explicitly specified.
+ drtm= [EFI,EARLY]
+ Format: { "off" | "auto" | "enforce" }
+ Control the EFI stub Dynamic Root of Trust for
+ Measurement (DRTM) launch policy.
+ off: do not attempt a DRTM launch.
+ auto: attempt a DRTM launch when supported, but fall
+ back to a normal boot if preparation or launch fails.
+ enforce: require a DRTM launch and refuse to fall back
+ to a normal boot if preparation or launch fails.
+ The default is selected by the EFI_STUB_DRTM_DEFAULT_*
+ configuration options.
+
dscc4.setup= [NET]
dt_cpu_ftrs= [PPC,EARLY]
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 3d6fb3ca2806ca..f77fa1ae716843 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -75,6 +75,36 @@ config EFI_GENERIC_STUB
config EFI_STUB_IMAGE_INFO
bool
+config EFI_STUB_DRTM
+ bool
+
+choice
+ prompt "Default DRTM launch policy"
+ depends on EFI_STUB_DRTM
+ default EFI_STUB_DRTM_DEFAULT_OFF
+ help
+ Select the DRTM policy used when no drtm= option is present on the
+ kernel command line. The command-line option overrides this default.
+
+config EFI_STUB_DRTM_DEFAULT_OFF
+ bool "Off"
+ help
+ Do not attempt a DRTM launch unless it is requested explicitly.
+
+config EFI_STUB_DRTM_DEFAULT_AUTO
+ bool "Automatic with fallback"
+ help
+ Attempt a DRTM launch when the firmware supports it, but fall back to
+ normal boot if preparation or a returnable launch attempt fails.
+
+config EFI_STUB_DRTM_DEFAULT_ENFORCE
+ bool "Enforce"
+ help
+ Require a DRTM launch and refuse normal-boot fallback if preparation
+ or a returnable launch attempt fails.
+
+endchoice
+
config EFI_ZBOOT
bool "Enable the generic EFI decompressor"
depends on EFI_GENERIC_STUB && !ARM
diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
index 83fade2b0d3b84..5b356c4be78975 100644
--- a/drivers/firmware/efi/libstub/efi-stub-entry.c
+++ b/drivers/firmware/efi/libstub/efi-stub-entry.c
@@ -67,6 +67,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
if (status != EFI_SUCCESS)
return status;
+ status = efi_drtm_prepare();
+ if (status != EFI_SUCCESS)
+ return status;
+
efi_info("Booting Linux Kernel...\n");
status = handle_kernel_image(&image_addr, &image_size,
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index f27f2e1f001997..2dd4a5ac916000 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -27,6 +27,37 @@ static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
int efi_mem_encrypt;
+#ifdef CONFIG_EFI_STUB_DRTM
+enum efi_drtm_policy efi_drtm_policy =
+ IS_ENABLED(CONFIG_EFI_STUB_DRTM_DEFAULT_ENFORCE) ? EFI_DRTM_ENFORCE :
+ IS_ENABLED(CONFIG_EFI_STUB_DRTM_DEFAULT_AUTO) ? EFI_DRTM_AUTO :
+ EFI_DRTM_OFF;
+
+static void efi_drtm_parse_options(char *options)
+{
+ char *keyword;
+
+ while (options) {
+ keyword = options;
+ while (*options && *options != ',')
+ options++;
+ if (*options)
+ *options++ = '\0';
+ else
+ options = NULL;
+
+ if (!strcmp(keyword, "off"))
+ efi_drtm_policy = EFI_DRTM_OFF;
+ else if (!strcmp(keyword, "auto"))
+ efi_drtm_policy = EFI_DRTM_AUTO;
+ else if (!strcmp(keyword, "enforce"))
+ efi_drtm_policy = EFI_DRTM_ENFORCE;
+ }
+}
+#else
+static void efi_drtm_parse_options(char *options) {}
+#endif
+
bool __pure __efi_soft_reserve_enabled(void)
{
return !efi_nosoftreserve;
@@ -89,6 +120,9 @@ efi_status_t efi_parse_options(char const *cmdline)
efi_mem_encrypt = 1;
else if (parse_option_str(val, "off"))
efi_mem_encrypt = -1;
+ } else if (IS_ENABLED(CONFIG_EFI_STUB_DRTM) &&
+ !strcmp(param, "drtm") && val) {
+ efi_drtm_parse_options(val);
} else if (!strcmp(param, "efi") && val) {
efi_nochunk = parse_option_str(val, "nochunk");
efi_novamap |= parse_option_str(val, "novamap");
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index da01d6005a62af..f3a6aefdc052ca 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1078,6 +1078,42 @@ efi_status_t check_platform_features(void);
void *get_efi_config_table(efi_guid_t guid);
+enum efi_drtm_policy {
+ EFI_DRTM_OFF,
+ EFI_DRTM_AUTO,
+ EFI_DRTM_ENFORCE,
+};
+
+#ifdef CONFIG_EFI_STUB_DRTM
+extern enum efi_drtm_policy efi_drtm_policy;
+efi_status_t efi_drtm_prepare(void);
+unsigned long efi_drtm_get_extra_size(void);
+efi_status_t efi_drtm_prepare_launch(unsigned long image_base,
+ unsigned long fdt_addr);
+void efi_drtm_launch(void);
+#else
+enum {efi_drtm_policy = EFI_DRTM_OFF};
+static inline efi_status_t efi_drtm_prepare(void)
+{
+ return EFI_SUCCESS;
+}
+
+static inline unsigned long efi_drtm_get_extra_size(void)
+{
+ return 0;
+}
+
+static inline efi_status_t
+efi_drtm_prepare_launch(unsigned long image_base, unsigned long fdt_addr)
+{
+ return EFI_SUCCESS;
+}
+
+static inline void efi_drtm_launch(void)
+{
+}
+#endif
+
/* NOTE: These functions do not print a trailing newline after the string */
void efi_char16_puts(efi_char16_t *);
void efi_puts(const char *str);
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 5b2dd709d7b151..15bb331f2dc56c 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -223,6 +223,7 @@ static
efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
efi_loaded_image_t *image,
unsigned long *new_fdt_addr,
+ unsigned long kernel_addr,
char *cmdline_ptr)
{
unsigned long desc_size;
@@ -289,6 +290,10 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
goto fail_free_new_fdt;
}
+ status = efi_drtm_prepare_launch(kernel_addr, *new_fdt_addr);
+ if (status != EFI_SUCCESS)
+ goto fail_free_new_fdt;
+
priv.new_fdt_addr = (void *)*new_fdt_addr;
status = efi_exit_boot_services(handle, &priv, exit_boot_func);
@@ -350,7 +355,7 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
efi_status_t status;
status = allocate_new_fdt_and_exit_boot(handle, image, &fdt_addr,
- cmdline_ptr);
+ kernel_addr, cmdline_ptr);
if (status != EFI_SUCCESS) {
efi_err("Failed to update FDT and exit boot services\n");
return status;
@@ -359,6 +364,7 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
if (IS_ENABLED(CONFIG_ARM))
efi_handle_post_ebs_state();
+ efi_drtm_launch();
efi_enter_kernel(kernel_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
/* not reached */
}
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index 960a542881d875..6ca231ad593b20 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -35,7 +35,7 @@ asmlinkage efi_status_t __efiapi
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
{
char *cmdline_ptr __free(efi_pool) = NULL;
- unsigned long image_base, alloc_size;
+ unsigned long image_base, image_size, alloc_size;
efi_loaded_image_t *image;
efi_status_t status;
@@ -52,12 +52,17 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
if (status != EFI_SUCCESS)
return status;
- efi_info("Decompressing Linux Kernel...\n");
-
- status = efi_zboot_decompress_init(&alloc_size);
+ status = efi_drtm_prepare();
if (status != EFI_SUCCESS)
return status;
+ efi_info("Decompressing Linux Kernel...\n");
+
+ status = efi_zboot_decompress_init(&image_size);
+ if (status != EFI_SUCCESS)
+ return status;
+ alloc_size = image_size + efi_drtm_get_extra_size();
+
// If the architecture has a preferred address for the image,
// try that first.
image_base = alloc_preferred_address(alloc_size);
@@ -92,8 +97,12 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
}
// Decompress the payload into the newly allocated buffer
- status = efi_zboot_decompress((void *)image_base, alloc_size);
+ status = efi_zboot_decompress((void *)image_base, image_size);
if (status == EFI_SUCCESS) {
+ /*
+ * Have to sync the entire allocation because the sync also
+ * remaps and changes the permissions.
+ */
efi_cache_sync_image(image_base, alloc_size);
status =
efi_stub_common(handle, image, image_base, cmdline_ptr);
--
2.43.0
More information about the linux-riscv
mailing list