mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-29 07:33:29 +08:00
fit: Support compression for non-kernel components (e.g. FDT)
This patch adds support for compressing non-kernel image nodes in a FIT image (kernel nodes could already be compressed previously). This can reduce the size of FIT images and therefore improve boot times (especially when an image bundles many different kernel FDTs). The images will automatically be decompressed on load. This patch does not support extracting compatible strings from compressed FDTs, so it's not very helpful in conjunction with CONFIG_FIT_BEST_MATCH yet, but it can already be used in environments that select the configuration to load explicitly. Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
This commit is contained in:
parent
2090854cd2
commit
b1307f884a
@ -22,6 +22,7 @@
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif /* !USE_HOSTCC*/
|
||||
|
||||
#include <bootm.h>
|
||||
#include <image.h>
|
||||
#include <bootstage.h>
|
||||
#include <u-boot/crc.h>
|
||||
@ -1576,6 +1577,13 @@ int fit_conf_find_compat(const void *fit, const void *fdt)
|
||||
kfdt_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fit_image_check_comp(fit, kfdt_noffset, IH_COMP_NONE)) {
|
||||
debug("Can't extract compat from \"%s\" (compressed)\n",
|
||||
kfdt_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a pointer to this configuration's fdt.
|
||||
*/
|
||||
@ -1795,11 +1803,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
|
||||
const char *fit_uname_config;
|
||||
const char *fit_base_uname_config;
|
||||
const void *fit;
|
||||
const void *buf;
|
||||
void *buf;
|
||||
void *loadbuf;
|
||||
size_t size;
|
||||
int type_ok, os_ok;
|
||||
ulong load, data, len;
|
||||
uint8_t os;
|
||||
ulong load, load_end, data, len;
|
||||
uint8_t os, comp;
|
||||
#ifndef USE_HOSTCC
|
||||
uint8_t os_arch;
|
||||
#endif
|
||||
@ -1895,12 +1904,6 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
|
||||
images->os.arch = os_arch;
|
||||
#endif
|
||||
|
||||
if (image_type == IH_TYPE_FLATDT &&
|
||||
!fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
|
||||
puts("FDT image is compressed");
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
|
||||
bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
|
||||
type_ok = fit_image_check_type(fit, noffset, image_type) ||
|
||||
fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
|
||||
@ -1931,7 +1934,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
|
||||
bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
|
||||
|
||||
/* get image data address and length */
|
||||
if (fit_image_get_data_and_size(fit, noffset, &buf, &size)) {
|
||||
if (fit_image_get_data_and_size(fit, noffset,
|
||||
(const void **)&buf, &size)) {
|
||||
printf("Could not find %s subimage data!\n", prop_name);
|
||||
bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
|
||||
return -ENOENT;
|
||||
@ -1939,30 +1943,15 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
|
||||
|
||||
#if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS)
|
||||
/* perform any post-processing on the image data */
|
||||
board_fit_image_post_process((void **)&buf, &size);
|
||||
board_fit_image_post_process(&buf, &size);
|
||||
#endif
|
||||
|
||||
len = (ulong)size;
|
||||
|
||||
/* verify that image data is a proper FDT blob */
|
||||
if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
|
||||
puts("Subimage data is not a FDT");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
|
||||
|
||||
/*
|
||||
* Work-around for eldk-4.2 which gives this warning if we try to
|
||||
* cast in the unmap_sysmem() call:
|
||||
* warning: initialization discards qualifiers from pointer target type
|
||||
*/
|
||||
{
|
||||
void *vbuf = (void *)buf;
|
||||
|
||||
data = map_to_sysmem(vbuf);
|
||||
}
|
||||
|
||||
data = map_to_sysmem(buf);
|
||||
load = data;
|
||||
if (load_op == FIT_LOAD_IGNORED) {
|
||||
/* Don't load */
|
||||
} else if (fit_image_get_load(fit, noffset, &load)) {
|
||||
@ -1974,8 +1963,6 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
|
||||
}
|
||||
} else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
|
||||
ulong image_start, image_end;
|
||||
ulong load_end;
|
||||
void *dst;
|
||||
|
||||
/*
|
||||
* move image data to the load address,
|
||||
@ -1993,14 +1980,45 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
|
||||
|
||||
printf(" Loading %s from 0x%08lx to 0x%08lx\n",
|
||||
prop_name, data, load);
|
||||
|
||||
dst = map_sysmem(load, len);
|
||||
memmove(dst, buf, len);
|
||||
data = load;
|
||||
} else {
|
||||
load = data; /* No load address specified */
|
||||
}
|
||||
|
||||
comp = IH_COMP_NONE;
|
||||
loadbuf = buf;
|
||||
/* Kernel images get decompressed later in bootm_load_os(). */
|
||||
if (!(image_type == IH_TYPE_KERNEL ||
|
||||
image_type == IH_TYPE_KERNEL_NOLOAD) &&
|
||||
!fit_image_get_comp(fit, noffset, &comp) &&
|
||||
comp != IH_COMP_NONE) {
|
||||
ulong max_decomp_len = len * 20;
|
||||
if (load == data) {
|
||||
loadbuf = malloc(max_decomp_len);
|
||||
load = map_to_sysmem(loadbuf);
|
||||
} else {
|
||||
loadbuf = map_sysmem(load, max_decomp_len);
|
||||
}
|
||||
if (image_decomp(comp, load, data, image_type,
|
||||
loadbuf, buf, len, max_decomp_len, &load_end)) {
|
||||
printf("Error decompressing %s\n", prop_name);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
len = load_end - load;
|
||||
} else if (load != data) {
|
||||
loadbuf = map_sysmem(load, len);
|
||||
memcpy(loadbuf, buf, len);
|
||||
}
|
||||
|
||||
/* verify that image data is a proper FDT blob */
|
||||
if (image_type == IH_TYPE_FLATDT && fdt_check_header(loadbuf)) {
|
||||
puts("Subimage data is not a FDT");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
|
||||
|
||||
*datap = data;
|
||||
*datap = load;
|
||||
*lenp = len;
|
||||
if (fit_unamep)
|
||||
*fit_unamep = (char *)fit_uname;
|
||||
|
@ -24,7 +24,7 @@ base_its = '''
|
||||
type = "kernel";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
compression = "%(compression)s";
|
||||
load = <0x40000>;
|
||||
entry = <0x8>;
|
||||
};
|
||||
@ -39,11 +39,11 @@ base_its = '''
|
||||
};
|
||||
fdt@1 {
|
||||
description = "snow";
|
||||
data = /incbin/("u-boot.dtb");
|
||||
data = /incbin/("%(fdt)s");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
%(fdt_load)s
|
||||
compression = "none";
|
||||
compression = "%(compression)s";
|
||||
signature@1 {
|
||||
algo = "sha1,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
@ -56,7 +56,7 @@ base_its = '''
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
%(ramdisk_load)s
|
||||
compression = "none";
|
||||
compression = "%(compression)s";
|
||||
};
|
||||
ramdisk@2 {
|
||||
description = "snow";
|
||||
@ -221,6 +221,10 @@ def test_fit(u_boot_console):
|
||||
print(data, file=fd)
|
||||
return fname
|
||||
|
||||
def make_compressed(filename):
|
||||
util.run_and_log(cons, ['gzip', '-f', '-k', filename])
|
||||
return filename + '.gz'
|
||||
|
||||
def find_matching(text, match):
|
||||
"""Find a match in a line of text, and return the unmatched line portion
|
||||
|
||||
@ -312,6 +316,7 @@ def test_fit(u_boot_console):
|
||||
loadables1 = make_kernel('test-loadables1.bin', 'lenrek')
|
||||
loadables2 = make_ramdisk('test-loadables2.bin', 'ksidmar')
|
||||
kernel_out = make_fname('kernel-out.bin')
|
||||
fdt = make_fname('u-boot.dtb')
|
||||
fdt_out = make_fname('fdt-out.dtb')
|
||||
ramdisk_out = make_fname('ramdisk-out.bin')
|
||||
loadables1_out = make_fname('loadables1-out.bin')
|
||||
@ -326,6 +331,7 @@ def test_fit(u_boot_console):
|
||||
'kernel_addr' : 0x40000,
|
||||
'kernel_size' : filesize(kernel),
|
||||
|
||||
'fdt' : fdt,
|
||||
'fdt_out' : fdt_out,
|
||||
'fdt_addr' : 0x80000,
|
||||
'fdt_size' : filesize(control_dtb),
|
||||
@ -351,6 +357,7 @@ def test_fit(u_boot_console):
|
||||
'loadables2_load' : '',
|
||||
|
||||
'loadables_config' : '',
|
||||
'compression' : 'none',
|
||||
}
|
||||
|
||||
# Make a basic FIT and a script to load it
|
||||
@ -417,6 +424,20 @@ def test_fit(u_boot_console):
|
||||
check_equal(loadables2, loadables2_out,
|
||||
'Loadables2 (ramdisk) not loaded')
|
||||
|
||||
# Kernel, FDT and Ramdisk all compressed
|
||||
with cons.log.section('(Kernel + FDT + Ramdisk) compressed'):
|
||||
params['compression'] = 'gzip'
|
||||
params['kernel'] = make_compressed(kernel)
|
||||
params['fdt'] = make_compressed(fdt)
|
||||
params['ramdisk'] = make_compressed(ramdisk)
|
||||
fit = make_fit(mkimage, params)
|
||||
cons.restart_uboot()
|
||||
output = cons.run_command_list(cmd.splitlines())
|
||||
check_equal(kernel, kernel_out, 'Kernel not loaded')
|
||||
check_equal(control_dtb, fdt_out, 'FDT not loaded')
|
||||
check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded')
|
||||
|
||||
|
||||
cons = u_boot_console
|
||||
try:
|
||||
# We need to use our own device tree file. Remember to restore it
|
||||
|
Loading…
Reference in New Issue
Block a user