[PATCH v3 3/4] efi: payload: export resolved state as a BareboxState UEFI variable

chalianis1 at gmail.com chalianis1 at gmail.com
Mon Aug 24 20:05:47 PDT 2026


From: Chali Anis <chalianis1 at gmail.com>

When a "barebox,state" node is already reachable via barebox's live
devicetree (statically compiled in, or injected by
CONFIG_STATE_OVERLAY), render its fully resolved description - backend
phandle included - with of_state_fixup() and publish it as a
"BareboxState" UEFI variable, so an OS-side consumer can locate the
state layout without needing a separate state.dtb file on the ESP.

state_to_efivars_export() and efi_late_init() are both late_efi_initcall,
and within one initcall level, execution follows definition order in the
object file, so state_to_efivars_export() must be defined after
efi_late_init(): on boards with no state node in their own static
devicetree, efi_late_init() is what loads and registers
/boot/EFI/barebox/state.dtb, and only once that has had a chance to run
does state_by_alias() have anything to find. Defined the other way
around, state_to_efivars_export() would always run first and never see
a state.dtb efi_late_init() had not loaded yet - it would only have
happened to work when CONFIG_STATE_OVERLAY had already registered the
node much earlier, at postcore_initcall, a narrower case than the
state.dtb fallback efi_late_init() exists to support.

Look the state instance up via the state_by_alias() helper
(common/state/state.c) rather than open-coding the equivalent
of_find_node_by_alias() + state_by_node(). This also means state not
being set up yet is just a clean no-op, rather than the -ENODEV that
open-coded version returned, which would've been logged as an initcall
failure for what is an entirely ordinary condition.

Assisted-by: Claude Sonnet 5
Signed-off-by: Chali Anis <chalianis1 at gmail.com>
---
 efi/payload/init.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/efi/payload/init.c b/efi/payload/init.c
index f0ce2a82cefc..cdb73afffa2c 100644
--- a/efi/payload/init.c
+++ b/efi/payload/init.c
@@ -287,7 +287,6 @@ core_efi_initcall(efi_register_firmware_nodes_fixup);
 #define EFI_LOADER_FEATURE_SECUREBOOT_ENROLL       (1LL << 11)
 #define EFI_LOADER_FEATURE_RETAIN_SHIM             (1LL << 12)
 
-
 static int efi_postcore_init(void)
 {
 	const struct efi_device_path *parent_image_dp, *loaded_image_dp;
@@ -404,6 +403,56 @@ static int efi_late_init(void)
 }
 late_efi_initcall(efi_late_init);
 
+/*
+ * Must run after efi_late_init(): on boards with no state node compiled
+ * into their own devicetree, efi_late_init() is what loads and registers
+ * /boot/EFI/barebox/state.dtb (or, on CONFIG_STATE_OVERLAY targets, that
+ * already happened much earlier). Only once that has had a chance to run
+ * does state_by_alias() have anything to find here.
+ */
+static int state_to_efivars_export(void)
+{
+	struct device_node *np;
+	struct state *state;
+	void *fdt;
+	size_t size;
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_STATE))
+		return 0;
+
+	state = state_by_alias("state");
+	if (!state)
+		return 0;
+
+	np = of_new_node(NULL, NULL);
+	if (!np)
+		return -ENOMEM;
+
+	ret = of_state_fixup(np, state);
+	if (ret)
+		goto out;
+
+	fdt = of_flatten_dtb(np);
+	if (!fdt) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	size = fdt_totalsize(fdt);
+
+	efi_set_variable("BareboxState", &efi_barebox_vendor_guid,
+			  EFI_VARIABLE_BOOTSERVICE_ACCESS |
+			  EFI_VARIABLE_RUNTIME_ACCESS,
+			  fdt, size);
+
+	free(fdt);
+	ret = 0;
+out:
+	of_delete_node(np);
+	return ret;
+}
+late_efi_initcall(state_to_efivars_export);
 static int do_efiexit(int argc, char *argv[])
 {
 	if (!BS)



More information about the barebox mailing list