If a FIT specifies a load address, the loader writes the base
devicetree there before processing overlays. A caller which wants
to prepare the tree at an address of its own cannot prevent this
early write, even if an overlay later fails.

Allow callers to prepare the devicetree without writing to addresses
specified by the FIT. Alignment and decompression still take place,
so the result is ready to use. Keep the existing bootm behavior.

Reviewed-by: Simon Glass <[email protected]>
Signed-off-by: Carlo Caione <[email protected]>
---
 boot/image-fdt.c | 3 ++-
 boot/image-fit.c | 8 +++++---
 include/image.h  | 8 +++++++-
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index e65114ff835..9678bf9c9b6 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -468,7 +468,8 @@ static int select_fdt(struct bootm_headers *images, const 
char *select, u8 arch,
                                fdt_noffset = boot_get_fdt_fit(images, fdt_addr,
                                                               &fit_uname_fdt,
                                                               
&fit_uname_config,
-                                                              arch, &load, 
&len,
+                                                              arch, 
FIT_LOAD_OPTIONAL,
+                                                              &load, &len,
                                                               NULL);
 
                                if (fdt_noffset < 0)
diff --git a/boot/image-fit.c b/boot/image-fit.c
index 83e731402d6..c3d7b59bd06 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2221,6 +2221,7 @@ static int fit_image_load_storage(struct bootm_headers 
*images, const void *fit,
        fit_image_get_comp(fit, noffset, &img_comp);
 
        if (img_comp == IH_COMP_NONE && load_op != FIT_LOAD_IGNORED &&
+           load_op != FIT_LOAD_PREPARE &&
            !fit_image_get_load(fit, noffset, &img_load)) {
                void *dst = map_sysmem(img_load, data_sz);
 
@@ -2445,7 +2446,7 @@ static int fit_image_load_alloc(struct bootm_headers 
*images, ulong addr,
 
        data = map_to_sysmem(buf);
        load = data;
-       if (load_op == FIT_LOAD_IGNORED) {
+       if (load_op == FIT_LOAD_IGNORED || load_op == FIT_LOAD_PREPARE) {
                log_debug("load_op: not loading\n");
                /* Don't load */
        } else if (fit_image_get_load(fit, noffset, &load)) {
@@ -2658,7 +2659,8 @@ out:
 
 int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
                     const char **fit_unamep, const char **fit_uname_configp,
-                    int arch, ulong *datap, ulong *lenp, bool *ownedp)
+                    int arch, enum fit_load_op load_op, ulong *datap,
+                    ulong *lenp, bool *ownedp)
 {
        int fdt_noffset, cfg_noffset, count;
        const void *fit;
@@ -2697,7 +2699,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong 
addr,
        fdt_noffset = fit_image_load_alloc(images, addr, &fit_uname,
                                           &fit_uname_config, arch, 
IH_TYPE_FLATDT,
                                           BOOTSTAGE_ID_FIT_FDT_START,
-                                          FIT_LOAD_OPTIONAL, &load, &len,
+                                          load_op, &load, &len,
                                           &load_owned);
 
        if (fdt_noffset < 0)
diff --git a/include/image.h b/include/image.h
index 4ef5344c718..882a772a727 100644
--- a/include/image.h
+++ b/include/image.h
@@ -608,6 +608,7 @@ enum fit_load_op {
        FIT_LOAD_OPTIONAL,      /* Can be provided, but optional */
        FIT_LOAD_OPTIONAL_NON_ZERO,     /* Optional, a value of 0 is ignored */
        FIT_LOAD_REQUIRED,      /* Must be provided */
+       FIT_LOAD_PREPARE,       /* Ignore load address, but align/decompress */
 };
 
 int boot_get_setup(struct bootm_headers *images, uint8_t arch, ulong 
*setup_start,
@@ -719,6 +720,10 @@ int boot_get_setup_fit(struct bootm_headers *images, 
uint8_t arch,
  *                     name (e.g. "conf-1") or NULL to use the default. On
  *                     exit points to the selected configuration name.
  * @param arch         Expected architecture (IH_ARCH_...)
+ * @param load_op      Load-address policy for the base image only; see
+ *                     enum fit_load_op. FIT_LOAD_PREPARE ignores the address 
but
+ *                     still aligns/decompresses as needed. Overlays always use
+ *                     FIT_LOAD_IGNORED.
  * @param datap                Returns address of loaded image
  * @param lenp         Returns length of loaded image
  * @param ownedp       Returns true if the loaded image is separately allocated
@@ -729,7 +734,8 @@ int boot_get_setup_fit(struct bootm_headers *images, 
uint8_t arch,
  */
 int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
                     const char **fit_unamep, const char **fit_uname_configp,
-                    int arch, ulong *datap, ulong *lenp, bool *ownedp);
+                    int arch, enum fit_load_op load_op, ulong *datap,
+                    ulong *lenp, bool *ownedp);
 
 /**
  * fit_image_load() - load an image from a FIT

-- 
2.56.0

Reply via email to