[PATCH v1 14/14] efi: loader: bootm: apply overlays carried by a UKI
Johannes Schneider
johannes.schneider at leica-geosystems.com
Sat Oct 3 18:19:47 PDT 2026
A UKI has no place for the overlays a FIT image carries next to its
devicetrees, and systemd-stub knows nothing about overlays. Carry them
in a ".bbdtbo" PE section, covered by the image's Authenticode
signature: a devicetree whose child nodes each hold one overlay in a
"data" property, named like the overlay file.
Unpack them to /tmp/efi-overlays and point global.of.overlay.path there
while the payload runs, so EFI_DT_FIXUP_PROTOCOL applies them to the
devicetree systemd-stub installs, filtered by global.of.overlay.filter
and pattern like overlays from a FIT image. Without such a section the
path is empty for that time, as it may point at the boot partition,
which now holds the UKI. The previous value is restored when the payload
returns.
Refuse a UKI whose overlay section cannot be unpacked, which would
otherwise boot without the hardware its overlays describe.
Only with CONFIG_OFTREE, which EFI_DT_FIXUP_PROTOCOL depends on.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johannes Schneider <johannes.schneider at leica-geosystems.com>
---
efi/loader/bootm.c | 86 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/efi/loader/bootm.c b/efi/loader/bootm.c
index 47f7a3d1e2..71c61935b1 100644
--- a/efi/loader/bootm.c
+++ b/efi/loader/bootm.c
@@ -37,6 +37,7 @@
#include <efi/devicepath.h>
#include <efi/loader/authenticode.h>
#include <efi/loader/pe.h>
+#include <globalvar.h>
#include <loadable.h>
#include <of.h>
#include <barebox-info.h>
@@ -223,6 +224,62 @@ static int efi_loader_verify(struct image_data *data, void *efi, size_t size)
return 0;
}
+#define EFI_UKI_OVERLAY_SECTION ".bbdtbo"
+#define EFI_UKI_OVERLAY_DIR "/tmp/efi-overlays"
+
+/*
+ * The overlay section is a devicetree whose child nodes each hold one overlay
+ * in a "data" property, named like the overlay file
+ */
+static int efi_uki_unpack_overlays(void *efi, size_t size)
+{
+ struct device_node *root, *np;
+ const void *blob, *ovl;
+ char *path;
+ size_t len;
+ int ovl_len, n = 0, ret = 0;
+
+ blob = efi_pe_find_section(efi, size, EFI_UKI_OVERLAY_SECTION, &len);
+ if (!blob)
+ return 0;
+
+ root = of_unflatten_dtb(blob, len);
+ if (IS_ERR(root))
+ return PTR_ERR(root);
+
+ unlink_recursive(EFI_UKI_OVERLAY_DIR, NULL);
+ ret = make_directory(EFI_UKI_OVERLAY_DIR);
+ if (ret)
+ goto out;
+
+ for_each_child_of_node(root, np) {
+ ovl = of_get_property(np, "data", &ovl_len);
+ if (!ovl)
+ continue;
+
+ path = basprintf(EFI_UKI_OVERLAY_DIR "/%s", np->name);
+ ret = write_file(path, ovl, ovl_len);
+ free(path);
+ if (ret)
+ goto out;
+ n++;
+ }
+
+ pr_info("unpacked %d overlay(s) to %s\n", n, EFI_UKI_OVERLAY_DIR);
+ ret = n;
+out:
+ of_delete_node(root);
+ return ret;
+}
+
+static bool efi_image_brings_devicetree(void *efi, size_t size)
+{
+ size_t len;
+
+ return efi_pe_find_section(efi, size, ".dtbauto", &len) ||
+ efi_pe_find_section(efi, size, ".dtb", &len);
+}
+
static const char *efi_machine_compatible(void)
{
const char *compat = barebox_get_of_machine_compatible();
@@ -361,8 +418,9 @@ static int efi_loader_bootm(struct image_data *data)
void *fdt;
int flags = 0;
size_t size, section_size;
+ char *overlay_path = NULL;
const char *compat;
- bool match;
+ bool match, uki;
memory_bank_first_find_space(&start, &end);
@@ -384,6 +442,11 @@ static int efi_loader_bootm(struct image_data *data)
match = IS_ENABLED(CONFIG_OFTREE) && compat &&
efi_uki_has_dtbauto_for((void *)os_res->start, size, compat);
+ uki = IS_ENABLED(CONFIG_OFTREE) &&
+ efi_image_brings_devicetree((void *)os_res->start, size);
+ if (uki)
+ overlay_path = xstrdup(getenv("global.of.overlay.path") ?: "");
+
/* systemd-stub passes the load options on as kernel command line */
if (filetype_is_linux_efi_image(data->kernel_type) ||
efi_pe_find_section((void *)os_res->start, size, ".linux",
@@ -432,6 +495,18 @@ static int efi_loader_bootm(struct image_data *data)
goto out;
}
+ if (uki) {
+ int n = efi_uki_unpack_overlays((void *)os_res->start, size);
+
+ if (n < 0) {
+ pr_err("cannot unpack the UKI overlays: %pe\n", ERR_PTR(n));
+ ret = n;
+ goto out;
+ }
+
+ globalvar_set("of.overlay.path", n ? EFI_UKI_OVERLAY_DIR : "");
+ }
+
efiret = efi_install_initrd(data, os_res->end + 1);
if(efiret != EFI_SUCCESS)
goto out;
@@ -502,9 +577,18 @@ static int efi_loader_bootm(struct image_data *data)
/* Control is returned to us, disable EFI watchdog */
efi_set_watchdog(0);
+ if (overlay_path) {
+ globalvar_set("of.overlay.path", overlay_path);
+ free(overlay_path);
+ }
+
return -efi_errno(efiret);
out:
+ if (overlay_path) {
+ globalvar_set("of.overlay.path", overlay_path);
+ free(overlay_path);
+ }
efi_initrd_unregister();
efi_install_configuration_table(&efi_fdt_guid, NULL);
efi_free_pool(file_path);
--
2.43.0
More information about the barebox
mailing list