[U-Boot] [PATCH v3 0/10] image: Reduce code duplication and refactor

In creating a new feature[*] I found that the image code includes quite a bit of duplication in places. In particular the code to load a kernel, FDT and ramdisk is all fairly similar, but subtly different.
This series introduces a new function fit_image_load() which loads an image from a FIT and supports the various features. For the bootstage updates, these are standardised so that each file has its own range and the events within that range have corresponding numbers. This means that the boot progress numbers will change slightly with this series.
The image.c file is still very long. Rather than perpetuate the #ifdefs in the code I have split out the image.c code that is dependent on CONFIG_OF_LIBFDT into image-fdt.c.
Several architectures have their own way of setting up a ramdisk and FDT for booting. An attempt is made here to unify these by providing a function image_setup_linux() to handle the overall task, and image_setup_fdt() to set up the FDT.
For ARM, the bootm code is a maze of #ifdefs, which means that many boards compile the code differently and it takes longer to detect breakages. To get around this, some defines are added to ARM's bootm.h to permit the use of if() instead of #ifdef, making use of the compiler's dead code elimination.
Also this series introduces a very basic test of image loading using sandbox. Some patches add bootm support for sandbox, and also a 'sb save' command to save memory to a host file (used to check that the bootm actually worked).
A test program for sandbox is added as a basic sanity check of image loading as performed by bootm.
* The new feature is support for FIT booting on x86, available in patchwork starting here:
http://patchwork.ozlabs.org/patch/211526/
Changes in v3: - Rebase without verified boot patches
Changes in v2: - Add workaround for ELDK-4.2 to avoid cast warning - Put quotes around error when selected FIT config cannot be found - Correct definition of IMAGE_ENABLE_BEST_MATCH - Fix checkpatch checks about parenthesis alignment - Rebase on previous patches - Add workaround for ELDK-4.2 to avoid cast warning
Simon Glass (10): bootstage: Introduce sub-IDs for use with image loading mkimage: Add map_sysmem() and IH_ARCH_DEFAULT to simplfy building image: Introduce fit_image_load() to load images from FITs image: Use fit_image_load() to load ramdisk image: Use fit_image_load() to load FDT sandbox: Adjust bootm command to work with sandbox image: Use fit_image_load() to load kernel sandbox: image: Adjust FIT image printing to work with sandbox bootstage: Remove unused entries related to kernel/ramdisk/fdt load sandbox: image: Create a test for loading FIT images
common/cmd_bootm.c | 170 +++----------------- common/image-fdt.c | 207 ++++-------------------- common/image-fit.c | 310 +++++++++++++++++++++++++----------- common/image.c | 122 ++------------ include/bootstage.h | 51 +++--- include/image.h | 105 +++++++++++- test/image/test-fit.py | 422 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/mkimage.h | 12 ++ 8 files changed, 846 insertions(+), 553 deletions(-) create mode 100755 test/image/test-fit.py

Loading a ramdisk, kernel or FDT goes through similar stages. Create a block of IDs for each task, and define a consistent numbering within the block. This will allow use of common code for image loading.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: None
include/bootstage.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/include/bootstage.h b/include/bootstage.h index 6dc0422..e29e9ee 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -37,6 +37,24 @@ enum bootstage_flags { BOOTSTAGEF_ALLOC = 1 << 1, /* Allocate an id */ };
+/* bootstate sub-IDs used for kernel and ramdisk ranges */ +enum { + BOOTSTAGE_SUB_FORMAT, + BOOTSTAGE_SUB_FORMAT_OK, + BOOTSTAGE_SUB_NO_UNIT_NAME, + BOOTSTAGE_SUB_UNIT_NAME, + BOOTSTAGE_SUB_SUBNODE, + + BOOTSTAGE_SUB_CHECK, + BOOTSTAGE_SUB_HASH = 5, + BOOTSTAGE_SUB_CHECK_ARCH = 5, + BOOTSTAGE_SUB_CHECK_ALL, + BOOTSTAGE_SUB_GET_DATA, + BOOTSTAGE_SUB_CHECK_ALL_OK = 7, + BOOTSTAGE_SUB_GET_DATA_OK, + BOOTSTAGE_SUB_LOAD, +}; + /* * A list of boot stages that we know about. Each of these indicates the * state that we are at, and the action that we are about to perform. For @@ -137,10 +155,12 @@ enum bootstage_id { BOOTSTAGE_ID_NET_DONE_ERR, BOOTSTAGE_ID_NET_DONE,
+ BOOTSTAGE_ID_FIT_FDT_START = 90, /* * Boot stages related to loading a FIT image. Some of these are a * bit wonky. */ + BOOTSTAGE_ID_FIT_KERNEL_START = 100, BOOTSTAGE_ID_FIT_FORMAT = 100, BOOTSTAGE_ID_FIT_NO_UNIT_NAME, BOOTSTAGE_ID_FIT_UNIT_NAME, @@ -161,6 +181,8 @@ enum bootstage_id { BOOTSTAGE_ID_FIT_LOADADDR, BOOTSTAGE_ID_OVERWRITTEN,
+ /* Next 10 IDs used by BOOTSTAGE_SUB_... */ + BOOTSTAGE_ID_FIT_RD_START = 120, /* Ramdisk stages */ BOOTSTAGE_ID_FIT_RD_FORMAT = 120, BOOTSTAGE_ID_FIT_RD_FORMAT_OK, BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME,

These are not actually used in mkimage itself, but the image code (which is common with mkimage) does use them. To avoid #ifdefs in the image code just for mkimage, define dummy version of these here. The compiler will eliminate the dead code anyway.
A better way to handle this might be to split out more things from common.h so that mkimage can include them. At present any file that mkimage uses has to be very careful what headers it includes.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: None
tools/mkimage.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/tools/mkimage.h b/tools/mkimage.h index e07a615..03c6c8f 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -44,12 +44,24 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+static inline void *map_sysmem(ulong paddr, unsigned long len) +{ + return (void *)(uintptr_t)paddr; +} + +static inline ulong map_to_sysmem(void *ptr) +{ + return (ulong)(uintptr_t)ptr; +} + #define MKIMAGE_TMPFILE_SUFFIX ".tmp" #define MKIMAGE_MAX_TMPFILE_LEN 256 #define MKIMAGE_DEFAULT_DTC_OPTIONS "-I dts -O dtb -p 500" #define MKIMAGE_MAX_DTC_CMDLINE_LEN 512 #define MKIMAGE_DTC "dtc" /* assume dtc is in $PATH */
+#define IH_ARCH_DEFAULT IH_ARCH_INVALID + /* * This structure defines all such variables those are initialized by * mkimage main core and need to be referred by image type specific

At present code to load an image from a FIT is duplicated in the three places where it is needed (kernel, fdt, ramdisk).
The differences between these different code copies is fairly minor. Create a new function in the fit code which can handle any of the requirements of those cases.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: - Rebase without verified boot patches
Changes in v2: - Add workaround for ELDK-4.2 to avoid cast warning - Put quotes around error when selected FIT config cannot be found - Correct definition of IMAGE_ENABLE_BEST_MATCH - Fix checkpatch checks about parenthesis alignment
common/image-fit.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/image.h | 97 +++++++++++++++++++++- 2 files changed, 326 insertions(+), 2 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c index 254feec..9f56b5d 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -31,6 +31,9 @@ #include <time.h> #else #include <common.h> +#include <errno.h> +#include <asm/io.h> +DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/
#include <bootstage.h> @@ -1448,6 +1451,22 @@ void fit_conf_print(const void *fit, int noffset, const char *p) printf("%s FDT: %s\n", p, uname); }
+int fit_image_select(const void *fit, int rd_noffset, int verify) +{ + fit_image_print(fit, rd_noffset, " "); + + if (verify) { + puts(" Verifying Hash Integrity ... "); + if (!fit_image_verify(fit, rd_noffset)) { + puts("Bad Data Hash\n"); + return -EACCES; + } + puts("OK\n"); + } + + return 0; +} + /** * fit_check_ramdisk - verify FIT format ramdisk subimage * @fit_hdr: pointer to the FIT ramdisk header @@ -1490,3 +1509,215 @@ int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK); return 1; } + +int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, + ulong addr) +{ + int cfg_noffset; + void *fit_hdr; + int noffset; + + debug("* %s: using config '%s' from image at 0x%08lx\n", + prop_name, images->fit_uname_cfg, addr); + + /* Check whether configuration has this property defined */ + fit_hdr = map_sysmem(addr, 0); + cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg); + if (cfg_noffset < 0) { + debug("* %s: no such config\n", prop_name); + return -ENOENT; + } + + noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name); + if (noffset < 0) { + debug("* %s: no '%s' in config\n", prop_name, prop_name); + return -ENOLINK; + } + + return noffset; +} + +int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, + const char **fit_unamep, const char *fit_uname_config, + int arch, int image_type, int bootstage_id, + enum fit_load_op load_op, ulong *datap, ulong *lenp) +{ + int cfg_noffset, noffset; + const char *fit_uname; + const void *fit; + const void *buf; + size_t size; + int type_ok, os_ok; + ulong load, data, len; + int ret; + + fit = map_sysmem(addr, 0); + fit_uname = fit_unamep ? *fit_unamep : NULL; + printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); + if (!fit_check_format(fit)) { + printf("Bad FIT %s image format!\n", prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); + return -ENOEXEC; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); + if (fit_uname) { + /* get ramdisk component image node offset */ + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); + noffset = fit_image_get_node(fit, fit_uname); + } else { + /* + * no image node unit name, try to get config + * node first. If config unit node name is NULL + * fit_conf_get_node() will try to find default config node + */ + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); + if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) { + cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob()); + } else { + cfg_noffset = fit_conf_get_node(fit, + fit_uname_config); + } + if (cfg_noffset < 0) { + puts("Could not find configuration node\n"); + bootstage_error(bootstage_id + + BOOTSTAGE_SUB_NO_UNIT_NAME); + return -ENOENT; + } + fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); + printf(" Using '%s' configuration\n", fit_uname_config); + if (image_type == IH_TYPE_KERNEL) { + /* Remember (and possibly verify) this config */ + images->fit_uname_cfg = fit_uname_config; + if (IMAGE_ENABLE_VERIFY && images->verify) { + puts(" Verifying Hash Integrity ... "); + if (!fit_config_verify(fit, cfg_noffset)) { + puts("Bad Data Hash\n"); + bootstage_error(bootstage_id + + BOOTSTAGE_SUB_HASH); + return -EACCES; + } + puts("OK\n"); + } + bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); + } + + noffset = fit_conf_get_prop_node(fit, cfg_noffset, + prop_name); + fit_uname = fit_get_name(fit, noffset, NULL); + } + if (noffset < 0) { + puts("Could not find subimage node\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); + return -ENOENT; + } + + printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); + + 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 (!fit_image_check_target_arch(fit, noffset)) { + puts("Unsupported Architecture\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); + return -ENOEXEC; + } + + 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) || + (image_type == IH_TYPE_KERNEL && + fit_image_check_type(fit, noffset, + IH_TYPE_KERNEL_NOLOAD)); + os_ok = image_type == IH_TYPE_FLATDT || + fit_image_check_os(fit, noffset, IH_OS_LINUX); + if (!type_ok || !os_ok) { + printf("No Linux %s %s Image\n", 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); + + /* get image data address and length */ + if (fit_image_get_data(fit, noffset, &buf, &size)) { + printf("Could not find %s subimage data!\n", prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); + return -ENOMEDIUM; + } + len = (ulong)size; + + /* verify that image data is a proper FDT blob */ + if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)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 + * case in the unmap_sysmem() call: + * warning: initialization discards qualifiers from pointer target type + */ + { + void *vbuf = (void *)buf; + + data = map_to_sysmem(vbuf); + } + + if (load_op == FIT_LOAD_IGNORED) { + /* 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 { + ulong image_start, image_end; + ulong load_end; + void *dst; + + /* + * 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); + + dst = map_sysmem(load, len); + memmove(dst, buf, len); + data = load; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); + + *datap = data; + *lenp = len; + if (fit_unamep) + *fit_unamep = (char *)fit_uname; + + return noffset; +} diff --git a/include/image.h b/include/image.h index b8cc523..5b1e98f 100644 --- a/include/image.h +++ b/include/image.h @@ -402,6 +402,13 @@ void genimg_print_size(uint32_t size); #endif void genimg_print_time(time_t timestamp);
+/* What to do with a image load address ('load = <> 'in the FIT) */ +enum fit_load_op { + FIT_LOAD_IGNORED, /* Ignore load address */ + FIT_LOAD_OPTIONAL, /* Can be provided, but optional */ + FIT_LOAD_REQUIRED, /* Must be provided */ +}; + #ifndef USE_HOSTCC /* Image format types, returned by _get_format() routine */ #define IMAGE_FORMAT_INVALID 0x00 @@ -415,6 +422,68 @@ ulong genimg_get_image(ulong img_addr); int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end);
+/** + * fit_image_load() - load an image from a FIT + * + * This deals with all aspects of loading an image from a FIT, including + * selecting the right image based on configuration, verifying it, printing + * out progress messages, checking the type/arch/os and optionally copying it + * to the right load address. + * + * @param images Boot images structure + * @param prop_name Property name to look up (FIT_..._PROP) + * @param addr Address of FIT in memory + * @param fit_unamep On entry this is the requested image name + * (e.g. "kernel@1") or NULL to use the default. On exit + * points to the selected image name + * @param fit_uname_config Requested configuration name, or NULL for the + * default + * @param arch Expected architecture (IH_ARCH_...) + * @param image_type Required image type (IH_TYPE_...). If this is + * IH_TYPE_KERNEL then we allow IH_TYPE_KERNEL_NOLOAD + * also. + * @param bootstage_id ID of starting bootstage to use for progress updates. + * This will be added to the BOOTSTAGE_SUB values when + * calling bootstage_mark() + * @param load_op Decribes what to do with the load address + * @param datap Returns address of loaded image + * @param lenp Returns length of loaded image + */ +int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, + const char **fit_unamep, const char *fit_uname_config, + int arch, int image_type, int bootstage_id, + enum fit_load_op load_op, ulong *datap, ulong *lenp); + +/** + * fit_get_node_from_config() - Look up an image a FIT by type + * + * This looks in the selected conf@ node (images->fit_uname_cfg) for a + * particular image type (e.g. "kernel") and then finds the image that is + * referred to. + * + * For example, for something like: + * + * images { + * kernel@1 { + * ... + * }; + * }; + * configurations { + * conf@1 { + * kernel = "kernel@1"; + * }; + * }; + * + * the function will return the node offset of the kernel@1 node, assuming + * that conf@1 is the chosen configuration. + * + * @param images Boot images structure + * @param prop_name Property name to look up (FIT_..._PROP) + * @param addr Address of FIT in memory + */ +int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, + ulong addr); + int boot_get_fdt(int flag, int argc, char * const argv[], bootm_headers_t *images, char **of_flat_tree, ulong *of_size); void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob); @@ -697,6 +766,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp); int fit_add_verification_data(void *fit);
int fit_image_verify(const void *fit, int noffset); +int fit_config_verify(const void *fit, int conf_noffset); int fit_all_image_verify(const void *fit); int fit_image_check_os(const void *fit, int noffset, uint8_t os); int fit_image_check_arch(const void *fit, int noffset, uint8_t arch); @@ -732,12 +802,35 @@ int fit_check_ramdisk(const void *fit, int os_noffset, int calculate_hash(const void *data, int data_len, const char *algo, uint8_t *value, int *value_len);
-#ifndef USE_HOSTCC +/* + * At present we only support verification on the device + */ +#if defined(CONFIG_FIT_SIGNATURE) +# ifdef USE_HOSTCC +# define IMAGE_ENABLE_VERIFY 0 +#else +# define IMAGE_ENABLE_VERIFY 1 +# endif +#else +# define IMAGE_ENABLE_VERIFY 0 +#endif + +#ifdef USE_HOSTCC +# define gd_fdt_blob() NULL +#else +# define gd_fdt_blob() (gd->fdt_blob) +#endif + +#ifdef CONFIG_FIT_BEST_MATCH +#define IMAGE_ENABLE_BEST_MATCH 1 +#else +#define IMAGE_ENABLE_BEST_MATCH 0 +#endif + static inline int fit_image_check_target_arch(const void *fdt, int node) { return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT); } -#endif /* USE_HOSTCC */
#ifdef CONFIG_FIT_VERBOSE #define fit_unsupported(msg) printf("! %s:%d " \

Use the new common code to load a ramdisk. The functionality should not change.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: None
common/image-fit.c | 62 --------------------------- common/image.c | 122 +++++++---------------------------------------------- include/image.h | 1 - 3 files changed, 16 insertions(+), 169 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c index 9f56b5d..16fb196 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1371,25 +1371,6 @@ int fit_conf_get_kernel_node(const void *fit, int noffset) }
/** - * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_ramdisk_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP); -} - -/** * fit_conf_get_fdt_node - get fdt image node offset that corresponds to * a given configuration * @fit: pointer to the FIT format image header @@ -1467,49 +1448,6 @@ int fit_image_select(const void *fit, int rd_noffset, int verify) return 0; }
-/** - * fit_check_ramdisk - verify FIT format ramdisk subimage - * @fit_hdr: pointer to the FIT ramdisk header - * @rd_noffset: ramdisk subimage node offset within FIT image - * @arch: requested ramdisk image architecture type - * @verify: data CRC verification flag - * - * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, - int verify) -{ - fit_image_print(fit, rd_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, rd_noffset)) { - puts("Bad Data Hash\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH); - return 0; - } - puts("OK\n"); - } - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); - if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) || - !fit_image_check_arch(fit, rd_noffset, arch) || - !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) { - printf("No Linux %s Ramdisk Image\n", - genimg_get_arch_name(arch)); - bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); - return 0; - } - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK); - return 1; -} - int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, ulong addr) { diff --git a/common/image.c b/common/image.c index e91c89e..f863502 100644 --- a/common/image.c +++ b/common/image.c @@ -51,6 +51,7 @@
#include <u-boot/md5.h> #include <sha1.h> +#include <asm/errno.h> #include <asm/io.h>
#ifdef CONFIG_CMD_BDI @@ -810,14 +811,10 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, char *end; #endif #if defined(CONFIG_FIT) - void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_ramdisk = NULL; ulong default_addr; int rd_noffset; - int cfg_noffset; - const void *data; - size_t size; #endif
*rd_start = 0; @@ -865,32 +862,16 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, #if defined(CONFIG_FIT) } else { /* use FIT configuration provided in first bootm - * command argument + * command argument. If the property is not defined, + * quit silently. */ rd_addr = map_to_sysmem(images->fit_hdr_os); - fit_uname_config = images->fit_uname_cfg; - debug("* ramdisk: using config '%s' from image " - "at 0x%08lx\n", - fit_uname_config, rd_addr); - - /* - * Check whether configuration has ramdisk defined, - * if not, don't try to use it, quit silently. - */ - fit_hdr = images->fit_hdr_os; - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - debug("* ramdisk: no such config\n"); - return 1; - } - - rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, - cfg_noffset); - if (rd_noffset < 0) { - debug("* ramdisk: no ramdisk in config\n"); + rd_noffset = fit_get_node_from_config(images, + FIT_RAMDISK_PROP, rd_addr); + if (rd_noffset == -ENOLINK) return 0; - } + else if (rd_noffset < 0) + return 1; } #endif
@@ -921,87 +902,16 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - fit_hdr = buf; - printf("## Loading init Ramdisk from FIT " - "Image at %08lx ...\n", rd_addr); - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT); - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT ramdisk image format!\n"); - bootstage_error( - BOOTSTAGE_ID_FIT_RD_FORMAT); + rd_noffset = fit_image_load(images, FIT_RAMDISK_PROP, + rd_addr, &fit_uname_ramdisk, + fit_uname_config, arch, + IH_TYPE_RAMDISK, + BOOTSTAGE_ID_FIT_RD_START, + FIT_LOAD_REQUIRED, &rd_data, &rd_len); + if (rd_noffset < 0) return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT_OK); - - if (!fit_uname_ramdisk) { - /* - * no ramdisk image node unit name, try to get config - * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config node - */ - bootstage_mark( - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - puts("Could not find configuration " - "node\n"); - bootstage_error( - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); - return 1; - } - fit_uname_config = fdt_get_name(fit_hdr, - cfg_noffset, NULL); - printf(" Using '%s' configuration\n", - fit_uname_config); - - rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, - cfg_noffset); - fit_uname_ramdisk = fit_get_name(fit_hdr, - rd_noffset, NULL); - } else { - /* get ramdisk component image node offset */ - bootstage_mark( - BOOTSTAGE_ID_FIT_RD_UNIT_NAME); - rd_noffset = fit_image_get_node(fit_hdr, - fit_uname_ramdisk); - } - if (rd_noffset < 0) { - puts("Could not find subimage node\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_SUBNODE); - return 1; - } - - printf(" Trying '%s' ramdisk subimage\n", - fit_uname_ramdisk); - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK); - if (!fit_check_ramdisk(fit_hdr, rd_noffset, arch, - images->verify)) - return 1; - - /* get ramdisk image data address and length */ - if (fit_image_get_data(fit_hdr, rd_noffset, &data, - &size)) { - puts("Could not find ramdisk subimage data!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_GET_DATA); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_GET_DATA_OK); - - rd_data = (ulong)data; - rd_len = size; - - if (fit_image_get_load(fit_hdr, rd_noffset, &rd_load)) { - puts("Can't get ramdisk subimage load " - "address!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_LOAD); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_LOAD);
- images->fit_hdr_rd = fit_hdr; + images->fit_hdr_rd = map_sysmem(rd_addr, 0); images->fit_uname_rd = fit_uname_ramdisk; images->fit_noffset_rd = rd_noffset; break; diff --git a/include/image.h b/include/image.h index 5b1e98f..28a1470 100644 --- a/include/image.h +++ b/include/image.h @@ -777,7 +777,6 @@ int fit_check_format(const void *fit); int fit_conf_find_compat(const void *fit, const void *fdt); int fit_conf_get_node(const void *fit, const char *conf_uname); int fit_conf_get_kernel_node(const void *fit, int noffset); -int fit_conf_get_ramdisk_node(const void *fit, int noffset); int fit_conf_get_fdt_node(const void *fit, int noffset);
/**

Use the new common code to load a flat device tree. Also fix up a few casts so that this code works with sandbox. Other than that the functionality should not change.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: - Rebase on previous patches
common/cmd_bootm.c | 4 +- common/image-fdt.c | 207 ++++++++--------------------------------------------- common/image-fit.c | 19 ----- include/image.h | 6 +- 4 files changed, 34 insertions(+), 202 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index dd6cafa..9eec4e3 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -306,7 +306,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
#if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, &images, + ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images, &images.ft_addr, &images.ft_len); if (ret) { puts("Could not find a valid device tree\n"); @@ -1803,7 +1803,7 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
#if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, images, + ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images, &images->ft_addr, &images->ft_len); if (ret) { puts("Could not find a valid device tree\n"); diff --git a/common/image-fdt.c b/common/image-fdt.c index 158c9cf..0d421d9 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -211,51 +211,11 @@ error: return 1; }
-#if defined(CONFIG_FIT) -/** - * fit_check_fdt - verify FIT format FDT subimage - * @fit_hdr: pointer to the FIT header - * fdt_noffset: FDT subimage node offset within FIT image - * @verify: data CRC verification flag - * - * fit_check_fdt() verifies integrity of the FDT subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) -{ - fit_image_print(fit, fdt_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, fdt_noffset)) { - fdt_error("Bad Data Hash"); - return 0; - } - puts("OK\n"); - } - - if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) { - fdt_error("Not a FDT image"); - return 0; - } - - if (!fit_image_check_comp(fit, fdt_noffset, IH_COMP_NONE)) { - fdt_error("FDT image is compressed"); - return 0; - } - - return 1; -} -#endif - /** * boot_get_fdt - main fdt handling routine * @argc: command argument count * @argv: command argument list + * @arch: architecture (IH_ARCH_...) * @images: pointer to the bootm images structure * @of_flat_tree: pointer to a char* variable, will hold fdt start address * @of_size: pointer to a ulong variable, will hold fdt length @@ -273,24 +233,20 @@ static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) * 1, if fdt image is found but corrupted * of_flat_tree and of_size are set to 0 if no fdt exists */ -int boot_get_fdt(int flag, int argc, char * const argv[], +int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, bootm_headers_t *images, char **of_flat_tree, ulong *of_size) { const image_header_t *fdt_hdr; ulong fdt_addr; char *fdt_blob = NULL; ulong image_start, image_data, image_end; - ulong load_start, load_end; + ulong load, load_end; void *buf; #if defined(CONFIG_FIT) - void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_fdt = NULL; ulong default_addr; - int cfg_noffset; int fdt_noffset; - const void *data; - size_t size; #endif
*of_flat_tree = NULL; @@ -333,31 +289,15 @@ int boot_get_fdt(int flag, int argc, char * const argv[], * command argument */ fdt_addr = map_to_sysmem(images->fit_hdr_os); - fit_uname_config = images->fit_uname_cfg; - debug("* fdt: using config '%s' from image at 0x%08lx\n", - fit_uname_config, fdt_addr); - - /* - * Check whether configuration has FDT blob defined, - * if not quit silently. - */ - fit_hdr = images->fit_hdr_os; - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - debug("* fdt: no such config\n"); + fdt_noffset = fit_get_node_from_config(images, + FIT_FDT_PROP, + fdt_addr); + if (fdt_noffset == -ENOLINK) return 0; - } - - fdt_noffset = fit_conf_get_fdt_node(fit_hdr, - cfg_noffset); - if (fdt_noffset < 0) { - debug("* fdt: no fdt in config\n"); - return 0; - } + else if (fdt_noffset < 0) + return 1; } #endif - debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", fdt_addr);
@@ -387,29 +327,28 @@ int boot_get_fdt(int flag, int argc, char * const argv[], image_data = (ulong)image_get_data(fdt_hdr); image_end = image_get_image_end(fdt_hdr);
- load_start = image_get_load(fdt_hdr); - load_end = load_start + image_get_data_size(fdt_hdr); + load = image_get_load(fdt_hdr); + load_end = load + image_get_data_size(fdt_hdr);
- if (load_start == image_start || - load_start == image_data) { + if (load == image_start || + load == image_data) { fdt_blob = (char *)image_data; break; }
- if ((load_start < image_end) && - (load_end > image_start)) { + if ((load < image_end) && (load_end > image_start)) { fdt_error("fdt overwritten"); goto error; }
debug(" Loading FDT from 0x%08lx to 0x%08lx\n", - image_data, load_start); + image_data, load);
- memmove((void *)load_start, + memmove((void *)load, (void *)image_data, image_get_data_size(fdt_hdr));
- fdt_blob = (char *)load_start; + fdt_addr = load; break; case IMAGE_FORMAT_FIT: /* @@ -420,107 +359,20 @@ int boot_get_fdt(int flag, int argc, char * const argv[], #if defined(CONFIG_FIT) /* check FDT blob vs FIT blob */ if (fit_check_format(buf)) { - /* - * FIT image - */ - fit_hdr = buf; - printf("## Flattened Device Tree from FIT Image at %08lx\n", - fdt_addr); - - if (!fit_uname_fdt) { - /* - * no FDT blob image node unit name, - * try to get config node first. If - * config unit node name is NULL - * fit_conf_get_node() will try to - * find default config node - */ - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - - if (cfg_noffset < 0) { - fdt_error("Could not find configuration node\n"); - goto error; - } - - fit_uname_config = fdt_get_name(fit_hdr, - cfg_noffset, NULL); - printf(" Using '%s' configuration\n", - fit_uname_config); - - fdt_noffset = fit_conf_get_fdt_node( - fit_hdr, - cfg_noffset); - fit_uname_fdt = fit_get_name(fit_hdr, - fdt_noffset, NULL); - } else { - /* - * get FDT component image node - * offset - */ - fdt_noffset = fit_image_get_node( - fit_hdr, - fit_uname_fdt); - } - if (fdt_noffset < 0) { - fdt_error("Could not find subimage node\n"); - goto error; - } - - printf(" Trying '%s' FDT blob subimage\n", - fit_uname_fdt); - - if (!fit_check_fdt(fit_hdr, fdt_noffset, - images->verify)) - goto error; - - /* get ramdisk image data address and length */ - if (fit_image_get_data(fit_hdr, fdt_noffset, - &data, &size)) { - fdt_error("Could not find FDT subimage data"); - goto error; - } + ulong load, len;
- /* - * verify that image data is a proper FDT - * blob - */ - if (fdt_check_header((char *)data) != 0) { - fdt_error("Subimage data is not a FTD"); - goto error; - } - - /* - * move image data to the load address, - * make sure we don't overwrite initial image - */ - image_start = (ulong)fit_hdr; - image_end = fit_get_end(fit_hdr); - - if (fit_image_get_load(fit_hdr, fdt_noffset, - &load_start) == 0) { - load_end = load_start + size; + fdt_noffset = fit_image_load(images, + FIT_FDT_PROP, + fdt_addr, &fit_uname_fdt, + fit_uname_config, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_OPTIONAL, &load, &len);
- if ((load_start < image_end) && - (load_end > image_start)) { - fdt_error("FDT overwritten"); - goto error; - } - - printf(" Loading FDT from 0x%08lx to 0x%08lx\n", - (ulong)data, load_start); - - memmove((void *)load_start, - (void *)data, size); - - fdt_blob = (char *)load_start; - } else { - fdt_blob = (char *)data; - } - - images->fit_hdr_fdt = fit_hdr; + images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); images->fit_uname_fdt = fit_uname_fdt; images->fit_noffset_fdt = fdt_noffset; + fdt_addr = load; break; } else #endif @@ -528,7 +380,6 @@ int boot_get_fdt(int flag, int argc, char * const argv[], /* * FDT blob */ - fdt_blob = buf; debug("* fdt: raw FDT blob\n"); printf("## Flattened Device Tree blob at %08lx\n", (long)fdt_addr); @@ -539,8 +390,8 @@ int boot_get_fdt(int flag, int argc, char * const argv[], goto error; }
- printf(" Booting using the fdt blob at 0x%p\n", fdt_blob); - + printf(" Booting using the fdt blob at %#08lx\n", fdt_addr); + fdt_blob = map_sysmem(fdt_addr, 0); } else if (images->legacy_hdr_valid && image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { diff --git a/common/image-fit.c b/common/image-fit.c index 16fb196..15c92be 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1371,25 +1371,6 @@ int fit_conf_get_kernel_node(const void *fit, int noffset) }
/** - * fit_conf_get_fdt_node - get fdt image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_fdt_node() retrives fdt image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_fdt_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP); -} - -/** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header * @noffset: offset of the configuration node diff --git a/include/image.h b/include/image.h index 28a1470..3695c62 100644 --- a/include/image.h +++ b/include/image.h @@ -484,8 +484,9 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, ulong addr);
-int boot_get_fdt(int flag, int argc, char * const argv[], - bootm_headers_t *images, char **of_flat_tree, ulong *of_size); +int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, + bootm_headers_t *images, + char **of_flat_tree, ulong *of_size); void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob); int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size);
@@ -777,7 +778,6 @@ int fit_check_format(const void *fit); int fit_conf_find_compat(const void *fit, const void *fdt); int fit_conf_get_node(const void *fit, const char *conf_uname); int fit_conf_get_kernel_node(const void *fit, int noffset); -int fit_conf_get_fdt_node(const void *fit, int noffset);
/** * fit_conf_get_prop_node() - Get node refered to by a configuration

Use map_sysmem() when converting from addresses to pointers, so that bootm can be used with sandbox.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: None
common/cmd_bootm.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 9eec4e3..5c5e7c3 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -336,12 +336,15 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) ulong image_len = os.image_len; __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN; int no_overlap = 0; + void *load_buf, *image_buf; #if defined(CONFIG_LZMA) || defined(CONFIG_LZO) int ret; #endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */
const char *type_name = genimg_get_type_name(os.type);
+ load_buf = map_sysmem(load, image_len); + image_buf = map_sysmem(image_start, image_len); switch (comp) { case IH_COMP_NONE: if (load == blob_start || load == image_start) { @@ -349,8 +352,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) no_overlap = 1; } else { printf(" Loading %s ... ", type_name); - memmove_wd((void *)load, (void *)image_start, - image_len, CHUNKSZ); + memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); } *load_end = load + image_len; puts("OK\n"); @@ -358,8 +360,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) #ifdef CONFIG_GZIP case IH_COMP_GZIP: printf(" Uncompressing %s ... ", type_name); - if (gunzip((void *)load, unc_len, - (uchar *)image_start, &image_len) != 0) { + if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) { puts("GUNZIP: uncompress, out-of-mem or overwrite " "error - must RESET board to recover\n"); if (boot_progress) @@ -378,9 +379,9 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - int i = BZ2_bzBuffToBuffDecompress((char *)load, - &unc_len, (char *)image_start, image_len, - CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); + int i = BZ2_bzBuffToBuffDecompress(load_buf, &unc_len, + image_buf, image_len, + CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf("BUNZIP2: uncompress or overwrite error %d " "- must RESET board to recover\n", i); @@ -397,9 +398,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) SizeT lzma_len = unc_len; printf(" Uncompressing %s ... ", type_name);
- ret = lzmaBuffToBuffDecompress( - (unsigned char *)load, &lzma_len, - (unsigned char *)image_start, image_len); + ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, + image_buf, image_len); unc_len = lzma_len; if (ret != SZ_OK) { printf("LZMA: uncompress or overwrite error %d " @@ -415,9 +415,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) case IH_COMP_LZO: printf(" Uncompressing %s ... ", type_name);
- ret = lzop_decompress((const unsigned char *)image_start, - image_len, (unsigned char *)load, - &unc_len); + ret = lzop_decompress(image_buf, image_len, load_buf, + &unc_len); if (ret != LZO_E_OK) { printf("LZO: uncompress or overwrite error %d " "- must RESET board to recover\n", ret);

Use the new common code to load a kernel. The functionality should not change.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: - Rebase without verified boot patches
Changes in v2: None
common/cmd_bootm.c | 141 +++-------------------------------------------------- common/image-fit.c | 19 -------- include/image.h | 1 - 3 files changed, 8 insertions(+), 153 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 5c5e7c3..d97c9c7 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -93,11 +93,6 @@ static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); static void fixup_silent_linux(void); #endif
-static image_header_t *image_get_kernel(ulong img_addr, int verify); -#if defined(CONFIG_FIT) -static int fit_check_kernel(const void *fit, int os_noffset, int verify); -#endif - static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len); @@ -796,54 +791,6 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify) }
/** - * fit_check_kernel - verify FIT format kernel subimage - * @fit_hdr: pointer to the FIT image header - * os_noffset: kernel subimage node offset within FIT image - * @verify: data CRC verification flag - * - * fit_check_kernel() verifies integrity of the kernel subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -#if defined(CONFIG_FIT) -static int fit_check_kernel(const void *fit, int os_noffset, int verify) -{ - fit_image_print(fit, os_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, os_noffset)) { - puts("Bad Data Hash\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH); - return 0; - } - puts("OK\n"); - } - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_ARCH); - - if (!fit_image_check_target_arch(fit, os_noffset)) { - puts("Unsupported Architecture\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH); - return 0; - } - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_KERNEL); - if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) && - !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_NOLOAD)) { - puts("Not a kernel image\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL); - return 0; - } - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED); - return 1; -} -#endif /* CONFIG_FIT */ - -/** * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length @@ -863,12 +810,8 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, ulong img_addr; const void *buf; #if defined(CONFIG_FIT) - const void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; - const void *data; - size_t len; - int cfg_noffset; int os_noffset; #endif
@@ -945,84 +888,16 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - fit_hdr = buf; - printf("## Booting kernel from FIT Image at %08lx ...\n", - img_addr); - - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT kernel image format!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_FORMAT); + os_noffset = fit_image_load(images, FIT_KERNEL_PROP, + img_addr, + &fit_uname_kernel, fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_KERNEL, + BOOTSTAGE_ID_FIT_KERNEL_START, + FIT_LOAD_IGNORED, os_data, os_len); + if (os_noffset < 0) return NULL; - } - bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT); - - if (!fit_uname_kernel) { - /* - * no kernel image node unit name, try to get config - * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config - * node - */ - bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); -#ifdef CONFIG_FIT_BEST_MATCH - if (fit_uname_config) - cfg_noffset = - fit_conf_get_node(fit_hdr, - fit_uname_config); - else - cfg_noffset = - fit_conf_find_compat(fit_hdr, - gd->fdt_blob); -#else - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); -#endif - if (cfg_noffset < 0) { - bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); - return NULL; - } - /* save configuration uname provided in the first - * bootm argument - */ - images->fit_uname_cfg = fdt_get_name(fit_hdr, - cfg_noffset, - NULL); - printf(" Using '%s' configuration\n", - images->fit_uname_cfg); - bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); - - os_noffset = fit_conf_get_kernel_node(fit_hdr, - cfg_noffset); - fit_uname_kernel = fit_get_name(fit_hdr, os_noffset, - NULL); - } else { - /* get kernel component image node offset */ - bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME); - os_noffset = fit_image_get_node(fit_hdr, - fit_uname_kernel); - } - if (os_noffset < 0) { - bootstage_error(BOOTSTAGE_ID_FIT_CONFIG); - return NULL; - } - - printf(" Trying '%s' kernel subimage\n", fit_uname_kernel); - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE); - if (!fit_check_kernel(fit_hdr, os_noffset, images->verify)) - return NULL; - - /* get kernel image data address and length */ - if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) { - puts("Could not find kernel subimage data!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR); - return NULL; - } - bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO);
- *os_len = len; - *os_data = (ulong)data; - images->fit_hdr_os = (void *)fit_hdr; + images->fit_hdr_os = map_sysmem(img_addr, 0); images->fit_uname_os = fit_uname_kernel; images->fit_noffset_os = os_noffset; break; diff --git a/common/image-fit.c b/common/image-fit.c index 15c92be..589f53d 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1352,25 +1352,6 @@ int fit_conf_get_prop_node(const void *fit, int noffset, }
/** - * fit_conf_get_kernel_node - get kernel image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_kernel_node() retrives kernel image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_kernel_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP); -} - -/** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header * @noffset: offset of the configuration node diff --git a/include/image.h b/include/image.h index 3695c62..8ccc00b 100644 --- a/include/image.h +++ b/include/image.h @@ -777,7 +777,6 @@ int fit_check_format(const void *fit);
int fit_conf_find_compat(const void *fit, const void *fdt); int fit_conf_get_node(const void *fit, const char *conf_uname); -int fit_conf_get_kernel_node(const void *fit, int noffset);
/** * fit_conf_get_prop_node() - Get node refered to by a configuration

Use map_sysmem() to convert from address to pointer, so that sandbox can print FIT information without crashing.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: - Add workaround for ELDK-4.2 to avoid cast warning
common/image-fit.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c index 589f53d..7bf82d3 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -351,10 +351,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
#ifndef USE_HOSTCC printf("%s Data Start: ", p); - if (ret) + if (ret) { printf("unavailable\n"); - else - printf("0x%08lx\n", (ulong)data); + } else { + void *vdata = (void *)data; + + printf("0x%08lx\n", (ulong)map_to_sysmem(vdata)); + } #endif
printf("%s Data Size: ", p);

Now that the code for loading these three images from a FIT is common, we don't need individual boostage IDs for each of them.
Note: there are some minor changes in the bootstage numbering, particuarly for kernel loading. I don't believe this matters.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: None
include/bootstage.h | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-)
diff --git a/include/bootstage.h b/include/bootstage.h index e29e9ee..ef07a87 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -161,20 +161,10 @@ enum bootstage_id { * bit wonky. */ BOOTSTAGE_ID_FIT_KERNEL_START = 100, - BOOTSTAGE_ID_FIT_FORMAT = 100, - BOOTSTAGE_ID_FIT_NO_UNIT_NAME, - BOOTSTAGE_ID_FIT_UNIT_NAME, - BOOTSTAGE_ID_FIT_CONFIG, - BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE, - BOOTSTAGE_ID_FIT_CHECK_HASH = 104, - - BOOTSTAGE_ID_FIT_CHECK_ARCH, - BOOTSTAGE_ID_FIT_CHECK_KERNEL, - BOOTSTAGE_ID_FIT_CHECKED, - - BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR = 107, - BOOTSTAGE_ID_FIT_KERNEL_INFO, + + BOOTSTAGE_ID_FIT_CONFIG = 110, BOOTSTAGE_ID_FIT_TYPE, + BOOTSTAGE_ID_FIT_KERNEL_INFO,
BOOTSTAGE_ID_FIT_COMPRESSION, BOOTSTAGE_ID_FIT_OS, @@ -183,19 +173,6 @@ enum bootstage_id {
/* Next 10 IDs used by BOOTSTAGE_SUB_... */ BOOTSTAGE_ID_FIT_RD_START = 120, /* Ramdisk stages */ - BOOTSTAGE_ID_FIT_RD_FORMAT = 120, - BOOTSTAGE_ID_FIT_RD_FORMAT_OK, - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME, - BOOTSTAGE_ID_FIT_RD_UNIT_NAME, - BOOTSTAGE_ID_FIT_RD_SUBNODE, - - BOOTSTAGE_ID_FIT_RD_CHECK, - BOOTSTAGE_ID_FIT_RD_HASH = 125, - BOOTSTAGE_ID_FIT_RD_CHECK_ALL, - BOOTSTAGE_ID_FIT_RD_GET_DATA, - BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK = 127, - BOOTSTAGE_ID_FIT_RD_GET_DATA_OK, - BOOTSTAGE_ID_FIT_RD_LOAD,
BOOTSTAGE_ID_IDE_FIT_READ = 140, BOOTSTAGE_ID_IDE_FIT_READ_OK,

The image code is fairly complex with various different options. It would be useful to have comprehensive tests for this.
As a start, create a script which tries out loading a kernel/ramdisk/fdt from a FIT and checks that the images appear in the right place in memory.
This uses sandbox which now supports bootm and related features.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v3: None Changes in v2: None
test/image/test-fit.py | 422 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100755 test/image/test-fit.py
diff --git a/test/image/test-fit.py b/test/image/test-fit.py new file mode 100755 index 0000000..c4e8211 --- /dev/null +++ b/test/image/test-fit.py @@ -0,0 +1,422 @@ +#!/usr/bin/python +# +# Copyright (c) 2013, Google Inc. +# +# Sanity check of the FIT handling in U-Boot +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# To run this: +# +# make O=sandbox sandbox_config +# make O=sandbox +# ./test/image/test-fit.py -u sandbox/u-boot + +import doctest +from optparse import OptionParser +import os +import shutil +import struct +import sys +import tempfile + +# The 'command' library in patman is convenient for running commands +base_path = os.path.dirname(sys.argv[0]) +patman = os.path.join(base_path, '../../tools/patman') +sys.path.append(patman) + +import command + +# Define a base ITS which we can adjust using % and a dictionary +base_its = ''' +/dts-v1/; + +/ { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel@1 { + data = /incbin/("%(kernel)s"); + type = "kernel"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x40000>; + entry = <0x8>; + }; + fdt@1 { + description = "snow"; + data = /incbin/("u-boot.dtb"); + type = "flat_dt"; + arch = "sandbox"; + %(fdt_load)s + compression = "none"; + signature@1 { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + }; + }; + ramdisk@1 { + description = "snow"; + data = /incbin/("%(ramdisk)s"); + type = "ramdisk"; + arch = "sandbox"; + os = "linux"; + %(ramdisk_load)s + compression = "none"; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + %(ramdisk_config)s + }; + }; +}; +''' + +# Define a base FDT - currently we don't use anything in this +base_fdt = ''' +/dts-v1/; + +/ { + model = "Sandbox Verified Boot Test"; + compatible = "sandbox"; + +}; +''' + +# This is the U-Boot script that is run for each test. First load the fit, +# then do the 'bootm' command, then save out memory from the places where +# we expect 'bootm' to write things. Then quit. +base_script = ''' +sb load host 0 %(fit_addr)x %(fit)s +fdt addr %(fit_addr)x +bootm start %(fit_addr)x +bootm loados +sb save host 0 %(kernel_out)s %(kernel_addr)x %(kernel_size)x +sb save host 0 %(fdt_out)s %(fdt_addr)x %(fdt_size)x +sb save host 0 %(ramdisk_out)s %(ramdisk_addr)x %(ramdisk_size)x +reset +''' + +def make_fname(leaf): + """Make a temporary filename + + Args: + leaf: Leaf name of file to create (within temporary directory) + Return: + Temporary filename + """ + global base_dir + + return os.path.join(base_dir, leaf) + +def filesize(fname): + """Get the size of a file + + Args: + fname: Filename to check + Return: + Size of file in bytes + """ + return os.stat(fname).st_size + +def read_file(fname): + """Read the contents of a file + + Args: + fname: Filename to read + Returns: + Contents of file as a string + """ + with open(fname, 'r') as fd: + return fd.read() + +def make_dtb(): + """Make a sample .dts file and compile it to a .dtb + + Returns: + Filename of .dtb file created + """ + src = make_fname('u-boot.dts') + dtb = make_fname('u-boot.dtb') + with open(src, 'w') as fd: + print >>fd, base_fdt + command.Output('dtc', src, '-O', 'dtb', '-o', dtb) + return dtb + +def make_its(params): + """Make a sample .its file with parameters embedded + + Args: + params: Dictionary containing parameters to embed in the %() strings + Returns: + Filename of .its file created + """ + its = make_fname('test.its') + with open(its, 'w') as fd: + print >>fd, base_its % params + return its + +def make_fit(mkimage, params): + """Make a sample .fit file ready for loading + + This creates a .its script with the selected parameters and uses mkimage to + turn this into a .fit image. + + Args: + mkimage: Filename of 'mkimage' utility + params: Dictionary containing parameters to embed in the %() strings + Return: + Filename of .fit file created + """ + fit = make_fname('test.fit') + its = make_its(params) + command.Output(mkimage, '-f', its, fit) + with open(make_fname('u-boot.dts'), 'w') as fd: + print >>fd, base_fdt + return fit + +def make_kernel(): + """Make a sample kernel with test data + + Returns: + Filename of kernel created + """ + fname = make_fname('test-kernel.bin') + data = '' + for i in range(100): + data += 'this kernel %d is unlikely to boot\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def make_ramdisk(): + """Make a sample ramdisk with test data + + Returns: + Filename of ramdisk created + """ + fname = make_fname('test-ramdisk.bin') + data = '' + for i in range(100): + data += 'ramdisk %d was seldom used in the middle ages\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def find_matching(text, match): + """Find a match in a line of text, and return the unmatched line portion + + This is used to extract a part of a line from some text. The match string + is used to locate the line - we use the first line that contains that + match text. + + Once we find a match, we discard the match string itself from the line, + and return what remains. + + TODO: If this function becomes more generally useful, we could change it + to use regex and return groups. + + Args: + text: Text to check (each line separated by \n) + match: String to search for + Return: + String containing unmatched portion of line + Exceptions: + ValueError: If match is not found + + >>> find_matching('first line:10\nsecond_line:20', 'first line:') + '10' + >>> find_matching('first line:10\nsecond_line:20', 'second linex') + Traceback (most recent call last): + ... + ValueError: Test aborted + >>> find_matching('first line:10\nsecond_line:20', 'second_line:') + '20' + """ + for line in text.splitlines(): + pos = line.find(match) + if pos != -1: + return line[:pos] + line[pos + len(match):] + + print "Expected '%s' but not found in output:" + print text + raise ValueError('Test aborted') + +def set_test(name): + """Set the name of the current test and print a message + + Args: + name: Name of test + """ + global test_name + + test_name = name + print name + +def fail(msg): + """Raise an error with a helpful failure message + + Args: + msg: Message to display + """ + raise ValueError("Test '%s' failed: %s" % (test_name, msg)) + +def run_fit_test(mkimage, u_boot): + """Basic sanity check of FIT loading in U-Boot + + TODO: Almost everything: + - hash algorithms - invalid hash/contents should be detected + - signature algorithms - invalid sig/contents should be detected + - compression + - checking that errors are detected like: + - image overwriting + - missing images + - invalid configurations + - incorrect os/arch/type fields + - empty data + - images too large/small + - invalid FDT (e.g. putting a random binary in instead) + - default configuration selection + - bootm command line parameters should have desired effect + - run code coverage to make sure we are testing all the code + """ + global test_name + + # Set up invariant files + control_dtb = make_dtb() + kernel = make_kernel() + ramdisk = make_ramdisk() + kernel_out = make_fname('kernel-out.bin') + fdt_out = make_fname('fdt-out.dtb') + ramdisk_out = make_fname('ramdisk-out.bin') + + # Set up basic parameters with default values + params = { + 'fit_addr' : 0x1000, + + 'kernel' : kernel, + 'kernel_out' : kernel_out, + 'kernel_addr' : 0x40000, + 'kernel_size' : filesize(kernel), + + 'fdt_out' : fdt_out, + 'fdt_addr' : 0x80000, + 'fdt_size' : filesize(control_dtb), + 'fdt_load' : '', + + 'ramdisk' : ramdisk, + 'ramdisk_out' : ramdisk_out, + 'ramdisk_addr' : 0xc0000, + 'ramdisk_size' : filesize(ramdisk), + 'ramdisk_load' : '', + 'ramdisk_config' : '', + } + + # Make a basic FIT and a script to load it + fit = make_fit(mkimage, params) + params['fit'] = fit + cmd = base_script % params + + # First check that we can load a kernel + # We could perhaps reduce duplication with some loss of readability + set_test('Kernel load') + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) == read_file(fdt_out): + fail('FDT loaded but should be ignored') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Find out the offset in the FIT where U-Boot has found the FDT + line = find_matching(stdout, 'Booting using the fdt blob at ') + fit_offset = int(line, 16) - params['fit_addr'] + fdt_magic = struct.pack('>L', 0xd00dfeed) + data = read_file(fit) + + # Now find where it actually is in the FIT (skip the first word) + real_fit_offset = data.find(fdt_magic, 4) + if fit_offset != real_fit_offset: + fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' % + (fit_offset, real_fit_offset)) + + # Now a kernel and an FDT + set_test('Kernel + FDT load') + params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) != read_file(fdt_out): + fail('FDT not loaded') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Try a ramdisk + set_test('Kernel + FDT + Ramdisk load') + params['ramdisk_config'] = 'ramdisk = "ramdisk@1";' + params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(ramdisk) != read_file(ramdisk_out): + fail('Ramdisk not loaded') + +def run_tests(): + """Parse options, run the FIT tests and print the result""" + global base_path, base_dir + + # Work in a temporary directory + base_dir = tempfile.mkdtemp() + parser = OptionParser() + parser.add_option('-u', '--u-boot', + default=os.path.join(base_path, 'u-boot'), + help='Select U-Boot sandbox binary') + parser.add_option('-k', '--keep', action='store_true', + help="Don't delete temporary directory even when tests pass") + parser.add_option('-t', '--selftest', action='store_true', + help='Run internal self tests') + (options, args) = parser.parse_args() + + # Find the path to U-Boot, and assume mkimage is in its tools/mkimage dir + base_path = os.path.dirname(options.u_boot) + mkimage = os.path.join(base_path, 'tools/mkimage') + + # There are a few doctests - handle these here + if options.selftest: + doctest.testmod() + return + + title = 'FIT Tests' + print title, '\n', '=' * len(title) + + run_fit_test(mkimage, options.u_boot) + + print '\nTests passed' + print 'Caveat: this is only a sanity check - test coverage is poor' + + # Remove the tempoerary directory unless we are asked to keep it + if options.keep: + print "Output files are in '%s'" % base_dir + else: + shutil.rmtree(base_dir) + +run_tests()

Hi,
On Thu, May 16, 2013 at 4:53 PM, Simon Glass sjg@chromium.org wrote:
In creating a new feature[*] I found that the image code includes quite a bit of duplication in places. In particular the code to load a kernel, FDT and ramdisk is all fairly similar, but subtly different.
This series introduces a new function fit_image_load() which loads an image from a FIT and supports the various features. For the bootstage updates, these are standardised so that each file has its own range and the events within that range have corresponding numbers. This means that the boot progress numbers will change slightly with this series.
The image.c file is still very long. Rather than perpetuate the #ifdefs in the code I have split out the image.c code that is dependent on CONFIG_OF_LIBFDT into image-fdt.c.
Several architectures have their own way of setting up a ramdisk and FDT for booting. An attempt is made here to unify these by providing a function image_setup_linux() to handle the overall task, and image_setup_fdt() to set up the FDT.
For ARM, the bootm code is a maze of #ifdefs, which means that many boards compile the code differently and it takes longer to detect breakages. To get around this, some defines are added to ARM's bootm.h to permit the use of if() instead of #ifdef, making use of the compiler's dead code elimination.
Also this series introduces a very basic test of image loading using sandbox. Some patches add bootm support for sandbox, and also a 'sb save' command to save memory to a host file (used to check that the bootm actually worked).
A test program for sandbox is added as a basic sanity check of image loading as performed by bootm.
- The new feature is support for FIT booting on x86, available in patchwork
starting here:
http://patchwork.ozlabs.org/patch/211526/
Changes in v3:
- Rebase without verified boot patches
FYI Tom this is the series sent out in January, but rebased on top of mainline without the verified boot patches.
Regards, Simon
Changes in v2:
- Add workaround for ELDK-4.2 to avoid cast warning
- Put quotes around error when selected FIT config cannot be found
- Correct definition of IMAGE_ENABLE_BEST_MATCH
- Fix checkpatch checks about parenthesis alignment
- Rebase on previous patches
- Add workaround for ELDK-4.2 to avoid cast warning
Simon Glass (10): bootstage: Introduce sub-IDs for use with image loading mkimage: Add map_sysmem() and IH_ARCH_DEFAULT to simplfy building image: Introduce fit_image_load() to load images from FITs image: Use fit_image_load() to load ramdisk image: Use fit_image_load() to load FDT sandbox: Adjust bootm command to work with sandbox image: Use fit_image_load() to load kernel sandbox: image: Adjust FIT image printing to work with sandbox bootstage: Remove unused entries related to kernel/ramdisk/fdt load sandbox: image: Create a test for loading FIT images
common/cmd_bootm.c | 170 +++----------------- common/image-fdt.c | 207 ++++-------------------- common/image-fit.c | 310 +++++++++++++++++++++++++----------- common/image.c | 122 ++------------ include/bootstage.h | 51 +++--- include/image.h | 105 +++++++++++- test/image/test-fit.py | 422 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/mkimage.h | 12 ++ 8 files changed, 846 insertions(+), 553 deletions(-) create mode 100755 test/image/test-fit.py
-- 1.8.2.1

On Thu, May 16, 2013 at 04:53:18PM -0700, Simon Glass wrote:
In creating a new feature[*] I found that the image code includes quite a bit of duplication in places. In particular the code to load a kernel, FDT and ramdisk is all fairly similar, but subtly different.
This series introduces a new function fit_image_load() which loads an image from a FIT and supports the various features. For the bootstage updates, these are standardised so that each file has its own range and the events within that range have corresponding numbers. This means that the boot progress numbers will change slightly with this series.
The image.c file is still very long. Rather than perpetuate the #ifdefs in the code I have split out the image.c code that is dependent on CONFIG_OF_LIBFDT into image-fdt.c.
Several architectures have their own way of setting up a ramdisk and FDT for booting. An attempt is made here to unify these by providing a function image_setup_linux() to handle the overall task, and image_setup_fdt() to set up the FDT.
For ARM, the bootm code is a maze of #ifdefs, which means that many boards compile the code differently and it takes longer to detect breakages. To get around this, some defines are added to ARM's bootm.h to permit the use of if() instead of #ifdef, making use of the compiler's dead code elimination.
Also this series introduces a very basic test of image loading using sandbox. Some patches add bootm support for sandbox, and also a 'sb save' command to save memory to a host file (used to check that the bootm actually worked).
A test program for sandbox is added as a basic sanity check of image loading as performed by bootm.
- The new feature is support for FIT booting on x86, available in patchwork
starting here:
http://patchwork.ozlabs.org/patch/211526/
Changes in v3:
- Rebase without verified boot patches
Changes in v2:
- Add workaround for ELDK-4.2 to avoid cast warning
- Put quotes around error when selected FIT config cannot be found
- Correct definition of IMAGE_ENABLE_BEST_MATCH
- Fix checkpatch checks about parenthesis alignment
- Rebase on previous patches
- Add workaround for ELDK-4.2 to avoid cast warning
Simon Glass (10): bootstage: Introduce sub-IDs for use with image loading mkimage: Add map_sysmem() and IH_ARCH_DEFAULT to simplfy building image: Introduce fit_image_load() to load images from FITs image: Use fit_image_load() to load ramdisk image: Use fit_image_load() to load FDT sandbox: Adjust bootm command to work with sandbox image: Use fit_image_load() to load kernel sandbox: image: Adjust FIT image printing to work with sandbox bootstage: Remove unused entries related to kernel/ramdisk/fdt load sandbox: image: Create a test for loading FIT images
common/cmd_bootm.c | 170 +++----------------- common/image-fdt.c | 207 ++++-------------------- common/image-fit.c | 310 +++++++++++++++++++++++++----------- common/image.c | 122 ++------------ include/bootstage.h | 51 +++--- include/image.h | 105 +++++++++++- test/image/test-fit.py | 422 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/mkimage.h | 12 ++ 8 files changed, 846 insertions(+), 553 deletions(-) create mode 100755 test/image/test-fit.py
Applied to u-boot/master, thanks!
participants (2)
-
Simon Glass
-
Tom Rini