[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:51:41 UTC 2017


Hi all,

I forgot to mention in the title that it is a RFC only. I'd like to know 
if you think that this feature is desirable or not. and if the approach 
seems correct. If so I will send a proper patch later with the proper 
Kconfig description and proposed modifications.

Jean-Jacques



On 07/07/2017 15:46, Jean-Jacques Hiblot wrote:
> + 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
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



More information about the U-Boot mailing list