[PATCH v2 00/18] boot: Make fit_image_load() easier to maintain

From: Simon Glass <sjg@chromium.org> Before fit_image_load() was created, The code to load kernels, ramdisks and devicetrees from a FIT was spread around many functions. By combining most of the code in one place, it became possible to add more features in a consistent way. The 'loadables' feature much easier to plumb in, for example. While fit_image_load() was a substantial advance, it has never been a svelte function and the passing years have not been entirely kind. With a few new features on the horizon, this is a good time to improve the implementation. This series splits much of the code from fit_image_load() into a number of smaller functions. Most of the changes are fairly mechanical, with just a few renames and tweaks here and there. This should make the function much easier to maintain. It may also encourage someone to take a look at its callers, which could also use some attention. Changes in v2: - Drop separate fit_uname variable in select_image() Simon Glass (18): efi: Drop information about removing C flags test: fit: Avoid restarting U-Boot test: Rename test_fit() to test_fit_base() sandbox: Adjust how OS-interface files are built test: Add a check for a missing kernel boot: Split out the first part of fit_image_load() boot: Move call to fit_image_select() and rename it boot: Tidy up setting of the OS arch on host builds boot: Move type and OS checking into a new function boot: Move handling of the load_op into a separate function boot: Move obtaining data from a FIT image into a function boot: Check the image is allowed before setting os.arch boot: Move the architecture check into check_allowed() boot: Move image-decompression into a separate function boot: Move decomp_image() into handle_load_op() boot: Move setting the OS arch into check_allowed() boot: Drop unnecessary data variable boot: Tidy local variables in fit_image_load() arch/sandbox/Makefile | 2 +- arch/sandbox/cpu/Makefile | 23 +-- boot/image-fit.c | 336 ++++++++++++++++++++++++++++---------- include/image.h | 11 +- lib/efi_client/Makefile | 1 - scripts/Makefile.lib | 16 +- test/py/tests/test_fit.py | 48 +++--- 7 files changed, 297 insertions(+), 140 deletions(-) -- 2.43.0 base-commit: d3d71c2fc469909bfa7ad134c88235aa9ad590f3 branch: load2

From: Simon Glass <sjg@chromium.org> A 'removing flags -mregparm=3' message appears when building sometimes. It isn't very useful and does not indicate a problem, so remove it. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) lib/efi_client/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/efi_client/Makefile b/lib/efi_client/Makefile index d7a3232c6bb..7b53f8fb9fb 100644 --- a/lib/efi_client/Makefile +++ b/lib/efi_client/Makefile @@ -28,5 +28,4 @@ CFLAGS_stub.o += -fpic -fshort-wchar CFLAGS_REMOVE_efi.o += -mregparm=3 CFLAGS_efi.o += -fpic -fshort-wchar -$(info removing flags $(CFLAGS_REMOVE_$(stub_obj))) extra-$(CONFIG_EFI_STUB) += $(stub_obj) stub.o efi.o -- 2.43.0

From: Simon Glass <sjg@chromium.org> We don't actually need to use the test FDT as the control FDT. It slows down the test since U-Boot needs to be restarted each time. Instead of restarting, update the test to clear memory before it loads the FIT. Rename the data-variable to fdt_data since is it no-longer the control FDT. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) test/py/tests/test_fit.py | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 619f73153a0..002fd85847a 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -104,6 +104,7 @@ base_fdt = ''' # then run the 'bootm' command, then save out memory from the places where # we expect 'bootm' to write things. Then quit. base_script = ''' +mw 0 0 180000 host load hostfs 0 %(fit_addr)x %(fit)s fdt addr %(fit_addr)x bootm start %(fit_addr)x @@ -260,7 +261,7 @@ def test_fit(ubman): - run code coverage to make sure we are testing all the code """ # Set up invariant files - control_dtb = fit_util.make_dtb(ubman, base_fdt, 'u-boot') + fdt_data = fit_util.make_dtb(ubman, base_fdt, 'u-boot') kernel = fit_util.make_kernel(ubman, 'test-kernel.bin', 'kernel') ramdisk = make_ramdisk('test-ramdisk.bin', 'ramdisk') loadables1 = fit_util.make_kernel(ubman, 'test-loadables1.bin', 'lenrek') @@ -284,7 +285,7 @@ def test_fit(ubman): 'fdt' : fdt, 'fdt_out' : fdt_out, 'fdt_addr' : 0x80000, - 'fdt_size' : filesize(control_dtb), + 'fdt_size' : filesize(fdt_data), 'fdt_load' : '', 'ramdisk' : ramdisk, @@ -317,12 +318,10 @@ def test_fit(ubman): # First check that we can load a kernel # We could perhaps reduce duplication with some loss of readability - ubman.config.dtb = control_dtb - ubman.restart_uboot() with ubman.log.section('Kernel load'): output = ubman.run_command_list(cmd.splitlines()) check_equal(kernel, kernel_out, 'Kernel not loaded') - check_not_equal(control_dtb, fdt_out, + check_not_equal(fdt_data, fdt_out, 'FDT loaded but should be ignored') check_not_equal(ramdisk, ramdisk_out, 'Ramdisk loaded but should not be') @@ -351,10 +350,9 @@ def test_fit(ubman): with ubman.log.section('Kernel + FDT load'): params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] fit = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() output = ubman.run_command_list(cmd.splitlines()) check_equal(kernel, kernel_out, 'Kernel not loaded') - check_equal(control_dtb, fdt_out, 'FDT not loaded') + check_equal(fdt_data, fdt_out, 'FDT not loaded') check_not_equal(ramdisk, ramdisk_out, 'Ramdisk loaded but should not be') @@ -363,7 +361,6 @@ def test_fit(ubman): params['ramdisk_config'] = 'ramdisk = "ramdisk-1";' params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] fit = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() output = ubman.run_command_list(cmd.splitlines()) check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded') @@ -375,7 +372,6 @@ def test_fit(ubman): params['loadables2_load'] = ('load = <%#x>;' % params['loadables2_addr']) fit = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() output = ubman.run_command_list(cmd.splitlines()) check_equal(loadables1, loadables1_out, 'Loadables1 (kernel) not loaded') @@ -389,21 +385,12 @@ def test_fit(ubman): params['fdt'] = make_compressed(fdt) params['ramdisk'] = make_compressed(ramdisk) fit = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() output = ubman.run_command_list(cmd.splitlines()) check_equal(kernel, kernel_out, 'Kernel not loaded') - check_equal(control_dtb, fdt_out, 'FDT not loaded') + check_equal(fdt_data, fdt_out, 'FDT not loaded') check_not_equal(ramdisk, ramdisk_out, 'Ramdisk got decompressed?') check_equal(ramdisk + '.gz', ramdisk_out, 'Ramdist not loaded') - # We need to use our own device tree file. Remember to restore it - # afterwards. - old_dtb = ubman.config.dtb - try: - mkimage = ubman.config.build_dir + '/tools/mkimage' - run_fit_test(mkimage) - finally: - # Go back to the original U-Boot with the correct dtb. - ubman.config.dtb = old_dtb - ubman.restart_uboot() + mkimage = ubman.config.build_dir + '/tools/mkimage' + run_fit_test(mkimage) -- 2.43.0

From: Simon Glass <sjg@chromium.org> The current name is uses as a root name by a few other tests, such as test_fit_ecdsa() which makes it hard to run just this test. Rename it to test_fit_base() Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) test/py/tests/test_fit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 002fd85847a..f34f4614324 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -119,7 +119,7 @@ host save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('fit_signature') @pytest.mark.requiredtool('dtc') -def test_fit(ubman): +def test_fit_base(ubman): def make_fname(leaf): """Make a temporary filename -- 2.43.0

From: Simon Glass <sjg@chromium.org> The current mechanism uses a completely separate build rule for each file which must be built with system headers. Before adding any more files, adjust the scheme so that the flags are handled in the common Makefile, with sandbox simply listing the files affected. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) arch/sandbox/Makefile | 2 +- arch/sandbox/cpu/Makefile | 23 ++++------------------- scripts/Makefile.lib | 16 +++++++++++----- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile index a335f8acfde..5bbf9f1f96b 100644 --- a/arch/sandbox/Makefile +++ b/arch/sandbox/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+ -head-y := arch/sandbox/cpu/start.o arch/sandbox/cpu/os.o +head-y := arch/sandbox/cpu/start.o head-$(CONFIG_SANDBOX_SDL) += arch/sandbox/cpu/sdl.o libs-y += arch/sandbox/cpu/ libs-y += arch/sandbox/lib/ diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index aac65e48675..03cdf2ae0f1 100644 --- a/arch/sandbox/cpu/Makefile +++ b/arch/sandbox/cpu/Makefile @@ -5,29 +5,14 @@ # (C) Copyright 2000-2003 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-y := cache.o cpu.o mem.o state.o -extra-y := start.o os.o +obj-y := cache.o cpu.o mem.o state.o os.o +extra-y := start.o extra-$(CONFIG_SANDBOX_SDL) += sdl.o obj-$(CONFIG_XPL_BUILD) += spl.o obj-$(CONFIG_ETH_SANDBOX_RAW) += eth-raw-os.o -# os.c is build in the system environment, so needs standard includes -# CFLAGS_REMOVE_os.o cannot be used to drop header include path -quiet_cmd_cc_os.o = CC $(quiet_modtag) $@ -cmd_cc_os.o = $(CC) $(filter-out -nostdinc, \ - $(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $< - -$(obj)/os.o: $(src)/os.c FORCE - $(call if_changed_dep,cc_os.o) - -# eth-raw-os.c is built in the system env, so needs standard includes -# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path -quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag) $@ -cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \ - $(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $< - -$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE - $(call if_changed_dep,cc_eth-raw-os.o) +# Compile these files with system headers +CFLAGS_USE_SYSHDRS := eth-raw-os.o os.o sdl.o # sdl.c fails to build with -fshort-wchar using musl cmd_cc_sdl.o = $(CC) $(filter-out -nostdinc -fshort-wchar, \ diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 4102e662c5f..6d6a21f262a 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -162,15 +162,21 @@ __cpp_flags = $(call flags,_cpp_flags) endif endif -# Modified for U-Boot: LINUXINCLUDE -> UBOOTINCLUDE -c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(UBOOTINCLUDE) \ - $(__c_flags) $(modkern_cflags) \ +# Handle special sandbox files which need to be built with system headers +use_syshdrs = $(filter $(basetarget).o, $(CFLAGS_USE_SYSHDRS)) +nostdinc = $(if $(use_syshdrs),,$(NOSTDINC_FLAGS)) +ubootinclude = $(if $(use_syshdrs),$(patsubst -I%,-idirafter%,\ + $(UBOOTINCLUDE)),$(UBOOTINCLUDE)) + +# Modified for U-Boot: NOSTDINC_FLAGS -> nostdinc and LINUXINCLUDE -> ubootinclude +c_flags = -Wp,-MD,$(depfile) $(nostdinc) $(ubootinclude) \ + $(__c_flags) $(modkern_cflags) \ $(basename_flags) $(modname_flags) -a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(UBOOTINCLUDE) \ +a_flags = -Wp,-MD,$(depfile) $(nostdinc) $(ubootinclude) \ $(__a_flags) $(modkern_aflags) -cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(UBOOTINCLUDE) \ +cpp_flags = -Wp,-MD,$(depfile) $(nostdinc) $(ubootinclude) \ $(__cpp_flags) ld_flags = $(KBUILD_LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) -- 2.43.0

From: Simon Glass <sjg@chromium.org> U-Boot should complain if the kernel is missing, so add a check for this in test_fit_base() Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) test/py/tests/test_fit.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index f34f4614324..756b6809600 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -70,7 +70,7 @@ base_its = ''' configurations { default = "conf-1"; conf-1 { - kernel = "kernel-1"; + %(kernel_config)s fdt = "fdt-1"; %(ramdisk_config)s %(loadables_config)s @@ -281,6 +281,7 @@ def test_fit_base(ubman): 'kernel_out' : kernel_out, 'kernel_addr' : 0x40000, 'kernel_size' : filesize(kernel), + 'kernel_config' : 'kernel = "kernel-1";', 'fdt' : fdt, 'fdt_out' : fdt_out, @@ -389,8 +390,16 @@ def test_fit_base(ubman): check_equal(kernel, kernel_out, 'Kernel not loaded') check_equal(fdt_data, fdt_out, 'FDT not loaded') check_not_equal(ramdisk, ramdisk_out, 'Ramdisk got decompressed?') - check_equal(ramdisk + '.gz', ramdisk_out, 'Ramdist not loaded') + check_equal(ramdisk + '.gz', ramdisk_out, 'Ramdisk not loaded') + # Try without a kernel + with ubman.log.section('No kernel + FDT'): + params['kernel_config'] = '' + params['ramdisk_config'] = '' + params['ramdisk_load'] = '' + fit = fit_util.make_fit(ubman, mkimage, base_its, params) + output = ubman.run_command_list(cmd.splitlines()) + assert "can't get kernel image!" in '\n'.join(output) mkimage = ubman.config.build_dir + '/tools/mkimage' run_fit_test(mkimage) -- 2.43.0

From: Simon Glass <sjg@chromium.org> This function is over 250 lines long. Split out the image-selection part into its own function. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: - Drop separate fit_uname variable in select_image() boot/image-fit.c | 99 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index f67627680bd..a86dc721348 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2054,33 +2054,34 @@ static const char *fit_get_image_type_property(int ph_type) return "unknown"; } -int fit_image_load(struct bootm_headers *images, ulong addr, - const char **fit_unamep, const char **fit_uname_configp, - int arch, int ph_type, int bootstage_id, - enum fit_load_op load_op, ulong *datap, ulong *lenp) +/** + * select_image() - Select the image to load + * + * image->fit_uname_cfg is set if the image type is IH_TYPE_KERNEL + * + * @fit: Pointer to FIT + * @images: Boot images structure + * @fit_unamep: On entry *fit_unamep is a pointer to the requested image name + * (e.g. "kernel") or *fit_unamep is NULL to use the default. On exist, set to + * the selected image name. Note that fit_unamep cannot be NULL + * @fit_uname_config: Requested configuration name (e.g. "conf-1") or NULL to + * use the default + * @ph_type: Required image type (IH_TYPE_...) and phase (IH_PHASE_...) + * @bootstage_id: ID of starting bootstage to use for progress updates + * @fit_base_uname_configp: Returns config name selected, or NULL if *fit_unamep + * was used to select an image node + * Return: node offset of image node, on success, else -ve error code + */ +static int select_image(const void *fit, struct bootm_headers *images, + const char **fit_unamep, const char *fit_uname_config, + const char *prop_name, int ph_type, int bootstage_id, + const char **fit_base_uname_configp) { - int image_type = image_ph_type(ph_type); int cfg_noffset, noffset; - const char *fit_uname; - const char *fit_uname_config; - const char *fit_base_uname_config; - const void *fit; - void *buf; - void *loadbuf; - size_t size; - int type_ok, os_ok; - ulong load, load_end, data, len; - uint8_t os, comp; - const char *prop_name; int ret; - fit = map_sysmem(addr, 0); - fit_uname = fit_unamep ? *fit_unamep : NULL; - fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL; - fit_base_uname_config = NULL; + *fit_base_uname_configp = NULL; prop_name = fit_get_image_type_property(ph_type); - printf("## Loading %s (%s) from FIT Image at %08lx ...\n", - prop_name, genimg_get_phase_name(image_ph_phase(ph_type)), addr); bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); ret = fit_check_format(fit, IMAGE_SIZE_INVAL); @@ -2092,10 +2093,10 @@ int fit_image_load(struct bootm_headers *images, ulong addr, return ret; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); - if (fit_uname) { + if (*fit_unamep) { /* get FIT component image node offset */ bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); - noffset = fit_image_get_node(fit, fit_uname); + noffset = fit_image_get_node(fit, *fit_unamep); } else { /* * no image node unit name, try to get config @@ -2116,11 +2117,12 @@ int fit_image_load(struct bootm_headers *images, ulong addr, } cfg_noffset = ret; - fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL); - printf(" Using '%s' configuration\n", fit_base_uname_config); + *fit_base_uname_configp = fdt_get_name(fit, cfg_noffset, NULL); + printf(" Using '%s' configuration\n", + *fit_base_uname_configp); /* Remember this config */ - if (image_type == IH_TYPE_KERNEL) - images->fit_uname_cfg = fit_base_uname_config; + if (image_ph_type(ph_type) == IH_TYPE_KERNEL) + images->fit_uname_cfg = *fit_base_uname_configp; if (FIT_IMAGE_ENABLE_VERIFY && images->verify) { puts(" Verifying Hash Integrity ... "); @@ -2137,15 +2139,52 @@ int fit_image_load(struct bootm_headers *images, ulong addr, noffset = fit_conf_get_prop_node(fit, cfg_noffset, prop_name, image_ph_phase(ph_type)); - fit_uname = fit_get_name(fit, noffset, NULL); + *fit_unamep = fit_get_name(fit, noffset, NULL); } + if (noffset < 0) { printf("Could not find subimage node type '%s'\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); return -ENOENT; } - printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); + printf(" Trying '%s' %s subimage\n", *fit_unamep, prop_name); + + return noffset; +} + +int fit_image_load(struct bootm_headers *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, int ph_type, int bootstage_id, + enum fit_load_op load_op, ulong *datap, ulong *lenp) +{ + int image_type = image_ph_type(ph_type); + int noffset; + const char *fit_uname; + const char *fit_uname_config; + const char *fit_base_uname_config; + const void *fit; + void *buf; + void *loadbuf; + size_t size; + int type_ok, os_ok; + ulong load, load_end, data, len; + uint8_t os, comp; + const char *prop_name; + int ret; + + fit = map_sysmem(addr, 0); + prop_name = fit_get_image_type_property(ph_type); + printf("## Loading %s (%s) from FIT Image at %08lx ...\n", + prop_name, genimg_get_phase_name(image_ph_phase(ph_type)), addr); + + fit_uname = fit_unamep ? *fit_unamep : NULL; + fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL; + noffset = select_image(fit, images, &fit_uname, fit_uname_config, + prop_name, ph_type, bootstage_id, + &fit_base_uname_config); + if (noffset < 0) + return noffset; ret = fit_image_select(fit, noffset, images->verify); if (ret) { -- 2.43.0

From: Simon Glass <sjg@chromium.org> This function is named a bit vaguely, since it prints some info and then does verification of the image. Rename it to print_and_verify() and move the call to select_image(). Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index a86dc721348..f8e13d524de 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -1973,7 +1973,7 @@ int fit_get_data_conf_prop(const void *fit, const char *prop_name, return fit_get_data_tail(fit, noffset, data, size); } -static int fit_image_select(const void *fit, int rd_noffset, int verify) +static int print_and_verify(const void *fit, int rd_noffset, int verify) { fit_image_print(fit, rd_noffset, " "); @@ -2149,6 +2149,11 @@ static int select_image(const void *fit, struct bootm_headers *images, } printf(" Trying '%s' %s subimage\n", *fit_unamep, prop_name); + ret = print_and_verify(fit, noffset, images->verify); + if (ret) { + bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); + return ret; + } return noffset; } @@ -2171,7 +2176,6 @@ int fit_image_load(struct bootm_headers *images, ulong addr, ulong load, load_end, data, len; uint8_t os, comp; const char *prop_name; - int ret; fit = map_sysmem(addr, 0); prop_name = fit_get_image_type_property(ph_type); @@ -2186,12 +2190,6 @@ int fit_image_load(struct bootm_headers *images, ulong addr, if (noffset < 0) return noffset; - ret = fit_image_select(fit, noffset, images->verify); - if (ret) { - bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); - return ret; - } - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) { if (!fit_image_check_target_arch(fit, noffset)) { -- 2.43.0

From: Simon Glass <sjg@chromium.org> This field is not present in host builds. Create an inline function to handle this complexity, so we can drop the #ifdef in the C file. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 10 ++-------- include/image.h | 7 +++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index f8e13d524de..954d32bded4 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2174,7 +2174,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr, size_t size; int type_ok, os_ok; ulong load, load_end, data, len; - uint8_t os, comp; + uint8_t os, comp, os_arch; const char *prop_name; fit = map_sysmem(addr, 0); @@ -2199,14 +2199,8 @@ int fit_image_load(struct bootm_headers *images, ulong addr, } } -#ifndef USE_HOSTCC - { - uint8_t os_arch; - fit_image_get_arch(fit, noffset, &os_arch); - images->os.arch = os_arch; - } -#endif + images_set_arch(images, os_arch); bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); type_ok = fit_image_check_type(fit, noffset, image_type) || diff --git a/include/image.h b/include/image.h index 283cc9c5741..3a6afb5d954 100644 --- a/include/image.h +++ b/include/image.h @@ -459,6 +459,13 @@ struct bootm_headers { extern struct bootm_headers images; +static inline void images_set_arch(struct bootm_headers *images, int os_arch) +{ +#ifndef USE_HOSTCC + images->os.arch = os_arch; +#endif +} + /* * Some systems (for example LWMON) have very short watchdog periods; * we must make sure to split long operations like memmove() or -- 2.43.0

From: Simon Glass <sjg@chromium.org> Move the code which checks whether the image can be loaded into a separate check_allowed() function. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 98 ++++++++++++++++++++++++++++++------------------ include/image.h | 4 +- 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 954d32bded4..c9a3413862c 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2158,9 +2158,64 @@ static int select_image(const void *fit, struct bootm_headers *images, return noffset; } +/** + * check_allowed() - Check if an image is allowed to be loaded + * + * @fit: FIT to check + * @noffset: Node offset of the image being loaded + * @image_type: Type of the image + * @arch: Expected architecture for the image + * @bootstage_id: ID of starting bootstage to use for progress updates + * Return: 0 if OK, -EIO if not + */ +static int check_allowed(const void *fit, int noffset, + enum image_type_t image_type, enum image_arch_t arch, + int bootstage_id) +{ + bool type_ok, os_ok; + uint8_t os; + + 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) || + fit_image_check_type(fit, noffset, IH_TYPE_TEE) || + fit_image_check_type(fit, noffset, IH_TYPE_TFA_BL31) || + (image_type == IH_TYPE_KERNEL && + fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); + + os_ok = image_type == IH_TYPE_FLATDT || + image_type == IH_TYPE_FPGA || + fit_image_check_os(fit, noffset, IH_OS_LINUX) || + fit_image_check_os(fit, noffset, IH_OS_U_BOOT) || + fit_image_check_os(fit, noffset, IH_OS_TEE) || + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || + fit_image_check_os(fit, noffset, IH_OS_EFI) || + fit_image_check_os(fit, noffset, IH_OS_VXWORKS) || + fit_image_check_os(fit, noffset, IH_OS_ELF); + + /* + * If either of the checks fail, we should report an error, but + * if the image type is coming from the "loadables" field, we + * don't care what it is + */ + if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) { + fit_image_get_os(fit, noffset, &os); + printf("No %s %s %s Image\n", + genimg_get_os_name(os), + genimg_get_arch_name(arch), + genimg_get_type_name(image_type)); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); + return -EIO; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); + + return 0; +} + int fit_image_load(struct bootm_headers *images, ulong addr, const char **fit_unamep, const char **fit_uname_configp, - int arch, int ph_type, int bootstage_id, + enum image_arch_t arch, int ph_type, int bootstage_id, enum fit_load_op load_op, ulong *datap, ulong *lenp) { int image_type = image_ph_type(ph_type); @@ -2172,10 +2227,10 @@ int fit_image_load(struct bootm_headers *images, ulong addr, void *buf; void *loadbuf; size_t size; - int type_ok, os_ok; ulong load, load_end, data, len; - uint8_t os, comp, os_arch; + uint8_t comp, os_arch; const char *prop_name; + int ret; fit = map_sysmem(addr, 0); prop_name = fit_get_image_type_property(ph_type); @@ -2202,40 +2257,9 @@ int fit_image_load(struct bootm_headers *images, ulong addr, fit_image_get_arch(fit, noffset, &os_arch); images_set_arch(images, os_arch); - 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) || - fit_image_check_type(fit, noffset, IH_TYPE_TEE) || - fit_image_check_type(fit, noffset, IH_TYPE_TFA_BL31) || - (image_type == IH_TYPE_KERNEL && - fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); - - os_ok = image_type == IH_TYPE_FLATDT || - image_type == IH_TYPE_FPGA || - fit_image_check_os(fit, noffset, IH_OS_LINUX) || - fit_image_check_os(fit, noffset, IH_OS_U_BOOT) || - fit_image_check_os(fit, noffset, IH_OS_TEE) || - fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || - fit_image_check_os(fit, noffset, IH_OS_EFI) || - fit_image_check_os(fit, noffset, IH_OS_VXWORKS) || - fit_image_check_os(fit, noffset, IH_OS_ELF); - - /* - * If either of the checks fail, we should report an error, but - * if the image type is coming from the "loadables" field, we - * don't care what it is - */ - if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) { - fit_image_get_os(fit, noffset, &os); - printf("No %s %s %s Image\n", - genimg_get_os_name(os), - genimg_get_arch_name(arch), - genimg_get_type_name(image_type)); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); - return -EIO; - } - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); + ret = check_allowed(fit, noffset, image_type, arch, bootstage_id); + if (ret) + return ret; /* get image data address and length */ if (fit_image_get_data(fit, noffset, (const void **)&buf, &size)) { diff --git a/include/image.h b/include/image.h index 3a6afb5d954..0402cf92219 100644 --- a/include/image.h +++ b/include/image.h @@ -113,7 +113,7 @@ enum { * New IDs *MUST* be appended at the end of the list and *NEVER* * inserted for backward compatibility. */ -enum { +enum image_arch_t { IH_ARCH_INVALID = 0, /* Invalid CPU */ IH_ARCH_ALPHA, /* Alpha */ IH_ARCH_ARM, /* ARM */ @@ -837,7 +837,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, */ int fit_image_load(struct bootm_headers *images, ulong addr, const char **fit_unamep, const char **fit_uname_configp, - int arch, int image_ph_type, int bootstage_id, + enum image_arch_t arch, int image_ph_type, int bootstage_id, enum fit_load_op load_op, ulong *datap, ulong *lenp); /** -- 2.43.0

From: Simon Glass <sjg@chromium.org> Since fit_image_load() is still too long, move the load-operation handling into a separate function. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 107 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index c9a3413862c..97b26c3171f 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2213,6 +2213,75 @@ static int check_allowed(const void *fit, int noffset, return 0; } +/** + * handle_load_op() - Handle the load operation + * + * Process the load_op and figure out where the image should be loaded, now + * that it has been located + * + * @fit: FIT to check + * @noffset: Node offset of the image being loaded + * @prop_name: Property name (in the configuration node) indicating the image + * that was loaded + * @buf: Pointer to image (within the FIT) + * @size: Size of the image in bytes + * @image_type: Type of the image + * @load_op: Load operation to process + * @bootstage_id: ID of starting bootstage to use for progress updates + * @datap: Returns buf + * @loadp: Returns the address to which the data should be loaded + * @load_endp: Returns the end address of the data-loading location + * Return: 0 if OK, -ve on error + */ +static int handle_load_op(const void *fit, int noffset, const char *prop_name, + const void *buf, ulong size, + enum image_type_t image_type, + enum fit_load_op load_op, int bootstage_id, + ulong *datap, ulong *loadp, ulong *load_endp) +{ + ulong data, load; + + data = map_to_sysmem(buf); + load = data; + *load_endp = 0; + if (load_op == FIT_LOAD_IGNORED) { + log_debug("load_op: not loading\n"); + /* Don't load */ + } else if (fit_image_get_load(fit, noffset, &load)) { + if (load_op == FIT_LOAD_REQUIRED) { + printf("Can't get %s subimage load address!\n", + prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); + return -EBADF; + } + } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) { + ulong image_start, image_end; + + /* + * move image data to the load address, + * make sure we don't overwrite initial image + */ + image_start = map_to_sysmem(fit); + image_end = image_start + fit_get_size(fit); + + *load_endp = load + size; + if (image_type != IH_TYPE_KERNEL && + load < image_end && *load_endp > image_start) { + printf("Error: %s overwritten\n", prop_name); + return -EXDEV; + } + + printf(" Loading %s from 0x%08lx to 0x%08lx\n", + prop_name, data, load); + } else { + load = data; /* No load address specified */ + } + *datap = data; + *loadp = load; + + return 0; +} + int fit_image_load(struct bootm_headers *images, ulong addr, const char **fit_unamep, const char **fit_uname_configp, enum image_arch_t arch, int ph_type, int bootstage_id, @@ -2286,40 +2355,10 @@ int fit_image_load(struct bootm_headers *images, ulong addr, bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); - data = map_to_sysmem(buf); - load = data; - if (load_op == FIT_LOAD_IGNORED) { - log_debug("load_op: not loading\n"); - /* Don't load */ - } else if (fit_image_get_load(fit, noffset, &load)) { - if (load_op == FIT_LOAD_REQUIRED) { - printf("Can't get %s subimage load address!\n", - prop_name); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); - return -EBADF; - } - } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) { - ulong image_start, image_end; - - /* - * move image data to the load address, - * make sure we don't overwrite initial image - */ - image_start = addr; - image_end = addr + fit_get_size(fit); - - load_end = load + len; - if (image_type != IH_TYPE_KERNEL && - load < image_end && load_end > image_start) { - printf("Error: %s overwritten\n", prop_name); - return -EXDEV; - } - - printf(" Loading %s from 0x%08lx to 0x%08lx\n", - prop_name, data, load); - } else { - load = data; /* No load address specified */ - } + ret = handle_load_op(fit, noffset, prop_name, buf, len, image_type, + load_op, bootstage_id, &data, &load, &load_end); + if (ret) + return ret; comp = IH_COMP_NONE; loadbuf = buf; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Move this code into a separate function, to help further slim down fit_image_load(). Move the bootstage_mark() call in there too. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 75 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 97b26c3171f..9d99bfd4d82 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2213,6 +2213,53 @@ static int check_allowed(const void *fit, int noffset, return 0; } +/** + * obtain_data() - Obtain the data from the FIT + * + * Get the location of the data in the FIT and see if it needs to be deciphered + * or processed in some grubby board-specific way. + * + * @fit: FIT to check + * @noffset: Node offset of the image being loaded + * @prop_name: Property name (in the configuration node) indicating the image + * that was loaded + * @bootstage_id: ID of starting bootstage to use for progress updates + * @bufp: Returns a pointer to the data + * @size: Returns the size of the data + * Return: 0 if OK, -ve on error + */ +static int obtain_data(const void *fit, int noffset, const char *prop_name, + int bootstage_id, void *bufp, ulong *sizep) +{ + size_t size; + + /* get image data address and length */ + if (fit_image_get_data(fit, noffset, (const void **)bufp, &size)) { + printf("Could not find %s subimage data!\n", prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); + return -ENOENT; + } + + /* Decrypt data before uncompress/move */ + if (IS_ENABLED(CONFIG_FIT_CIPHER) && IMAGE_ENABLE_DECRYPT) { + puts(" Decrypting Data ... "); + if (fit_image_uncipher(fit, noffset, bufp, &size)) { + puts("Error\n"); + return -EACCES; + } + puts("OK\n"); + } + + /* perform any post-processing on the image data */ + if (!tools_build() && IS_ENABLED(CONFIG_FIT_IMAGE_POST_PROCESS)) + board_fit_image_post_process(fit, noffset, bufp, &size); + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); + *sizep = size; + + return 0; +} + /** * handle_load_op() - Handle the load operation * @@ -2295,7 +2342,6 @@ int fit_image_load(struct bootm_headers *images, ulong addr, const void *fit; void *buf; void *loadbuf; - size_t size; ulong load, load_end, data, len; uint8_t comp, os_arch; const char *prop_name; @@ -2330,30 +2376,9 @@ int fit_image_load(struct bootm_headers *images, ulong addr, if (ret) return ret; - /* get image data address and length */ - if (fit_image_get_data(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; - } - - /* Decrypt data before uncompress/move */ - if (IS_ENABLED(CONFIG_FIT_CIPHER) && IMAGE_ENABLE_DECRYPT) { - puts(" Decrypting Data ... "); - if (fit_image_uncipher(fit, noffset, &buf, &size)) { - puts("Error\n"); - return -EACCES; - } - puts("OK\n"); - } - - /* perform any post-processing on the image data */ - if (!tools_build() && IS_ENABLED(CONFIG_FIT_IMAGE_POST_PROCESS)) - board_fit_image_post_process(fit, noffset, &buf, &size); - - len = (ulong)size; - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); + ret = obtain_data(fit, noffset, prop_name, bootstage_id, &buf, &len); + if (ret) + return ret; ret = handle_load_op(fit, noffset, prop_name, buf, len, image_type, load_op, bootstage_id, &data, &load, &load_end); -- 2.43.0

From: Simon Glass <sjg@chromium.org> There is no point in setting the architecture if the image cannot be used. Move the check a little higher within fit_image_load(). Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 9d99bfd4d82..d4901d8e6d2 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2369,13 +2369,13 @@ int fit_image_load(struct bootm_headers *images, ulong addr, } } - fit_image_get_arch(fit, noffset, &os_arch); - images_set_arch(images, os_arch); - ret = check_allowed(fit, noffset, image_type, arch, bootstage_id); if (ret) return ret; + fit_image_get_arch(fit, noffset, &os_arch); + images_set_arch(images, os_arch); + ret = obtain_data(fit, noffset, prop_name, bootstage_id, &buf, &len); if (ret) return ret; -- 2.43.0

From: Simon Glass <sjg@chromium.org> We may as well have all the checks together, so move the call to fit_image_check_target_arch() into check_allowed(). Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index d4901d8e6d2..cd2052be0a4 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2175,6 +2175,15 @@ static int check_allowed(const void *fit, int noffset, bool type_ok, os_ok; uint8_t os; + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); + if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) { + if (!fit_image_check_target_arch(fit, noffset)) { + puts("Unsupported Architecture\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); + return -ENOEXEC; + } + } + 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) || @@ -2360,15 +2369,6 @@ int fit_image_load(struct bootm_headers *images, ulong addr, if (noffset < 0) return noffset; - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); - if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) { - if (!fit_image_check_target_arch(fit, noffset)) { - puts("Unsupported Architecture\n"); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); - return -ENOEXEC; - } - } - ret = check_allowed(fit, noffset, image_type, arch, bootstage_id); if (ret) return ret; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Move handling of decompression (or perhaps relocation) of the image into a separate function, to slim down fit_image_load() a little more. Move the bootstage_mark() call in there too. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 135 +++++++++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 45 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index cd2052be0a4..e08e229f6d4 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2269,6 +2269,91 @@ static int obtain_data(const void *fit, int noffset, const char *prop_name, return 0; } +/** + * decomp_image() - Decompress / relocate the image + * + * If the image is compressed, decompress it to the provided load address, + * making sure it fits within the allowed space. + * + * If the image is not compressed, copy it (to the load address)if needed. + * + * Kernels are not decompressed here, since that is handled in bootm_load_os() + * + * Compression is ignored on ramdisks, although a warning is provided. Since the + * ramdisk normally uses its own compression, doing additional compression at + * the FIT level is counter-productive. + * + * For devicetree, check that the image is actually a devicetree + * + * @fit: FIT to check + * @noffset: Node offset of the image being loaded + * @prop_name: Property name (in the configuration node) indicating the image + * that was loaded + * @buf: Pointer to image (within the FIT) + * @size: Size of the image in bytes + * @image_type: Type of the image + * @load_op: Load operation to process + * @bootstage_id: ID of starting bootstage to use for progress updates + * @data: Data buffer + * @load: Address to which the data should be loaded + * @load_end: End address of the data-loading location + * Return: 0 if OK, -ve on error + */ +int decomp_image(const void *fit, int noffset, const char *prop_name, + void *buf, ulong size, enum image_type_t image_type, + enum fit_load_op load_op, int bootstage_id, ulong data, + ulong load, ulong load_end) +{ + void *loadbuf; + uint8_t comp; + + comp = IH_COMP_NONE; + loadbuf = buf; + /* Kernel images get decompressed later in bootm_load_os(). */ + if (!fit_image_get_comp(fit, noffset, &comp) && + comp != IH_COMP_NONE && + load_op != FIT_LOAD_IGNORED && + !(image_type == IH_TYPE_KERNEL || + image_type == IH_TYPE_KERNEL_NOLOAD || + image_type == IH_TYPE_RAMDISK)) { + ulong max_decomp_len = size * 20; + + log_debug("decompressing image\n"); + 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, + size, max_decomp_len, &load_end)) { + printf("Error decompressing %s\n", prop_name); + + return -ENOEXEC; + } + size = load_end - load; + } else if (load != data) { + log_debug("copying\n"); + loadbuf = map_sysmem(load, size); + memcpy(loadbuf, buf, size); + } + + if (image_type == IH_TYPE_RAMDISK && comp != IH_COMP_NONE) + puts("WARNING: 'compression' nodes for ramdisks are deprecated," + " please fix your .its file!\n"); + + /* verify that image data is a proper FDT blob */ + if (load_op != FIT_LOAD_IGNORED && image_type == IH_TYPE_FLATDT && + fdt_check_header(loadbuf)) { + puts("Subimage data is not a FDT\n"); + return -ENOEXEC; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); + + return 0; +} + /** * handle_load_op() - Handle the load operation * @@ -2350,9 +2435,8 @@ int fit_image_load(struct bootm_headers *images, ulong addr, const char *fit_base_uname_config; const void *fit; void *buf; - void *loadbuf; ulong load, load_end, data, len; - uint8_t comp, os_arch; + uint8_t os_arch; const char *prop_name; int ret; @@ -2385,49 +2469,10 @@ int fit_image_load(struct bootm_headers *images, ulong addr, if (ret) return ret; - comp = IH_COMP_NONE; - loadbuf = buf; - /* Kernel images get decompressed later in bootm_load_os(). */ - if (!fit_image_get_comp(fit, noffset, &comp) && - comp != IH_COMP_NONE && - load_op != FIT_LOAD_IGNORED && - !(image_type == IH_TYPE_KERNEL || - image_type == IH_TYPE_KERNEL_NOLOAD || - image_type == IH_TYPE_RAMDISK)) { - ulong max_decomp_len = len * 20; - - log_debug("decompressing image\n"); - 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); - - return -ENOEXEC; - } - len = load_end - load; - } else if (load != data) { - log_debug("copying\n"); - loadbuf = map_sysmem(load, len); - memcpy(loadbuf, buf, len); - } - - if (image_type == IH_TYPE_RAMDISK && comp != IH_COMP_NONE) - puts("WARNING: 'compression' nodes for ramdisks are deprecated," - " please fix your .its file!\n"); - - /* verify that image data is a proper FDT blob */ - if (load_op != FIT_LOAD_IGNORED && image_type == IH_TYPE_FLATDT && - fdt_check_header(loadbuf)) { - puts("Subimage data is not a FDT\n"); - return -ENOEXEC; - } - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); + ret = decomp_image(fit, noffset, prop_name, buf, len, image_type, + load_op, bootstage_id, data, load, load_end); + if (ret) + return ret; upl_add_image(fit, noffset, load, len); -- 2.43.0

From: Simon Glass <sjg@chromium.org> Decompress is really part of loading, so simplify the code slightly by moving decompression out of the top-level fit_image_load() function. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index e08e229f6d4..244397b26c5 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2358,7 +2358,8 @@ int decomp_image(const void *fit, int noffset, const char *prop_name, * handle_load_op() - Handle the load operation * * Process the load_op and figure out where the image should be loaded, now - * that it has been located + * that it has been located. Decompress and move as necessary to get the image + * into the right place - see decomp_image() * * @fit: FIT to check * @noffset: Node offset of the image being loaded @@ -2371,20 +2372,19 @@ int decomp_image(const void *fit, int noffset, const char *prop_name, * @bootstage_id: ID of starting bootstage to use for progress updates * @datap: Returns buf * @loadp: Returns the address to which the data should be loaded - * @load_endp: Returns the end address of the data-loading location * Return: 0 if OK, -ve on error */ static int handle_load_op(const void *fit, int noffset, const char *prop_name, - const void *buf, ulong size, - enum image_type_t image_type, + void *buf, ulong size, enum image_type_t image_type, enum fit_load_op load_op, int bootstage_id, - ulong *datap, ulong *loadp, ulong *load_endp) + ulong *datap, ulong *loadp) { - ulong data, load; + ulong data, load, load_end; + int ret; data = map_to_sysmem(buf); load = data; - *load_endp = 0; + load_end = 0; if (load_op == FIT_LOAD_IGNORED) { log_debug("load_op: not loading\n"); /* Don't load */ @@ -2405,9 +2405,9 @@ static int handle_load_op(const void *fit, int noffset, const char *prop_name, image_start = map_to_sysmem(fit); image_end = image_start + fit_get_size(fit); - *load_endp = load + size; + load_end = load + size; if (image_type != IH_TYPE_KERNEL && - load < image_end && *load_endp > image_start) { + load < image_end && load_end > image_start) { printf("Error: %s overwritten\n", prop_name); return -EXDEV; } @@ -2417,6 +2417,12 @@ static int handle_load_op(const void *fit, int noffset, const char *prop_name, } else { load = data; /* No load address specified */ } + + ret = decomp_image(fit, noffset, prop_name, buf, size, image_type, + load_op, bootstage_id, data, load, load_end); + if (ret) + return ret; + *datap = data; *loadp = load; @@ -2435,7 +2441,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr, const char *fit_base_uname_config; const void *fit; void *buf; - ulong load, load_end, data, len; + ulong load, data, len; uint8_t os_arch; const char *prop_name; int ret; @@ -2465,12 +2471,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr, return ret; ret = handle_load_op(fit, noffset, prop_name, buf, len, image_type, - load_op, bootstage_id, &data, &load, &load_end); - if (ret) - return ret; - - ret = decomp_image(fit, noffset, prop_name, buf, len, image_type, - load_op, bootstage_id, data, load, load_end); + load_op, bootstage_id, &data, &load); if (ret) return ret; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Remove a few more lines from fit_image_load() by dealing with this small detail in check_allowed(). Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 244397b26c5..26d29715683 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2163,17 +2163,19 @@ static int select_image(const void *fit, struct bootm_headers *images, * * @fit: FIT to check * @noffset: Node offset of the image being loaded + * @images: Boot images structure * @image_type: Type of the image * @arch: Expected architecture for the image * @bootstage_id: ID of starting bootstage to use for progress updates * Return: 0 if OK, -EIO if not */ static int check_allowed(const void *fit, int noffset, + struct bootm_headers *images, enum image_type_t image_type, enum image_arch_t arch, int bootstage_id) { bool type_ok, os_ok; - uint8_t os; + uint8_t os, os_arch; bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) { @@ -2219,6 +2221,9 @@ static int check_allowed(const void *fit, int noffset, bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); + fit_image_get_arch(fit, noffset, &os_arch); + images_set_arch(images, os_arch); + return 0; } @@ -2442,7 +2447,6 @@ int fit_image_load(struct bootm_headers *images, ulong addr, const void *fit; void *buf; ulong load, data, len; - uint8_t os_arch; const char *prop_name; int ret; @@ -2459,13 +2463,11 @@ int fit_image_load(struct bootm_headers *images, ulong addr, if (noffset < 0) return noffset; - ret = check_allowed(fit, noffset, image_type, arch, bootstage_id); + ret = check_allowed(fit, noffset, images, image_type, arch, + bootstage_id); if (ret) return ret; - fit_image_get_arch(fit, noffset, &os_arch); - images_set_arch(images, os_arch); - ret = obtain_data(fit, noffset, prop_name, bootstage_id, &buf, &len); if (ret) return ret; -- 2.43.0

From: Simon Glass <sjg@chromium.org> This is always the same as 'buf' and is not used in any case. Drop it. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 26d29715683..006143ff6b1 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2375,14 +2375,13 @@ int decomp_image(const void *fit, int noffset, const char *prop_name, * @image_type: Type of the image * @load_op: Load operation to process * @bootstage_id: ID of starting bootstage to use for progress updates - * @datap: Returns buf * @loadp: Returns the address to which the data should be loaded * Return: 0 if OK, -ve on error */ static int handle_load_op(const void *fit, int noffset, const char *prop_name, void *buf, ulong size, enum image_type_t image_type, enum fit_load_op load_op, int bootstage_id, - ulong *datap, ulong *loadp) + ulong *loadp) { ulong data, load, load_end; int ret; @@ -2428,7 +2427,6 @@ static int handle_load_op(const void *fit, int noffset, const char *prop_name, if (ret) return ret; - *datap = data; *loadp = load; return 0; @@ -2446,7 +2444,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr, const char *fit_base_uname_config; const void *fit; void *buf; - ulong load, data, len; + ulong load, len; const char *prop_name; int ret; @@ -2473,7 +2471,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr, return ret; ret = handle_load_op(fit, noffset, prop_name, buf, len, image_type, - load_op, bootstage_id, &data, &load); + load_op, bootstage_id, &load); if (ret) return ret; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Arrange these so that they look a little nicer. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/image-fit.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 006143ff6b1..a4d1abff803 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2438,15 +2438,14 @@ int fit_image_load(struct bootm_headers *images, ulong addr, enum fit_load_op load_op, ulong *datap, ulong *lenp) { int image_type = image_ph_type(ph_type); - int noffset; - const char *fit_uname; - const char *fit_uname_config; const char *fit_base_uname_config; + const char *fit_uname_config; + const char *fit_uname; + const char *prop_name; + int noffset, ret; const void *fit; - void *buf; ulong load, len; - const char *prop_name; - int ret; + void *buf; fit = map_sysmem(addr, 0); prop_name = fit_get_image_type_property(ph_type); -- 2.43.0
participants (1)
-
Simon Glass