[RFC PATCH v2 0/6] image: add a stage pre-load

This serie adds a stage pre-load before launching an image. This stage is used to read a header before the image and this header contains the signature of the full image. So u-boot may check the full image before using any data of the image.
Changelog: v2: - move the code to image-pre-load - add support of stage pre-load for spl - add support of stage pre-load on spl_ram
Philippe Reynes (6): lib: allow to build asn1 decoder and oid registry in SPL lib: crypto: allow to build crypyo in SPL lib: rsa: allow rsa verify with pkey in SPL common: image: add a stage pre-load cmd: bootm: add a stage pre-load common: spl: fit_ram: allow to use image pre load
cmd/Kconfig | 9 ++ cmd/bootm.c | 2 +- common/Kconfig.boot | 33 +++++ common/Makefile | 1 + common/bootm.c | 33 +++++ common/image-pre-load.c | 291 ++++++++++++++++++++++++++++++++++++++++ common/spl/spl_ram.c | 21 ++- include/image.h | 10 ++ lib/Kconfig | 6 + lib/Makefile | 9 +- lib/crypto/Kconfig | 15 +++ lib/crypto/Makefile | 19 ++- lib/rsa/Kconfig | 8 ++ 13 files changed, 446 insertions(+), 11 deletions(-) create mode 100644 common/image-pre-load.c

This commit adds the options: - SPL_ASN1_DECODER - SPL_OID_REGISTRY
Signed-off-by: Philippe Reynes philippe.reynes@softathome.com --- lib/Kconfig | 6 ++++++ lib/Makefile | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/lib/Kconfig b/lib/Kconfig index 70bf8e7a46..ebff84f113 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -758,11 +758,17 @@ config ASN1_DECODER help Enable asn1 decoder library.
+config SPL_ASN1_DECODER + bool + config OID_REGISTRY bool help Enable fast lookup object identifier registry.
+config SPL_OID_REGISTRY + bool + config SMBIOS_PARSER bool "SMBIOS parser" help diff --git a/lib/Makefile b/lib/Makefile index 5ddbc77ed6..900e684d62 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,7 +17,6 @@ obj-$(CONFIG_OF_LIVE) += of_live.o obj-$(CONFIG_CMD_DHRYSTONE) += dhry/ obj-$(CONFIG_ARCH_AT91) += at91/ obj-$(CONFIG_OPTEE_LIB) += optee/ -obj-$(CONFIG_ASN1_DECODER) += asn1_decoder.o obj-y += crypto/
obj-$(CONFIG_AES) += aes.o @@ -67,6 +66,7 @@ obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o obj-$(CONFIG_SHA512) += sha512.o obj-$(CONFIG_CRYPT_PW) += crypt/ +obj-$(CONFIG_$(SPL_)ASN1_DECODER) += asn1_decoder.o
obj-$(CONFIG_$(SPL_)ZLIB) += zlib/ obj-$(CONFIG_$(SPL_)ZSTD) += zstd/ @@ -128,9 +128,9 @@ obj-$(CONFIG_$(SPL_TPL_)STRTO) += strto.o else # Main U-Boot always uses the full printf support obj-y += vsprintf.o strto.o -obj-$(CONFIG_OID_REGISTRY) += oid_registry.o obj-$(CONFIG_SSCANF) += sscanf.o endif +obj-$(CONFIG_$(SPL_)OID_REGISTRY) += oid_registry.o
obj-y += abuf.o obj-y += date.o @@ -141,6 +141,9 @@ obj-$(CONFIG_LIB_ELF) += elf.o # Build a fast OID lookup registry from include/linux/oid_registry.h # $(obj)/oid_registry.o: $(obj)/oid_registry_data.c +ifdef CONFIG_SPL_BUILD +CFLAGS_oid_registry.o += -I$(obj) +endif
$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ $(srctree)/scripts/build_OID_registry

This commit adds the options: - SPL_ASYMMETRIC_KEY_TYPE - SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE - SPL_RSA_PUBLIC_KEY_PARSER
Signed-off-by: Philippe Reynes philippe.reynes@softathome.com --- lib/Makefile | 2 +- lib/crypto/Kconfig | 15 +++++++++++++++ lib/crypto/Makefile | 19 +++++++++++++------ 3 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/lib/Makefile b/lib/Makefile index 900e684d62..df70917b49 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,7 +17,6 @@ obj-$(CONFIG_OF_LIVE) += of_live.o obj-$(CONFIG_CMD_DHRYSTONE) += dhry/ obj-$(CONFIG_ARCH_AT91) += at91/ obj-$(CONFIG_OPTEE_LIB) += optee/ -obj-y += crypto/
obj-$(CONFIG_AES) += aes.o obj-$(CONFIG_AES) += aes/ @@ -57,6 +56,7 @@ obj-$(CONFIG_TPM_V1) += tpm-v1.o obj-$(CONFIG_TPM_V2) += tpm-v2.o endif
+obj-y += crypto/ obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi/ obj-$(CONFIG_$(SPL_)MD5) += md5.o obj-$(CONFIG_ECDSA) += ecdsa/ diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 6369bafac0..9351865f2c 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -8,6 +8,10 @@ menuconfig ASYMMETRIC_KEY_TYPE
if ASYMMETRIC_KEY_TYPE
+config SPL_ASYMMETRIC_KEY_TYPE + bool "Asymmetric (public-key cryptographic) key Support within SPL" + depends on SPL + config ASYMMETRIC_PUBLIC_KEY_SUBTYPE bool "Asymmetric public-key crypto algorithm subtype" help @@ -16,6 +20,10 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE appropriate hash algorithms (such as SHA-1) must be available. ENOPKG will be reported if the requisite algorithm is unavailable.
+config SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + bool "Asymmetric public-key crypto algorithm subtype within SPL" + depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE + config RSA_PUBLIC_KEY_PARSER bool "RSA public key parser" depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE @@ -27,6 +35,13 @@ config RSA_PUBLIC_KEY_PARSER public key data and provides the ability to instantiate a public key.
+config SPL_RSA_PUBLIC_KEY_PARSER + bool "RSA public key parser within SPL" + depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select SPL_ASN1_DECODER + select ASN1_COMPILER + select SPL_OID_REGISTRY + config X509_CERTIFICATE_PARSER bool "X.509 certificate parser" depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index f3a414525d..6792b1d4f0 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -3,27 +3,34 @@ # Makefile for asymmetric cryptographic keys #
-obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o +obj-$(CONFIG_$(SPL_)ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := asymmetric_type.o
-obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o +obj-$(CONFIG_$(SPL_)ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
# # RSA public key parser # -obj-$(CONFIG_RSA_PUBLIC_KEY_PARSER) += rsa_public_key.o +obj-$(CONFIG_$(SPL_)RSA_PUBLIC_KEY_PARSER) += rsa_public_key.o rsa_public_key-y := \ rsapubkey.asn1.o \ rsa_helper.o
$(obj)/rsapubkey.asn1.o: $(obj)/rsapubkey.asn1.c $(obj)/rsapubkey.asn1.h +ifdef CONFIG_SPL_BUILD +CFLAGS_rsapubkey.asn1.o += -I$(obj) +endif + $(obj)/rsa_helper.o: $(obj)/rsapubkey.asn1.h +ifdef CONFIG_SPL_BUILD +CFLAGS_rsa_helper.o += -I$(obj) +endif
# # X.509 Certificate handling # -obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o +obj-$(CONFIG_$(SPL_)X509_CERTIFICATE_PARSER) += x509_key_parser.o x509_key_parser-y := \ x509.asn1.o \ x509_akid.asn1.o \ @@ -40,11 +47,11 @@ $(obj)/x509_akid.asn1.o: $(obj)/x509_akid.asn1.c $(obj)/x509_akid.asn1.h # # PKCS#7 message handling # -obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o +obj-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER) += pkcs7_message.o pkcs7_message-y := \ pkcs7.asn1.o \ pkcs7_parser.o -obj-$(CONFIG_PKCS7_VERIFY) += pkcs7_verify.o +obj-$(CONFIG_$(SPL_)PKCS7_VERIFY) += pkcs7_verify.o
$(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h $(obj)/pkcs7.asn1.o: $(obj)/pkcs7.asn1.c $(obj)/pkcs7.asn1.h

This commit adds the option SPL_RSA_VERIFY_WITH_PKEY.
Signed-off-by: Philippe Reynes philippe.reynes@softathome.com --- lib/rsa/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig index 469596abe7..608d51c428 100644 --- a/lib/rsa/Kconfig +++ b/lib/rsa/Kconfig @@ -46,6 +46,14 @@ config RSA_VERIFY_WITH_PKEY directly specified in image_sign_info, where all the necessary key properties will be calculated on the fly in verification code.
+config SPL_RSA_VERIFY_WITH_PKEY + bool "Execute RSA verification without key parameters from FDT within SPL" + depends on SPL + select SPL_RSA_VERIFY + select SPL_ASYMMETRIC_KEY_TYPE + select SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select SPL_RSA_PUBLIC_KEY_PARSER + config RSA_SOFTWARE_EXP bool "Enable driver for RSA Modular Exponentiation in software" depends on DM

This commit adds a stage pre-load that could check or modify an image.
For the moment, only a header with a signature is supported. This header has this format: - magic : 4 bytes - image size : 4 bytes - signature : n bytes - padding : up to header size
The stage use a node /image/pre-load/sig to get some information: - header-size (mandatory) : size of the header - algo-name (mandatory) : name of the algo used to sign - padding-name : name of padding used to sign - signature-size : size of the signature (in the header) - mandatory : set to yes if this sig is mandatory - public-key (madatory) : value of the public key
Before running the image, the stage pre-load check the signature provided in the header.
This is an initial support, later we could add the support of: - ciphering - uncompressing - ...
Signed-off-by: Philippe Reynes philippe.reynes@softathome.com --- common/Kconfig.boot | 33 +++++ common/Makefile | 1 + common/image-pre-load.c | 291 ++++++++++++++++++++++++++++++++++++++++ include/image.h | 9 ++ 4 files changed, 334 insertions(+) create mode 100644 common/image-pre-load.c
diff --git a/common/Kconfig.boot b/common/Kconfig.boot index a8d4be23a9..916fdde71f 100644 --- a/common/Kconfig.boot +++ b/common/Kconfig.boot @@ -958,6 +958,39 @@ config AUTOBOOT_MENU_SHOW
endmenu
+menu "Image support" + +config IMAGE_PRE_LOAD + bool "Image pre-load support" + help + Enable image pre-load support + +config SPL_IMAGE_PRE_LOAD + bool "Image pre-load support within SPL" + depends on SPL && IMAGE_PRE_LOAD + help + Enable image pre-load support in SPL + +config IMAGE_PRE_LOAD_SIG + bool "Image pre-load signature support" + depends on IMAGE_PRE_LOAD + select FIT_SIGNATURE + select RSA + select RSA_VERIFY_WITH_PKEY + help + Enable image pre-load signature support + +config SPL_IMAGE_PRE_LOAD_SIG + bool "Image pre-load signature support witin SPL" + depends on SPL_IMAGE_PRE_LOAD && IMAGE_PRE_LOAD_SIG + select SPL_FIT_SIGNATURE + select SPL_RSA + select SPL_RSA_VERIFY_WITH_PKEY + help + Enable image pre-load signature support in SPL + +endmenu + config USE_BOOTARGS bool "Enable boot arguments" help diff --git a/common/Makefile b/common/Makefile index e7839027b6..9b322e3ae4 100644 --- a/common/Makefile +++ b/common/Makefile @@ -102,6 +102,7 @@ endif endif
obj-y += image.o image-board.o +obj-$(CONFIG_$(SPL_TPL_)IMAGE_PRE_LOAD) += image-pre-load.o obj-$(CONFIG_$(SPL_TPL_)HASH) += hash.o obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o diff --git a/common/image-pre-load.c b/common/image-pre-load.c new file mode 100644 index 0000000000..6ed21c3f51 --- /dev/null +++ b/common/image-pre-load.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Philippe Reynes philippe.reynes@softathome.com + */ + +#include <common.h> +#include <asm/global_data.h> +DECLARE_GLOBAL_DATA_PTR; +#include <image.h> +#include <mapmem.h> + +#define IMAGE_PRE_LOAD_SIG_MAGIC 0x55425348 +#define IMAGE_PRE_LOAD_SIG_OFFSET_MAGIC 0 +#define IMAGE_PRE_LOAD_SIG_OFFSET_IMG_LEN 4 +#define IMAGE_PRE_LOAD_SIG_OFFSET_SIG 8 + +#define IMAGE_PRE_LOAD_PATH "/image/pre-load/sig" +#define IMAGE_PRE_LOAD_PROP_HEADER_SIZE "header-size" +#define IMAGE_PRE_LOAD_PROP_ALGO_NAME "algo-name" +#define IMAGE_PRE_LOAD_PROP_PADDING_NAME "padding-name" +#define IMAGE_PRE_LOAD_PROP_SIG_SIZE "signature-size" +#define IMAGE_PRE_LOAD_PROP_PUBLIC_KEY "public-key" +#define IMAGE_PRE_LOAD_PROP_MANDATORY "mandatory" + +#ifndef CONFIG_SYS_BOOTM_LEN +/* use 8MByte as default max gunzip size */ +#define CONFIG_SYS_BOOTM_LEN 0x800000 +#endif + +struct image_sig_header { + u32 magic; + u32 size; + u8 *sig; +}; + +struct image_sig_info { + ulong header_size; + char *algo_name; + char *padding_name; + u8 *key; + int key_len; + u32 sig_size; + int mandatory; +}; + +ulong image_load_offset; + +/* + * This function gathers information about the signature check + * that could be done before launching the image. + * + * return: + * -1 => an error has occurred + * 0 => OK + * 1 => no setup + */ +static int image_pre_load_sig_setup(struct image_sig_info *info) +{ + const void *algo_name, *padding_name, *key, *mandatory; + const u32 *header_size, *sig_size; + int key_len; + int node, ret = 0; + + if (!info) { + printf("ERROR: info is NULL for image pre-load sig check\n"); + ret = -1; + goto out; + } + + memset(info, 0, sizeof(*info)); + + node = fdt_path_offset(gd_fdt_blob(), IMAGE_PRE_LOAD_PATH); + if (node < 0) { + printf("INFO: no info for image pre-load sig check\n"); + ret = 1; + goto out; + } + + header_size = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_HEADER_SIZE, NULL); + if (!header_size) { + printf("ERROR: no header-size for image pre-load sig check\n"); + ret = -1; + goto out; + } + + algo_name = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_ALGO_NAME, NULL); + if (!algo_name) { + printf("ERROR: no algo_name for image pre-load sig check\n"); + ret = -1; + goto out; + } + + padding_name = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_PADDING_NAME, NULL); + if (!padding_name) { + printf("INFO: no padding_name provided, so using pkcs-1.5\n"); + padding_name = "pkcs-1.5"; + } + + sig_size = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_SIG_SIZE, NULL); + if (!sig_size) { + printf("ERROR: no signature-size for image pre-load sig check\n"); + ret = -1; + goto out; + } + + key = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_PUBLIC_KEY, &key_len); + if (!key) { + printf("ERROR: no key for image pre-load sig check\n"); + ret = -1; + goto out; + } + + info->header_size = fdt32_to_cpu(*header_size); + info->algo_name = (char *)algo_name; + info->padding_name = (char *)padding_name; + info->key = (uint8_t *)key; + info->key_len = key_len; + info->sig_size = fdt32_to_cpu(*sig_size); + + mandatory = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_MANDATORY, NULL); + if (mandatory && !strcmp((char *)mandatory, "yes")) + info->mandatory = 1; + + out: + return ret; +} + +static int image_pre_load_sig_get_header_u32(struct image_sig_info *info, + ulong addr, u32 offset, + u32 *value) +{ + void *header; + u32 *tmp; + int ret = 0; + + header = map_sysmem(addr, info->header_size); + if (!header) { + printf("ERROR: can't map header image pre-load sig\n"); + ret = -1; + goto out; + } + + tmp = header + offset; + *value = be32_to_cpu(*tmp); + + unmap_sysmem(header); + + out: + return ret; +} + +static int image_pre_load_sig_get_magic(struct image_sig_info *info, + ulong addr, u32 *magic) +{ + int ret; + + ret = image_pre_load_sig_get_header_u32(info, addr, + IMAGE_PRE_LOAD_SIG_OFFSET_MAGIC, magic); + + return ret; +} + +static int image_pre_load_sig_get_img_len(struct image_sig_info *info, + ulong addr, u32 *len) +{ + int ret; + + ret = image_pre_load_sig_get_header_u32(info, addr, + IMAGE_PRE_LOAD_SIG_OFFSET_IMG_LEN, len); + if (ret < 0) + goto out; + + if (*len > CONFIG_SYS_BOOTM_LEN) { + printf("ERROR: size of image (%u) bigger than CONFIG_SYS_BOOTM_LEN (%u)\n", + *len, CONFIG_SYS_BOOTM_LEN); + ret = -1; + goto out; + } + + if (*len == 0) { + printf("ERROR: size of image (%u) is zero\n", *len); + ret = -1; + goto out; + } + + out: + return ret; +} + +static int image_pre_load_sig_check(struct image_sig_info *info, ulong addr, int img_len) +{ + void *image; + struct image_sign_info sig_info; + struct image_region reg; + u32 sig_len; + u8 *sig; + int ret = 0; + + image = (void *)map_sysmem(addr, info->header_size + img_len); + if (!image) { + printf("ERROR: can't map full image\n"); + ret = -1; + goto out; + } + + memset(&sig_info, 0, sizeof(sig_info)); + sig_info.name = info->algo_name; + sig_info.padding = image_get_padding_algo(info->padding_name); + sig_info.checksum = image_get_checksum_algo(sig_info.name); + sig_info.crypto = image_get_crypto_algo(sig_info.name); + sig_info.key = info->key; + sig_info.keylen = info->key_len; + + reg.data = image + info->header_size; + reg.size = img_len; + + sig = (uint8_t *)image + IMAGE_PRE_LOAD_SIG_OFFSET_SIG; + sig_len = info->sig_size; + + ret = sig_info.crypto->verify(&sig_info, ®, 1, sig, sig_len); + if (ret) { + printf("ERROR: signature check has failed (err=%d)\n", ret); + ret = -1; + goto out_unmap; + } + + printf("INFO: signature check has succeed\n"); + +out_unmap: + unmap_sysmem(image); + + out: + return ret; +} + +int image_pre_load_sig(ulong addr) +{ + struct image_sig_info info; + u32 magic, img_len; + int ret; + + ret = image_pre_load_sig_setup(&info); + if (ret < 0) + goto out; + if (ret > 0) { + ret = 0; + goto out; + } + + ret = image_pre_load_sig_get_magic(&info, addr, &magic); + if (ret < 0) + goto out; + + if (magic != IMAGE_PRE_LOAD_SIG_MAGIC) { + if (info.mandatory) { + printf("ERROR: signature is mandatory\n"); + ret = -1; + } + goto out; + } + + ret = image_pre_load_sig_get_img_len(&info, addr, &img_len); + if (ret < 0) + goto out; + + ret = image_pre_load_sig_check(&info, addr, img_len); + + if (!ret) + image_load_offset += info.header_size; + + out: + return ret; +} + +int image_pre_load(ulong addr) +{ + int ret = 0; + + image_load_offset = 0; + + if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD_SIG)) + ret = image_pre_load_sig(addr); + + return ret; +} diff --git a/include/image.h b/include/image.h index fd662e74b4..5f83e4c747 100644 --- a/include/image.h +++ b/include/image.h @@ -48,6 +48,7 @@ struct fdt_region; extern ulong image_load_addr; /* Default Load Address */ extern ulong image_save_addr; /* Default Save Address */ extern ulong image_save_size; /* Default Save Size */ +extern ulong image_load_offset; /* Default Load Address Offset */
/* An invalid size, meaning that the image size is not known */ #define IMAGE_SIZE_INVAL (-1UL) @@ -1289,6 +1290,14 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name); */ struct padding_algo *image_get_padding_algo(const char *name);
+/** + * image_pre_load() - Manage pre load header + * + * @param addr Address of the image + * @return: 0 on success, -ve on error + */ +int image_pre_load(ulong addr); + /** * fit_image_verify_required_sigs() - Verify signatures marked as 'required' *

This commit adds a stage pre-load to the command bootm. Right now, this stage may be used to read a header and check the signature of the full image.
Signed-off-by: Philippe Reynes philippe.reynes@softathome.com --- cmd/Kconfig | 9 +++++++++ cmd/bootm.c | 2 +- common/bootm.c | 33 +++++++++++++++++++++++++++++++++ include/image.h | 1 + 4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/cmd/Kconfig b/cmd/Kconfig index 5b30b13e43..b20a346acf 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -194,6 +194,15 @@ config CMD_BOOTM help Boot an application image from the memory.
+config CMD_BOOTM_PRE_LOAD + bool "enable pre-load on bootm" + depends on CMD_BOOTM + default n + help + Enable support of stage pre-load for the bootm command. + This stage allow to check of modifty the image provided + to the bootm command. + config BOOTM_EFI bool "Support booting UEFI FIT images" depends on CMD_BOOTEFI && CMD_BOOTM && FIT diff --git a/cmd/bootm.c b/cmd/bootm.c index 92468d09a1..acfb8eedde 100644 --- a/cmd/bootm.c +++ b/cmd/bootm.c @@ -126,7 +126,7 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) }
return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START | - BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER | + BOOTM_STATE_FINDOS | BOOTM_STATE_PRE_LOAD | BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS | #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH BOOTM_STATE_RAMDISK | diff --git a/common/bootm.c b/common/bootm.c index 4482f84b40..4803c577cc 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -87,6 +87,33 @@ static int bootm_start(struct cmd_tbl *cmdtp, int flag, int argc, return 0; }
+static ulong bootm_data_addr(int argc, char *const argv[]) +{ + ulong addr; + + if (argc > 0) + addr = simple_strtoul(argv[0], NULL, 16); + else + addr = image_load_addr; + + return addr; +} + +static int bootm_pre_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ulong data_addr = bootm_data_addr(argc, argv); + int ret = 0; + + if (CONFIG_IS_ENABLED(CMD_BOOTM_PRE_LOAD)) + ret = image_pre_load(data_addr); + + if (ret) + ret = CMD_RET_FAILURE; + + return ret; +} + static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -677,6 +704,9 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, if (states & BOOTM_STATE_START) ret = bootm_start(cmdtp, flag, argc, argv);
+ if (!ret && (states & BOOTM_STATE_PRE_LOAD)) + ret = bootm_pre_load(cmdtp, flag, argc, argv); + if (!ret && (states & BOOTM_STATE_FINDOS)) ret = bootm_find_os(cmdtp, flag, argc, argv);
@@ -866,6 +896,9 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, &fit_uname_config, &fit_uname_kernel);
+ if (CONFIG_IS_ENABLED(CMD_BOOTM_PRE_LOAD)) + img_addr += image_load_offset; + bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
/* check image type, for FIT images get FIT kernel node */ diff --git a/include/image.h b/include/image.h index 5f83e4c747..42fb01ab07 100644 --- a/include/image.h +++ b/include/image.h @@ -351,6 +351,7 @@ typedef struct bootm_headers { #define BOOTM_STATE_OS_PREP (0x00000100) #define BOOTM_STATE_OS_FAKE_GO (0x00000200) /* 'Almost' run the OS */ #define BOOTM_STATE_OS_GO (0x00000400) +#define BOOTM_STATE_PRE_LOAD (0x00000800) int state;
#if defined(CONFIG_LMB) && !defined(USE_HOSTCC)

This commit add the support of image pre load in spl or tpl when loading an image from ram.
Signed-off-by: Philippe Reynes philippe.reynes@softathome.com --- common/spl/spl_ram.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index df9f3a4d00..c8c7155a93 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -24,9 +24,17 @@ static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { + ulong addr; + debug("%s: sector %lx, count %lx, buf %lx\n", __func__, sector, count, (ulong)buf); - memcpy(buf, (void *)(CONFIG_SPL_LOAD_FIT_ADDRESS + sector), count); + + addr = (ulong)CONFIG_SPL_LOAD_FIT_ADDRESS + sector; + if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) + addr += image_load_offset; + + memcpy(buf, (void *)addr, count); + return count; }
@@ -37,6 +45,17 @@ static int spl_ram_load_image(struct spl_image_info *spl_image,
header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS;
+ if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) { + unsigned long addr = (unsigned long)header; + int ret = image_pre_load(addr); + + if (ret) + return ret; + + addr += image_load_offset; + header = (struct image_header *)addr; + } + #if CONFIG_IS_ENABLED(DFU) if (bootdev->boot_device == BOOT_DEVICE_DFU) spl_dfu_cmd(0, "dfu_alt_info_ram", "ram", "0");
participants (1)
-
Philippe Reynes