From mboxrd@z Thu Jan 1 00:00:00 1970 From: Julius Werner Date: Wed, 15 May 2019 15:29:57 -0700 Subject: [U-Boot] [PATCH v4 1/2] fit: Support compression for non-kernel components (e.g. FDT) In-Reply-To: <20190515222958.194325-1-jwerner@chromium.org> References: <20190515222958.194325-1-jwerner@chromium.org> Message-ID: <20190515222958.194325-2-jwerner@chromium.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 --- - 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 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 ac901e131c..469c5c8f49 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -22,6 +22,7 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ +#include #include #include #include @@ -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 (bootm_decomp_image(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.20.1