[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