[PATCH v2 05/16] passage: Support a control devicetree
Simon Glass
sjg at chromium.org
Mon Jan 17 16:04:17 CET 2022
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>
---
Changes in v2:
- Incorporate devicetree source
- Rebase to master
common/bloblist.c | 1 +
common/board_f.c | 16 +++++++++++----
dts/Kconfig | 12 +++++++++++
include/asm-generic/global_data.h | 4 ++++
include/bloblist.h | 1 +
include/fdtdec.h | 4 ++++
lib/fdtdec.c | 33 +++++++++++++++++++++++++++++++
7 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/common/bloblist.c b/common/bloblist.c
index df45d45de90..3a2fba212c9 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 04d98366bd6..0794cc50a57 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) {
@@ -821,6 +826,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
@@ -830,7 +838,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,
@@ -940,9 +948,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 fb7df533f92..65d129453c6 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 || OF_HAS_PRIOR_STAGE
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 3fe1534ed9d..34b4139e498 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -638,6 +638,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 d0e128acf10..c0045572275 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/include/fdtdec.h b/include/fdtdec.h
index 15f2d2bbbaa..b4e452326b3 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -56,6 +56,9 @@ struct bd_info;
*
* @FDTSRC_SEPARATE: Appended to U-Boot. This is the normal approach if U-Boot
* is the only firmware being booted
+ * @FDTSRC_PASSAGE: From the standard passage (passed in from previous
+ * phase/stage). This is the normal approach if prior-stage firmware is
+ * used, such as TF-A
* @FDTSRC_FIT: Found in a multi-dtb FIT. This should be used when U-Boot must
* select a devicetree from many options
* @FDTSRC_BOARD: Located by custom board code. This should only be used when
@@ -68,6 +71,7 @@ struct bd_info;
*/
enum fdt_source_t {
FDTSRC_SEPARATE,
+ FDTSRC_PASSAGE,
FDTSRC_FIT,
FDTSRC_BOARD,
FDTSRC_EMBED,
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 280cda61a72..86613208b14 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>
@@ -78,6 +81,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
static const char *const fdt_src_name[] = {
[FDTSRC_SEPARATE] = "separate",
+ [FDTSRC_PASSAGE] = "passage",
[FDTSRC_FIT] = "fit",
[FDTSRC_BOARD] = "board",
[FDTSRC_EMBED] = "embed",
@@ -1649,6 +1653,35 @@ int fdtdec_setup(void)
gd->fdt_src = FDTSRC_EMBED;
}
+ /* Passed in via the standard passage */
+ if (IS_ENABLED(CONFIG_OF_PASSAGE) && gd->passage_dtb) {
+ void *passage_dtb = map_sysmem(gd->passage_dtb, 0);
+ void *fdt = NULL;
+
+ /* Use the bloblist if available */
+ if (CONFIG_IS_ENABLED(BLOBLIST)) {
+ fdt = bloblist_find(BLOBLISTT_CONTROL_DTB, 0);
+
+ if (fdt == passage_dtb)
+ 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 = passage_dtb;
+ log_debug("passage: Found dtb addr %lx\n",
+ gd->passage_dtb);
+ }
+ }
+ if (fdt) {
+ gd->fdt_blob = fdt;
+ gd->fdt_src = FDTSRC_PASSAGE;
+ 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.34.1.703.g22d0c6ccf7-goog
More information about the U-Boot
mailing list