[U-Boot] [PATCH v2] rpi: passthrough of the firmware provided FDT blob

Cédric Schieli cschieli at gmail.com
Mon Nov 7 15:44:55 CET 2016


Raspberry firmware used to pass a FDT blob at a fixed address (0x100),
but this is not true anymore. The address now depends on both the
memory size and the blob size [1].

If one wants to passthrough this FDT blob to the kernel, the most
reliable way is to save its address from the r2/x0 register in the
U-Boot entry point and expose it in a environment variable for
further processing.

This patch just does this:
- save the provided address in the global variable fw_dtb_pointer
- expose it in ${fdt_addr} if it points to a a valid FDT blob

There are many different ways to use it. One can, for example, use
the following script which will extract from the tree the command
line built by the firmware, then hand over the blob to a previously
loaded kernel:

if fdt addr ${fdt_addr}
then
	fdt get value bootargs /chosen bootargs
	bootz ${kernel_addr_r} - ${fdt_addr}
fi

Alternatively, users relying on sysboot/pxe can simply omit any FDT
statement in their extlinux.conf file, U-Boot will automagically pick
${fdt_addr} and pass it to the kernel.

Please note that for this to work the U-Boot binary must be tagged
with a recent version of the mkknlimg script found in the Rasperry
Fundation's kernel tree:

<kernel>/scripts/mkknlimg --dtok <uboot>/u-boot.bin /boot/u-boot.bin

[1] https://www.raspberrypi.org/forums//viewtopic.php?f=107&t=134018

Signed-off-by: Cédric Schieli <cschieli at gmail.com>
---

Changes in v2:
- merge the series in a single patch
- convert the save_boot_params() function to C code
- add a board_get_usable_ram_top() function to protect the blob
  during relocation
- remove the (obsolete) extern declaration from include/configs/rpi.h
- rename the global variable to fw_dtb_pointer
- rename the environment variable to ${fdt_addr}
- fix 64-bits compatibility issues
- document possible uses of ${fdt_addr}

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

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 6245b36..b1614b9 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -25,6 +25,21 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* From init.S */
+extern void save_boot_params_ret(void);
+
+static unsigned long fw_dtb_pointer __attribute__ ((section(".data")));
+
+#ifdef CONFIG_ARM64
+void save_boot_params(unsigned long dtb)
+#else
+void save_boot_params(unsigned long r0, unsigned long r1, unsigned long dtb)
+#endif
+{
+	fw_dtb_pointer = dtb;
+	save_boot_params_ret();
+}
+
 static const struct bcm2835_gpio_platdata gpio_platdata = {
 	.base = BCM2835_GPIO_BASE,
 };
@@ -285,6 +300,31 @@ static void set_fdtfile(void)
 	setenv("fdtfile", fdtfile);
 }
 
+/*
+ * If the firmware provided a valid FDT at boot time, let's expose it in
+ * ${fdt_addr} so it may be passed unmodified to the kernel.
+ */
+static void set_fdt_addr(void)
+{
+	if (getenv("fdt_addr"))
+		return;
+
+	if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
+		return;
+
+	setenv_hex("fdt_addr", fw_dtb_pointer);
+}
+
+/*
+ * Prevent relocation from stomping on a firmware provided FDT blob.
+ */
+unsigned long board_get_usable_ram_top(unsigned long total_size)
+{
+	if ((gd->ram_top - fw_dtb_pointer) > SZ_64M)
+		return gd->ram_top;
+	return fw_dtb_pointer &~0xffff;
+}
+
 static void set_usbethaddr(void)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1);
@@ -356,6 +396,7 @@ static void set_serial_number(void)
 
 int misc_init_r(void)
 {
+	set_fdt_addr();
 	set_fdtfile();
 	set_usbethaddr();
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
-- 
2.7.3



More information about the U-Boot mailing list