[U-Boot] [PATCH v2 0/4] New tag for Flattened Image Trees (FIT) - Booting Xen from a FIT.

The FIT config now supports a tag named "loadables:" which is a comma separated list. Users can add any number of images to the list, and u-boot will move the selected binaries to their listed load_addresses. This allows u-boot to boot xen from using an FIT configuration. Xen expects a kernel to be placed at a predetermined location, however the "kernel" field was already filled by xen itself. This change allows the user to move the required binary before xen boots, all within the FIT's configuration.
Karl Apsite (4): add test for two 'loadables' mkimage will now report information about loadable add boot_get_loadables() to load listed images Combine bootm_find_<thing> functions together
common/bootm.c | 49 ++++++++++++----------- common/cmd_bootm.c | 4 +- common/image-fit.c | 25 +++++++++++- common/image.c | 71 ++++++++++++++++++++++++++++++++++ doc/uImage.FIT/source_file_format.txt | 4 ++ include/bootm.h | 2 +- include/bootstage.h | 1 + include/image.h | 28 +++++++++++++- test/image/test-fit.py | 73 ++++++++++++++++++++++++++++++----- 9 files changed, 221 insertions(+), 36 deletions(-)

From: Karl Apsite karl.apsite@dornerworks.com
A simple test that attmpts to load two loadables and verify that they are properly unpacked in the u-boot sandbox.
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com ---
test/image/test-fit.py | 73 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 9 deletions(-)
diff --git a/test/image/test-fit.py b/test/image/test-fit.py index e9e756a..ef6b24f 100755 --- a/test/image/test-fit.py +++ b/test/image/test-fit.py @@ -48,6 +48,15 @@ base_its = ''' load = <0x40000>; entry = <0x8>; }; + kernel@2 { + data = /incbin/("%(loadables1)s"); + type = "kernel"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + %(loadables1_load)s + entry = <0x0>; + }; fdt@1 { description = "snow"; data = /incbin/("u-boot.dtb"); @@ -69,6 +78,15 @@ base_its = ''' %(ramdisk_load)s compression = "none"; }; + ramdisk@2 { + description = "snow"; + data = /incbin/("%(loadables2)s"); + type = "ramdisk"; + arch = "sandbox"; + os = "linux"; + %(loadables2_load)s + compression = "none"; + }; }; configurations { default = "conf@1"; @@ -76,6 +94,7 @@ base_its = ''' kernel = "kernel@1"; fdt = "fdt@1"; %(ramdisk_config)s + %(loadables_config)s }; }; }; @@ -103,6 +122,8 @@ bootm loados sb save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x sb save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x sb save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x +sb save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x +sb save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x reset '''
@@ -188,30 +209,32 @@ def make_fit(mkimage, params): print >>fd, base_fdt return fit
-def make_kernel(): +def make_kernel(filename, text): """Make a sample kernel with test data
+ Args: + filename: the name of the file you want to create Returns: - Filename of kernel created + Full path and filename of the kernel it created """ - fname = make_fname('test-kernel.bin') + fname = make_fname(filename) data = '' for i in range(100): - data += 'this kernel %d is unlikely to boot\n' % i + data += 'this %s %d is unlikely to boot\n' % (text, i) with open(fname, 'w') as fd: print >>fd, data return fname
-def make_ramdisk(): +def make_ramdisk(filename, text): """Make a sample ramdisk with test data
Returns: Filename of ramdisk created """ - fname = make_fname('test-ramdisk.bin') + fname = make_fname(filename) data = '' for i in range(100): - data += 'ramdisk %d was seldom used in the middle ages\n' % i + data += '%s %d was seldom used in the middle ages\n' % (text, i) with open(fname, 'w') as fd: print >>fd, data return fname @@ -298,11 +321,15 @@ def run_fit_test(mkimage, u_boot):
# Set up invariant files control_dtb = make_dtb() - kernel = make_kernel() - ramdisk = make_ramdisk() + kernel = make_kernel('test-kernel.bin', 'kernel') + ramdisk = make_ramdisk('test-ramdisk.bin', 'ramdisk') + loadables1 = make_kernel('test-loadables1.bin', 'lenrek') + loadables2 = make_ramdisk('test-loadables2.bin', 'ksidmar') kernel_out = make_fname('kernel-out.bin') fdt_out = make_fname('fdt-out.dtb') ramdisk_out = make_fname('ramdisk-out.bin') + loadables1_out = make_fname('loadables1-out.bin') + loadables2_out = make_fname('loadables2-out.bin')
# Set up basic parameters with default values params = { @@ -324,6 +351,20 @@ def run_fit_test(mkimage, u_boot): 'ramdisk_size' : filesize(ramdisk), 'ramdisk_load' : '', 'ramdisk_config' : '', + + 'loadables1' : loadables1, + 'loadables1_out' : loadables1_out, + 'loadables1_addr' : 0x100000, + 'loadables1_size' : filesize(loadables1), + 'loadables1_load' : '', + + 'loadables2' : loadables2, + 'loadables2_out' : loadables2_out, + 'loadables2_addr' : 0x140000, + 'loadables2_size' : filesize(loadables2), + 'loadables2_load' : '', + + 'loadables_config' : '', }
# Make a basic FIT and a script to load it @@ -378,6 +419,19 @@ def run_fit_test(mkimage, u_boot): if read_file(ramdisk) != read_file(ramdisk_out): fail('Ramdisk not loaded', stdout)
+ # Configuration with some Loadables + set_test('Kernel + FDT + Ramdisk load + Loadables') + params['loadables_config'] = 'loadables = "kernel@2", "ramdisk@2";' + params['loadables1_load'] = 'load = <%#x>;' % params['loadables1_addr'] + params['loadables2_load'] = 'load = <%#x>;' % params['loadables2_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + debug_stdout(stdout) + if read_file(loadables1) != read_file(loadables1_out): + fail('Loadables1 (kernel) not loaded', stdout) + if read_file(loadables2) != read_file(loadables2_out): + fail('Loadables2 (ramdisk) not loaded', stdout) + def run_tests(): """Parse options, run the FIT tests and print the result""" global base_path, base_dir @@ -406,6 +460,7 @@ def run_tests(): title = 'FIT Tests' print title, '\n', '=' * len(title)
+ print "Output files are in '%s'" % base_dir run_fit_test(mkimage, options.u_boot)
print '\nTests passed'

On 15 May 2015 at 15:13, Karl Apsite Karl.Apsite@dornerworks.com wrote:
From: Karl Apsite karl.apsite@dornerworks.com
A simple test that attmpts to load two loadables and verify that they are properly unpacked in the u-boot sandbox.
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com
test/image/test-fit.py | 73 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
But when you resend please do check the order of the patches. I don't think this test will pass until the other code is in. We need to keep bisectability of building and tests passing.

From: Karl Apsite karl.apsite@dornerworks.com
Added FIT_LOADABLE_PROP, so the user can identify an optional entry named "loadables" in their .its configuration. "loadables" is a comma separated list in the .its
example configuration: config@1 { description = "Xen 4.6.0-one loadable"; kernel = "xen_kernel@1"; fdt = "fdt@1"; loadables = "linux_kernel@1"; };
config@2 { description = "Xen 4.6.0-two loadables"; kernel = "xen_kernel@1"; fdt = "fdt@1"; loadables = "linux_kernel@2", "linux_kernel@1"; };
example output: ... Configuration 0 (config@1) Description: Xen 4.6.0-one loadable Kernel: xen_kernel@1 FDT: fdt@1 Loadables: linux_kernel@1 Configuration 1 (config@2) Description: Xen 4.6.0-two loadables Kernel: xen_kernel@1 FDT: fdt@1 Loadables: linux_kernel@2 linux_kernel@1
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com ---
common/image-fit.c | 17 +++++++++++++++++ doc/uImage.FIT/source_file_format.txt | 4 ++++ include/image.h | 1 + 3 files changed, 22 insertions(+)
diff --git a/common/image-fit.c b/common/image-fit.c index 4eb4d42..fc9ea1f 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1436,6 +1436,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) char *desc; char *uname; int ret; + int loadables_index;
/* Mandatory properties */ ret = fit_get_desc(fit, noffset, &desc); @@ -1460,6 +1461,22 @@ void fit_conf_print(const void *fit, int noffset, const char *p) uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL); if (uname) printf("%s FDT: %s\n", p, uname); + + /* Print out all of the specified loadables */ + for (loadables_index = 0; + !fdt_get_string_index(fit, noffset, + FIT_LOADABLE_PROP, + loadables_index, + (const char **)&uname) > 0; + loadables_index++) + { + if (loadables_index == 0) { + printf("%s Loadables: ", p); + } else { + printf("%s ", p); + } + printf("%s\n", uname); + } }
static int fit_image_select(const void *fit, int rd_noffset, int verify) diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt index 427ea49..004acd1 100644 --- a/doc/uImage.FIT/source_file_format.txt +++ b/doc/uImage.FIT/source_file_format.txt @@ -235,6 +235,7 @@ o config@1 |- kernel = "kernel sub-node unit name" |- ramdisk = "ramdisk sub-node unit name" |- fdt = "fdt sub-node unit-name" + |- loadables = "loadables sub-node unit-name"
Mandatory properties: @@ -249,6 +250,9 @@ o config@1 "fdt type"). - setup : Unit name of the corresponding setup binary (used for booting an x86 kernel). This contains the setup.bin file built by the kernel. + - loadables : Unit name containing a list of additional binaries to be loaded at + their given locations. "loadables" is a comma-separated list of strings. + u-boot will load each binary at its given start-address.
The FDT blob is required to properly boot FDT based kernel, so the minimal configuration for 2.6 FDT kernel is (kernel, fdt) pair. diff --git a/include/image.h b/include/image.h index 60b924a..97b96b3 100644 --- a/include/image.h +++ b/include/image.h @@ -742,6 +742,7 @@ int bootz_setup(ulong image, ulong *start, ulong *end); #define FIT_KERNEL_PROP "kernel" #define FIT_RAMDISK_PROP "ramdisk" #define FIT_FDT_PROP "fdt" +#define FIT_LOADABLE_PROP "loadables" #define FIT_DEFAULT_PROP "default" #define FIT_SETUP_PROP "setup"

Hi Karl,
On 15 May 2015 at 15:13, Karl Apsite Karl.Apsite@dornerworks.com wrote:
From: Karl Apsite karl.apsite@dornerworks.com
Added FIT_LOADABLE_PROP, so the user can identify an optional entry named "loadables" in their .its configuration. "loadables" is a comma separated list in the .its
example configuration: config@1 { description = "Xen 4.6.0-one loadable"; kernel = "xen_kernel@1"; fdt = "fdt@1"; loadables = "linux_kernel@1"; };
config@2 { description = "Xen 4.6.0-two loadables"; kernel = "xen_kernel@1"; fdt = "fdt@1"; loadables = "linux_kernel@2", "linux_kernel@1"; };
example output: ... Configuration 0 (config@1) Description: Xen 4.6.0-one loadable Kernel: xen_kernel@1 FDT: fdt@1 Loadables: linux_kernel@1 Configuration 1 (config@2) Description: Xen 4.6.0-two loadables Kernel: xen_kernel@1 FDT: fdt@1 Loadables: linux_kernel@2 linux_kernel@1
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com
Reviewed-by: Simon Glass sjg@chromium.org
But I think you should remove this stuff from your commit message. It should go in the docs.
Regards, Simon

From: Karl Apsite karl.apsite@dornerworks.com
Added a trimmed down instance of boot_get_<thing>() to satisfy the minimum requierments of the added feature. The function follows the normal patterns set by other boot_get<thing>'s, which should make it a bit easier to combine them all together into one boot_get_image() function in a later refactor.
Documentation for the new function can be found in source: include/image.h
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com ---
common/bootm.c | 26 ++++++++++++++++++-- common/image-fit.c | 8 +++++- common/image.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/bootstage.h | 1 + include/image.h | 27 +++++++++++++++++++- 5 files changed, 129 insertions(+), 4 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c index 6842029..f42fb66 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -214,7 +214,7 @@ static int bootm_find_ramdisk(int flag, int argc, char * const argv[]) ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH, &images.rd_start, &images.rd_end); if (ret) { - puts("Ramdisk image is corrupt or invalid\n"); + printf("Ramdisk image is corrupt or invalid\n"); return 1; }
@@ -230,7 +230,7 @@ static int bootm_find_fdt(int flag, int argc, char * const argv[]) 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"); + printf("Could not find a valid device tree\n"); return 1; }
@@ -240,6 +240,23 @@ static int bootm_find_fdt(int flag, int argc, char * const argv[]) } #endif
+#if defined(CONFIG_FIT) +static int bootm_find_loadables(int flag, int argc, char * const argv[]) +{ + int ret; + + /* find all of the loadables */ + ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT, + NULL, NULL); + if (ret) { + printf("Loadable(s) is corrupt or invalid\n"); + return 1; + } + + return 0; +} +#endif + int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]) { if (bootm_find_ramdisk(flag, argc, argv)) @@ -250,6 +267,11 @@ int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]) return 1; #endif
+#if defined(CONFIG_FIT) + if (bootm_find_loadables(flag, argc, argv)) + return 1; +#endif + return 0; }
diff --git a/common/image-fit.c b/common/image-fit.c index fc9ea1f..ecd3e67 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1544,6 +1544,8 @@ static const char *fit_get_image_type_property(int type) return FIT_RAMDISK_PROP; case IH_TYPE_X86_SETUP: return FIT_SETUP_PROP; + case IH_TYPE_LOADABLE: + return FIT_LOADABLE_PROP; }
return "unknown"; @@ -1661,7 +1663,11 @@ int fit_image_load(bootm_headers_t *images, ulong addr, os_ok = image_type == IH_TYPE_FLATDT || fit_image_check_os(fit, noffset, IH_OS_LINUX) || fit_image_check_os(fit, noffset, IH_OS_OPENRTOS); - if (!type_ok || !os_ok) { + + /* 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), diff --git a/common/image.c b/common/image.c index fdec496..e5cff05 100644 --- a/common/image.c +++ b/common/image.c @@ -1165,6 +1165,77 @@ int boot_get_setup(bootm_headers_t *images, uint8_t arch, #endif }
+#if defined(CONFIG_FIT) +int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images, + uint8_t arch, const ulong *ld_start, ulong * const ld_len) +{ + /* + * These variables are used to hold the current image location + * in system memory. + */ + ulong tmp_img_addr; + /* + * These two variables are requirements for fit_image_load, but + * their values are not used + */ + ulong img_data, img_len; + void *buf; + int loadables_index; + int conf_noffset; + int fit_img_result; + char *uname; + + /* Check to see if the images struct has a FIT configuration */ + if (!genimg_has_config(images)) { + debug("## FIT configuration was not specified\n"); + return 0; + } + + /* + * Obtain the os FIT header from the images struct + * copy from dataflash if needed + */ + tmp_img_addr = map_to_sysmem(images->fit_hdr_os); + tmp_img_addr = genimg_get_image(tmp_img_addr); + buf = map_sysmem(tmp_img_addr, 0); + /* + * Check image type. For FIT images get FIT node + * and attempt to locate a generic binary. + */ + switch (genimg_get_format(buf)) { + case IMAGE_FORMAT_FIT: + conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg); + + for (loadables_index = 0; + !fdt_get_string_index(buf, conf_noffset, + FIT_LOADABLE_PROP, + loadables_index, + (const char **)&uname) > 0; + loadables_index++) + { + fit_img_result = fit_image_load(images, + tmp_img_addr, + (const char **)&uname, + &(images->fit_uname_cfg), arch, + IH_TYPE_LOADABLE, + BOOTSTAGE_ID_FIT_LOADABLE_START, + FIT_LOAD_OPTIONAL_NON_ZERO, + &img_data, &img_len); + if (fit_img_result < 0) { + /* Something went wrong! */ + return fit_img_result; + } + } + break; + default: + puts("The given image format is not supported (corrupt?)\n"); + return 1; + } + + return 0; +} +#endif + #ifdef CONFIG_SYS_BOOT_GET_CMDLINE /** * boot_get_cmdline - allocate and initialize kernel cmdline diff --git a/include/bootstage.h b/include/bootstage.h index be44014..8885053 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -168,6 +168,7 @@ enum bootstage_id { BOOTSTAGE_ID_NAND_FIT_READ = 150, BOOTSTAGE_ID_NAND_FIT_READ_OK,
+ BOOTSTAGE_ID_FIT_LOADABLE_START = 160, /* for Loadable Images */ /* * These boot stages are new, higher level, and not directly related * to the old boot progress numbers. They are useful for recording diff --git a/include/image.h b/include/image.h index 97b96b3..b6eb57e 100644 --- a/include/image.h +++ b/include/image.h @@ -244,6 +244,7 @@ struct lmb; #define IH_TYPE_SOCFPGAIMAGE 19 /* Altera SOCFPGA Preloader */ #define IH_TYPE_X86_SETUP 20 /* x86 setup.bin Image */ #define IH_TYPE_LPC32XXIMAGE 21 /* x86 setup.bin Image */ +#define IH_TYPE_LOADABLE 22 /* A list of typeless images */
/* * Compression Types @@ -455,7 +456,31 @@ 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); -#endif + +/** + * boot_get_loadable - routine to load a list of binaries to memory + * @argc: Ignored Argument + * @argv: Ignored Argument + * @images: pointer to the bootm images structure + * @arch: expected architecture for the image + * @ld_start: Ignored Argument + * @ld_len: Ignored Argument + * + * boot_get_loadable() will take the given FIT configuration, and look + * for a field named "loadables". Loadables, is a list of elements in + * the FIT given as strings. exe: + * loadables = "linux_kernel@1", "fdt@2"; + * this function will attempt to parse each string, and load the + * corresponding element from the FIT into memory. Once placed, + * no aditional actions are taken. + * + * @return: + * 0, if only valid images or no images are found + * error code, if an error occurs during fit_image_load + */ +int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images, + uint8_t arch, const ulong *ld_start, ulong * const ld_len); +#endif /* !USE_HOSTCC */
int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, ulong *setup_start, ulong *setup_len);

Hi Karl,
On 15 May 2015 at 15:13, Karl Apsite Karl.Apsite@dornerworks.com wrote:
From: Karl Apsite karl.apsite@dornerworks.com
Added a trimmed down instance of boot_get_<thing>() to satisfy the minimum requierments of the added feature. The function follows the normal patterns set by other boot_get<thing>'s, which should make it a bit easier to combine them all together into one boot_get_image() function in a later refactor.
Documentation for the new function can be found in source: include/image.h
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com
Looks good to me - but see comment below.
common/bootm.c | 26 ++++++++++++++++++-- common/image-fit.c | 8 +++++- common/image.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/bootstage.h | 1 + include/image.h | 27 +++++++++++++++++++- 5 files changed, 129 insertions(+), 4 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c index 6842029..f42fb66 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -214,7 +214,7 @@ static int bootm_find_ramdisk(int flag, int argc, char * const argv[]) ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH, &images.rd_start, &images.rd_end); if (ret) {
puts("Ramdisk image is corrupt or invalid\n");
printf("Ramdisk image is corrupt or invalid\n");
This seems unrelated to your patch - can you pull out this clean-up into a separate patch? It could precede this one in the stack.
return 1; }
@@ -230,7 +230,7 @@ static int bootm_find_fdt(int flag, int argc, char * const argv[]) 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");
printf("Could not find a valid device tree\n"); return 1; }
@@ -240,6 +240,23 @@ static int bootm_find_fdt(int flag, int argc, char * const argv[]) } #endif
+#if defined(CONFIG_FIT) +static int bootm_find_loadables(int flag, int argc, char * const argv[]) +{
int ret;
/* find all of the loadables */
ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT,
NULL, NULL);
if (ret) {
printf("Loadable(s) is corrupt or invalid\n");
return 1;
}
return 0;
+} +#endif
int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]) { if (bootm_find_ramdisk(flag, argc, argv)) @@ -250,6 +267,11 @@ int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]) return 1; #endif
+#if defined(CONFIG_FIT)
if (bootm_find_loadables(flag, argc, argv))
return 1;
+#endif
return 0;
}
diff --git a/common/image-fit.c b/common/image-fit.c index fc9ea1f..ecd3e67 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1544,6 +1544,8 @@ static const char *fit_get_image_type_property(int type) return FIT_RAMDISK_PROP; case IH_TYPE_X86_SETUP: return FIT_SETUP_PROP;
case IH_TYPE_LOADABLE:
return FIT_LOADABLE_PROP; } return "unknown";
@@ -1661,7 +1663,11 @@ int fit_image_load(bootm_headers_t *images, ulong addr, os_ok = image_type == IH_TYPE_FLATDT || fit_image_check_os(fit, noffset, IH_OS_LINUX) || fit_image_check_os(fit, noffset, IH_OS_OPENRTOS);
if (!type_ok || !os_ok) {
/* 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),
diff --git a/common/image.c b/common/image.c index fdec496..e5cff05 100644 --- a/common/image.c +++ b/common/image.c @@ -1165,6 +1165,77 @@ int boot_get_setup(bootm_headers_t *images, uint8_t arch, #endif }
+#if defined(CONFIG_FIT) +int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
uint8_t arch, const ulong *ld_start, ulong * const ld_len)
+{
/*
* These variables are used to hold the current image location
* in system memory.
*/
ulong tmp_img_addr;
/*
* These two variables are requirements for fit_image_load, but
* their values are not used
*/
ulong img_data, img_len;
void *buf;
int loadables_index;
int conf_noffset;
int fit_img_result;
char *uname;
/* Check to see if the images struct has a FIT configuration */
if (!genimg_has_config(images)) {
debug("## FIT configuration was not specified\n");
return 0;
}
/*
* Obtain the os FIT header from the images struct
* copy from dataflash if needed
*/
tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
tmp_img_addr = genimg_get_image(tmp_img_addr);
buf = map_sysmem(tmp_img_addr, 0);
/*
* Check image type. For FIT images get FIT node
* and attempt to locate a generic binary.
*/
switch (genimg_get_format(buf)) {
case IMAGE_FORMAT_FIT:
conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
for (loadables_index = 0;
!fdt_get_string_index(buf, conf_noffset,
FIT_LOADABLE_PROP,
loadables_index,
(const char **)&uname) > 0;
loadables_index++)
{
fit_img_result = fit_image_load(images,
tmp_img_addr,
(const char **)&uname,
&(images->fit_uname_cfg), arch,
IH_TYPE_LOADABLE,
BOOTSTAGE_ID_FIT_LOADABLE_START,
FIT_LOAD_OPTIONAL_NON_ZERO,
&img_data, &img_len);
if (fit_img_result < 0) {
/* Something went wrong! */
return fit_img_result;
}
}
break;
default:
puts("The given image format is not supported (corrupt?)\n");
printf?
return 1;
}
return 0;
+} +#endif
#ifdef CONFIG_SYS_BOOT_GET_CMDLINE /**
- boot_get_cmdline - allocate and initialize kernel cmdline
diff --git a/include/bootstage.h b/include/bootstage.h index be44014..8885053 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -168,6 +168,7 @@ enum bootstage_id { BOOTSTAGE_ID_NAND_FIT_READ = 150, BOOTSTAGE_ID_NAND_FIT_READ_OK,
BOOTSTAGE_ID_FIT_LOADABLE_START = 160, /* for Loadable Images */ /* * These boot stages are new, higher level, and not directly related * to the old boot progress numbers. They are useful for recording
diff --git a/include/image.h b/include/image.h index 97b96b3..b6eb57e 100644 --- a/include/image.h +++ b/include/image.h @@ -244,6 +244,7 @@ struct lmb; #define IH_TYPE_SOCFPGAIMAGE 19 /* Altera SOCFPGA Preloader */ #define IH_TYPE_X86_SETUP 20 /* x86 setup.bin Image */ #define IH_TYPE_LPC32XXIMAGE 21 /* x86 setup.bin Image */ +#define IH_TYPE_LOADABLE 22 /* A list of typeless images */
/*
- Compression Types
@@ -455,7 +456,31 @@ 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); -#endif
+/**
- boot_get_loadable - routine to load a list of binaries to memory
- @argc: Ignored Argument
- @argv: Ignored Argument
- @images: pointer to the bootm images structure
- @arch: expected architecture for the image
- @ld_start: Ignored Argument
- @ld_len: Ignored Argument
- boot_get_loadable() will take the given FIT configuration, and look
- for a field named "loadables". Loadables, is a list of elements in
- the FIT given as strings. exe:
- loadables = "linux_kernel@1", "fdt@2";
- this function will attempt to parse each string, and load the
- corresponding element from the FIT into memory. Once placed,
- no aditional actions are taken.
- @return:
0, if only valid images or no images are found
error code, if an error occurs during fit_image_load
- */
+int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
uint8_t arch, const ulong *ld_start, ulong * const ld_len);
+#endif /* !USE_HOSTCC */
int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, ulong *setup_start, ulong *setup_len); -- 2.3.7
Regards, Simon

bootm_find_ramdisk_fdt() renamed to bootm_find_images() for readability.
The function bootm_find_ramdisk_fdt() appears to be a simple wrapper for bootm_find_ramdisk(), bootm_find_fdt(), and now bootm_find_loadables(). I didn't see any other callers entering a bootm_find<thing>, so removing the wrapper, and condensing these together hopefully makes the code a little simpler.
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com ---
common/bootm.c | 53 ++++++++++++++++++----------------------------------- common/cmd_bootm.c | 4 ++-- include/bootm.h | 2 +- 3 files changed, 21 insertions(+), 38 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c index f42fb66..75705f3 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -206,7 +206,23 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc, return 0; }
-static int bootm_find_ramdisk(int flag, int argc, char * const argv[]) +/** + * bootm_find_images - wrapper to find and locate various images + * @flag: Ignored Argument + * @argc: command argument count + * @argv: command argument list + * + * boot_find_images() will attempt to load an available ramdisk, + * flattened device tree, as well as specifically marked + * "loadable" images (loadables are FIT only) + * + * Note: bootm_find_images will skip an image if it is not found + * + * @return: + * 0, if all existing images were loaded correctly + * 1, if an image is found but corrupted, or invalid + */ +int bootm_find_images(int flag, int argc, char * const argv[]) { int ret;
@@ -218,14 +234,7 @@ static int bootm_find_ramdisk(int flag, int argc, char * const argv[]) return 1; }
- return 0; -} - #if defined(CONFIG_OF_LIBFDT) -static int bootm_find_fdt(int flag, int argc, char * const argv[]) -{ - int ret; - /* find flattened device tree */ ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images, &images.ft_addr, &images.ft_len); @@ -233,18 +242,10 @@ static int bootm_find_fdt(int flag, int argc, char * const argv[]) printf("Could not find a valid device tree\n"); return 1; } - set_working_fdt_addr((ulong)images.ft_addr); - - return 0; -} #endif
#if defined(CONFIG_FIT) -static int bootm_find_loadables(int flag, int argc, char * const argv[]) -{ - int ret; - /* find all of the loadables */ ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT, NULL, NULL); @@ -252,24 +253,6 @@ static int bootm_find_loadables(int flag, int argc, char * const argv[]) printf("Loadable(s) is corrupt or invalid\n"); return 1; } - - return 0; -} -#endif - -int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]) -{ - if (bootm_find_ramdisk(flag, argc, argv)) - return 1; - -#if defined(CONFIG_OF_LIBFDT) - if (bootm_find_fdt(flag, argc, argv)) - return 1; -#endif - -#if defined(CONFIG_FIT) - if (bootm_find_loadables(flag, argc, argv)) - return 1; #endif
return 0; @@ -283,7 +266,7 @@ static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc, (images.os.type == IH_TYPE_MULTI)) && (images.os.os == IH_OS_LINUX || images.os.os == IH_OS_VXWORKS)) - return bootm_find_ramdisk_fdt(flag, argc, argv); + return bootm_find_images(flag, argc, argv);
return 0; } diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 6b6aca6..48738ac 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -580,7 +580,7 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc, * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not * have a header that provide this informaiton. */ - if (bootm_find_ramdisk_fdt(flag, argc, argv)) + if (bootm_find_images(flag, argc, argv)) return 1;
return 0; @@ -721,7 +721,7 @@ static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc, * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not * have a header that provide this informaiton. */ - if (bootm_find_ramdisk_fdt(flag, argc, argv)) + if (bootm_find_images(flag, argc, argv)) return 1;
return 0; diff --git a/include/bootm.h b/include/bootm.h index 6181488..4981377 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -49,7 +49,7 @@ int boot_selected_os(int argc, char * const argv[], int state, ulong bootm_disable_interrupts(void);
/* This is a special function used by booti/bootz */ -int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]); +int bootm_find_images(int flag, int argc, char * const argv[]);
int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int states, bootm_headers_t *images, int boot_progress);

On 15 May 2015 at 15:13, Karl Apsite Karl.Apsite@dornerworks.com wrote:
bootm_find_ramdisk_fdt() renamed to bootm_find_images() for readability.
The function bootm_find_ramdisk_fdt() appears to be a simple wrapper for bootm_find_ramdisk(), bootm_find_fdt(), and now bootm_find_loadables(). I didn't see any other callers entering a bootm_find<thing>, so removing the wrapper, and condensing these together hopefully makes the code a little simpler.
Signed-off-by: Karl Apsite Karl.Apsite@dornerworks.com
common/bootm.c | 53 ++++++++++++++++++----------------------------------- common/cmd_bootm.c | 4 ++-- include/bootm.h | 2 +- 3 files changed, 21 insertions(+), 38 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

+Tom in case he has a comment
Hi Karl,
On 15 May 2015 at 15:13, Karl Apsite Karl.Apsite@dornerworks.com wrote:
The FIT config now supports a tag named "loadables:" which is a comma separated list. Users can add any number of images to the list, and u-boot will move the selected binaries to their listed load_addresses. This allows u-boot to boot xen from using an FIT configuration. Xen expects a kernel to be placed at a predetermined location, however the "kernel" field was already filled by xen itself. This change allows the user to move the required binary before xen boots, all within the FIT's configuration.
I think I've convinced myself that this ('loadables') is a good solution to the problem. I'm not 100% comfortable with the name but I don't have a better one, and no one else has chimed in.
Will you actually use multiple images in your application?
Karl Apsite (4): add test for two 'loadables' mkimage will now report information about loadable add boot_get_loadables() to load listed images Combine bootm_find_<thing> functions together
common/bootm.c | 49 ++++++++++++----------- common/cmd_bootm.c | 4 +- common/image-fit.c | 25 +++++++++++- common/image.c | 71 ++++++++++++++++++++++++++++++++++ doc/uImage.FIT/source_file_format.txt | 4 ++ include/bootm.h | 2 +- include/bootstage.h | 1 + include/image.h | 28 +++++++++++++- test/image/test-fit.py | 73 ++++++++++++++++++++++++++++++----- 9 files changed, 221 insertions(+), 36 deletions(-)
-- 2.3.7
Regards, Simon

Hi Simon,
On 05/18/2015 11:28 AM, Simon Glass wrote:
+Tom in case he has a comment
Hi Karl,
On 15 May 2015 at 15:13, Karl Apsite Karl.Apsite@dornerworks.com wrote:
The FIT config now supports a tag named "loadables:" which is a comma separated list. Users can add any number of images to the list, and u-boot will move the selected binaries to their listed load_addresses. This allows u-boot to boot xen from using an FIT configuration. Xen expects a kernel to be placed at a predetermined location, however the "kernel" field was already filled by xen itself. This change allows the user to move the required binary before xen boots, all within the FIT's configuration.
I think I've convinced myself that this ('loadables') is a good solution to the problem. I'm not 100% comfortable with the name but I don't have a better one, and no one else has chimed in.
Will you actually use multiple images in your application?
We initially wanted to create this feature for Xen initially, and that only required loading one "loadable", or simply another kernel binary along side the first one.
While I was working on loading another binary in this fashion, we thought of a few other use cases that might benefit from this feature involving a number of the embedded systems we work with. Many of our use cases involve other peripheries that need to be configured or programmed with data during the boot process. By extending this configuration to an FIT, we can load/configure N-number of peripherals during boot, and gain some of the benefits that an FIT can provide: - Automatic checksum validation - Multiple configurations at the ready, all inside one "pre-baked image" - All while keeping the interface that a customer might use relatively simple `> bootm "#config@2"` or `"#config@3"`, etc. This is quite beneficial when we'd normally have to rely on u-boot scripts to do everything instead.
As a final consideration (and to be clear, this is requires a lot more investigation), one of the long-term goals that has been proposed to Xen, involves splitting up the "master control domain" (known as dom0) into a number of smaller domains/microkernels, each responsible for a certain task/service. E.G. a networking domain, a file-system IO domain, etc. So while this doesn't solve a large number of problems that are currently blocking that complex feature, this might help open the door to allow Xen to break components/services into different executables/kernels, and load them simultaneously.
Karl Apsite (4): add test for two 'loadables' mkimage will now report information about loadable add boot_get_loadables() to load listed images Combine bootm_find_<thing> functions together
common/bootm.c | 49 ++++++++++++----------- common/cmd_bootm.c | 4 +- common/image-fit.c | 25 +++++++++++- common/image.c | 71 ++++++++++++++++++++++++++++++++++ doc/uImage.FIT/source_file_format.txt | 4 ++ include/bootm.h | 2 +- include/bootstage.h | 1 + include/image.h | 28 +++++++++++++- test/image/test-fit.py | 73 ++++++++++++++++++++++++++++++----- 9 files changed, 221 insertions(+), 36 deletions(-)
-- 2.3.7
Regards, Simon
participants (2)
-
Karl Apsite
-
Simon Glass