[PATCH 17/31] passage: Support a control devicetree
Simon Glass
sjg at chromium.org
Mon Nov 1 02:17:19 CET 2021
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 <sjg at 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
More information about the U-Boot
mailing list