Add support for accepting a control devicetree from the incoming passage.
This allows SPL (or some other program) to pass a devicetree to U-Boot
proper in a standard way.

Pass the devicetree through the early parts of U-Boot needs a list care.
If it is in the bloblist, there is no need to reserve a separate space for
it to relocate into, since it will be relocated as part of the bloblist.

Also we must init the bloblist before calling fdtdec_setup(), so the
devicetree can be read from the bloblist*. This is not normally safe,
since malloc() is be called by bloblist_init() if CONFIG_BLOBLIST_ALLOC
is enabled. But in the case of a devicetree in the incoming passage, we
know we won't need to allocate the bloblist, since the previous phase has
set it up for us.

Finally, move the reloc_fdt() call after the reloc_bloblist() since, as
mentioned above, when the passage is used there is no need to relocate the
devicetree.

There is one subtlety here. If bloblist support is not enabled in U-Boot,
it can still receive a control devicetree, using the passage_dtb_off value
added to passage_bloblist. This allows the devicetree passing to work
even if the bloblist itself is ignored. In that case we do need to
relocate the devicetree. Use a global_data flag for this case.

* Actually we could init the bloblist later, since we have the offset of
the devicetree in a register, but that seems like an extreme measure,
bypassing U-Boot's own bloblist implementation to get at the data.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 common/bloblist.c                 |  1 +
 common/board_f.c                  | 16 ++++++++++++----
 dts/Kconfig                       | 12 ++++++++++++
 include/asm-generic/global_data.h |  4 ++++
 include/bloblist.h                |  1 +
 lib/fdtdec.c                      | 30 ++++++++++++++++++++++++++++++
 6 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/common/bloblist.c b/common/bloblist.c
index d36e0a94dff..310ca87dbc4 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -39,6 +39,7 @@ static struct tag_name {
        { BLOBLISTT_NONE, "(none)" },
 
        /* BLOBLISTT_AREA_FIRMWARE_TOP */
+       { BLOBLISTT_CONTROL_DTB, "Control DTB" },
 
        /* BLOBLISTT_AREA_FIRMWARE */
        { BLOBLISTT_ACPI_GNVS, "ACPI GNVS" },
diff --git a/common/board_f.c b/common/board_f.c
index 86c77a42847..3684c21a0f7 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -517,7 +517,7 @@ static int reserve_global_data(void)
 
 static int reserve_fdt(void)
 {
-       if (!IS_ENABLED(CONFIG_OF_EMBED)) {
+       if (!IS_ENABLED(CONFIG_OF_EMBED) && !(gd->flags & GD_FLG_OF_PASSAGE)) {
                /*
                 * If the device tree is sitting immediately above our image
                 * then we must relocate it. If it is embedded in the data
@@ -622,7 +622,12 @@ static int init_post(void)
 
 static int reloc_fdt(void)
 {
-       if (!IS_ENABLED(CONFIG_OF_EMBED)) {
+       if (IS_ENABLED(CONFIG_OF_PASSAGE) && (gd->flags & GD_FLG_OF_PASSAGE)) {
+               void *blob = bloblist_find(BLOBLISTT_CONTROL_DTB, 0);
+
+               log_info("passage: Control dtb relocated to %p\n", blob);
+               gd->fdt_blob = blob;
+       } else if (!IS_ENABLED(CONFIG_OF_EMBED)) {
                if (gd->flags & GD_FLG_SKIP_RELOC)
                        return 0;
                if (gd->new_fdt) {
@@ -819,6 +824,9 @@ __weak int clear_bss(void)
 
 static const init_fnc_t init_sequence_f[] = {
        setup_mon_len,
+#ifdef CONFIG_OF_PASSAGE
+       bloblist_init,
+#endif
 #ifdef CONFIG_OF_CONTROL
        fdtdec_setup,
 #endif
@@ -828,7 +836,7 @@ static const init_fnc_t init_sequence_f[] = {
        initf_malloc,
        log_init,
        initf_bootstage,        /* uses its own timer, so does not need DM */
-#ifdef CONFIG_BLOBLIST
+#if !defined(CONFIG_OF_PASSAGE) && defined(CONFIG_BLOBLIST)
        bloblist_init,
 #endif
        setup_spl_handoff,
@@ -938,9 +946,9 @@ static const init_fnc_t init_sequence_f[] = {
        setup_bdinfo,
        display_new_sp,
        INIT_FUNC_WATCHDOG_RESET
-       reloc_fdt,
        reloc_bootstage,
        reloc_bloblist,
+       reloc_fdt,
        setup_reloc,
 #if defined(CONFIG_X86) || defined(CONFIG_ARC)
        copy_uboot_to_ram,
diff --git a/dts/Kconfig b/dts/Kconfig
index 5dcc79d5192..7e4d9852a44 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -96,6 +96,18 @@ config OF_EMBED
 
 endchoice
 
+config OF_PASSAGE
+       bool "Devicetree provided by the standard passage protocol"
+       help
+         If this option is enabled, the device tree may be provided by the
+         standard passage, meaning that a previous phase/stage passes a
+         bloblist containing this. This is the standard way to pass a
+         devicetree between firmware components at runtime. The device tree
+         bundled with the image (if any) will be overridden / ignored.
+
+         Note: If BLOBLIST is not enabled, this does not decode the
+         bloblist, but just picks up the devicetree by itself.
+
 config OF_BOARD
        bool "Provided by the board (e.g a previous loader) at runtime"
        default y if SANDBOX
diff --git a/include/asm-generic/global_data.h 
b/include/asm-generic/global_data.h
index ef4119f27f4..717fe2edb46 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -627,6 +627,10 @@ enum gd_flags {
         * @GD_FLG_SMP_READY: SMP initialization is complete
         */
        GD_FLG_SMP_READY = 0x80000,
+       /**
+        * @GD_FLG_OF_PASSAGE: Using devicetree from standard passage protocol
+        */
+       GD_FLG_OF_PASSAGE = 0x80000,
 };
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/bloblist.h b/include/bloblist.h
index 2ede0ce3150..607e42129d4 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -31,6 +31,7 @@ enum bloblist_tag_t {
         * projects.
         */
        BLOBLISTT_AREA_FIRMWARE_TOP = 0x1,
+       BLOBLISTT_CONTROL_DTB = 1,      /* Devicetree used for control */
 
        /* Standard area to allocate blobs used across firmware components */
        BLOBLISTT_AREA_FIRMWARE = 0x100,
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 31a509bc221..4ca56e06b2f 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -3,8 +3,11 @@
  * Copyright (c) 2011 The Chromium OS Authors.
  */
 
+#define LOG_CATEGORY   LOGC_DT
+
 #ifndef USE_HOSTCC
 #include <common.h>
+#include <bloblist.h>
 #include <boot_fit.h>
 #include <dm.h>
 #include <hang.h>
@@ -1631,6 +1634,33 @@ int fdtdec_setup(void)
        else /* embed dtb in ELF file for testing / development */
                gd->fdt_blob = dtb_dt_embedded();
 
+       /* Passed in via the standard passage */
+       if (IS_ENABLED(CONFIG_OF_PASSAGE) && gd->passage_dtb_off) {
+               void *fdt = NULL;
+
+               /* Use the bloblist if available */
+               if (CONFIG_IS_ENABLED(BLOBLIST)) {
+                       fdt = bloblist_find(BLOBLISTT_CONTROL_DTB, 0);
+
+                       if (fdt)
+                               gd->flags |= GD_FLG_OF_PASSAGE;
+               } else {
+                       void *bloblist;
+
+                       /* Cursory check for a valid bloblist; use the offset */
+                       bloblist = bloblist_check_magic(gd->passage_bloblist);
+                       if (bloblist) {
+                               fdt = bloblist + gd->passage_dtb_off;
+                               log_debug("passage: Found dtb offset %lx\n",
+                                         gd->passage_dtb_off);
+                       }
+               }
+               if (fdt) {
+                       gd->fdt_blob = fdt;
+                       log_debug("passage: Found control dtb at %p\n", fdt);
+               }
+       }
+
        /* Allow the board to override the fdt address. */
        if (IS_ENABLED(CONFIG_OF_BOARD)) {
                gd->fdt_blob = board_fdt_blob_setup(&ret);
-- 
2.33.1.1089.g2158813163f-goog

Reply via email to