[U-Boot] [PATCH] spl: dm: Make it possible for the SPL to pick its own DTB from a FIT
Jean-Jacques Hiblot
jjhiblot at ti.com
Fri Jul 7 13:46:21 UTC 2017
+ Tom Rini <trini at konsulko.com>
On 07/07/2017 13:44, 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 at ti.com>
> ---
>
> The impact in terms of boot time is not high when using LZO but I gues it can vary
> from platform to platform.
> The size of the SPL binary is increased (1.5kB more code on ARM), but the compression
> really flattens the DTBS. so at the end of the day, enabling this option doesn't add much.
>
> Here are some sumbers with a DRA7 platform (numbers in bytes):
> size delta with ref
> MLO.reference 123450
> MLO.lzo_1_DTB 123715 +265
> MLO.lzo_4_DTB 124237 +787
> MLO.gzip_4_DTB 132006 +8556
> MLO.no_comp_4_DTB 134184 +10734
>
> common/spl/spl_fit.c | 2 +-
> dts/Kconfig | 48 ++++++++++++++++++++++++++++++++++
> dts/Makefile | 18 +++++++++++--
> include/spl.h | 15 +++++++++++
> lib/Kconfig | 11 ++++++++
> lib/Makefile | 6 ++---
> lib/fdtdec.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> scripts/Makefile.spl | 35 ++++++++++++++++++++++++-
> 8 files changed, 201 insertions(+), 7 deletions(-)
>
> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> index 4c42a96..3479b05 100644
> --- a/common/spl/spl_fit.c
> +++ b/common/spl/spl_fit.c
> @@ -75,7 +75,7 @@ static int spl_fit_find_config_node(const void *fdt)
> * Return: the node offset of the respective image node or a negative
> * error number.
> */
> -static int spl_fit_get_image_node(const void *fit, int images,
> +int spl_fit_get_image_node(const void *fit, int images,
> const char *type, int index)
> {
> const char *name, *str;
> diff --git a/dts/Kconfig b/dts/Kconfig
> index b3009af..80f21e0 100644
> --- a/dts/Kconfig
> +++ b/dts/Kconfig
> @@ -99,6 +99,54 @@ config OF_LIST
> reading a board ID value). This is a list of device tree files
> (without the directory or .dtb suffix) separated by <space>.
>
> +
> +config SPL_MULTI_DTB
> + depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA
> + bool "support embedding several DTB in the SPL"
> + default n
> +
> +config SPL_OF_LIST
> + string "List of device tree files to include for DT control in SPL"
> + depends on SPL_MULTI_DTB
> + default OF_LIST
> + help
> + blablablabla
> +
> +choice
> + prompt "SPL OF LIST compression"
> + depends on SPL_MULTI_DTB
> + default SPL_MULTI_DTB_LZO
> +
> +config SPL_MULTI_DTB_LZO
> + bool "Compress the DTBs with LZO"
> + depends on SYS_MALLOC_F
> + select SPL_LZO
> + help
> + Compres the FIT image containing the DTBs available for the SPL
> + using LZO compression. (requires lzop on host).
> +
> +config SPL_MULTI_DTB_GZ
> + bool "Compress the DTBs with GZip"
> + depends on SYS_MALLOC_F
> + select SPL_GZIP
> + help
> + Compres the FIT image containing the DTBs available for the SPL
> + using GZIP compression. (requires gzip on host)
> +
> +config SPL_MULTI_DTB_NO_COMPRESSION
> + bool "do not compress the DTBs"
> + help
> + Do not tompres 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
> +
> +config SPL_MULTI_DTB_GZ_SZ
> + hex "Size of mmemory allocated to uncompress the dtbs"
> + depends on SYS_MALLOC_F && (SPL_MULTI_DTB_GZ || SPL_MULTI_DTB_LZO)
> + default 0x10000
> + help
> + blablabla
> +
> config OF_SPL_REMOVE_PROPS
> string "List of device tree properties to drop for SPL"
> depends on SPL_OF_CONTROL
> diff --git a/dts/Makefile b/dts/Makefile
> index 3a93daf..5cab6bd 100644
> --- a/dts/Makefile
> +++ b/dts/Makefile
> @@ -22,9 +22,23 @@ DTB := $(ARCH_PATH)/$(DEVICE_TREE).dtb
> dtb_depends += $(DTB:.dtb=.dts)
> endif
>
> +
> +ARCH_SPL_DTB := $(patsubst %,$(ARCH_PATH)/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST)))
> +LOCAL_SPL_DTBS := $(patsubst %,$(obj)/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST)))
> +
> +.PHONY: arch-dtbs
> +
> $(obj)/dt.dtb: $(DTB) FORCE
> $(call if_changed,shipped)
>
> +ARCH_SPL_DTB_EXECPT_ONE := $(filter-out $(DTB),$(ARCH_SPL_DTB))
> +$(ARCH_SPL_DTB_EXECPT_ONE): arch-dtbs
> + @
> +
> +.SECONDEXPANSION:
> +$(LOCAL_SPL_DTBS): $$(patsubst $(TARGETDIR)/%, %, arch/$(ARCH)/$$@)
> + $(shell cp $< $@)
> +
> targets += dt.dtb
>
> $(DTB): $(dtb_depends)
> @@ -46,10 +60,10 @@ arch-dtbs:
>
> obj-$(CONFIG_OF_EMBED) := dt.dtb.o
>
> -dtbs: $(obj)/dt.dtb
> +dtbs: $(obj)/dt.dtb $(LOCAL_SPL_DTBS)
> @:
>
> -clean-files := dt.dtb.S
> +clean-files := dt.dtb.S *.dtb
>
> # Let clean descend into dts directories
> subdir- += ../arch/arm/dts ../arch/microblaze/dts ../arch/mips/dts ../arch/sandbox/dts ../arch/x86/dts
> diff --git a/include/spl.h b/include/spl.h
> index ffadce9..8ff96c3 100644
> --- a/include/spl.h
> +++ b/include/spl.h
> @@ -49,6 +49,21 @@ struct spl_load_info {
> };
>
> /**
> + * spl_fit_get_image_node(): By using the matching configuration subnode,
> + * retrieve the name of an image, specified by a property name and an index
> + * into that.
> + * @fit: Pointer to the FDT blob.
> + * @images: Offset of the /images subnode.
> + * @type: Name of the property within the configuration subnode.
> + * @index: Index into the list of strings in this property.
> + *
> + * Return: the node offset of the respective image node or a negative
> + * error number.
> + */
> +int spl_fit_get_image_node(const void *fit, int images,
> + const char *type, int index);
> +
> +/**
> * spl_load_simple_fit() - Loads a fit image from a device.
> * @spl_image: Image description to set up
> * @info: Structure containing the information required to load data.
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 09670f0..6865325 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -158,6 +158,17 @@ config LZMA
>
> config LZO
> bool
> +
> +config SPL_LZO
> + bool
> +
> +config SPL_GZIP
> + bool
> + depends on SPL_ZLIB
> +
> +config SPL_ZLIB
> + bool
> +
> endmenu
>
> config ERRNO_STR
> diff --git a/lib/Makefile b/lib/Makefile
> index eacc7d6..82b2de0 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
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index 91503b8..68322d8 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -7,6 +7,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>
> @@ -1208,6 +1210,65 @@ int fdtdec_setup_memory_banksize(void)
> }
> #endif
>
> +#if defined(CONFIG_SPL_MULTI_DTB) && defined(CONFIG_SPL_BUILD)
> +const void *get_dtb_blob_from_fit(const void *fit)
> +{
> + int node, images;
> + ulong fit_size, offset;
> +
> +#if defined(CONFIG_SPL_MULTI_DTB_GZ) || defined(CONFIG_SPL_MULTI_DTB_LZO)
> + if (image_get_magic(fit) != FDT_MAGIC) {
> + /* not a valid FIT, maybe it is a compressed fit */
> + void *dst = malloc(CONFIG_SPL_MULTI_DTB_GZ_SZ);
> + size_t sz_out = CONFIG_SPL_MULTI_DTB_GZ_SZ;
> + ulong sz_in = 1024*1024; /* not more than 1MB */
> + if (!dst) {
> + puts("Unable to allocate memory to uncompress the DTBs\n");
> + return NULL;
> + }
> +#ifdef CONFIG_SPL_MULTI_DTB_GZ
> + int rc = gunzip(dst, sz_out,
> + (u8 *)fit, &sz_in);
> +#elif defined CONFIG_SPL_MULTI_DTB_LZO
> + int rc = lzop_decompress(fit, sz_in, dst, &sz_out);
> +#endif
> + if (rc < 0) {
> + /* not a valid compressed blob */
> + free(dst);
> + return NULL;
> + }
> + fit = dst;
> + }
> +#endif
> +
> + if (image_get_magic(fit) != FDT_MAGIC) {
> + debug("not a FIT image\n");
> + return NULL;
> + }
> +
> + fit_size = fdt_totalsize(fit);
> + fit_size = (fit_size + 3) & ~3; /* align on 32bit upper boundary */
> +
> + /* find the node holding the images information */
> + images = fdt_path_offset(fit, FIT_IMAGES_PATH);
> + if (images < 0) {
> + debug("could not find the '/images' node\n");
> + return NULL;
> + }
> +
> + /* Figure out which device tree the board wants to use */
> + node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
> + if (node < 0)
> + return NULL;
> +
> + offset = fdtdec_get_int(fit, node, "data-offset", -1);
> + if (offset < 0)
> + return NULL;
> +
> + return fit + fit_size + offset;
> +}
> +#endif
> +
> int fdtdec_setup(void)
> {
> #if CONFIG_IS_ENABLED(OF_CONTROL)
> @@ -1239,6 +1300,18 @@ int fdtdec_setup(void)
> gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
> (uintptr_t)gd->fdt_blob);
> # endif
> +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_MULTI_DTB)
> + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) {
> + const void *fdt_blob;
> + fdt_blob = get_dtb_blob_from_fit(gd->fdt_blob);
> + if (fdt_blob) {
> + debug("found FIT containg several DTBs\n");
> + gd->fdt_blob = fdt_blob;
> + } else {
> + debug("legacy DTB file\n");
> + }
> + }
> +#endif
> #endif
> return fdtdec_prepare_fdt();
> }
> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> index ac3c2c7..39aa939 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),y)
> +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).dtb
> +else ifeq ($(CONFIG_SPL_MULTI_DTB_LZO),y)
> +FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.lzo
> +else ifeq ($(CONFIG_SPL_MULTI_DTB_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) JJH" -E \
> + $(patsubst %,-b $(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST)))
> +
> +$(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 $< > $@
> \ No newline at end of file
More information about the U-Boot
mailing list