[U-Boot] [PATCH v4 0/9] spl: dm: Make it possible for the SPL to pick its own DTB from a FIT

Following the RFC, here is the series implementing the mechanism in a cleaner way. The idea is that the SPL may take advantage of selecting its DTB from a pool of available DTBs. To do that several DTBs are embedded in a compressed FIT image appended at the end of the SPL. The patch is done in such way that this mechanism can easily be extended to other ways of loading the DTBs.
Here are some numbers: +----------------------------------------+ | Size |delta |boot-time| delta | | (bytes) |(bytes) |(ms) | (ms) | +---------------------------------------------------------------+ | reference | 120185 | | 1331 | | +---------------------------------------------------------------+ | feature | | | | | | deactiVated | 120185 | 0 | 1330 | -1 | +---------------------------------------------------------------+ | 1 DTB LZO | 120208 | 23 | 1331 | 0 | +---------------------------------------------------------------+ | 4 DTB LZO | 120810 | 625 | 1336 | 5 | +---------------------------------------------------------------+ | 4 DTB LZO | | | | | | no malloc | 120746 | 561 | 1343 | 12 | +---------------------------------------------------------------+ | 4 DTB GZIP | 128552 | 8367 | 1353 | 22 | +---------------------------------------------------------------+ | 4 DTB No comp | 132352 | 12167 | 1351 | 20 | +----------------------+----------+----------+---------+--------+
changes since v3: - Added reviewed-by tags - Fixed nits and spelling mistakes reported by Simon G. - updated the help in Kconfig to take in account commit f1896c ("spl: make SPL and normal u-boot stage use independent SYS_MALLOC_F_LEN")
changes since v2: - rebased on u-boot/master - improved help in Kconfig for the compression options in SPL - improved commit message for patch #1 - Added some comments to describe locate_dtb_in_fit() and fit_find_config_node() - Added a description of the mecanism in a README
changes since v1: - improved help in Kconfig for the SPL_MULTI_DTB_FIT option - Added "reviewed-by" tags
changes since RFC: - split the RFC patch in several patches. - leverage work from Cooper Jr., Franklin (CONFIG_FIT_EMBED) as a big part of the code is similar. Rename CONFIG_FIT_EMBED as CONFIG_MULTI_DTB_FIT to prevent confusion with CONFIG_OF_EMBED. - use the default configuration if no match is provided by board_fit_config_name_match(). note that this is generic not just for this feature. - provide an option to not use dynamic memory allocation. - added a patch related to board detection on omap that's required to take advantage of this feature.
Jean-Jacques Hiblot (9): dts: renamed FIT_EMBED to MULTI_DTB_FIT and moved it to the dts Kconfig fit: use 'const' for the input of fdt_offset() and locate_dtb_in_fit() fit: fixed bug in locate_dtb_in_fit() fit: If no matching config is found in fit_find_config_node(), use the default one lzo: add a function to check the validity of the header gzip: add a function to parse the header lib: allow building lzo and gunzip for the SPL spl: dm: Make it possible for the SPL to pick its own DTB from a FIT omap: detect board before spl_early_init()
Makefile | 2 +- arch/arm/mach-omap2/hwinit-common.c | 4 +- board/ti/ks2_evm/board_k2e.c | 2 +- board/ti/ks2_evm/board_k2g.c | 2 +- board/ti/ks2_evm/board_k2hk.c | 2 +- board/ti/ks2_evm/board_k2l.c | 2 +- common/Kconfig | 16 ------ common/Makefile | 2 +- common/boot_fit.c | 6 +-- common/common_fit.c | 20 +++++++ configs/k2e_evm_defconfig | 2 +- configs/k2g_evm_defconfig | 2 +- configs/k2hk_evm_defconfig | 2 +- configs/k2l_evm_defconfig | 2 +- doc/README.multi-dtb-fit | 49 +++++++++++++++++ dts/Kconfig | 103 +++++++++++++++++++++++++++++++++++- include/boot_fit.h | 9 +++- include/common.h | 1 + include/image.h | 13 +++++ include/linux/lzo.h | 3 ++ lib/Kconfig | 17 +++++- lib/Makefile | 6 +-- lib/fdtdec.c | 85 +++++++++++++++++++++++++---- lib/gunzip.c | 15 ++++-- lib/lzo/lzo1x_decompress.c | 21 ++++++-- scripts/Makefile.spl | 35 +++++++++++- 26 files changed, 369 insertions(+), 54 deletions(-) create mode 100644 doc/README.multi-dtb-fit

CONFIG_FIT_EMBED might be confused with CONFIG_OF_EMBED, rename it MULTI_DTB_FIT as it is able to get a DTB from a FIT image containing multiple DTBs. Also move the option to the Kconfig dedicated to the DTS options and create a README for this feature.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org ---
no change since v3
Makefile | 2 +- board/ti/ks2_evm/board_k2e.c | 2 +- board/ti/ks2_evm/board_k2g.c | 2 +- board/ti/ks2_evm/board_k2hk.c | 2 +- board/ti/ks2_evm/board_k2l.c | 2 +- common/Kconfig | 16 ---------------- common/Makefile | 2 +- configs/k2e_evm_defconfig | 2 +- configs/k2g_evm_defconfig | 2 +- configs/k2hk_evm_defconfig | 2 +- configs/k2l_evm_defconfig | 2 +- doc/README.multi-dtb-fit | 9 +++++++++ dts/Kconfig | 20 +++++++++++++++++++- lib/fdtdec.c | 2 +- 14 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 doc/README.multi-dtb-fit
diff --git a/Makefile b/Makefile index 50a002e..d5869e1 100644 --- a/Makefile +++ b/Makefile @@ -876,7 +876,7 @@ dts/dt.dtb: checkdtc u-boot quiet_cmd_copy = COPY $@ cmd_copy = cp $< $@
-ifeq ($(CONFIG_FIT_EMBED),y) +ifeq ($(CONFIG_MULTI_DTB_FIT),y)
fit-dtb.blob: dts/dt.dtb FORCE $(call if_changed,mkimage) diff --git a/board/ti/ks2_evm/board_k2e.c b/board/ti/ks2_evm/board_k2e.c index 266a66b..6c77d91 100644 --- a/board/ti/ks2_evm/board_k2e.c +++ b/board/ti/ks2_evm/board_k2e.c @@ -166,7 +166,7 @@ int get_num_eth_ports(void) } #endif
-#if defined(CONFIG_FIT_EMBED) +#if defined(CONFIG_MULTI_DTB_FIT) int board_fit_config_name_match(const char *name) { if (!strcmp(name, "keystone-k2e-evm")) diff --git a/board/ti/ks2_evm/board_k2g.c b/board/ti/ks2_evm/board_k2g.c index 2160576..b1dd606 100644 --- a/board/ti/ks2_evm/board_k2g.c +++ b/board/ti/ks2_evm/board_k2g.c @@ -216,7 +216,7 @@ int board_mmc_init(bd_t *bis) } #endif
-#if defined(CONFIG_FIT_EMBED) +#if defined(CONFIG_MULTI_DTB_FIT) int board_fit_config_name_match(const char *name) { bool eeprom_read = board_ti_was_eeprom_read(); diff --git a/board/ti/ks2_evm/board_k2hk.c b/board/ti/ks2_evm/board_k2hk.c index c733099..e99e635 100644 --- a/board/ti/ks2_evm/board_k2hk.c +++ b/board/ti/ks2_evm/board_k2hk.c @@ -150,7 +150,7 @@ int board_early_init_f(void) } #endif
-#if defined(CONFIG_FIT_EMBED) +#if defined(CONFIG_MULTI_DTB_FIT) int board_fit_config_name_match(const char *name) { if (!strcmp(name, "keystone-k2hk-evm")) diff --git a/board/ti/ks2_evm/board_k2l.c b/board/ti/ks2_evm/board_k2l.c index 166367b..c65f331 100644 --- a/board/ti/ks2_evm/board_k2l.c +++ b/board/ti/ks2_evm/board_k2l.c @@ -138,7 +138,7 @@ int board_early_init_f(void) } #endif
-#if defined(CONFIG_FIT_EMBED) +#if defined(CONFIG_MULTI_DTB_FIT) int board_fit_config_name_match(const char *name) { if (!strcmp(name, "keystone-k2l-evm")) diff --git a/common/Kconfig b/common/Kconfig index 0983891..3c7e3a2 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -810,22 +810,6 @@ config SYS_STDIO_DEREGISTER
endmenu
-config DTB_RESELECT - bool "Support swapping dtbs at a later point in boot" - depends on FIT_EMBED - help - It is possible during initial boot you may need to use a generic - dtb until you can fully determine the board your running on. This - config allows boards to implement a function at a later point - during boot to switch to the "correct" dtb. - -config FIT_EMBED - bool "Support a FIT image embedded in the U-boot image" - help - This option provides hooks to allow U-boot to parse an - appended FIT image and enable board specific code to then select - the correct DTB to be used. - config DEFAULT_FDT_FILE string "Default fdt file" help diff --git a/common/Makefile b/common/Makefile index 60681c8..3bff64f 100644 --- a/common/Makefile +++ b/common/Makefile @@ -148,7 +148,7 @@ obj-y += image.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o obj-$(CONFIG_$(SPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_)FIT) += image-fit.o -obj-$(CONFIG_FIT_EMBED) += boot_fit.o common_fit.o +obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o obj-$(CONFIG_$(SPL_)FIT_SIGNATURE) += image-sig.o obj-$(CONFIG_IO_TRACE) += iotrace.o obj-y += memsize.o diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig index b3763e4..291b377 100644 --- a/configs/k2e_evm_defconfig +++ b/configs/k2e_evm_defconfig @@ -13,7 +13,7 @@ CONFIG_OF_BOARD_SETUP=y CONFIG_ENV_IS_IN_NAND=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_DTB_RESELECT=y -CONFIG_FIT_EMBED=y +CONFIG_MULTI_DTB_FIT=y CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig index 1eed605..3ac5905 100644 --- a/configs/k2g_evm_defconfig +++ b/configs/k2g_evm_defconfig @@ -12,7 +12,7 @@ CONFIG_DEFAULT_DEVICE_TREE="keystone-k2g-evm" CONFIG_OF_BOARD_SETUP=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_DTB_RESELECT=y -CONFIG_FIT_EMBED=y +CONFIG_MULTI_DTB_FIT=y CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig index 59cd9ef..d0eef23 100644 --- a/configs/k2hk_evm_defconfig +++ b/configs/k2hk_evm_defconfig @@ -13,7 +13,7 @@ CONFIG_OF_BOARD_SETUP=y CONFIG_ENV_IS_IN_NAND=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_DTB_RESELECT=y -CONFIG_FIT_EMBED=y +CONFIG_MULTI_DTB_FIT=y CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig index db45fe1..e87c4ce 100644 --- a/configs/k2l_evm_defconfig +++ b/configs/k2l_evm_defconfig @@ -13,7 +13,7 @@ CONFIG_OF_BOARD_SETUP=y CONFIG_ENV_IS_IN_NAND=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_DTB_RESELECT=y -CONFIG_FIT_EMBED=y +CONFIG_MULTI_DTB_FIT=y CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y diff --git a/doc/README.multi-dtb-fit b/doc/README.multi-dtb-fit new file mode 100644 index 0000000..d182d4e --- /dev/null +++ b/doc/README.multi-dtb-fit @@ -0,0 +1,9 @@ +MULTI DTB FIT + +The purpose of this feature is to enable u-boot to select its DTB from a FIT +image appended at the end of the binary. + +Usually the DTB is selected by the SPL and passed down to u-boot. But some +platforms don't use the SPL. In this case MULTI_DTB_FIT can used to provide +u-boot with a choice of DTBs. The FIT image is automatically image at the end +of the compilation and appended to u-boot.bin diff --git a/dts/Kconfig b/dts/Kconfig index 1bc9656..c78438a 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -90,7 +90,7 @@ config DEFAULT_DEVICE_TREE
config OF_LIST string "List of device tree files to include for DT control" - depends on SPL_LOAD_FIT || FIT_EMBED + depends on SPL_LOAD_FIT || MULTI_DTB_FIT default DEFAULT_DEVICE_TREE help This option specifies a list of device tree files to use for DT @@ -100,6 +100,24 @@ config OF_LIST device tree files (without the directory or .dtb suffix) separated by <space>.
+ +config DTB_RESELECT + bool "Support swapping dtbs at a later point in boot" + depends on MULTI_DTB_FIT + help + It is possible during initial boot you may need to use a generic + dtb until you can fully determine the board your running on. This + config allows boards to implement a function at a later point + during boot to switch to the "correct" dtb. + +config MULTI_DTB_FIT + bool "support embedding several DTBs in a FIT image for u-boot" + help + This option provides hooks to allow U-boot to parse an + appended FIT image and enable board specific code to then select + the correct DTB to be used. Use this if you need to support + multiple DTBs but don't use the SPL. + config OF_SPL_REMOVE_PROPS string "List of device tree properties to drop for SPL" depends on SPL_OF_CONTROL diff --git a/lib/fdtdec.c b/lib/fdtdec.c index d2dbd0f..0374f21 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1217,7 +1217,7 @@ int fdtdec_setup(void) else gd->fdt_blob = (ulong *)&__bss_end;
-# elif defined CONFIG_FIT_EMBED +# elif defined CONFIG_MULTI_DTB_FIT gd->fdt_blob = locate_dtb_in_fit(&_end);
if (gd->fdt_blob == NULL || gd->fdt_blob <= ((void *)&_end)) {

On 7 August 2017 at 04:07, Jean-Jacques Hiblot jjhiblot@ti.com wrote:
CONFIG_FIT_EMBED might be confused with CONFIG_OF_EMBED, rename it MULTI_DTB_FIT as it is able to get a DTB from a FIT image containing multiple DTBs. Also move the option to the Kconfig dedicated to the DTS options and create a README for this feature.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org
no change since v3
Makefile | 2 +- board/ti/ks2_evm/board_k2e.c | 2 +- board/ti/ks2_evm/board_k2g.c | 2 +- board/ti/ks2_evm/board_k2hk.c | 2 +- board/ti/ks2_evm/board_k2l.c | 2 +- common/Kconfig | 16 ---------------- common/Makefile | 2 +- configs/k2e_evm_defconfig | 2 +- configs/k2g_evm_defconfig | 2 +- configs/k2hk_evm_defconfig | 2 +- configs/k2l_evm_defconfig | 2 +- doc/README.multi-dtb-fit | 9 +++++++++ dts/Kconfig | 20 +++++++++++++++++++- lib/fdtdec.c | 2 +- 14 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 doc/README.multi-dtb-fit
Reviewed-by: Simon Glass sjg@chromium.org

Those 2 functions don't modify their input, we can mark it const. This prevents compilation warnings when they are provided const input.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org ---
change since v3: updated the description of locate_dtb_in_fit()
common/boot_fit.c | 4 ++-- include/boot_fit.h | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/common/boot_fit.c b/common/boot_fit.c index 51440a6..3767c63 100644 --- a/common/boot_fit.c +++ b/common/boot_fit.c @@ -13,7 +13,7 @@ #include <image.h> #include <libfdt.h>
-int fdt_offset(void *fit) +static int fdt_offset(const void *fit) { int images, node, fdt_len, fdt_node, fdt_offset; const char *fdt_name; @@ -55,7 +55,7 @@ int fdt_offset(void *fit) return fdt_offset; }
-void *locate_dtb_in_fit(void *fit) +void *locate_dtb_in_fit(const void *fit) { struct image_header *header; int size; diff --git a/include/boot_fit.h b/include/boot_fit.h index b7d2462..e16ae5b 100644 --- a/include/boot_fit.h +++ b/include/boot_fit.h @@ -5,5 +5,10 @@ * SPDX-License-Identifier: GPL-2.0+ */
-int fdt_offset(void *fit); -void *locate_dtb_in_fit(void *fit); +/** + * locate_dtb_in_fit - Find a DTB matching the board in a FIT image + * @fit: pointer to the FIT image + * + * @return a pointer to a matching DTB blob if found, NULL otherwise + */ +void *locate_dtb_in_fit(const void *fit);

If the dtb is the first data of the FIT, the its offset is 0x0. Change the test to '<' instead of '<='
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org ---
no change since v3
common/boot_fit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/boot_fit.c b/common/boot_fit.c index 3767c63..8e81745 100644 --- a/common/boot_fit.c +++ b/common/boot_fit.c @@ -73,7 +73,7 @@ void *locate_dtb_in_fit(const void *fit)
ret = fdt_offset(fit);
- if (ret <= 0) + if (ret < 0) return NULL; else return (void *)fit+size+ret;

If board_fit_config_name_match() doesn't match any configuration node, then use the default one (if provided).
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org ---
change since v3: fixed spelling mistakes reported by Simon G.
common/common_fit.c | 20 ++++++++++++++++++++ include/image.h | 13 +++++++++++++ 2 files changed, 33 insertions(+)
diff --git a/common/common_fit.c b/common/common_fit.c index 5f5f3f9..85b33d8 100644 --- a/common/common_fit.c +++ b/common/common_fit.c @@ -32,6 +32,9 @@ int fit_find_config_node(const void *fdt) { const char *name; int conf, node, len; + const char *dflt_conf_name; + const char *dflt_conf_desc = NULL; + int dflt_conf_node = -ENOENT;
conf = fdt_path_offset(fdt, FIT_CONFS_PATH); if (conf < 0) { @@ -39,6 +42,9 @@ int fit_find_config_node(const void *fdt) conf); return -EINVAL; } + + dflt_conf_name = fdt_getprop(fdt, conf, "default", &len); + for (node = fdt_first_subnode(fdt, conf); node >= 0; node = fdt_next_subnode(fdt, node)) { @@ -50,6 +56,15 @@ int fit_find_config_node(const void *fdt) #endif return -EINVAL; } + + if (dflt_conf_name) { + const char *node_name = fdt_get_name(fdt, node, NULL); + if (strcmp(dflt_conf_name, node_name) == 0) { + dflt_conf_node = node; + dflt_conf_desc = name; + } + } + if (board_fit_config_name_match(name)) continue;
@@ -58,5 +73,10 @@ int fit_find_config_node(const void *fdt) return node; }
+ if (dflt_conf_node != -ENOENT) { + debug("Selecting default config '%s'", dflt_conf_desc); + return dflt_conf_node; + } + return -ENOENT; } diff --git a/include/image.h b/include/image.h index c6f1513..d52d112 100644 --- a/include/image.h +++ b/include/image.h @@ -1273,6 +1273,19 @@ void board_fit_image_post_process(void **p_image, size_t *p_size); #define FDT_ERROR ((ulong)(-1))
ulong fdt_getprop_u32(const void *fdt, int node, const char *prop); + +/** + * fit_find_config_node() - Find the node for the best DTB in a FIT image + * + * A FIT image contains one or more DTBs. This function parses the + * configurations described in the FIT images and returns the node of + * the first matching DTB. To check if a DTB matches a board, this function + * calls board_fit_config_name_match(). If no matching DTB is found, it returns + * the node described by the default configuration if it exists. + * + * @fdt: pointer to flat device tree + * @return the node if found, -ve otherwise + */ int fit_find_config_node(const void *fdt);
/**

Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org ---
no change since v3
include/linux/lzo.h | 3 +++ lib/lzo/lzo1x_decompress.c | 21 +++++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/include/linux/lzo.h b/include/linux/lzo.h index 88687fa..8981d04 100644 --- a/include/linux/lzo.h +++ b/include/linux/lzo.h @@ -31,6 +31,9 @@ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, int lzop_decompress(const unsigned char *src, size_t src_len, unsigned char *dst, size_t *dst_len);
+/* check if the header is valid (based on magic numbers) */ +bool lzop_is_valid_header(const unsigned char *src); + /* * Return values (< 0 = Error) */ diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c index ccc90b8..65fef0b 100644 --- a/lib/lzo/lzo1x_decompress.c +++ b/lib/lzo/lzo1x_decompress.c @@ -30,16 +30,29 @@ static const unsigned char lzop_magic[] = {
#define HEADER_HAS_FILTER 0x00000800L
-static inline const unsigned char *parse_header(const unsigned char *src) + +bool lzop_is_valid_header(const unsigned char *src) { - u16 version; int i; - /* read magic: 9 first bytes */ for (i = 0; i < ARRAY_SIZE(lzop_magic); i++) { if (*src++ != lzop_magic[i]) - return NULL; + return false; } + return true; +} + +static inline const unsigned char *parse_header(const unsigned char *src) +{ + u16 version; + int i; + + if (!lzop_is_valid_header(src)) + return NULL; + + /* skip header */ + src += 9; + /* get version (2bytes), skip library version (2), * 'need to be extracted' version (2) and * method (1) */

Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org --- no change since v3
include/common.h | 1 + lib/gunzip.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/include/common.h b/include/common.h index c8fb277..8678275 100644 --- a/include/common.h +++ b/include/common.h @@ -568,6 +568,7 @@ ulong usec2ticks (unsigned long usec); ulong ticks2usec (unsigned long ticks);
/* lib/gunzip.c */ +int gzip_parse_header(const unsigned char *src, unsigned long len); int gunzip(void *, int, unsigned char *, unsigned long *); int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp, int stoponerr, int offset); diff --git a/lib/gunzip.c b/lib/gunzip.c index 832b306..adb86c7 100644 --- a/lib/gunzip.c +++ b/lib/gunzip.c @@ -42,7 +42,7 @@ void gzfree(void *x, void *addr, unsigned nb) free (addr); }
-int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) +int gzip_parse_header(const unsigned char *src, unsigned long len) { int i, flags;
@@ -63,12 +63,21 @@ int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) ; if ((flags & HEAD_CRC) != 0) i += 2; - if (i >= *lenp) { + if (i >= len) { puts ("Error: gunzip out of data in header\n"); return (-1); } + return i; +} + +int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) +{ + int offset = gzip_parse_header(src, *lenp); + + if (offset < 0) + return offset;
- return zunzip(dst, dstlen, src, lenp, 1, i); + return zunzip(dst, dstlen, src, lenp, 1, offset); }
#ifdef CONFIG_CMD_UNZIP

Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org --- no change since v3
lib/Kconfig | 17 ++++++++++++++++- lib/Makefile | 6 +++--- 2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/lib/Kconfig b/lib/Kconfig index 2f5a210..5b90a91 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -159,7 +159,22 @@ config LZMA config LZO bool "Enable LZO decompression support" help - This enables support for LZO compression algorithm.r + This enables support for LZO compression algorithm. + +config SPL_LZO + bool "Enable LZO decompression support in SPL" + help + This enables support for LZO compression algorithm in the SPL. + +config SPL_GZIP + bool "Enable GZIP decompression support in SPL" + select SPL_ZLIB + help + This enables support for GZIP compression algorithm in the SPL. + +config SPL_ZLIB + bool + endmenu
config ERRNO_STR diff --git a/lib/Makefile b/lib/Makefile index eacc7d6..21cd4e2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,14 +4,15 @@ # # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_$(SPL_)ZLIB) += zlib/ +obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o +obj-$(CONFIG_$(SPL_)LZO) += lzo/
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_EFI_LOADER) += efi_loader/ obj-$(CONFIG_LZMA) += lzma/ -obj-$(CONFIG_LZO) += lzo/ -obj-$(CONFIG_ZLIB) += zlib/ obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_TIZEN) += tizen/ obj-$(CONFIG_FIT) += libfdt/ @@ -26,7 +27,6 @@ obj-y += crc16.o obj-$(CONFIG_ERRNO_STR) += errno_str.o obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o -obj-$(CONFIG_GZIP) += gunzip.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o obj-y += initcall.o

u-boot can be embedded within a FIT image with multiple DTBs. It then selects at run-time which one is best suited for the platform. Use the same principle here for the SPL: put the DTBs in a FIT image, compress it (LZO, GZIP, or no compression) and append it at the end of the SPL.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com ---
change since v3: updated the help in Kconfig to take in account commit f1896c ("spl: make SPL and normal u-boot stage use independent SYS_MALLOC_F_LEN")
doc/README.multi-dtb-fit | 44 +++++++++++++++++++++++-- dts/Kconfig | 83 ++++++++++++++++++++++++++++++++++++++++++++++ lib/fdtdec.c | 85 +++++++++++++++++++++++++++++++++++++++++++----- scripts/Makefile.spl | 35 +++++++++++++++++++- 4 files changed, 235 insertions(+), 12 deletions(-)
diff --git a/doc/README.multi-dtb-fit b/doc/README.multi-dtb-fit index d182d4e..5e593c8 100644 --- a/doc/README.multi-dtb-fit +++ b/doc/README.multi-dtb-fit @@ -1,9 +1,49 @@ MULTI DTB FIT
-The purpose of this feature is to enable u-boot to select its DTB from a FIT -image appended at the end of the binary. +The purpose of this feature is to enable u-boot or the SPL to select its DTB +from a FIT image appended at the end of the binary. +It comes in two flavor: u-boot (CONFIG_MULTI_DTB_FIT) and SPL +(CONFIG_SPL_MULTI_DTB_FIT)
+u-boot flavor: Usually the DTB is selected by the SPL and passed down to u-boot. But some platforms don't use the SPL. In this case MULTI_DTB_FIT can used to provide u-boot with a choice of DTBs. The FIT image is automatically image at the end of the compilation and appended to u-boot.bin + + + +SPL flavor: +the SPL uses only a small subset of the DTB and it usually depends more +on the SOC than on the board. So it's usually fine to include a DTB in the +SPL that doesn't exactly match the board. There are howerver somes cases +where it's not possible. In the later case, in order to support multiple +boards (or board revisions) with the same SPL binary, SPL_MULTI_DTB_FIT +can be used. The list of DTB is given in CONFIG_SPL_OF_LIST which by default +is the same list as CONFIG_OF_LIST +The FIT image is automatically generated at the end of the compilation, +compressed and appended to u-boot-spl.bin + +The impact of this option is relatively small. Here are some numbers measured +for a TI DRA7 platform: + + +----------------------------------------+ + | Size |delta |boot-time| delta | + | (bytes) |(bytes) |(ms) | (ms) | ++---------------------------------------------------------------+ +| reference | 120185 | | 1331 | | ++---------------------------------------------------------------+ +| feature | | | | | +| deactiVated | 120185 | 0 | 1330 | -1 | ++---------------------------------------------------------------+ +| 1 DTB LZO | 120208 | 23 | 1331 | 0 | ++---------------------------------------------------------------+ +| 4 DTB LZO | 120810 | 625 | 1336 | 5 | ++---------------------------------------------------------------+ +| 4 DTB LZO | | | | | +| no malloc | 120746 | 561 | 1343 | 12 | ++---------------------------------------------------------------+ +| 4 DTB GZIP | 128552 | 8367 | 1353 | 22 | ++---------------------------------------------------------------+ +| 4 DTB No comp | 132352 | 12167 | 1351 | 20 | ++----------------------+----------+----------+---------+--------+ diff --git a/dts/Kconfig b/dts/Kconfig index c78438a..ec91a71 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -118,6 +118,89 @@ config MULTI_DTB_FIT the correct DTB to be used. Use this if you need to support multiple DTBs but don't use the SPL.
+ +config SPL_MULTI_DTB_FIT + depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA + bool "support embedding several DTBs in a FIT image for the SPL" + help + This option provides the SPL with the ability to select its own + DTB at runtime from an appended FIT image containing several DTBs. + This allows using the same SPL binary on multiple platforms. + The primary purpose is to handle different versions of + the same platform without tweaking the platform code if the + differences can be expressed in the DTBs (common examples are: bus + capabilities, pad configurations). + +config SPL_OF_LIST + string "List of device tree files to include for DT control in SPL" + depends on SPL_MULTI_DTB_FIT + default OF_LIST + help + This option specifies a list of device tree files to use for DT + control in the SPL. These will be packaged into a FIT. At run-time, + the SPL will select the correct DT to use by examining the + hardware (e.g. reading a board ID value). This is a list of + device tree files (without the directory or .dtb suffix) + separated by <space>. + +choice + prompt "SPL OF LIST compression" + depends on SPL_MULTI_DTB_FIT + default SPL_MULTI_DTB_FIT_LZO + +config SPL_MULTI_DTB_FIT_LZO + bool "LZO" + depends on SYS_MALLOC_F + select SPL_LZO + help + Compress the FIT image containing the DTBs available for the SPL + using LZO compression. (requires lzop on host). + +config SPL_MULTI_DTB_FIT_GZ + bool "GZIP" + depends on SYS_MALLOC_F + select SPL_GZIP + help + Compress the FIT image containing the DTBs available for the SPL + using GZIP compression. (requires gzip on host) + +config SPL_MULTI_DTB_FIT_NO_COMPRESSION + bool "No compression" + help + Do not compress the FIT image containing the DTBs available for the SPL. + Use this options only if LZO is not available and the DTBs are very small. +endchoice + +choice + prompt "location of uncompressed DTBs " + depends on (SPL_MULTI_DTB_FIT_GZ || SPL_MULTI_DTB_FIT_LZO) + +config SPL_MULTI_DTB_FIT_DYN_ALLOC + bool "Dynamically allocate the memory" + depends on SYS_MALLOC_F + default y + +config SPL_MULTI_DTB_FIT_USER_DEFINED_AREA + bool "user-defined location" +endchoice + +config SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ + hex "Size of memory reserved to uncompress the DTBs" + depends on (SPL_MULTI_DTB_FIT_GZ || SPL_MULTI_DTB_FIT_LZO) + default 0x10000 + help + This is the size of this area where the DTBs are uncompressed. + If this area is dynamically allocated, make sure that + SPL_SYS_MALLOC_F_LEN is big enough to contain it. + +config SPL_MULTI_DTB_FIT_USER_DEF_ADDR + hex "Address of memory where dtbs are uncompressed" + depends on SPL_MULTI_DTB_FIT_USER_DEFINED_AREA + help + the FIT image containing the DTBs is uncompressed in an area defined + at compilation time. This is the address of this area. It must be + aligned on 2-byte boundary. + config OF_SPL_REMOVE_PROPS string "List of device tree properties to drop for SPL" depends on SPL_OF_CONTROL diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 0374f21..e7a1df6 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -8,6 +8,8 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <spl.h> +#include <linux/lzo.h> #include <serial.h> #include <libfdt.h> #include <fdt_support.h> @@ -1203,9 +1205,65 @@ int fdtdec_setup_memory_banksize(void) } #endif
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) +# if CONFIG_IS_ENABLED(GZIP) || CONFIG_IS_ENABLED(LZO) +static int uncompress_blob(const void *src, ulong sz_src, void **dstp) +{ + size_t sz_out = CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ; + ulong sz_in = sz_src; + void *dst; + int rc; + +# if CONFIG_IS_ENABLED(GZIP) + if (gzip_parse_header(src, sz_in) < 0) + return -1; +# elif CONFIG_IS_ENABLED(LZO) + if (!lzop_is_valid_header(src)) + return -EBADMSG; +# endif + +# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC) + dst = malloc(sz_out); + if (!dst) { + puts("uncompress_blob: Unable to allocate memory\n"); + return -ENOMEM; + } +# elif CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA) + dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR); +# else + return -ENOTSUPP; +# endif + +# if CONFIG_IS_ENABLED(GZIP) + rc = gunzip(dst, sz_out, (u8 *)src, &sz_in); +# elif CONFIG_IS_ENABLED(LZO) + rc = lzop_decompress(src, sz_in, dst, &sz_out); +# endif + if (rc < 0) { + /* not a valid compressed blob */ + puts("uncompress_blob: Unable to uncompress\n"); +# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC) + free(dst); +# endif + return -EBADMSG; + } + *dstp = dst; + return 0; +} +# else +static int uncompress_blob(const void *src, ulong sz_src, void **dstp) +{ + return -ENOTSUPP; +} +# endif +#endif + int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL) +# if CONFIG_IS_ENABLED(MULTI_DTB_FIT) + void *fdt_blob; +# endif # ifdef CONFIG_OF_EMBED /* Get a pointer to the FDT */ gd->fdt_blob = __dtb_dt_begin; @@ -1216,15 +1274,6 @@ int fdtdec_setup(void) gd->fdt_blob = (ulong *)&_image_binary_end; else gd->fdt_blob = (ulong *)&__bss_end; - -# elif defined CONFIG_MULTI_DTB_FIT - gd->fdt_blob = locate_dtb_in_fit(&_end); - - if (gd->fdt_blob == NULL || gd->fdt_blob <= ((void *)&_end)) { - puts("Failed to find proper dtb in embedded FIT Image\n"); - return -1; - } - # else /* FDT is at end of image */ gd->fdt_blob = (ulong *)&_end; @@ -1243,7 +1292,25 @@ int fdtdec_setup(void) gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob); # endif + +# if CONFIG_IS_ENABLED(MULTI_DTB_FIT) + /* + *try and uncompress the blob. + * max input size is set arbitrarily to 16MB (should more than enough) + */ + if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0) + gd->fdt_blob = fdt_blob; + + /* + * Check if blob is a FIT images containings DTBs. + * If so, pick the most relevant + */ + fdt_blob = locate_dtb_in_fit(gd->fdt_blob); + if (fdt_blob) + gd->fdt_blob = fdt_blob; +# endif #endif + return fdtdec_prepare_fdt(); }
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index ac3c2c7..18316a9 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -202,10 +202,21 @@ cmd_cat = cat $(filter-out $(PHONY), $^) > $@ quiet_cmd_copy = COPY $@ cmd_copy = cp $< $@
+ifneq ($(CONFIG_SPL_MULTI_DTB_FIT),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).dtb +else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_LZO),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.lzo +else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_GZ),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.gz +else +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit +endif + + ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),yy) $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \ $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \ - $(obj)/$(SPL_BIN).dtb FORCE + $(FINAL_DTB_CONTAINER) FORCE $(call if_changed,cat)
$(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-dtb.bin FORCE @@ -369,6 +380,28 @@ checkdtoc: tools PHONY += FORCE FORCE:
+PHONY += dtbs +dtbs: + $(Q)$(MAKE) $(build)=dts dtbs + # Declare the contents of the .PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY) + +SHRUNK_ARCH_DTB = $(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) +.SECONDEXPANSION: +$(SHRUNK_ARCH_DTB): $$(patsubst $(obj)/dts/%, arch/$(ARCH)/dts/%, $$@) + $(call if_changed,fdtgrep) + +MKIMAGEFLAGS_$(SPL_BIN).multidtb.fit = -f auto -A $(ARCH) -T firmware -C none -O u-boot \ + -n "Multi DTB fit image for $(SPL_BIN)" -E \ + $(patsubst %,-b %,$(SHRUNK_ARCH_DTB)) + +$(obj)/$(SPL_BIN).multidtb.fit: /dev/null $(SHRUNK_ARCH_DTB) FORCE + $(call if_changed,mkimage) + +$(obj)/$(SPL_BIN).multidtb.fit.gz: $(obj)/$(SPL_BIN).multidtb.fit + @gzip -kf9 $< > $@ + +$(obj)/$(SPL_BIN).multidtb.fit.lzo: $(obj)/$(SPL_BIN).multidtb.fit + @lzop -f9 $< > $@

On Mon, Aug 07, 2017 at 12:07:53PM +0200, Jean-Jacques Hiblot wrote:
u-boot can be embedded within a FIT image with multiple DTBs. It then selects at run-time which one is best suited for the platform. Use the same principle here for the SPL: put the DTBs in a FIT image, compress it (LZO, GZIP, or no compression) and append it at the end of the SPL.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Hi Jean-Jacques,
On 7 August 2017 at 04:07, Jean-Jacques Hiblot jjhiblot@ti.com wrote:
u-boot can be embedded within a FIT image with multiple DTBs. It then selects at run-time which one is best suited for the platform. Use the same principle here for the SPL: put the DTBs in a FIT image, compress it (LZO, GZIP, or no compression) and append it at the end of the SPL.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
change since v3: updated the help in Kconfig to take in account commit f1896c ("spl: make SPL and normal u-boot stage use independent SYS_MALLOC_F_LEN")
doc/README.multi-dtb-fit | 44 +++++++++++++++++++++++-- dts/Kconfig | 83 ++++++++++++++++++++++++++++++++++++++++++++++ lib/fdtdec.c | 85 +++++++++++++++++++++++++++++++++++++++++++----- scripts/Makefile.spl | 35 +++++++++++++++++++- 4 files changed, 235 insertions(+), 12 deletions(-)
Unfortunately I have quite a few comments and a few nits below. I feel this is an important feature and most of my comments relate to polish. It's a nice implementation.
diff --git a/doc/README.multi-dtb-fit b/doc/README.multi-dtb-fit index d182d4e..5e593c8 100644 --- a/doc/README.multi-dtb-fit +++ b/doc/README.multi-dtb-fit @@ -1,9 +1,49 @@ MULTI DTB FIT
-The purpose of this feature is to enable u-boot to select its DTB from a FIT -image appended at the end of the binary. +The purpose of this feature is to enable u-boot or the SPL to select its DTB +from a FIT image appended at the end of the binary.
Since FIT means Flat Image Tree (I think) we should probably write 'FIT' everywhere instead of 'FIT image'.
+It comes in two flavor: u-boot (CONFIG_MULTI_DTB_FIT) and SPL +(CONFIG_SPL_MULTI_DTB_FIT)
+u-boot flavor:
U-Boot (please fix throughout)
Usually the DTB is selected by the SPL and passed down to u-boot. But some platforms don't use the SPL. In this case MULTI_DTB_FIT can used to provide u-boot with a choice of DTBs. The FIT image is automatically image at the end of the compilation and appended to u-boot.bin
'automatically image' - does that mean automatically built? Or (looking below) generated?
+SPL flavor: +the SPL uses only a small subset of the DTB and it usually depends more +on the SOC than on the board. So it's usually fine to include a DTB in the +SPL that doesn't exactly match the board. There are howerver somes cases
however some
+where it's not possible. In the later case, in order to support multiple +boards (or board revisions) with the same SPL binary, SPL_MULTI_DTB_FIT +can be used. The list of DTB is given in CONFIG_SPL_OF_LIST which by default +is the same list as CONFIG_OF_LIST
The DTB files are packed into a FIT
+The FIT image is automatically generated at the end of the compilation, +compressed and appended to u-boot-spl.bin
so that SPL can locate it and select the correct DTB from inside the FIT.
I think this needs expanding a bit: - board_fit_config_name_match() is used to find the correct DTB within the FIT - mention an example board that uses this feature (so people can trace the code) - how memory is allocated for decompression - mention compression - it is automatic in the build and SPL decompresses the correct DTB
+The impact of this option is relatively small. Here are some numbers measured +for a TI DRA7 platform:
+----------------------------------------+
| Size |delta |boot-time| delta |
| (bytes) |(bytes) |(ms) | (ms) |
++---------------------------------------------------------------+ +| reference | 120185 | | 1331 | | ++---------------------------------------------------------------+ +| feature | | | | | +| deactiVated | 120185 | 0 | 1330 | -1 | ++---------------------------------------------------------------+ +| 1 DTB LZO | 120208 | 23 | 1331 | 0 | ++---------------------------------------------------------------+ +| 4 DTB LZO | 120810 | 625 | 1336 | 5 | ++---------------------------------------------------------------+ +| 4 DTB LZO | | | | | +| no malloc | 120746 | 561 | 1343 | 12 | ++---------------------------------------------------------------+ +| 4 DTB GZIP | 128552 | 8367 | 1353 | 22 | ++---------------------------------------------------------------+ +| 4 DTB No comp | 132352 | 12167 | 1351 | 20 | ++----------------------+----------+----------+---------+--------+ diff --git a/dts/Kconfig b/dts/Kconfig index c78438a..ec91a71 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -118,6 +118,89 @@ config MULTI_DTB_FIT the correct DTB to be used. Use this if you need to support multiple DTBs but don't use the SPL.
+config SPL_MULTI_DTB_FIT
depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA
bool "support embedding several DTBs in a FIT image for the SPL"
Can you please capitalise the options in this file, so 'Bool'
help
This option provides the SPL with the ability to select its own
DTB at runtime from an appended FIT image containing several DTBs.
This allows using the same SPL binary on multiple platforms.
The primary purpose is to handle different versions of
the same platform without tweaking the platform code if the
differences can be expressed in the DTBs (common examples are: bus
capabilities, pad configurations).
+config SPL_OF_LIST
string "List of device tree files to include for DT control in SPL"
depends on SPL_MULTI_DTB_FIT
default OF_LIST
help
This option specifies a list of device tree files to use for DT
control in the SPL. These will be packaged into a FIT. At run-time,
the SPL will select the correct DT to use by examining the
hardware (e.g. reading a board ID value). This is a list of
device tree files (without the directory or .dtb suffix)
separated by <space>.
+choice
prompt "SPL OF LIST compression"
depends on SPL_MULTI_DTB_FIT
default SPL_MULTI_DTB_FIT_LZO
+config SPL_MULTI_DTB_FIT_LZO
bool "LZO"
depends on SYS_MALLOC_F
select SPL_LZO
help
Compress the FIT image containing the DTBs available for the SPL
using LZO compression. (requires lzop on host).
+config SPL_MULTI_DTB_FIT_GZ
We seem to use GZIP so could you update this to SPL_MULTI_DTB_FIT_GZIP?
bool "GZIP"
depends on SYS_MALLOC_F
select SPL_GZIP
help
Compress the FIT image containing the DTBs available for the SPL
using GZIP compression. (requires gzip on host)
+config SPL_MULTI_DTB_FIT_NO_COMPRESSION
bool "No compression"
help
Do not compress the FIT image containing the DTBs available for the SPL.
Use this options only if LZO is not available and the DTBs are very small.
+endchoice
+choice
prompt "location of uncompressed DTBs "
depends on (SPL_MULTI_DTB_FIT_GZ || SPL_MULTI_DTB_FIT_LZO)
+config SPL_MULTI_DTB_FIT_DYN_ALLOC
bool "Dynamically allocate the memory"
depends on SYS_MALLOC_F
default y
+config SPL_MULTI_DTB_FIT_USER_DEFINED_AREA
bool "user-defined location"
+endchoice
+config SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ
hex "Size of memory reserved to uncompress the DTBs"
depends on (SPL_MULTI_DTB_FIT_GZ || SPL_MULTI_DTB_FIT_LZO)
default 0x10000
help
This is the size of this area where the DTBs are uncompressed.
If this area is dynamically allocated, make sure that
SPL_SYS_MALLOC_F_LEN is big enough to contain it.
+config SPL_MULTI_DTB_FIT_USER_DEF_ADDR
hex "Address of memory where dtbs are uncompressed"
depends on SPL_MULTI_DTB_FIT_USER_DEFINED_AREA
help
the FIT image containing the DTBs is uncompressed in an area defined
at compilation time. This is the address of this area. It must be
aligned on 2-byte boundary.
Great to see a malloc() option here and that being the default. I feel we have too many hard-coded addresses.
Also can you clarify in the README that this decompression happens during spl_init() or spl_early_init()? I think it is important to know when the DT is available.
config OF_SPL_REMOVE_PROPS string "List of device tree properties to drop for SPL" depends on SPL_OF_CONTROL diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 0374f21..e7a1df6 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -8,6 +8,8 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <spl.h> +#include <linux/lzo.h> #include <serial.h> #include <libfdt.h> #include <fdt_support.h>
If you have time you could send a patch to sort these correctly.
@@ -1203,9 +1205,65 @@ int fdtdec_setup_memory_banksize(void) } #endif
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) +# if CONFIG_IS_ENABLED(GZIP) || CONFIG_IS_ENABLED(LZO) +static int uncompress_blob(const void *src, ulong sz_src, void **dstp) +{
size_t sz_out = CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ;
ulong sz_in = sz_src;
void *dst;
int rc;
+# if CONFIG_IS_ENABLED(GZIP)
can we use:
if (CONFIG_IS_ENABLED(GZIP))
here? and below? We should try to avoid extreme #ifdeffing.
if (gzip_parse_header(src, sz_in) < 0)
return -1;
+# elif CONFIG_IS_ENABLED(LZO)
if (!lzop_is_valid_header(src))
return -EBADMSG;
+# endif
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)
dst = malloc(sz_out);
if (!dst) {
puts("uncompress_blob: Unable to allocate memory\n");
return -ENOMEM;
}
+# elif CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA)
dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR);
+# else
return -ENOTSUPP;
+# endif
+# if CONFIG_IS_ENABLED(GZIP)
rc = gunzip(dst, sz_out, (u8 *)src, &sz_in);
+# elif CONFIG_IS_ENABLED(LZO)
rc = lzop_decompress(src, sz_in, dst, &sz_out);
+# endif
if (rc < 0) {
/* not a valid compressed blob */
puts("uncompress_blob: Unable to uncompress\n");
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)
free(dst);
+# endif
return -EBADMSG;
}
*dstp = dst;
return 0;
+} +# else +static int uncompress_blob(const void *src, ulong sz_src, void **dstp) +{
return -ENOTSUPP;
+} +# endif +#endif
int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL) +# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
void *fdt_blob;
+# endif # ifdef CONFIG_OF_EMBED /* Get a pointer to the FDT */ gd->fdt_blob = __dtb_dt_begin; @@ -1216,15 +1274,6 @@ int fdtdec_setup(void) gd->fdt_blob = (ulong *)&_image_binary_end; else gd->fdt_blob = (ulong *)&__bss_end;
-# elif defined CONFIG_MULTI_DTB_FIT
gd->fdt_blob = locate_dtb_in_fit(&_end);
if (gd->fdt_blob == NULL || gd->fdt_blob <= ((void *)&_end)) {
puts("Failed to find proper dtb in embedded FIT Image\n");
return -1;
}
# else /* FDT is at end of image */ gd->fdt_blob = (ulong *)&_end; @@ -1243,7 +1292,25 @@ int fdtdec_setup(void) gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob); # endif
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
/*
*try and uncompress the blob.
* max input size is set arbitrarily to 16MB (should more than enough)
This seems ugly. Can you call fdt_totalsize() instead?
*/
if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
gd->fdt_blob = fdt_blob;
/*
* Check if blob is a FIT images containings DTBs.
* If so, pick the most relevant
*/
fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
if (fdt_blob)
gd->fdt_blob = fdt_blob;
+# endif #endif
return fdtdec_prepare_fdt();
}
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index ac3c2c7..18316a9 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -202,10 +202,21 @@ cmd_cat = cat $(filter-out $(PHONY), $^) > $@ quiet_cmd_copy = COPY $@ cmd_copy = cp $< $@
+ifneq ($(CONFIG_SPL_MULTI_DTB_FIT),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).dtb +else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_LZO),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.lzo +else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_GZ),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.gz +else +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit +endif
ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),yy) $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \ $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
$(obj)/$(SPL_BIN).dtb FORCE
$(FINAL_DTB_CONTAINER) FORCE $(call if_changed,cat)
$(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-dtb.bin FORCE @@ -369,6 +380,28 @@ checkdtoc: tools PHONY += FORCE FORCE:
+PHONY += dtbs +dtbs:
$(Q)$(MAKE) $(build)=dts dtbs
# Declare the contents of the .PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY)
+SHRUNK_ARCH_DTB = $(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) +.SECONDEXPANSION: +$(SHRUNK_ARCH_DTB): $$(patsubst $(obj)/dts/%, arch/$(ARCH)/dts/%, $$@)
$(call if_changed,fdtgrep)
+MKIMAGEFLAGS_$(SPL_BIN).multidtb.fit = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
-n "Multi DTB fit image for $(SPL_BIN)" -E \
$(patsubst %,-b %,$(SHRUNK_ARCH_DTB))
+$(obj)/$(SPL_BIN).multidtb.fit: /dev/null $(SHRUNK_ARCH_DTB) FORCE
$(call if_changed,mkimage)
+$(obj)/$(SPL_BIN).multidtb.fit.gz: $(obj)/$(SPL_BIN).multidtb.fit
@gzip -kf9 $< > $@
+$(obj)/$(SPL_BIN).multidtb.fit.lzo: $(obj)/$(SPL_BIN).multidtb.fit
@lzop -f9 $< > $@
-- 1.9.1
Regards, Simon

Hi Simon,
On 13/08/2017 23:35, Simon Glass wrote:
Hi Jean-Jacques,
On 7 August 2017 at 04:07, Jean-Jacques Hiblot jjhiblot@ti.com wrote:
u-boot can be embedded within a FIT image with multiple DTBs. It then selects at run-time which one is best suited for the platform. Use the same principle here for the SPL: put the DTBs in a FIT image, compress it (LZO, GZIP, or no compression) and append it at the end of the SPL.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
change since v3: updated the help in Kconfig to take in account commit f1896c ("spl: make SPL and normal u-boot stage use independent SYS_MALLOC_F_LEN")
doc/README.multi-dtb-fit | 44 +++++++++++++++++++++++-- dts/Kconfig | 83 ++++++++++++++++++++++++++++++++++++++++++++++ lib/fdtdec.c | 85 +++++++++++++++++++++++++++++++++++++++++++----- scripts/Makefile.spl | 35 +++++++++++++++++++- 4 files changed, 235 insertions(+), 12 deletions(-)
Unfortunately I have quite a few comments and a few nits below. I feel this is an important feature and most of my comments relate to polish. It's a nice implementation.
Thanks
diff --git a/doc/README.multi-dtb-fit b/doc/README.multi-dtb-fit index d182d4e..5e593c8 100644 --- a/doc/README.multi-dtb-fit +++ b/doc/README.multi-dtb-fit @@ -1,9 +1,49 @@ MULTI DTB FIT
-The purpose of this feature is to enable u-boot to select its DTB from a FIT -image appended at the end of the binary. +The purpose of this feature is to enable u-boot or the SPL to select its DTB +from a FIT image appended at the end of the binary.
Since FIT means Flat Image Tree (I think) we should probably write 'FIT' everywhere instead of 'FIT image'.
+It comes in two flavor: u-boot (CONFIG_MULTI_DTB_FIT) and SPL +(CONFIG_SPL_MULTI_DTB_FIT)
+u-boot flavor:
U-Boot (please fix throughout)
Usually the DTB is selected by the SPL and passed down to u-boot. But some platforms don't use the SPL. In this case MULTI_DTB_FIT can used to provide u-boot with a choice of DTBs. The FIT image is automatically image at the end of the compilation and appended to u-boot.bin
'automatically image' - does that mean automatically built? Or (looking below) generated?
+SPL flavor: +the SPL uses only a small subset of the DTB and it usually depends more +on the SOC than on the board. So it's usually fine to include a DTB in the +SPL that doesn't exactly match the board. There are howerver somes cases
however some
+where it's not possible. In the later case, in order to support multiple +boards (or board revisions) with the same SPL binary, SPL_MULTI_DTB_FIT +can be used. The list of DTB is given in CONFIG_SPL_OF_LIST which by default +is the same list as CONFIG_OF_LIST
The DTB files are packed into a FIT
+The FIT image is automatically generated at the end of the compilation, +compressed and appended to u-boot-spl.bin
so that SPL can locate it and select the correct DTB from inside the FIT.
I think this needs expanding a bit:
- board_fit_config_name_match() is used to find the correct DTB within the FIT
- mention an example board that uses this feature (so people can trace the code)
- how memory is allocated for decompression
- mention compression - it is automatic in the build and SPL
decompresses the correct DTB
+The impact of this option is relatively small. Here are some numbers measured +for a TI DRA7 platform:
+----------------------------------------+
| Size |delta |boot-time| delta |
| (bytes) |(bytes) |(ms) | (ms) |
++---------------------------------------------------------------+ +| reference | 120185 | | 1331 | | ++---------------------------------------------------------------+ +| feature | | | | | +| deactiVated | 120185 | 0 | 1330 | -1 | ++---------------------------------------------------------------+ +| 1 DTB LZO | 120208 | 23 | 1331 | 0 | ++---------------------------------------------------------------+ +| 4 DTB LZO | 120810 | 625 | 1336 | 5 | ++---------------------------------------------------------------+ +| 4 DTB LZO | | | | | +| no malloc | 120746 | 561 | 1343 | 12 | ++---------------------------------------------------------------+ +| 4 DTB GZIP | 128552 | 8367 | 1353 | 22 | ++---------------------------------------------------------------+ +| 4 DTB No comp | 132352 | 12167 | 1351 | 20 | ++----------------------+----------+----------+---------+--------+ diff --git a/dts/Kconfig b/dts/Kconfig index c78438a..ec91a71 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -118,6 +118,89 @@ config MULTI_DTB_FIT the correct DTB to be used. Use this if you need to support multiple DTBs but don't use the SPL.
+config SPL_MULTI_DTB_FIT
depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA
bool "support embedding several DTBs in a FIT image for the SPL"
Can you please capitalise the options in this file, so 'Bool'
help
This option provides the SPL with the ability to select its own
DTB at runtime from an appended FIT image containing several DTBs.
This allows using the same SPL binary on multiple platforms.
The primary purpose is to handle different versions of
the same platform without tweaking the platform code if the
differences can be expressed in the DTBs (common examples are: bus
capabilities, pad configurations).
+config SPL_OF_LIST
string "List of device tree files to include for DT control in SPL"
depends on SPL_MULTI_DTB_FIT
default OF_LIST
help
This option specifies a list of device tree files to use for DT
control in the SPL. These will be packaged into a FIT. At run-time,
the SPL will select the correct DT to use by examining the
hardware (e.g. reading a board ID value). This is a list of
device tree files (without the directory or .dtb suffix)
separated by <space>.
+choice
prompt "SPL OF LIST compression"
depends on SPL_MULTI_DTB_FIT
default SPL_MULTI_DTB_FIT_LZO
+config SPL_MULTI_DTB_FIT_LZO
bool "LZO"
depends on SYS_MALLOC_F
select SPL_LZO
help
Compress the FIT image containing the DTBs available for the SPL
using LZO compression. (requires lzop on host).
+config SPL_MULTI_DTB_FIT_GZ
We seem to use GZIP so could you update this to SPL_MULTI_DTB_FIT_GZIP?
bool "GZIP"
depends on SYS_MALLOC_F
select SPL_GZIP
help
Compress the FIT image containing the DTBs available for the SPL
using GZIP compression. (requires gzip on host)
+config SPL_MULTI_DTB_FIT_NO_COMPRESSION
bool "No compression"
help
Do not compress the FIT image containing the DTBs available for the SPL.
Use this options only if LZO is not available and the DTBs are very small.
+endchoice
+choice
prompt "location of uncompressed DTBs "
depends on (SPL_MULTI_DTB_FIT_GZ || SPL_MULTI_DTB_FIT_LZO)
+config SPL_MULTI_DTB_FIT_DYN_ALLOC
bool "Dynamically allocate the memory"
depends on SYS_MALLOC_F
default y
+config SPL_MULTI_DTB_FIT_USER_DEFINED_AREA
bool "user-defined location"
+endchoice
+config SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ
hex "Size of memory reserved to uncompress the DTBs"
depends on (SPL_MULTI_DTB_FIT_GZ || SPL_MULTI_DTB_FIT_LZO)
default 0x10000
help
This is the size of this area where the DTBs are uncompressed.
If this area is dynamically allocated, make sure that
SPL_SYS_MALLOC_F_LEN is big enough to contain it.
+config SPL_MULTI_DTB_FIT_USER_DEF_ADDR
hex "Address of memory where dtbs are uncompressed"
depends on SPL_MULTI_DTB_FIT_USER_DEFINED_AREA
help
the FIT image containing the DTBs is uncompressed in an area defined
at compilation time. This is the address of this area. It must be
aligned on 2-byte boundary.
Great to see a malloc() option here and that being the default. I feel we have too many hard-coded addresses.
Also can you clarify in the README that this decompression happens during spl_init() or spl_early_init()? I think it is important to know when the DT is available.
- config OF_SPL_REMOVE_PROPS string "List of device tree properties to drop for SPL" depends on SPL_OF_CONTROL
diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 0374f21..e7a1df6 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -8,6 +8,8 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <spl.h> +#include <linux/lzo.h> #include <serial.h> #include <libfdt.h> #include <fdt_support.h>
If you have time you could send a patch to sort these correctly.
@@ -1203,9 +1205,65 @@ int fdtdec_setup_memory_banksize(void) } #endif
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) +# if CONFIG_IS_ENABLED(GZIP) || CONFIG_IS_ENABLED(LZO) +static int uncompress_blob(const void *src, ulong sz_src, void **dstp) +{
size_t sz_out = CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ;
ulong sz_in = sz_src;
void *dst;
int rc;
+# if CONFIG_IS_ENABLED(GZIP)
can we use:
if (CONFIG_IS_ENABLED(GZIP))
here? and below? We should try to avoid extreme #ifdeffing.
if (gzip_parse_header(src, sz_in) < 0)
return -1;
+# elif CONFIG_IS_ENABLED(LZO)
if (!lzop_is_valid_header(src))
return -EBADMSG;
+# endif
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)
dst = malloc(sz_out);
if (!dst) {
puts("uncompress_blob: Unable to allocate memory\n");
return -ENOMEM;
}
+# elif CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA)
dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR);
+# else
return -ENOTSUPP;
+# endif
+# if CONFIG_IS_ENABLED(GZIP)
rc = gunzip(dst, sz_out, (u8 *)src, &sz_in);
+# elif CONFIG_IS_ENABLED(LZO)
rc = lzop_decompress(src, sz_in, dst, &sz_out);
+# endif
if (rc < 0) {
/* not a valid compressed blob */
puts("uncompress_blob: Unable to uncompress\n");
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)
free(dst);
+# endif
return -EBADMSG;
}
*dstp = dst;
return 0;
+} +# else +static int uncompress_blob(const void *src, ulong sz_src, void **dstp) +{
return -ENOTSUPP;
+} +# endif +#endif
- int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL)
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
void *fdt_blob;
+# endif # ifdef CONFIG_OF_EMBED /* Get a pointer to the FDT */ gd->fdt_blob = __dtb_dt_begin; @@ -1216,15 +1274,6 @@ int fdtdec_setup(void) gd->fdt_blob = (ulong *)&_image_binary_end; else gd->fdt_blob = (ulong *)&__bss_end;
-# elif defined CONFIG_MULTI_DTB_FIT
gd->fdt_blob = locate_dtb_in_fit(&_end);
if (gd->fdt_blob == NULL || gd->fdt_blob <= ((void *)&_end)) {
puts("Failed to find proper dtb in embedded FIT Image\n");
return -1;
}
- # else /* FDT is at end of image */ gd->fdt_blob = (ulong *)&_end;
@@ -1243,7 +1292,25 @@ int fdtdec_setup(void) gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob); # endif
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
/*
*try and uncompress the blob.
* max input size is set arbitrarily to 16MB (should more than enough)
This seems ugly. Can you call fdt_totalsize() instead?
Unfortunately we cannot. The data itself is not part of the fdt, it is appended after it. In the fdt, we find the descriptions, and for each binary the size and the offset relative to the end of the fdt.
JJ
*/
if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
gd->fdt_blob = fdt_blob;
/*
* Check if blob is a FIT images containings DTBs.
* If so, pick the most relevant
*/
fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
if (fdt_blob)
gd->fdt_blob = fdt_blob;
+# endif #endif
}return fdtdec_prepare_fdt();
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index ac3c2c7..18316a9 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -202,10 +202,21 @@ cmd_cat = cat $(filter-out $(PHONY), $^) > $@ quiet_cmd_copy = COPY $@ cmd_copy = cp $< $@
+ifneq ($(CONFIG_SPL_MULTI_DTB_FIT),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).dtb +else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_LZO),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.lzo +else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_GZ),y) +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.gz +else +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit +endif
- ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),yy) $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \ $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
$(obj)/$(SPL_BIN).dtb FORCE
$(FINAL_DTB_CONTAINER) FORCE $(call if_changed,cat)
$(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-dtb.bin FORCE
@@ -369,6 +380,28 @@ checkdtoc: tools PHONY += FORCE FORCE:
+PHONY += dtbs +dtbs:
$(Q)$(MAKE) $(build)=dts dtbs
- # Declare the contents of the .PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY)
+SHRUNK_ARCH_DTB = $(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) +.SECONDEXPANSION: +$(SHRUNK_ARCH_DTB): $$(patsubst $(obj)/dts/%, arch/$(ARCH)/dts/%, $$@)
$(call if_changed,fdtgrep)
+MKIMAGEFLAGS_$(SPL_BIN).multidtb.fit = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
-n "Multi DTB fit image for $(SPL_BIN)" -E \
$(patsubst %,-b %,$(SHRUNK_ARCH_DTB))
+$(obj)/$(SPL_BIN).multidtb.fit: /dev/null $(SHRUNK_ARCH_DTB) FORCE
$(call if_changed,mkimage)
+$(obj)/$(SPL_BIN).multidtb.fit.gz: $(obj)/$(SPL_BIN).multidtb.fit
@gzip -kf9 $< > $@
+$(obj)/$(SPL_BIN).multidtb.fit.lzo: $(obj)/$(SPL_BIN).multidtb.fit
@lzop -f9 $< > $@
-- 1.9.1
Regards, Simon

Hi Jean-Jacques,
On 24 August 2017 at 04:52, Jean-Jacques Hiblot jjhiblot@ti.com wrote:
Hi Simon,
On 13/08/2017 23:35, Simon Glass wrote:
Hi Jean-Jacques,
On 7 August 2017 at 04:07, Jean-Jacques Hiblot jjhiblot@ti.com wrote:
u-boot can be embedded within a FIT image with multiple DTBs. It then selects at run-time which one is best suited for the platform. Use the same principle here for the SPL: put the DTBs in a FIT image, compress it (LZO, GZIP, or no compression) and append it at the end of the SPL.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
change since v3: updated the help in Kconfig to take in account commit f1896c ("spl: make SPL and normal u-boot stage use independent SYS_MALLOC_F_LEN")
doc/README.multi-dtb-fit | 44 +++++++++++++++++++++++-- dts/Kconfig | 83 ++++++++++++++++++++++++++++++++++++++++++++++ lib/fdtdec.c | 85 +++++++++++++++++++++++++++++++++++++++++++----- scripts/Makefile.spl | 35 +++++++++++++++++++- 4 files changed, 235 insertions(+), 12 deletions(-)
Unfortunately I have quite a few comments and a few nits below. I feel this is an important feature and most of my comments relate to polish. It's a nice implementation.
Thanks
[..]
@@ -1243,7 +1292,25 @@ int fdtdec_setup(void) gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
(uintptr_t)gd->fdt_blob); # endif
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
/*
*try and uncompress the blob.
* max input size is set arbitrarily to 16MB (should more than
enough)
This seems ugly. Can you call fdt_totalsize() instead?
Unfortunately we cannot. The data itself is not part of the fdt, it is appended after it. In the fdt, we find the descriptions, and for each binary the size and the offset relative to the end of the fdt.
So I think we need header so we can find out:
- the compression algorithm (since otherwise I'm not sure how you tell) - the compressed size -the original uncompressed size
without having to decompress to find out. Perhaps add a magic value also?
JJ
[..]

Hi Simon,
It's has been a month since you've reviewed the series, I think it's time that I send a v5. I tried to address all your remarks but I stumbled on this one below:
JJ
On 13/08/2017 23:35, Simon Glass wrote:
diff --git a/dts/Kconfig b/dts/Kconfig
index c78438a..ec91a71 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -118,6 +118,89 @@ config MULTI_DTB_FIT the correct DTB to be used. Use this if you need to support multiple DTBs but don't use the SPL.
+config SPL_MULTI_DTB_FIT
depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA
bool "support embedding several DTBs in a FIT image for the SPL"
Can you please capitalise the options in this file, so 'Bool'*
I tried to do that, but it didn't work. Could it be a matter of the host configuration ?
help
This option provides the SPL with the ability to select its own
DTB at runtime from an appended FIT image containing several DTBs.
This allows using the same SPL binary on multiple platforms.
The primary purpose is to handle different versions of
the same platform without tweaking the platform code if the
differences can be expressed in the DTBs (common examples are: bus
capabilities, pad configurations).
+config SPL_OF_LIST
string "List of device tree files to include for DT control in SPL"
depends on SPL_MULTI_DTB_FIT
default OF_LIST
help
This option specifies a list of device tree files to use for DT
control in the SPL. These will be packaged into a FIT. At run-time,
the SPL will select the correct DT to use by examining the
hardware (e.g. reading a board ID value). This is a list of
device tree files (without the directory or .dtb suffix)
separated by <space>.
+choice
prompt "SPL OF LIST compression"
depends on SPL_MULTI_DTB_FIT
default SPL_MULTI_DTB_FIT_LZO
+config SPL_MULTI_DTB_FIT_LZO
bool "LZO"
depends on SYS_MALLOC_F
select SPL_LZO
help
Compress the FIT image containing the DTBs available for the SPL
using LZO compression. (requires lzop on host).
+config SPL_MULTI_DTB_FIT_GZ

On Tue, Sep 12, 2017 at 03:23:38PM +0200, Jean-Jacques Hiblot wrote:
Hi Simon,
It's has been a month since you've reviewed the series, I think it's time that I send a v5. I tried to address all your remarks but I stumbled on this one below:
JJ
On 13/08/2017 23:35, Simon Glass wrote:
diff --git a/dts/Kconfig b/dts/Kconfig
index c78438a..ec91a71 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -118,6 +118,89 @@ config MULTI_DTB_FIT the correct DTB to be used. Use this if you need to support multiple DTBs but don't use the SPL.
+config SPL_MULTI_DTB_FIT
depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA
bool "support embedding several DTBs in a FIT image for the SPL"
Can you please capitalise the options in this file, so 'Bool'*
I tried to do that, but it didn't work. Could it be a matter of the host configuration ?
Er, it must be lower case config, depends, bool, help, etc.

Hi Jean-Jacques,
On 12 September 2017 at 07:23, Jean-Jacques Hiblot jjhiblot@ti.com wrote:
Hi Simon,
It's has been a month since you've reviewed the series, I think it's time that I send a v5. I tried to address all your remarks but I stumbled on this one below:
JJ
On 13/08/2017 23:35, Simon Glass wrote:
diff --git a/dts/Kconfig b/dts/Kconfig
index c78438a..ec91a71 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -118,6 +118,89 @@ config MULTI_DTB_FIT the correct DTB to be used. Use this if you need to support multiple DTBs but don't use the SPL.
+config SPL_MULTI_DTB_FIT
depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA
bool "support embedding several DTBs in a FIT image for the SPL"
Can you please capitalise the options in this file, so 'Bool'*
I tried to do that, but it didn't work. Could it be a matter of the host configuration ?
That's me being silly, sorry. I mean:
bool "Support ..."
Regards, Simon

In order to be able to select the right DTB, we need to have identified the board before spl_early_init() is called.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org ---
no change since v3
arch/arm/mach-omap2/hwinit-common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-omap2/hwinit-common.c b/arch/arm/mach-omap2/hwinit-common.c index 7324d52..56890a0 100644 --- a/arch/arm/mach-omap2/hwinit-common.c +++ b/arch/arm/mach-omap2/hwinit-common.c @@ -165,9 +165,11 @@ void early_system_init(void) * to prevent overwrites. */ save_omap_boot_params(); - spl_early_init(); #endif do_board_detect(); +#ifdef CONFIG_SPL_BUILD + spl_early_init(); +#endif vcores_init(); #ifdef CONFIG_DEBUG_UART_OMAP debug_uart_init();
participants (3)
-
Jean-Jacques Hiblot
-
Simon Glass
-
Tom Rini