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.kl...@gmx.de> Cc: Matthias Brugger <mbrug...@suse.com> Cc: Peter Robinson <pbrobin...@gmail.com> Cc: Tom Rini <tr...@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