[U-Boot] [PATCH 0/9] spl: Add full fit and u-boot dto support

Add support for using the full fitImage parsing code in SPL. This is useful ie. if we want SPL to verify the U-Boot proper fitImage using RSA signature. While verifying image signature can be added to the simplified fitImage handling code in U-Boot SPL, verifying configuration signatures becomes quite hairy. Thus, loading the entire fitImage and then applying the full fitImage handling code on it is far less intrusive change. The size of the SPL with full fitImage code obviously grows, so this might not be suitable for size-constrained systems.
The remaining four patches allow applying a DTO from fitImage onto the SPL's internal DT and restart the image loading process. The usecase here is ie. to put a replacement public key into the DTO, patch the /signature node and load offset node of the U-Boot SPL's DT and restart the image loading process to load U-Boot proper signed with the replacement private key. The user is then able to replace the DTO and sign own U-Boot fitImage without replacing the SPL binary itself.
Marek Vasut (9): fit: Fix CONFIG_FIT_SPL_PRINT fit: Add empty fit_print_contents() and fit_image_print() fit: Add standalone image type handling fit: Verify all configuration signatures spl: Add full fitImage support spl: Add support for overlaying U-Boot DT spl: Restart loading if load_image returns -EAGAIN spl: ram: Add support for fetching image position from control DT spl: spi: Add support for fetching image position from control DT
Kconfig | 17 +++++++++++ README | 2 +- common/image-fit.c | 36 +++++++++++++--------- common/spl/spl.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++- common/spl/spl_ram.c | 21 ++++++++++--- common/spl/spl_spi.c | 13 ++++++++ include/image.h | 1 + 7 files changed, 154 insertions(+), 22 deletions(-)

Rename CONFIG_FIT_SPL_PRINT to CONFIG_SPL_FIT_PRINT and add Kconfig entry for it.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- Kconfig | 6 ++++++ README | 2 +- common/image-fit.c | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/Kconfig b/Kconfig index 9b8a807799..cd32096f21 100644 --- a/Kconfig +++ b/Kconfig @@ -270,6 +270,12 @@ config SPL_FIT depends on SPL select SPL_OF_LIBFDT
+config SPL_FIT_PRINT + bool "Support FIT printing within SPL" + depends on SPL_FIT + help + Support printing the content of the fitImage in a verbose manner in SPL. + config SPL_FIT_SIGNATURE bool "Enable signature verification of FIT firmware within SPL" depends on SPL_DM diff --git a/README b/README index 93c7ea9665..20da964367 100644 --- a/README +++ b/README @@ -2848,7 +2848,7 @@ FIT uImage format: use an arch-specific makefile fragment instead, for example if more than one image needs to be produced.
- CONFIG_FIT_SPL_PRINT + CONFIG_SPL_FIT_PRINT Printing information about a FIT image adds quite a bit of code to SPL. So this is normally disabled in SPL. Use this option to re-enable it. This will affect the output of the diff --git a/common/image-fit.c b/common/image-fit.c index b785d8a36e..98334a0caa 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -143,7 +143,7 @@ int fit_get_subimage_count(const void *fit, int images_noffset) return count; }
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT) +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FIT_PRINT) /** * fit_print_contents - prints out the contents of the FIT format image * @fit: pointer to the FIT format image header @@ -460,7 +460,7 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) } }
-#endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT) */ +#endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FIT_PRINT) */
/** * fit_get_desc - get node description property

On 28 December 2017 at 05:06, Marek Vasut marex@denx.de wrote:
Rename CONFIG_FIT_SPL_PRINT to CONFIG_SPL_FIT_PRINT and add Kconfig entry for it.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
Kconfig | 6 ++++++ README | 2 +- common/image-fit.c | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

These functions may be needed in SPL, so add empty variants of them if CONFIG_SPL_FIT_PRINT is disabled.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- common/image-fit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/common/image-fit.c b/common/image-fit.c index 98334a0caa..f0e713d88f 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -459,7 +459,9 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) } } } - +#else +void fit_print_contents(const void *fit) { } +void fit_image_print(const void *fit, int image_noffset, const char *p) { } #endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FIT_PRINT) */
/**

On 28 December 2017 at 05:06, Marek Vasut marex@denx.de wrote:
These functions may be needed in SPL, so add empty variants of them if CONFIG_SPL_FIT_PRINT is disabled.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/image-fit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

Just add IH_TYPE_STANDALONE to fit_get_image_type_property().
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- common/image-fit.c | 2 ++ include/image.h | 1 + 2 files changed, 3 insertions(+)
diff --git a/common/image-fit.c b/common/image-fit.c index f0e713d88f..8871e2dcd3 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1699,6 +1699,8 @@ static const char *fit_get_image_type_property(int type) return FIT_LOADABLE_PROP; case IH_TYPE_FPGA: return FIT_FPGA_PROP; + case IH_TYPE_STANDALONE: + return FIT_STANDALONE_PROP; }
return "unknown"; diff --git a/include/image.h b/include/image.h index a128a623e5..82799fc512 100644 --- a/include/image.h +++ b/include/image.h @@ -907,6 +907,7 @@ int bootz_setup(ulong image, ulong *start, ulong *end); #define FIT_DEFAULT_PROP "default" #define FIT_SETUP_PROP "setup" #define FIT_FPGA_PROP "fpga" +#define FIT_STANDALONE_PROP "standalone"
#define FIT_MAX_HASH_LEN HASH_MAX_DIGEST_SIZE

On 28 December 2017 at 05:06, Marek Vasut marex@denx.de wrote:
Just add IH_TYPE_STANDALONE to fit_get_image_type_property().
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/image-fit.c | 2 ++ include/image.h | 1 + 2 files changed, 3 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Rather than verifying configuration signature of the configuration node containing the kernel image types, verify all configuration nodes, even those that do not contain kernel images. This is useful when the nodes contain ie. standalone OSes or U-Boot.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- common/image-fit.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c index 8871e2dcd3..f559032691 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1766,22 +1766,24 @@ int fit_image_load(bootm_headers_t *images, ulong addr, } fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL); printf(" Using '%s' configuration\n", fit_base_uname_config); - if (image_type == IH_TYPE_KERNEL) { - /* Remember (and possibly verify) this config */ + /* Remember this config */ + if (image_type == IH_TYPE_KERNEL) images->fit_uname_cfg = fit_base_uname_config; - if (IMAGE_ENABLE_VERIFY && images->verify) { - puts(" Verifying Hash Integrity ... "); - if (fit_config_verify(fit, cfg_noffset)) { - puts("Bad Data Hash\n"); - bootstage_error(bootstage_id + - BOOTSTAGE_SUB_HASH); - return -EACCES; - } - puts("OK\n"); + + /* Verify this config */ + if (IMAGE_ENABLE_VERIFY && images->verify) { + puts(" Verifying Hash Integrity ... "); + if (fit_config_verify(fit, cfg_noffset)) { + puts("Bad Data Hash\n"); + bootstage_error(bootstage_id + + BOOTSTAGE_SUB_HASH); + return -EACCES; } - bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); + puts("OK\n"); }
+ bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); + noffset = fit_conf_get_prop_node(fit, cfg_noffset, prop_name); fit_uname = fit_get_name(fit, noffset, NULL);

On 28 December 2017 at 05:06, Marek Vasut marex@denx.de wrote:
Rather than verifying configuration signature of the configuration node containing the kernel image types, verify all configuration nodes, even those that do not contain kernel images. This is useful when the nodes contain ie. standalone OSes or U-Boot.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/image-fit.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c index 8871e2dcd3..f559032691 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1766,22 +1766,24 @@ int fit_image_load(bootm_headers_t *images, ulong addr, } fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL); printf(" Using '%s' configuration\n", fit_base_uname_config);
if (image_type == IH_TYPE_KERNEL) {
/* Remember (and possibly verify) this config */
/* Remember this config */
if (image_type == IH_TYPE_KERNEL) images->fit_uname_cfg = fit_base_uname_config;
if (IMAGE_ENABLE_VERIFY && images->verify) {
puts(" Verifying Hash Integrity ... ");
if (fit_config_verify(fit, cfg_noffset)) {
puts("Bad Data Hash\n");
bootstage_error(bootstage_id +
BOOTSTAGE_SUB_HASH);
return -EACCES;
}
puts("OK\n");
/* Verify this config */
if (IMAGE_ENABLE_VERIFY && images->verify) {
puts(" Verifying Hash Integrity ... ");
if (fit_config_verify(fit, cfg_noffset)) {
puts("Bad Data Hash\n");
bootstage_error(bootstage_id +
BOOTSTAGE_SUB_HASH);
return -EACCES; }
bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
puts("OK\n");
What is this for? Doesn't the above function print the hash type or an error?
}
bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
noffset = fit_conf_get_prop_node(fit, cfg_noffset, prop_name); fit_uname = fit_get_name(fit, noffset, NULL);
-- 2.15.0
Regards, Simon

Add support for loading U-Boot and optionally FDT from a fitImage in SPL by using the full fitImage support from U-Boot. While we do have limited SPL loading support in SPL with a small footprint, it is missing a lot of important features, like checking signatures. This support has all the fitImage features, while the footprint is obviously larger.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- Kconfig | 11 +++++++++++ common/spl/spl.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+)
diff --git a/Kconfig b/Kconfig index cd32096f21..4d0c1a01c1 100644 --- a/Kconfig +++ b/Kconfig @@ -293,6 +293,17 @@ config SPL_LOAD_FIT particular it can handle selecting from multiple device tree and passing the correct one to U-Boot.
+config SPL_LOAD_FIT_FULL + bool "Enable SPL loading U-Boot as a FIT" + select SPL_FIT + help + Normally with the SPL framework a legacy image is generated as part + of the build. This contains U-Boot along with information as to + where it should be loaded. This option instead enables generation + of a FIT (Flat Image Tree) which provides more flexibility. In + particular it can handle selecting from multiple device tree + and passing the correct one to U-Boot. + config SPL_FIT_IMAGE_POST_PROCESS bool "Enable post-processing of FIT artifacts after loading by the SPL" depends on SPL_LOAD_FIT diff --git a/common/spl/spl.c b/common/spl/spl.c index 76c1963611..d429ea2c82 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -139,9 +139,52 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) spl_image->name = "U-Boot"; }
+#ifdef CONFIG_SPL_LOAD_FIT_FULL +/* Parse and load full fitImage in SPL */ +static int spl_load_fit_image(struct spl_image_info *spl_image, + const struct image_header *header) + +{ + bootm_headers_t images; + const char *fit_uname_config = NULL; + const char *fit_uname_fdt = FIT_FDT_PROP; + ulong fw_data = 0, dt_data = 0; + ulong fw_len = 0, dt_len = 0; + int ret; + + ret = fit_image_load(&images, (ulong)header, + NULL, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, + FIT_LOAD_REQUIRED, &fw_data, &fw_len); + if (ret < 0) + return ret; + + spl_image->size = fw_len; + spl_image->entry_point = fw_data; + spl_image->load_addr = fw_data; + spl_image->os = IH_OS_U_BOOT; + spl_image->name = "U-Boot"; + + debug("spl: payload image: %.*s load addr: 0x%lx size: %d\n", + (int)sizeof(spl_image->name), spl_image->name, + spl_image->load_addr, spl_image->size); + + ret = fit_image_load(&images, (ulong)header, + &fit_uname_fdt, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, + FIT_LOAD_OPTIONAL, &dt_data, &dt_len); + return 0; +} +#endif + int spl_parse_image_header(struct spl_image_info *spl_image, const struct image_header *header) { +#ifdef CONFIG_SPL_LOAD_FIT_FULL + int ret = spl_load_fit_image(spl_image, header); + if (!ret) + return ret; +#endif if (image_get_magic(header) == IH_MAGIC) { #ifdef CONFIG_SPL_LEGACY_IMAGE_SUPPORT u32 header_size = sizeof(struct image_header);

Hi Marek,
Add support for loading U-Boot and optionally FDT from a fitImage in SPL by using the full fitImage support from U-Boot. While we do have limited SPL loading support in SPL with a small footprint, it is missing a lot of important features, like checking signatures. This support has all the fitImage features, while the footprint is obviously larger.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
Kconfig | 11 +++++++++++ common/spl/spl.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+)
diff --git a/Kconfig b/Kconfig index cd32096f21..4d0c1a01c1 100644 --- a/Kconfig +++ b/Kconfig @@ -293,6 +293,17 @@ config SPL_LOAD_FIT particular it can handle selecting from multiple device tree and passing the correct one to U-Boot.
+config SPL_LOAD_FIT_FULL
- bool "Enable SPL loading U-Boot as a FIT"
- select SPL_FIT
- help
Normally with the SPL framework a legacy image is
generated as part
of the build. This contains U-Boot along with information
as to
where it should be loaded. This option instead enables
generation
of a FIT (Flat Image Tree) which provides more
flexibility. In
particular it can handle selecting from multiple device
tree
and passing the correct one to U-Boot.
config SPL_FIT_IMAGE_POST_PROCESS bool "Enable post-processing of FIT artifacts after loading by the SPL" depends on SPL_LOAD_FIT diff --git a/common/spl/spl.c b/common/spl/spl.c index 76c1963611..d429ea2c82 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -139,9 +139,52 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) spl_image->name = "U-Boot"; }
+#ifdef CONFIG_SPL_LOAD_FIT_FULL +/* Parse and load full fitImage in SPL */ +static int spl_load_fit_image(struct spl_image_info *spl_image,
const struct image_header *header)
^^^ - this blank line can be removed.
+{
- bootm_headers_t images;
- const char *fit_uname_config = NULL;
- const char *fit_uname_fdt = FIT_FDT_PROP;
- ulong fw_data = 0, dt_data = 0;
- ulong fw_len = 0, dt_len = 0;
- int ret;
- ret = fit_image_load(&images, (ulong)header,
NULL, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
FIT_LOAD_REQUIRED, &fw_data, &fw_len);
- if (ret < 0)
return ret;
- spl_image->size = fw_len;
- spl_image->entry_point = fw_data;
- spl_image->load_addr = fw_data;
- spl_image->os = IH_OS_U_BOOT;
- spl_image->name = "U-Boot";
- debug("spl: payload image: %.*s load addr: 0x%lx size: %d\n",
(int)sizeof(spl_image->name), spl_image->name,
spl_image->load_addr, spl_image->size);
- ret = fit_image_load(&images, (ulong)header,
&fit_uname_fdt, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1,
FIT_LOAD_OPTIONAL, &dt_data, &dt_len);
- return 0;
+} +#endif
int spl_parse_image_header(struct spl_image_info *spl_image, const struct image_header *header) { +#ifdef CONFIG_SPL_LOAD_FIT_FULL
- int ret = spl_load_fit_image(spl_image, header);
- if (!ret)
return ret;
+#endif if (image_get_magic(header) == IH_MAGIC) { #ifdef CONFIG_SPL_LEGACY_IMAGE_SUPPORT u32 header_size = sizeof(struct image_header);
Despite this minor thing:
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

Hi Marek,
On 28 December 2017 at 05:06, Marek Vasut marex@denx.de wrote:
Add support for loading U-Boot and optionally FDT from a fitImage in SPL by using the full fitImage support from U-Boot. While we do have limited SPL loading support in SPL with a small footprint, it is missing a lot of important features, like checking signatures. This support has all the fitImage features, while the footprint is obviously larger.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
Kconfig | 11 +++++++++++ common/spl/spl.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+)
diff --git a/Kconfig b/Kconfig index cd32096f21..4d0c1a01c1 100644 --- a/Kconfig +++ b/Kconfig @@ -293,6 +293,17 @@ config SPL_LOAD_FIT particular it can handle selecting from multiple device tree and passing the correct one to U-Boot.
+config SPL_LOAD_FIT_FULL
bool "Enable SPL loading U-Boot as a FIT"
select SPL_FIT
help
Normally with the SPL framework a legacy image is generated as part
of the build. This contains U-Boot along with information as to
where it should be loaded. This option instead enables generation
generation? Do you mean loading?
of a FIT (Flat Image Tree) which provides more flexibility. In
particular it can handle selecting from multiple device tree
trees
and passing the correct one to U-Boot.
Can you reword this to mention the 'limited' FIT support in SPL, and how to enable that. There needs to be a cross-reference between the two in the docs.
config SPL_FIT_IMAGE_POST_PROCESS bool "Enable post-processing of FIT artifacts after loading by the SPL" depends on SPL_LOAD_FIT diff --git a/common/spl/spl.c b/common/spl/spl.c index 76c1963611..d429ea2c82 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -139,9 +139,52 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) spl_image->name = "U-Boot"; }
+#ifdef CONFIG_SPL_LOAD_FIT_FULL +/* Parse and load full fitImage in SPL */ +static int spl_load_fit_image(struct spl_image_info *spl_image,
const struct image_header *header)
+{
bootm_headers_t images;
const char *fit_uname_config = NULL;
const char *fit_uname_fdt = FIT_FDT_PROP;
ulong fw_data = 0, dt_data = 0;
ulong fw_len = 0, dt_len = 0;
int ret;
ret = fit_image_load(&images, (ulong)header,
NULL, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
FIT_LOAD_REQUIRED, &fw_data, &fw_len);
if (ret < 0)
return ret;
spl_image->size = fw_len;
spl_image->entry_point = fw_data;
spl_image->load_addr = fw_data;
spl_image->os = IH_OS_U_BOOT;
spl_image->name = "U-Boot";
debug("spl: payload image: %.*s load addr: 0x%lx size: %d\n",
(int)sizeof(spl_image->name), spl_image->name,
spl_image->load_addr, spl_image->size);
ret = fit_image_load(&images, (ulong)header,
&fit_uname_fdt, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1,
FIT_LOAD_OPTIONAL, &dt_data, &dt_len);
return 0;
+} +#endif
int spl_parse_image_header(struct spl_image_info *spl_image, const struct image_header *header) { +#ifdef CONFIG_SPL_LOAD_FIT_FULL
Can you use if (IS_ENABLED()) and thus avoid the #ifdef above?
int ret = spl_load_fit_image(spl_image, header);
if (!ret)
return ret;
+#endif if (image_get_magic(header) == IH_MAGIC) { #ifdef CONFIG_SPL_LEGACY_IMAGE_SUPPORT u32 header_size = sizeof(struct image_header); -- 2.15.0
Is there a test for this code?
Regards, Simon

Add support for loading fitImage with device tree overlay image, which is applied to the U-Boot's own device tree. Once the DT is applied, the fitImage loading process is restarted.
This patch allows a usecase where the DTO patches ie. load address in the U-Boot's DT or patches in a new public key for authenticating the subsequently loaded fitImages.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- common/spl/spl.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index d429ea2c82..2444abbb08 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -140,6 +140,38 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) }
#ifdef CONFIG_SPL_LOAD_FIT_FULL +#ifdef CONFIG_OF_LIBFDT_OVERLAY +static int spl_fit_overlay_uboot_fdt_full(const struct image_header *header) +{ + bootm_headers_t images; + const char *fit_uname_config = NULL; + const char *fit_uname_dtbo = "u-boot-dtbo"; + ulong dto_data = 0; + ulong dto_len = 0; + int ret; + + ret = fit_image_load(&images, (ulong)header, + &fit_uname_dtbo, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, + FIT_LOAD_OPTIONAL, &dto_data, &dto_len); + if (ret < 0) + return 0; + + ret = fdt_overlay_apply_verbose((struct fdt_header *)gd->fdt_blob, + (void *)dto_data); + if (ret) + hang(); + + /* Restart the loading process to cater for the DT changes */ + return -EAGAIN; +} +#else +static int spl_fit_overlay_uboot_fdt_full(const struct image_header *header) +{ + return 0; +} +#endif + /* Parse and load full fitImage in SPL */ static int spl_load_fit_image(struct spl_image_info *spl_image, const struct image_header *header) @@ -152,6 +184,10 @@ static int spl_load_fit_image(struct spl_image_info *spl_image, ulong fw_len = 0, dt_len = 0; int ret;
+ ret = spl_fit_overlay_uboot_fdt_full(header); + if (ret) + return ret; + ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, @@ -182,7 +218,7 @@ int spl_parse_image_header(struct spl_image_info *spl_image, { #ifdef CONFIG_SPL_LOAD_FIT_FULL int ret = spl_load_fit_image(spl_image, header); - if (!ret) + if (!ret || ret == -EAGAIN) return ret; #endif if (image_get_magic(header) == IH_MAGIC) {

Hi Marek,
Add support for loading fitImage with device tree overlay image, which is applied to the U-Boot's own device tree. Once the DT is applied, the fitImage loading process is restarted.
This patch allows a usecase where the DTO patches ie. load address in the U-Boot's DT or patches in a new public key for authenticating the subsequently loaded fitImages.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index d429ea2c82..2444abbb08 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -140,6 +140,38 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) }
#ifdef CONFIG_SPL_LOAD_FIT_FULL +#ifdef CONFIG_OF_LIBFDT_OVERLAY +static int spl_fit_overlay_uboot_fdt_full(const struct image_header *header) +{
- bootm_headers_t images;
- const char *fit_uname_config = NULL;
- const char *fit_uname_dtbo = "u-boot-dtbo";
- ulong dto_data = 0;
- ulong dto_len = 0;
- int ret;
- ret = fit_image_load(&images, (ulong)header,
&fit_uname_dtbo, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1,
FIT_LOAD_OPTIONAL, &dto_data, &dto_len);
- if (ret < 0)
return 0;
- ret = fdt_overlay_apply_verbose((struct fdt_header
*)gd->fdt_blob,
(void *)dto_data);
- if (ret)
hang();
- /* Restart the loading process to cater for the DT changes */
- return -EAGAIN;
+} +#else +static int spl_fit_overlay_uboot_fdt_full(const struct image_header *header) +{
- return 0;
+} +#endif
/* Parse and load full fitImage in SPL */ static int spl_load_fit_image(struct spl_image_info *spl_image, const struct image_header *header) @@ -152,6 +184,10 @@ static int spl_load_fit_image(struct spl_image_info *spl_image, ulong fw_len = 0, dt_len = 0; int ret;
- ret = spl_fit_overlay_uboot_fdt_full(header);
- if (ret)
return ret;
- ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
@@ -182,7 +218,7 @@ int spl_parse_image_header(struct spl_image_info *spl_image, { #ifdef CONFIG_SPL_LOAD_FIT_FULL int ret = spl_load_fit_image(spl_image, header);
- if (!ret)
- if (!ret || ret == -EAGAIN) return ret;
#endif if (image_get_magic(header) == IH_MAGIC) {
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

Hi Marek,
On 28 December 2017 at 05:06, Marek Vasut marex@denx.de wrote:
Add support for loading fitImage with device tree overlay image, which is applied to the U-Boot's own device tree. Once the DT is applied, the fitImage loading process is restarted.
This patch allows a usecase where the DTO patches ie. load address in the U-Boot's DT or patches in a new public key for authenticating the subsequently loaded fitImages.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
This needs a test.
diff --git a/common/spl/spl.c b/common/spl/spl.c index d429ea2c82..2444abbb08 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -140,6 +140,38 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) }
#ifdef CONFIG_SPL_LOAD_FIT_FULL +#ifdef CONFIG_OF_LIBFDT_OVERLAY
Can we avoid this by doing
if (IS_ENABLED(...))
below?
+static int spl_fit_overlay_uboot_fdt_full(const struct image_header *header) +{
bootm_headers_t images;
const char *fit_uname_config = NULL;
const char *fit_uname_dtbo = "u-boot-dtbo";
ulong dto_data = 0;
ulong dto_len = 0;
int ret;
ret = fit_image_load(&images, (ulong)header,
&fit_uname_dtbo, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1,
FIT_LOAD_OPTIONAL, &dto_data, &dto_len);
if (ret < 0)
return 0;
ret = fdt_overlay_apply_verbose((struct fdt_header *)gd->fdt_blob,
(void *)dto_data);
if (ret)
hang();
/* Restart the loading process to cater for the DT changes */
return -EAGAIN;
+} +#else +static int spl_fit_overlay_uboot_fdt_full(const struct image_header *header) +{
return 0;
+} +#endif
/* Parse and load full fitImage in SPL */ static int spl_load_fit_image(struct spl_image_info *spl_image, const struct image_header *header) @@ -152,6 +184,10 @@ static int spl_load_fit_image(struct spl_image_info *spl_image, ulong fw_len = 0, dt_len = 0; int ret;
ret = spl_fit_overlay_uboot_fdt_full(header);
if (ret)
return ret;
ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
@@ -182,7 +218,7 @@ int spl_parse_image_header(struct spl_image_info *spl_image, { #ifdef CONFIG_SPL_LOAD_FIT_FULL int ret = spl_load_fit_image(spl_image, header);
if (!ret)
if (!ret || ret == -EAGAIN) return ret;
#endif if (image_get_magic(header) == IH_MAGIC) { -- 2.15.0
Regards, Simon

If the loader->load_image returns -EAGAIN, it is an indication the loading process should restart the loading, possible due to DTO being applied on the U-Boot's DT. Restart the loading until the loader stops returning -EAGAIN.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- common/spl/spl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index 2444abbb08..27f44c27b0 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -413,11 +413,16 @@ static int spl_load_image(struct spl_image_info *spl_image, struct spl_image_loader *loader) { struct spl_boot_device bootdev; + int ret;
bootdev.boot_device = loader->boot_device; bootdev.boot_device_name = NULL;
- return loader->load_image(spl_image, &bootdev); + do { + ret = loader->load_image(spl_image, &bootdev); + } while (ret == -EAGAIN); + + return ret; }
/**

Hi Marek,
If the loader->load_image returns -EAGAIN, it is an indication the loading process should restart the loading, possible due to DTO being applied on the U-Boot's DT. Restart the loading until the loader stops returning -EAGAIN.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index 2444abbb08..27f44c27b0 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -413,11 +413,16 @@ static int spl_load_image(struct spl_image_info *spl_image, struct spl_image_loader *loader) { struct spl_boot_device bootdev;
int ret;
bootdev.boot_device = loader->boot_device; bootdev.boot_device_name = NULL;
- return loader->load_image(spl_image, &bootdev);
- do {
ret = loader->load_image(spl_image, &bootdev);
- } while (ret == -EAGAIN);
Maybe it would be good to have some counter or timeout (although, I doubt if any timer is set properly so early) to give the user some information if we fail?
- return ret;
}
/**
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

On 12/28/2017 03:25 PM, Lukasz Majewski wrote:
Hi Marek,
If the loader->load_image returns -EAGAIN, it is an indication the loading process should restart the loading, possible due to DTO being applied on the U-Boot's DT. Restart the loading until the loader stops returning -EAGAIN.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index 2444abbb08..27f44c27b0 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -413,11 +413,16 @@ static int spl_load_image(struct spl_image_info *spl_image, struct spl_image_loader *loader) { struct spl_boot_device bootdev;
int ret;
bootdev.boot_device = loader->boot_device; bootdev.boot_device_name = NULL;
- return loader->load_image(spl_image, &bootdev);
- do {
ret = loader->load_image(spl_image, &bootdev);
- } while (ret == -EAGAIN);
Maybe it would be good to have some counter or timeout (although, I doubt if any timer is set properly so early) to give the user some information if we fail?
If you fail, ret won't be EAGAIN and you'd exit the loop and propagate the error.

Add support for fetching the image position in RAM from control DT rather than hard-coding it. While doing so, return the return value of spl_parse_header_image() to make it possible to test application of DTOs on U-Boot's control DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- common/spl/spl_ram.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index fa8c768773..c88d09ba04 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -14,12 +14,14 @@ #include <binman_sym.h> #include <mapmem.h> #include <spl.h> -#include <libfdt.h> +#include <fdtdec.h>
#ifndef CONFIG_SPL_LOAD_FIT_ADDRESS # define CONFIG_SPL_LOAD_FIT_ADDRESS 0 #endif
+DECLARE_GLOBAL_DATA_PTR; + static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { @@ -33,7 +35,12 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { struct image_header *header; + unsigned image_offs;
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + image_offs = fdtdec_get_config_int(gd->fdt_blob, + "u-boot,spl-image-offset", 0); +#endif header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS;
#if defined(CONFIG_SPL_DFU_SUPPORT) @@ -48,7 +55,7 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.bl_len = 1; load.read = spl_ram_load_read; - spl_load_simple_fit(spl_image, &load, 0, header); + return spl_load_simple_fit(spl_image, &load, 0, header); } else { ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos);
@@ -64,12 +71,16 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, * No binman support or no information. For now, fix it * to the address pointed to by U-Boot. */ - u_boot_pos = CONFIG_SYS_TEXT_BASE - - sizeof(struct image_header); + if (image_offs) + u_boot_pos = image_offs; + else + u_boot_pos = CONFIG_SYS_TEXT_BASE - + sizeof(struct image_u_boot_pos); } header = (struct image_header *)map_sysmem(u_boot_pos, 0);
- spl_parse_image_header(spl_image, header); + + return spl_parse_image_header(spl_image, header); }
return 0;

Hi Marek,
Add support for fetching the image position in RAM from control DT rather than hard-coding it. While doing so, return the return value of spl_parse_header_image() to make it possible to test application of DTOs on U-Boot's control DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl_ram.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index fa8c768773..c88d09ba04 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -14,12 +14,14 @@ #include <binman_sym.h> #include <mapmem.h> #include <spl.h> -#include <libfdt.h> +#include <fdtdec.h>
#ifndef CONFIG_SPL_LOAD_FIT_ADDRESS # define CONFIG_SPL_LOAD_FIT_ADDRESS 0 #endif
+DECLARE_GLOBAL_DATA_PTR;
static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { @@ -33,7 +35,12 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { struct image_header *header;
- unsigned image_offs;
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
- image_offs = fdtdec_get_config_int(gd->fdt_blob,
"u-boot,spl-image-offset", 0); +#endif header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS;
#if defined(CONFIG_SPL_DFU_SUPPORT) @@ -48,7 +55,7 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.bl_len = 1; load.read = spl_ram_load_read;
spl_load_simple_fit(spl_image, &load, 0, header);
return spl_load_simple_fit(spl_image, &load, 0,
header); } else { ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos); @@ -64,12 +71,16 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, * No binman support or no information. For now, fix it * to the address pointed to by U-Boot. */
u_boot_pos = CONFIG_SYS_TEXT_BASE -
sizeof(struct image_header);
if (image_offs)
u_boot_pos = image_offs;
else
u_boot_pos = CONFIG_SYS_TEXT_BASE -
sizeof(struct
image_u_boot_pos); } header = (struct image_header *)map_sysmem(u_boot_pos, 0);
spl_parse_image_header(spl_image, header);
return spl_parse_image_header(spl_image, header);
}
return 0;
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

Hi Marek,
On 28 December 2017 at 05:06, Marek Vasut marex@denx.de wrote:
Add support for fetching the image position in RAM from control DT rather than hard-coding it. While doing so, return the return value of spl_parse_header_image() to make it possible to test application of DTOs on U-Boot's control DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl_ram.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
Should this use the binman support instead? It seems to already do what you want.
If not, this should have docs and a test.
Regards, Simon

Add support for fetching the image position in RAM from control DT rather than hard-coding it. While doing so, return the return value of spl_parse_header_image() to make it possible to test application of DTOs on U-Boot's control DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org --- common/spl/spl_spi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 42880d56b9..c2613a494b 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -75,6 +75,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, unsigned payload_offs = CONFIG_SYS_SPI_U_BOOT_OFFS; struct spi_flash *flash; struct image_header *header; + unsigned image_offs, image_size;
/* * Load U-Boot image from SPI flash into RAM @@ -96,6 +97,18 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, payload_offs = fdtdec_get_config_int(gd->fdt_blob, "u-boot,spl-payload-offset", payload_offs); + image_offs = fdtdec_get_config_int(gd->fdt_blob, + "u-boot,spl-image-offset", 0); + image_size = fdtdec_get_config_int(gd->fdt_blob, + "u-boot,spl-image-size", 0); + if (image_size) { + err = spi_flash_read(flash, image_offs, + image_size, + (void *)CONFIG_SYS_TEXT_BASE); + if (err) + return err; + return spl_parse_image_header(spl_image, header); + } #endif
#ifdef CONFIG_SPL_OS_BOOT

Hi Marek,
Add support for fetching the image position in RAM from control DT rather than hard-coding it. While doing so, return the return value of spl_parse_header_image() to make it possible to test application of DTOs on U-Boot's control DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl_spi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 42880d56b9..c2613a494b 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -75,6 +75,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, unsigned payload_offs = CONFIG_SYS_SPI_U_BOOT_OFFS; struct spi_flash *flash; struct image_header *header;
unsigned image_offs, image_size;
/*
- Load U-Boot image from SPI flash into RAM
@@ -96,6 +97,18 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, payload_offs = fdtdec_get_config_int(gd->fdt_blob, "u-boot,spl-payload-offset", payload_offs);
- image_offs = fdtdec_get_config_int(gd->fdt_blob,
"u-boot,spl-image-offset", 0);
- image_size = fdtdec_get_config_int(gd->fdt_blob,
"u-boot,spl-image-size",
0);
- if (image_size) {
err = spi_flash_read(flash, image_offs,
image_size,
(void *)CONFIG_SYS_TEXT_BASE);
if (err)
return err;
return spl_parse_image_header(spl_image, header);
- }
#endif
#ifdef CONFIG_SPL_OS_BOOT
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

Hi Marek,
On 28 December 2017 at 07:29, Lukasz Majewski lukma@denx.de wrote:
Hi Marek,
Add support for fetching the image position in RAM from control DT rather than hard-coding it. While doing so, return the return value of spl_parse_header_image() to make it possible to test application of DTOs on U-Boot's control DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Pantelis Antoniou pantelis.antoniou@konsulko.com Cc: Simon Glass sjg@chromium.org
common/spl/spl_spi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
See comments on previous patch about using binman / adding docs/test.
Regards, Simon
participants (3)
-
Lukasz Majewski
-
Marek Vasut
-
Simon Glass