[PATCH] rpi: copy /system/linux,{serial,revision} from firmware FDT

Fiona Klute fiona.klute at gmx.de
Wed May 14 16:46:49 CEST 2025


Both the Raspberry Pi downstream kernel [1] and some userspace tools
[2] use the revision property to identify the board, and the latter
fails if it is absent. The firmware creates the /system node which is
not present in Linux DTS (mainline or vendor) for the Raspberry Pi
boards, so we need to do the same.

[1] https://github.com/raspberrypi/linux/blob/0f292fbb6346b05766152902076895558ac23f9a/arch/arm/mach-bcm/board_bcm2835.c#L23-L33
[2] https://github.com/jgarff/rpi_ws281x/blob/7fc0bf8b31d715bbecf28e852ede5aaa388180da/rpihw.c#L579

Signed-off-by: Fiona Klute <fiona.klute at gmx.de>
Cc: Matthias Brugger <mbrugger at suse.com>
Cc: Peter Robinson <pbrobinson at gmail.com>
Cc: Tom Rini <trini at konsulko.com>
---
I sent an RFC version of this patch [3] a while ago with the question
if there's a better way to create the /system node than creating a
temporary overlay. I didn't receive any response to that question, so
I guess not.

[3] https://lists.denx.de/pipermail/u-boot/2025-February/580364.html

 board/raspberrypi/rpi/rpi.c | 70 +++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 1b0b664fa2b..6545306f6da 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -562,6 +562,74 @@ int copy_property(void *dst, void *src, char *path, char *property)
 	return fdt_setprop(dst, dst_offset, property, prop, len);
 }
 
+void copy_system_node(void *fdt, void *fw_fdt)
+{
+	void *fdt_copy = NULL;
+	const fdt32_t *prop;
+	char fdto[1024];
+	int src_offset;
+	u32 fdt_size;
+	int len;
+
+	/*
+	 * If the firmware FDT does not have a /system node, there's
+	 * nothing to do.
+	 */
+	src_offset = fdt_path_offset(fw_fdt, "/system");
+	if (src_offset < 0)
+		return;
+
+	/* Create a temporary overlay that adds the /system node. */
+	if (fdt_create(fdto, sizeof(fdto)))
+		return;
+	if (fdt_finish_reservemap(fdto))
+		return;
+	if (fdt_begin_node(fdto, ""))
+		return;
+	if (fdt_begin_node(fdto, "fragment"))
+		return;
+	if (fdt_property_string(fdto, "target-path", "/"))
+		return;
+	if (fdt_begin_node(fdto, "__overlay__"))
+		return;
+	if (fdt_begin_node(fdto, "system"))
+		return;
+
+	prop = fdt_getprop(fw_fdt, src_offset, "linux,serial", &len);
+	if (prop)
+		fdt_property(fdto, "linux,serial", prop, len);
+	prop = fdt_getprop(fw_fdt, src_offset, "linux,revision", &len);
+	if (prop)
+		fdt_property(fdto, "linux,revision", prop, len);
+
+	if (fdt_end_node(fdto))
+		return;
+	if (fdt_end_node(fdto))
+		return;
+	if (fdt_end_node(fdto))
+		return;
+	if (fdt_end_node(fdto))
+		return;
+	if (fdt_finish(fdto))
+		return;
+
+	/*
+	 * A failed overlay apply is destructive to the target, so use
+	 * a temporary copy and replace the FDT if successful.
+	 */
+	fdt_size = fdt_totalsize(fdt);
+	fdt_copy = malloc(fdt_size);
+	if (!fdt_copy)
+		return;
+	memcpy(fdt_copy, fdt, fdt_size);
+	if (fdt_overlay_apply_verbose(fdt_copy, fdto))
+		goto cleanup;
+	memcpy(fdt, fdt_copy, fdt_size);
+
+ cleanup:
+	free(fdt_copy);
+}
+
 /* Copy tweaks from the firmware dtb to the loaded dtb */
 void  update_fdt_from_fw(void *fdt, void *fw_fdt)
 {
@@ -572,6 +640,8 @@ void  update_fdt_from_fw(void *fdt, void *fw_fdt)
 	/* The firmware provides a more precise model; so copy that */
 	copy_property(fdt, fw_fdt, "/", "model");
 
+	copy_system_node(fdt, fw_fdt);
+
 	/* memory reserve as suggested by the firmware */
 	copy_property(fdt, fw_fdt, "/", "memreserve");
 
-- 
2.49.0



More information about the U-Boot mailing list