[U-Boot] [PATCH v6 2/3] fit: Support compression for non-kernel components (e.g. FDT)

Simon Goldschmidt simon.k.r.goldschmidt at gmail.com
Thu Jul 25 04:39:03 UTC 2019


Julius Werner <jwerner at chromium.org> schrieb am Do., 25. Juli 2019, 04:38:

> This patch adds support for compressing non-kernel image nodes in a FIT
> image (kernel nodes could already be compressed previously). This can
> reduce the size of FIT images and therefore improve boot times
> (especially when an image bundles many different kernel FDTs). The
> images will automatically be decompressed on load.
>
> This patch does not support extracting compatible strings from
> compressed FDTs, so it's not very helpful in conjunction with
> CONFIG_FIT_BEST_MATCH yet, but it can already be used in environments
> that select the configuration to load explicitly.
>
> Signed-off-by: Julius Werner <jwerner at chromium.org>
> Reviewed-by: Simon Glass <sjg at chromium.org>
>

Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>

---
>  - Changes for v2:
>    - Changed from only supporting compressed FDTs to supporting all
>      non-kernel image node types.
>  - Changes for v3:
>    - Fixed up some debug output that was still written for v1.
>    - Fixed a mistake with handling FIT_LOAD_OPTIONAL_NON_ZERO when
>      'load' was 0 (i.e. unset).
>    - Added compression test case to the test_fit pytest.
>  - No changes for v4
>  - No changes for v5
>  - No changes for v6
>
>  common/image-fit.c        | 86 +++++++++++++++++++++++----------------
>  test/py/tests/test_fit.py | 29 +++++++++++--
>  2 files changed, 77 insertions(+), 38 deletions(-)
>
> diff --git a/common/image-fit.c b/common/image-fit.c
> index a74b44f298..c9ffc441aa 100644
> --- a/common/image-fit.c
> +++ b/common/image-fit.c
> @@ -22,6 +22,7 @@
>  DECLARE_GLOBAL_DATA_PTR;
>  #endif /* !USE_HOSTCC*/
>
> +#include <bootm.h>
>  #include <image.h>
>  #include <bootstage.h>
>  #include <u-boot/crc.h>
> @@ -1576,6 +1577,13 @@ int fit_conf_find_compat(const void *fit, const
> void *fdt)
>                               kfdt_name);
>                         continue;
>                 }
> +
> +               if (!fit_image_check_comp(fit, kfdt_noffset,
> IH_COMP_NONE)) {
> +                       debug("Can't extract compat from \"%s\"
> (compressed)\n",
> +                             kfdt_name);
> +                       continue;
> +               }
> +
>                 /*
>                  * Get a pointer to this configuration's fdt.
>                  */
> @@ -1795,11 +1803,12 @@ int fit_image_load(bootm_headers_t *images, ulong
> addr,
>         const char *fit_uname_config;
>         const char *fit_base_uname_config;
>         const void *fit;
> -       const void *buf;
> +       void *buf;
> +       void *loadbuf;
>         size_t size;
>         int type_ok, os_ok;
> -       ulong load, data, len;
> -       uint8_t os;
> +       ulong load, load_end, data, len;
> +       uint8_t os, comp;
>  #ifndef USE_HOSTCC
>         uint8_t os_arch;
>  #endif
> @@ -1895,12 +1904,6 @@ int fit_image_load(bootm_headers_t *images, ulong
> addr,
>         images->os.arch = os_arch;
>  #endif
>
> -       if (image_type == IH_TYPE_FLATDT &&
> -           !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
> -               puts("FDT image is compressed");
> -               return -EPROTONOSUPPORT;
> -       }
> -
>         bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
>         type_ok = fit_image_check_type(fit, noffset, image_type) ||
>                   fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
> @@ -1931,7 +1934,8 @@ int fit_image_load(bootm_headers_t *images, ulong
> addr,
>         bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
>
>         /* get image data address and length */
> -       if (fit_image_get_data_and_size(fit, noffset, &buf, &size)) {
> +       if (fit_image_get_data_and_size(fit, noffset,
> +                                       (const void **)&buf, &size)) {
>                 printf("Could not find %s subimage data!\n", prop_name);
>                 bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
>                 return -ENOENT;
> @@ -1939,30 +1943,15 @@ int fit_image_load(bootm_headers_t *images, ulong
> addr,
>
>  #if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS)
>         /* perform any post-processing on the image data */
> -       board_fit_image_post_process((void **)&buf, &size);
> +       board_fit_image_post_process(&buf, &size);
>  #endif
>
>         len = (ulong)size;
>
> -       /* verify that image data is a proper FDT blob */
> -       if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
> -               puts("Subimage data is not a FDT");
> -               return -ENOEXEC;
> -       }
> -
>         bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
>
> -       /*
> -        * Work-around for eldk-4.2 which gives this warning if we try to
> -        * cast in the unmap_sysmem() call:
> -        * warning: initialization discards qualifiers from pointer target
> type
> -        */
> -       {
> -               void *vbuf = (void *)buf;
> -
> -               data = map_to_sysmem(vbuf);
> -       }
> -
> +       data = map_to_sysmem(buf);
> +       load = data;
>         if (load_op == FIT_LOAD_IGNORED) {
>                 /* Don't load */
>         } else if (fit_image_get_load(fit, noffset, &load)) {
> @@ -1974,8 +1963,6 @@ int fit_image_load(bootm_headers_t *images, ulong
> addr,
>                 }
>         } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
>                 ulong image_start, image_end;
> -               ulong load_end;
> -               void *dst;
>
>                 /*
>                  * move image data to the load address,
> @@ -1993,14 +1980,45 @@ int fit_image_load(bootm_headers_t *images, ulong
> addr,
>
>                 printf("   Loading %s from 0x%08lx to 0x%08lx\n",
>                        prop_name, data, load);
> +       } else {
> +               load = data;    /* No load address specified */
> +       }
> +
> +       comp = IH_COMP_NONE;
> +       loadbuf = buf;
> +       /* Kernel images get decompressed later in bootm_load_os(). */
> +       if (!(image_type == IH_TYPE_KERNEL ||
> +             image_type == IH_TYPE_KERNEL_NOLOAD) &&
> +           !fit_image_get_comp(fit, noffset, &comp) &&
> +           comp != IH_COMP_NONE) {
> +               ulong max_decomp_len = len * 20;
> +               if (load == data) {
> +                       loadbuf = malloc(max_decomp_len);
> +                       load = map_to_sysmem(loadbuf);
> +               } else {
> +                       loadbuf = map_sysmem(load, max_decomp_len);
> +               }
> +               if (image_decomp(comp, load, data, image_type,
> +                               loadbuf, buf, len, max_decomp_len,
> &load_end)) {
> +                       printf("Error decompressing %s\n", prop_name);
>
> -               dst = map_sysmem(load, len);
> -               memmove(dst, buf, len);
> -               data = load;
> +                       return -ENOEXEC;
> +               }
> +               len = load_end - load;
> +       } else if (load != data) {
> +               loadbuf = map_sysmem(load, len);
> +               memcpy(loadbuf, buf, len);
>         }
> +
> +       /* verify that image data is a proper FDT blob */
> +       if (image_type == IH_TYPE_FLATDT && fdt_check_header(loadbuf)) {
> +               puts("Subimage data is not a FDT");
> +               return -ENOEXEC;
> +       }
> +
>         bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
>
> -       *datap = data;
> +       *datap = load;
>         *lenp = len;
>         if (fit_unamep)
>                 *fit_unamep = (char *)fit_uname;
> diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py
> index 49d6fea571..8009d2907b 100755
> --- a/test/py/tests/test_fit.py
> +++ b/test/py/tests/test_fit.py
> @@ -24,7 +24,7 @@ base_its = '''
>                          type = "kernel";
>                          arch = "sandbox";
>                          os = "linux";
> -                        compression = "none";
> +                        compression = "%(compression)s";
>                          load = <0x40000>;
>                          entry = <0x8>;
>                  };
> @@ -39,11 +39,11 @@ base_its = '''
>                  };
>                  fdt at 1 {
>                          description = "snow";
> -                        data = /incbin/("u-boot.dtb");
> +                        data = /incbin/("%(fdt)s");
>                          type = "flat_dt";
>                          arch = "sandbox";
>                          %(fdt_load)s
> -                        compression = "none";
> +                        compression = "%(compression)s";
>                          signature at 1 {
>                                  algo = "sha1,rsa2048";
>                                  key-name-hint = "dev";
> @@ -56,7 +56,7 @@ base_its = '''
>                          arch = "sandbox";
>                          os = "linux";
>                          %(ramdisk_load)s
> -                        compression = "none";
> +                        compression = "%(compression)s";
>                  };
>                  ramdisk at 2 {
>                          description = "snow";
> @@ -221,6 +221,10 @@ def test_fit(u_boot_console):
>              print(data, file=fd)
>          return fname
>
> +    def make_compressed(filename):
> +        util.run_and_log(cons, ['gzip', '-f', '-k', filename])
> +        return filename + '.gz'
> +
>      def find_matching(text, match):
>          """Find a match in a line of text, and return the unmatched line
> portion
>
> @@ -312,6 +316,7 @@ def test_fit(u_boot_console):
>          loadables1 = make_kernel('test-loadables1.bin', 'lenrek')
>          loadables2 = make_ramdisk('test-loadables2.bin', 'ksidmar')
>          kernel_out = make_fname('kernel-out.bin')
> +        fdt = make_fname('u-boot.dtb')
>          fdt_out = make_fname('fdt-out.dtb')
>          ramdisk_out = make_fname('ramdisk-out.bin')
>          loadables1_out = make_fname('loadables1-out.bin')
> @@ -326,6 +331,7 @@ def test_fit(u_boot_console):
>              'kernel_addr' : 0x40000,
>              'kernel_size' : filesize(kernel),
>
> +            'fdt' : fdt,
>              'fdt_out' : fdt_out,
>              'fdt_addr' : 0x80000,
>              'fdt_size' : filesize(control_dtb),
> @@ -351,6 +357,7 @@ def test_fit(u_boot_console):
>              'loadables2_load' : '',
>
>              'loadables_config' : '',
> +            'compression' : 'none',
>          }
>
>          # Make a basic FIT and a script to load it
> @@ -417,6 +424,20 @@ def test_fit(u_boot_console):
>              check_equal(loadables2, loadables2_out,
>                          'Loadables2 (ramdisk) not loaded')
>
> +        # Kernel, FDT and Ramdisk all compressed
> +        with cons.log.section('(Kernel + FDT + Ramdisk) compressed'):
> +            params['compression'] = 'gzip'
> +            params['kernel'] = make_compressed(kernel)
> +            params['fdt'] = make_compressed(fdt)
> +            params['ramdisk'] = make_compressed(ramdisk)
> +            fit = make_fit(mkimage, params)
> +            cons.restart_uboot()
> +            output = cons.run_command_list(cmd.splitlines())
> +            check_equal(kernel, kernel_out, 'Kernel not loaded')
> +            check_equal(control_dtb, fdt_out, 'FDT not loaded')
> +            check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded')
> +
> +
>      cons = u_boot_console
>      try:
>          # We need to use our own device tree file. Remember to restore it
> --
> 2.22.0.657.g960e92d24f-goog
>
>


More information about the U-Boot mailing list