diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 4 | ||||
-rw-r--r-- | common/Kconfig.boot | 10 | ||||
-rw-r--r-- | common/Makefile | 2 | ||||
-rw-r--r-- | common/bootm.c | 30 | ||||
-rw-r--r-- | common/bootm_os.c | 8 | ||||
-rw-r--r-- | common/hash.c | 108 | ||||
-rw-r--r-- | common/image-board.c | 956 | ||||
-rw-r--r-- | common/image-fdt.c | 245 | ||||
-rw-r--r-- | common/image-fit-sig.c | 7 | ||||
-rw-r--r-- | common/image-fit.c | 28 | ||||
-rw-r--r-- | common/image-host.c | 27 | ||||
-rw-r--r-- | common/image-sig.c | 40 | ||||
-rw-r--r-- | common/image.c | 1179 | ||||
-rw-r--r-- | common/spl/Kconfig | 13 |
14 files changed, 1338 insertions, 1319 deletions
diff --git a/common/Kconfig b/common/Kconfig index 0543b839d1..d6f77ab7b9 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -182,8 +182,8 @@ config SYS_CONSOLE_IS_IN_ENV default y if CONSOLE_MUX help This allows multiple input/output devices to be set at boot time. - For example, if stdout is set to "serial,video" then output will - be sent to both the serial and video devices on boot. The + For example, if stdout is set to "serial,vidconsole" then output + will be sent to both the serial and video devices on boot. The environment variables can be updated after boot to change the input/output devices. diff --git a/common/Kconfig.boot b/common/Kconfig.boot index f23b998852..9b84a8d005 100644 --- a/common/Kconfig.boot +++ b/common/Kconfig.boot @@ -165,6 +165,16 @@ config SPL_FIT_SIGNATURE select SPL_IMAGE_SIGN_INFO select SPL_FIT_FULL_CHECK +config SPL_FIT_SIGNATURE_MAX_SIZE + hex "Max size of signed FIT structures in SPL" + depends on SPL_FIT_SIGNATURE + default 0x10000000 + help + This option sets a max size in bytes for verified FIT uImages. + A sane value of 256MB protects corrupted DTB structures from overlapping + device memory. Assure this size does not extend past expected storage + space. + config SPL_LOAD_FIT bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)" select SPL_FIT diff --git a/common/Makefile b/common/Makefile index fb8173a5b8..e7839027b6 100644 --- a/common/Makefile +++ b/common/Makefile @@ -101,7 +101,7 @@ obj-y += malloc_simple.o endif endif -obj-y += image.o +obj-y += image.o image-board.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/bootm.c b/common/bootm.c index ea71522d0c..4482f84b40 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -115,7 +115,7 @@ static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc, images.os.arch = image_get_arch(os_hdr); break; #endif -#if IMAGE_ENABLE_FIT +#if CONFIG_IS_ENABLED(FIT) case IMAGE_FORMAT_FIT: if (fit_image_get_type(images.fit_hdr_os, images.fit_noffset_os, @@ -187,7 +187,7 @@ static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc, /* Kernel entry point is the setup.bin */ } else if (images.legacy_hdr_valid) { images.ep = image_get_ep(&images.legacy_hdr_os_copy); -#if IMAGE_ENABLE_FIT +#if CONFIG_IS_ENABLED(FIT) } else if (images.fit_uname_os) { int ret; @@ -271,7 +271,7 @@ int bootm_find_images(int flag, int argc, char *const argv[], ulong start, return 1; } -#if IMAGE_ENABLE_OF_LIBFDT +#if CONFIG_IS_ENABLED(OF_LIBFDT) /* find flattened device tree */ ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images, &images.ft_addr, &images.ft_len); @@ -295,16 +295,16 @@ int bootm_find_images(int flag, int argc, char *const argv[], ulong start, set_working_fdt_addr(map_to_sysmem(images.ft_addr)); #endif -#if IMAGE_ENABLE_FIT -#if defined(CONFIG_FPGA) - /* find bitstreams */ - ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT, - NULL, NULL); - if (ret) { - printf("FPGA image is corrupted or invalid\n"); - return 1; +#if CONFIG_IS_ENABLED(FIT) + if (IS_ENABLED(CONFIG_FPGA)) { + /* find bitstreams */ + ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT, + NULL, NULL); + if (ret) { + printf("FPGA image is corrupted or invalid\n"); + return 1; + } } -#endif /* find all of the loadables */ ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT, @@ -706,7 +706,7 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, } } #endif -#if IMAGE_ENABLE_OF_LIBFDT && defined(CONFIG_LMB) +#if CONFIG_IS_ENABLED(OF_LIBFDT) && defined(CONFIG_LMB) if (!ret && (states & BOOTM_STATE_FDT)) { boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr); ret = boot_relocate_fdt(&images->lmb, &images->ft_addr, @@ -858,7 +858,7 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, const void *buf; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; -#if IMAGE_ENABLE_FIT +#if CONFIG_IS_ENABLED(FIT) int os_noffset; #endif @@ -916,7 +916,7 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE); break; #endif -#if IMAGE_ENABLE_FIT +#if CONFIG_IS_ENABLED(FIT) case IMAGE_FORMAT_FIT: os_noffset = fit_image_load(images, img_addr, &fit_uname_kernel, &fit_uname_config, diff --git a/common/bootm_os.c b/common/bootm_os.c index d635037064..39623f9126 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -58,6 +58,14 @@ static void copy_args(char *dest, int argc, char *const argv[], char delim) } #endif +static void __maybe_unused fit_unsupported_reset(const char *msg) +{ + if (CONFIG_IS_ENABLED(FIT_VERBOSE)) { + printf("! FIT images not supported for '%s' - must reset board to recover!\n", + msg); + } +} + #ifdef CONFIG_BOOTM_NETBSD static int do_bootm_netbsd(int flag, int argc, char *const argv[], bootm_headers_t *images) diff --git a/common/hash.c b/common/hash.c index 3884298edf..79202e18a2 100644 --- a/common/hash.c +++ b/common/hash.c @@ -24,7 +24,9 @@ #include <u-boot/crc.h> #else #include "mkimage.h" +#include <linux/compiler_attributes.h> #include <time.h> +#include <linux/kconfig.h> #endif /* !USE_HOSTCC*/ #include <hash.h> @@ -41,8 +43,7 @@ DECLARE_GLOBAL_DATA_PTR; static void reloc_update(void); -#if defined(CONFIG_SHA1) && !defined(CONFIG_SHA_PROG_HW_ACCEL) -static int hash_init_sha1(struct hash_algo *algo, void **ctxp) +static int __maybe_unused hash_init_sha1(struct hash_algo *algo, void **ctxp) { sha1_context *ctx = malloc(sizeof(sha1_context)); sha1_starts(ctx); @@ -50,15 +51,16 @@ static int hash_init_sha1(struct hash_algo *algo, void **ctxp) return 0; } -static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf, - unsigned int size, int is_last) +static int __maybe_unused hash_update_sha1(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, + int is_last) { sha1_update((sha1_context *)ctx, buf, size); return 0; } -static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf, - int size) +static int __maybe_unused hash_finish_sha1(struct hash_algo *algo, void *ctx, + void *dest_buf, int size) { if (size < algo->digest_size) return -1; @@ -67,10 +69,8 @@ static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf, free(ctx); return 0; } -#endif -#if defined(CONFIG_SHA256) && !defined(CONFIG_SHA_PROG_HW_ACCEL) -static int hash_init_sha256(struct hash_algo *algo, void **ctxp) +static int __maybe_unused hash_init_sha256(struct hash_algo *algo, void **ctxp) { sha256_context *ctx = malloc(sizeof(sha256_context)); sha256_starts(ctx); @@ -78,15 +78,16 @@ static int hash_init_sha256(struct hash_algo *algo, void **ctxp) return 0; } -static int hash_update_sha256(struct hash_algo *algo, void *ctx, - const void *buf, unsigned int size, int is_last) +static int __maybe_unused hash_update_sha256(struct hash_algo *algo, void *ctx, + const void *buf, uint size, + int is_last) { sha256_update((sha256_context *)ctx, buf, size); return 0; } -static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void - *dest_buf, int size) +static int __maybe_unused hash_finish_sha256(struct hash_algo *algo, void *ctx, + void *dest_buf, int size) { if (size < algo->digest_size) return -1; @@ -95,10 +96,8 @@ static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void free(ctx); return 0; } -#endif -#if defined(CONFIG_SHA384) && !defined(CONFIG_SHA_PROG_HW_ACCEL) -static int hash_init_sha384(struct hash_algo *algo, void **ctxp) +static int __maybe_unused hash_init_sha384(struct hash_algo *algo, void **ctxp) { sha512_context *ctx = malloc(sizeof(sha512_context)); sha384_starts(ctx); @@ -106,15 +105,16 @@ static int hash_init_sha384(struct hash_algo *algo, void **ctxp) return 0; } -static int hash_update_sha384(struct hash_algo *algo, void *ctx, - const void *buf, unsigned int size, int is_last) +static int __maybe_unused hash_update_sha384(struct hash_algo *algo, void *ctx, + const void *buf, uint size, + int is_last) { sha384_update((sha512_context *)ctx, buf, size); return 0; } -static int hash_finish_sha384(struct hash_algo *algo, void *ctx, void - *dest_buf, int size) +static int __maybe_unused hash_finish_sha384(struct hash_algo *algo, void *ctx, + void *dest_buf, int size) { if (size < algo->digest_size) return -1; @@ -123,10 +123,8 @@ static int hash_finish_sha384(struct hash_algo *algo, void *ctx, void free(ctx); return 0; } -#endif -#if defined(CONFIG_SHA512) && !defined(CONFIG_SHA_PROG_HW_ACCEL) -static int hash_init_sha512(struct hash_algo *algo, void **ctxp) +static int __maybe_unused hash_init_sha512(struct hash_algo *algo, void **ctxp) { sha512_context *ctx = malloc(sizeof(sha512_context)); sha512_starts(ctx); @@ -134,15 +132,16 @@ static int hash_init_sha512(struct hash_algo *algo, void **ctxp) return 0; } -static int hash_update_sha512(struct hash_algo *algo, void *ctx, - const void *buf, unsigned int size, int is_last) +static int __maybe_unused hash_update_sha512(struct hash_algo *algo, void *ctx, + const void *buf, uint size, + int is_last) { sha512_update((sha512_context *)ctx, buf, size); return 0; } -static int hash_finish_sha512(struct hash_algo *algo, void *ctx, void - *dest_buf, int size) +static int __maybe_unused hash_finish_sha512(struct hash_algo *algo, void *ctx, + void *dest_buf, int size) { if (size < algo->digest_size) return -1; @@ -151,8 +150,6 @@ static int hash_finish_sha512(struct hash_algo *algo, void *ctx, void free(ctx); return 0; } -#endif - static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp) { @@ -181,7 +178,7 @@ static int hash_finish_crc16_ccitt(struct hash_algo *algo, void *ctx, return 0; } -static int hash_init_crc32(struct hash_algo *algo, void **ctxp) +static int __maybe_unused hash_init_crc32(struct hash_algo *algo, void **ctxp) { uint32_t *ctx = malloc(sizeof(uint32_t)); *ctx = 0; @@ -189,15 +186,16 @@ static int hash_init_crc32(struct hash_algo *algo, void **ctxp) return 0; } -static int hash_update_crc32(struct hash_algo *algo, void *ctx, - const void *buf, unsigned int size, int is_last) +static int __maybe_unused hash_update_crc32(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, + int is_last) { *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size); return 0; } -static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf, - int size) +static int __maybe_unused hash_finish_crc32(struct hash_algo *algo, void *ctx, + void *dest_buf, int size) { if (size < algo->digest_size) return -1; @@ -207,18 +205,13 @@ static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf, return 0; } -#ifdef USE_HOSTCC -# define I_WANT_MD5 1 -#else -# define I_WANT_MD5 CONFIG_IS_ENABLED(MD5) -#endif /* * These are the hash algorithms we support. If we have hardware acceleration * is enable we will use that, otherwise a software version of the algorithm. * Note that algorithm names must be in lower case. */ static struct hash_algo hash_algo[] = { -#if I_WANT_MD5 +#if CONFIG_IS_ENABLED(MD5) { .name = "md5", .digest_size = MD5_SUM_LEN, @@ -226,17 +219,17 @@ static struct hash_algo hash_algo[] = { .hash_func_ws = md5_wd, }, #endif -#ifdef CONFIG_SHA1 +#if CONFIG_IS_ENABLED(SHA1) { .name = "sha1", .digest_size = SHA1_SUM_LEN, .chunk_size = CHUNKSZ_SHA1, -#ifdef CONFIG_SHA_HW_ACCEL +#if CONFIG_IS_ENABLED(SHA_HW_ACCEL) .hash_func_ws = hw_sha1, #else .hash_func_ws = sha1_csum_wd, #endif -#ifdef CONFIG_SHA_PROG_HW_ACCEL +#if CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL) .hash_init = hw_sha_init, .hash_update = hw_sha_update, .hash_finish = hw_sha_finish, @@ -247,17 +240,17 @@ static struct hash_algo hash_algo[] = { #endif }, #endif -#ifdef CONFIG_SHA256 +#if CONFIG_IS_ENABLED(SHA256) { .name = "sha256", .digest_size = SHA256_SUM_LEN, .chunk_size = CHUNKSZ_SHA256, -#ifdef CONFIG_SHA_HW_ACCEL +#if CONFIG_IS_ENABLED(SHA_HW_ACCEL) .hash_func_ws = hw_sha256, #else .hash_func_ws = sha256_csum_wd, #endif -#ifdef CONFIG_SHA_PROG_HW_ACCEL +#if CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL) .hash_init = hw_sha_init, .hash_update = hw_sha_update, .hash_finish = hw_sha_finish, @@ -268,17 +261,17 @@ static struct hash_algo hash_algo[] = { #endif }, #endif -#ifdef CONFIG_SHA384 +#if CONFIG_IS_ENABLED(SHA384) { .name = "sha384", .digest_size = SHA384_SUM_LEN, .chunk_size = CHUNKSZ_SHA384, -#ifdef CONFIG_SHA512_HW_ACCEL +#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) .hash_func_ws = hw_sha384, #else .hash_func_ws = sha384_csum_wd, #endif -#if defined(CONFIG_SHA512_HW_ACCEL) && defined(CONFIG_SHA_PROG_HW_ACCEL) +#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) && CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL) .hash_init = hw_sha_init, .hash_update = hw_sha_update, .hash_finish = hw_sha_finish, @@ -289,17 +282,17 @@ static struct hash_algo hash_algo[] = { #endif }, #endif -#ifdef CONFIG_SHA512 +#if CONFIG_IS_ENABLED(SHA512) { .name = "sha512", .digest_size = SHA512_SUM_LEN, .chunk_size = CHUNKSZ_SHA512, -#ifdef CONFIG_SHA512_HW_ACCEL +#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) .hash_func_ws = hw_sha512, #else .hash_func_ws = sha512_csum_wd, #endif -#if defined(CONFIG_SHA512_HW_ACCEL) && defined(CONFIG_SHA_PROG_HW_ACCEL) +#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) && CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL) .hash_init = hw_sha_init, .hash_update = hw_sha_update, .hash_finish = hw_sha_finish, @@ -319,6 +312,7 @@ static struct hash_algo hash_algo[] = { .hash_update = hash_update_crc16_ccitt, .hash_finish = hash_finish_crc16_ccitt, }, +#if CONFIG_IS_ENABLED(CRC32) { .name = "crc32", .digest_size = 4, @@ -328,12 +322,13 @@ static struct hash_algo hash_algo[] = { .hash_update = hash_update_crc32, .hash_finish = hash_finish_crc32, }, +#endif }; /* Try to minimize code size for boards that don't want much hashing */ -#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \ - defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) || \ - defined(CONFIG_SHA384) || defined(CONFIG_SHA512) +#if CONFIG_IS_ENABLED(SHA256) || CONFIG_IS_ENABLED(CMD_SHA1SUM) || \ + CONFIG_IS_ENABLED(CRC32_VERIFY) || CONFIG_IS_ENABLED(CMD_HASH) || \ + CONFIG_IS_ENABLED(SHA384) || CONFIG_IS_ENABLED(SHA512) #define multi_hash() 1 #else #define multi_hash() 0 @@ -438,7 +433,8 @@ int hash_block(const char *algo_name, const void *data, unsigned int len, return 0; } -#if defined(CONFIG_CMD_HASH) || defined(CONFIG_CMD_SHA1SUM) || defined(CONFIG_CMD_CRC32) +#if !defined(CONFIG_SPL_BUILD) && (defined(CONFIG_CMD_HASH) || \ + defined(CONFIG_CMD_SHA1SUM) || defined(CONFIG_CMD_CRC32)) /** * store_result: Store the resulting sum to an address or variable * diff --git a/common/image-board.c b/common/image-board.c new file mode 100644 index 0000000000..e7660352e9 --- /dev/null +++ b/common/image-board.c @@ -0,0 +1,956 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Image code used by boards (and not host tools) + * + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +#include <common.h> +#include <bootstage.h> +#include <cpu_func.h> +#include <env.h> +#include <fpga.h> +#include <image.h> +#include <mapmem.h> +#include <rtc.h> +#include <watchdog.h> +#include <asm/cache.h> +#include <asm/global_data.h> + +#ifndef CONFIG_SYS_BARGSIZE +#define CONFIG_SYS_BARGSIZE 512 +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/** + * image_get_ramdisk - get and verify ramdisk image + * @rd_addr: ramdisk image start address + * @arch: expected ramdisk architecture + * @verify: checksum verification flag + * + * image_get_ramdisk() returns a pointer to the verified ramdisk image + * header. Routine receives image start address and expected architecture + * flag. Verification done covers data and header integrity and os/type/arch + * fields checking. + * + * returns: + * pointer to a ramdisk image header, if image was found and valid + * otherwise, return NULL + */ +static const image_header_t *image_get_ramdisk(ulong rd_addr, u8 arch, + int verify) +{ + const image_header_t *rd_hdr = (const image_header_t *)rd_addr; + + if (!image_check_magic(rd_hdr)) { + puts("Bad Magic Number\n"); + bootstage_error(BOOTSTAGE_ID_RD_MAGIC); + return NULL; + } + + if (!image_check_hcrc(rd_hdr)) { + puts("Bad Header Checksum\n"); + bootstage_error(BOOTSTAGE_ID_RD_HDR_CHECKSUM); + return NULL; + } + + bootstage_mark(BOOTSTAGE_ID_RD_MAGIC); + image_print_contents(rd_hdr); + + if (verify) { + puts(" Verifying Checksum ... "); + if (!image_check_dcrc(rd_hdr)) { + puts("Bad Data CRC\n"); + bootstage_error(BOOTSTAGE_ID_RD_CHECKSUM); + return NULL; + } + puts("OK\n"); + } + + bootstage_mark(BOOTSTAGE_ID_RD_HDR_CHECKSUM); + + if (!image_check_os(rd_hdr, IH_OS_LINUX) || + !image_check_arch(rd_hdr, arch) || + !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) { + printf("No Linux %s Ramdisk Image\n", + genimg_get_arch_name(arch)); + bootstage_error(BOOTSTAGE_ID_RAMDISK); + return NULL; + } + + return rd_hdr; +} + +/*****************************************************************************/ +/* Shared dual-format routines */ +/*****************************************************************************/ +ulong image_load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ +ulong image_save_addr; /* Default Save Address */ +ulong image_save_size; /* Default Save Size (in bytes) */ + +static int on_loadaddr(const char *name, const char *value, enum env_op op, + int flags) +{ + switch (op) { + case env_op_create: + case env_op_overwrite: + image_load_addr = hextoul(value, NULL); + break; + default: + break; + } + + return 0; +} +U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr); + +ulong env_get_bootm_low(void) +{ + char *s = env_get("bootm_low"); + + if (s) { + ulong tmp = hextoul(s, NULL); + return tmp; + } + +#if defined(CONFIG_SYS_SDRAM_BASE) + return CONFIG_SYS_SDRAM_BASE; +#elif defined(CONFIG_ARM) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_RISCV) + return gd->bd->bi_dram[0].start; +#else + return 0; +#endif +} + +phys_size_t env_get_bootm_size(void) +{ + phys_size_t tmp, size; + phys_addr_t start; + char *s = env_get("bootm_size"); + + if (s) { + tmp = (phys_size_t)simple_strtoull(s, NULL, 16); + return tmp; + } + + start = gd->ram_base; + size = gd->ram_size; + + if (start + size > gd->ram_top) + size = gd->ram_top - start; + + s = env_get("bootm_low"); + if (s) + tmp = (phys_size_t)simple_strtoull(s, NULL, 16); + else + tmp = start; + + return size - (tmp - start); +} + +phys_size_t env_get_bootm_mapsize(void) +{ + phys_size_t tmp; + char *s = env_get("bootm_mapsize"); + + if (s) { + tmp = (phys_size_t)simple_strtoull(s, NULL, 16); + return tmp; + } + +#if defined(CONFIG_SYS_BOOTMAPSZ) + return CONFIG_SYS_BOOTMAPSZ; +#else + return env_get_bootm_size(); +#endif +} + +void memmove_wd(void *to, void *from, size_t len, ulong chunksz) +{ + if (to == from) + return; + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + if (to > from) { + from += len; + to += len; + } + while (len > 0) { + size_t tail = (len > chunksz) ? chunksz : len; + + WATCHDOG_RESET(); + if (to > from) { + to -= tail; + from -= tail; + } + memmove(to, from, tail); + if (to < from) { + to += tail; + from += tail; + } + len -= tail; + } +#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ + memmove(to, from, len); +#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +} + +/** + * genimg_get_kernel_addr_fit - get the real kernel address and return 2 + * FIT strings + * @img_addr: a string might contain real image address + * @fit_uname_config: double pointer to a char, will hold pointer to a + * configuration unit name + * @fit_uname_kernel: double pointer to a char, will hold pointer to a subimage + * name + * + * genimg_get_kernel_addr_fit get the real kernel start address from a string + * which is normally the first argv of bootm/bootz + * + * returns: + * kernel start address + */ +ulong genimg_get_kernel_addr_fit(char * const img_addr, + const char **fit_uname_config, + const char **fit_uname_kernel) +{ + ulong kernel_addr; + + /* find out kernel image address */ + if (!img_addr) { + kernel_addr = image_load_addr; + debug("* kernel: default image load address = 0x%08lx\n", + image_load_addr); + } else if (CONFIG_IS_ENABLED(FIT) && + fit_parse_conf(img_addr, image_load_addr, &kernel_addr, + fit_uname_config)) { + debug("* kernel: config '%s' from image at 0x%08lx\n", + *fit_uname_config, kernel_addr); + } else if (CONFIG_IS_ENABLED(FIT) && + fit_parse_subimage(img_addr, image_load_addr, &kernel_addr, + fit_uname_kernel)) { + debug("* kernel: subimage '%s' from image at 0x%08lx\n", + *fit_uname_kernel, kernel_addr); + } else { + kernel_addr = hextoul(img_addr, NULL); + debug("* kernel: cmdline image address = 0x%08lx\n", + kernel_addr); + } + + return kernel_addr; +} + +/** + * genimg_get_kernel_addr() is the simple version of + * genimg_get_kernel_addr_fit(). It ignores those return FIT strings + */ +ulong genimg_get_kernel_addr(char * const img_addr) +{ + const char *fit_uname_config = NULL; + const char *fit_uname_kernel = NULL; + + return genimg_get_kernel_addr_fit(img_addr, &fit_uname_config, + &fit_uname_kernel); +} + +/** + * genimg_get_format - get image format type + * @img_addr: image start address + * + * genimg_get_format() checks whether provided address points to a valid + * legacy or FIT image. + * + * New uImage format and FDT blob are based on a libfdt. FDT blob + * may be passed directly or embedded in a FIT image. In both situations + * genimg_get_format() must be able to dectect libfdt header. + * + * returns: + * image format type or IMAGE_FORMAT_INVALID if no image is present + */ +int genimg_get_format(const void *img_addr) +{ + if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) { + const image_header_t *hdr; + + hdr = (const image_header_t *)img_addr; + if (image_check_magic(hdr)) + return IMAGE_FORMAT_LEGACY; + } + if (CONFIG_IS_ENABLED(FIT) || CONFIG_IS_ENABLED(OF_LIBFDT)) { + if (!fdt_check_header(img_addr)) + return IMAGE_FORMAT_FIT; + } + if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE) && + !android_image_check_header(img_addr)) + return IMAGE_FORMAT_ANDROID; + + return IMAGE_FORMAT_INVALID; +} + +/** + * fit_has_config - check if there is a valid FIT configuration + * @images: pointer to the bootm command headers structure + * + * fit_has_config() checks if there is a FIT configuration in use + * (if FTI support is present). + * + * returns: + * 0, no FIT support or no configuration found + * 1, configuration found + */ +int genimg_has_config(bootm_headers_t *images) +{ + if (CONFIG_IS_ENABLED(FIT) && images->fit_uname_cfg) + return 1; + + return 0; +} + +/** + * select_ramdisk() - Select and locate the ramdisk to use + * + * @images: pointer to the bootm images structure + * @select: name of ramdisk to select, or NULL for any + * @arch: expected ramdisk architecture + * @rd_datap: pointer to a ulong variable, will hold ramdisk pointer + * @rd_lenp: pointer to a ulong variable, will hold ramdisk length + * @return 0 if OK, -ENOPKG if no ramdisk (but an error should not be reported), + * other -ve value on other error + */ +static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch, + ulong *rd_datap, ulong *rd_lenp) +{ + ulong rd_addr = 0; + char *buf; + const char *fit_uname_config = images->fit_uname_cfg; + const char *fit_uname_ramdisk = NULL; + bool processed; + int rd_noffset; + + if (select) { + ulong default_addr; + bool done = true; + + if (CONFIG_IS_ENABLED(FIT)) { + /* + * If the init ramdisk comes from the FIT image and + * the FIT image address is omitted in the command + * line argument, try to use os FIT image address or + * default load address. + */ + if (images->fit_uname_os) + default_addr = (ulong)images->fit_hdr_os; + else + default_addr = image_load_addr; + + if (fit_parse_conf(select, default_addr, &rd_addr, + &fit_uname_config)) { + debug("* ramdisk: config '%s' from image at 0x%08lx\n", + fit_uname_config, rd_addr); + } else if (fit_parse_subimage(select, default_addr, + &rd_addr, + &fit_uname_ramdisk)) { + debug("* ramdisk: subimage '%s' from image at 0x%08lx\n", + fit_uname_ramdisk, rd_addr); + } else { + done = false; + } + } + if (!done) { + rd_addr = hextoul(select, NULL); + debug("* ramdisk: cmdline image address = 0x%08lx\n", + rd_addr); + } + } else if (CONFIG_IS_ENABLED(FIT)) { + /* use FIT configuration provided in first bootm + * command argument. If the property is not defined, + * quit silently (with -ENOPKG ) + */ + rd_addr = map_to_sysmem(images->fit_hdr_os); + rd_noffset = fit_get_node_from_config(images, FIT_RAMDISK_PROP, + rd_addr); + if (rd_noffset == -ENOENT) + return -ENOPKG; + else if (rd_noffset < 0) + return rd_noffset; + } + + /* + * Check if there is an initrd image at the + * address provided in the second bootm argument + * check image type, for FIT images get FIT node. + */ + buf = map_sysmem(rd_addr, 0); + processed = false; + switch (genimg_get_format(buf)) { + case IMAGE_FORMAT_LEGACY: + if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) { + const image_header_t *rd_hdr; + + printf("## Loading init Ramdisk from Legacy Image at %08lx ...\n", + rd_addr); + + bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK); + rd_hdr = image_get_ramdisk(rd_addr, arch, images->verify); + if (!rd_hdr) + return -ENOENT; + + *rd_datap = image_get_data(rd_hdr); + *rd_lenp = image_get_data_size(rd_hdr); + processed = true; + } + break; + case IMAGE_FORMAT_FIT: + if (CONFIG_IS_ENABLED(FIT)) { + rd_noffset = fit_image_load(images, rd_addr, + &fit_uname_ramdisk, + &fit_uname_config, arch, + IH_TYPE_RAMDISK, + BOOTSTAGE_ID_FIT_RD_START, + FIT_LOAD_OPTIONAL_NON_ZERO, + rd_datap, rd_lenp); + if (rd_noffset < 0) + return rd_noffset; + + images->fit_hdr_rd = map_sysmem(rd_addr, 0); + images->fit_uname_rd = fit_uname_ramdisk; + images->fit_noffset_rd = rd_noffset; + processed = true; + } + break; + case IMAGE_FORMAT_ANDROID: + if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE)) { + android_image_get_ramdisk((void *)images->os.start, + rd_datap, rd_lenp); + processed = true; + } + break; + } + + if (!processed) { + if (IS_ENABLED(CONFIG_SUPPORT_RAW_INITRD)) { + char *end = NULL; + + if (select) + end = strchr(select, ':'); + if (end) { + *rd_lenp = hextoul(++end, NULL); + *rd_datap = rd_addr; + processed = true; + } + } + + if (!processed) { + puts("Wrong Ramdisk Image Format\n"); + return -EINVAL; + } + } + + return 0; +} + +/** + * boot_get_ramdisk - main ramdisk handling routine + * @argc: command argument count + * @argv: command argument list + * @images: pointer to the bootm images structure + * @arch: expected ramdisk architecture + * @rd_start: pointer to a ulong variable, will hold ramdisk start address + * @rd_end: pointer to a ulong variable, will hold ramdisk end + * + * boot_get_ramdisk() is responsible for finding a valid ramdisk image. + * Currently supported are the following ramdisk sources: + * - multicomponent kernel/ramdisk image, + * - commandline provided address of decicated ramdisk image. + * + * returns: + * 0, if ramdisk image was found and valid, or skiped + * rd_start and rd_end are set to ramdisk start/end addresses if + * ramdisk image is found and valid + * + * 1, if ramdisk image is found but corrupted, or invalid + * rd_start and rd_end are set to 0 if no ramdisk exists + */ +int boot_get_ramdisk(int argc, char *const argv[], bootm_headers_t *images, + u8 arch, ulong *rd_start, ulong *rd_end) +{ + ulong rd_data, rd_len; + const char *select = NULL; + + *rd_start = 0; + *rd_end = 0; + + if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE)) { + char *buf; + + /* Look for an Android boot image */ + buf = map_sysmem(images->os.start, 0); + if (buf && genimg_get_format(buf) == IMAGE_FORMAT_ANDROID) + select = (argc == 0) ? env_get("loadaddr") : argv[0]; + } + + if (argc >= 2) + select = argv[1]; + + /* + * Look for a '-' which indicates to ignore the + * ramdisk argument + */ + if (select && strcmp(select, "-") == 0) { + debug("## Skipping init Ramdisk\n"); + rd_len = 0; + rd_data = 0; + } else if (select || genimg_has_config(images)) { + int ret; + + ret = select_ramdisk(images, select, arch, &rd_data, &rd_len); + if (ret == -ENOPKG) + return 0; + else if (ret) + return ret; + } else if (images->legacy_hdr_valid && + image_check_type(&images->legacy_hdr_os_copy, + IH_TYPE_MULTI)) { + /* + * Now check if we have a legacy mult-component image, + * get second entry data start address and len. + */ + bootstage_mark(BOOTSTAGE_ID_RAMDISK); + printf("## Loading init Ramdisk from multi component Legacy Image at %08lx ...\n", + (ulong)images->legacy_hdr_os); + + image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len); + } else { + /* + * no initrd image + */ + bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK); + rd_len = 0; + rd_data = 0; + } + + if (!rd_data) { + debug("## No init Ramdisk\n"); + } else { + *rd_start = rd_data; + *rd_end = rd_data + rd_len; + } + debug(" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", + *rd_start, *rd_end); + + return 0; +} + +/** + * boot_ramdisk_high - relocate init ramdisk + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @rd_data: ramdisk data start address + * @rd_len: ramdisk data length + * @initrd_start: pointer to a ulong variable, will hold final init ramdisk + * start address (after possible relocation) + * @initrd_end: pointer to a ulong variable, will hold final init ramdisk + * end address (after possible relocation) + * + * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment + * variable and if requested ramdisk data is moved to a specified location. + * + * Initrd_start and initrd_end are set to final (after relocation) ramdisk + * start/end addresses if ramdisk image start and len were provided, + * otherwise set initrd_start and initrd_end set to zeros. + * + * returns: + * 0 - success + * -1 - failure + */ +int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, + ulong *initrd_start, ulong *initrd_end) +{ + char *s; + ulong initrd_high; + int initrd_copy_to_ram = 1; + + s = env_get("initrd_high"); + if (s) { + /* a value of "no" or a similar string will act like 0, + * turning the "load high" feature off. This is intentional. + */ + initrd_high = hextoul(s, NULL); + if (initrd_high == ~0) + initrd_copy_to_ram = 0; + } else { + initrd_high = env_get_bootm_mapsize() + env_get_bootm_low(); + } + + debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n", + initrd_high, initrd_copy_to_ram); + + if (rd_data) { + if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ + debug(" in-place initrd\n"); + *initrd_start = rd_data; + *initrd_end = rd_data + rd_len; + lmb_reserve(lmb, rd_data, rd_len); + } else { + if (initrd_high) + *initrd_start = (ulong)lmb_alloc_base(lmb, + rd_len, 0x1000, initrd_high); + else + *initrd_start = (ulong)lmb_alloc(lmb, rd_len, + 0x1000); + + if (*initrd_start == 0) { + puts("ramdisk - allocation error\n"); + goto error; + } + bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK); + + *initrd_end = *initrd_start + rd_len; + printf(" Loading Ramdisk to %08lx, end %08lx ... ", + *initrd_start, *initrd_end); + + memmove_wd((void *)*initrd_start, + (void *)rd_data, rd_len, CHUNKSZ); + + /* + * Ensure the image is flushed to memory to handle + * AMP boot scenarios in which we might not be + * HW cache coherent + */ + if (IS_ENABLED(CONFIG_MP)) { + flush_cache((unsigned long)*initrd_start, + ALIGN(rd_len, ARCH_DMA_MINALIGN)); + } + puts("OK\n"); + } + } else { + *initrd_start = 0; + *initrd_end = 0; + } + debug(" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", + *initrd_start, *initrd_end); + + return 0; + +error: + return -1; +} + +int boot_get_setup(bootm_headers_t *images, u8 arch, + ulong *setup_start, ulong *setup_len) +{ + if (!CONFIG_IS_ENABLED(FIT)) + return -ENOENT; + + return boot_get_setup_fit(images, arch, setup_start, setup_len); +} + +int boot_get_fpga(int argc, char *const argv[], bootm_headers_t *images, + u8 arch, const ulong *ld_start, ulong * const ld_len) +{ + ulong tmp_img_addr, img_data, img_len; + void *buf; + int conf_noffset; + int fit_img_result; + const char *uname, *name; + int err; + int devnum = 0; /* TODO support multi fpga platforms */ + + if (!IS_ENABLED(CONFIG_FPGA)) + return -ENOSYS; + + /* 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 + */ + tmp_img_addr = map_to_sysmem(images->fit_hdr_os); + 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); + + uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0, + NULL); + if (!uname) { + debug("## FPGA image is not specified\n"); + return 0; + } + fit_img_result = fit_image_load(images, + tmp_img_addr, + (const char **)&uname, + &images->fit_uname_cfg, + arch, + IH_TYPE_FPGA, + BOOTSTAGE_ID_FPGA_INIT, + FIT_LOAD_OPTIONAL_NON_ZERO, + &img_data, &img_len); + + debug("FPGA image (%s) loaded to 0x%lx/size 0x%lx\n", + uname, img_data, img_len); + + if (fit_img_result < 0) { + /* Something went wrong! */ + return fit_img_result; + } + + if (!fpga_is_partial_data(devnum, img_len)) { + name = "full"; + err = fpga_loadbitstream(devnum, (char *)img_data, + img_len, BIT_FULL); + if (err) + err = fpga_load(devnum, (const void *)img_data, + img_len, BIT_FULL); + } else { + name = "partial"; + err = fpga_loadbitstream(devnum, (char *)img_data, + img_len, BIT_PARTIAL); + if (err) + err = fpga_load(devnum, (const void *)img_data, + img_len, BIT_PARTIAL); + } + + if (err) + return err; + + printf(" Programming %s bitstream... OK\n", name); + break; + default: + printf("The given image format is not supported (corrupt?)\n"); + return 1; + } + + return 0; +} + +static void fit_loadable_process(u8 img_type, + ulong img_data, + ulong img_len) +{ + int i; + const unsigned int count = + ll_entry_count(struct fit_loadable_tbl, fit_loadable); + struct fit_loadable_tbl *fit_loadable_handler = + ll_entry_start(struct fit_loadable_tbl, fit_loadable); + /* For each loadable handler */ + for (i = 0; i < count; i++, fit_loadable_handler++) + /* matching this type */ + if (fit_loadable_handler->type == img_type) + /* call that handler with this image data */ + fit_loadable_handler->handler(img_data, img_len); +} + +int boot_get_loadable(int argc, char *const argv[], bootm_headers_t *images, + u8 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; + const char *uname; + u8 img_type; + + /* 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 + */ + tmp_img_addr = map_to_sysmem(images->fit_hdr_os); + 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; + uname = fdt_stringlist_get(buf, conf_noffset, + FIT_LOADABLE_PROP, + loadables_index, NULL), uname; + loadables_index++) { + fit_img_result = fit_image_load(images, tmp_img_addr, + &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; + } + + fit_img_result = fit_image_get_node(buf, uname); + if (fit_img_result < 0) { + /* Something went wrong! */ + return fit_img_result; + } + fit_img_result = fit_image_get_type(buf, + fit_img_result, + &img_type); + if (fit_img_result < 0) { + /* Something went wrong! */ + return fit_img_result; + } + + fit_loadable_process(img_type, img_data, img_len); + } + break; + default: + printf("The given image format is not supported (corrupt?)\n"); + return 1; + } + + return 0; +} + +/** + * boot_get_cmdline - allocate and initialize kernel cmdline + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @cmd_start: pointer to a ulong variable, will hold cmdline start + * @cmd_end: pointer to a ulong variable, will hold cmdline end + * + * boot_get_cmdline() allocates space for kernel command line below + * BOOTMAPSZ + env_get_bootm_low() address. If "bootargs" U-Boot environment + * variable is present its contents is copied to allocated kernel + * command line. + * + * returns: + * 0 - success + * -1 - failure + */ +int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end) +{ + char *cmdline; + char *s; + + cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf, + env_get_bootm_mapsize() + env_get_bootm_low()); + if (!cmdline) + return -1; + + s = env_get("bootargs"); + if (!s) + s = ""; + + strcpy(cmdline, s); + + *cmd_start = (ulong)cmdline; + *cmd_end = *cmd_start + strlen(cmdline); + + debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); + + return 0; +} + +/** + * boot_get_kbd - allocate and initialize kernel copy of board info + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @kbd: double pointer to board info data + * + * boot_get_kbd() allocates space for kernel copy of board info data below + * BOOTMAPSZ + env_get_bootm_low() address and kernel board info is initialized + * with the current u-boot board info data. + * + * returns: + * 0 - success + * -1 - failure + */ +int boot_get_kbd(struct lmb *lmb, struct bd_info **kbd) +{ + *kbd = (struct bd_info *)(ulong)lmb_alloc_base(lmb, + sizeof(struct bd_info), + 0xf, + env_get_bootm_mapsize() + + env_get_bootm_low()); + if (!*kbd) + return -1; + + **kbd = *gd->bd; + + debug("## kernel board info at 0x%08lx\n", (ulong)*kbd); + +#if defined(DEBUG) + if (IS_ENABLED(CONFIG_CMD_BDI) + do_bdinfo(NULL, 0, 0, NULL); +#endif + + return 0; +} + +int image_setup_linux(bootm_headers_t *images) +{ + ulong of_size = images->ft_len; + char **of_flat_tree = &images->ft_addr; + struct lmb *lmb = &images->lmb; + int ret; + + if (CONFIG_IS_ENABLED(OF_LIBFDT)) + boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); + + if (IS_ENABLED(CONFIG_SYS_BOOT_GET_CMDLINE)) { + ret = boot_get_cmdline(lmb, &images->cmdline_start, + &images->cmdline_end); + if (ret) { + puts("ERROR with allocation of cmdline\n"); + return ret; + } + } + + if (CONFIG_IS_ENABLED(OF_LIBFDT)) { + ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); + if (ret) + return ret; + } + + if (CONFIG_IS_ENABLED(OF_LIBFDT) && of_size) { + ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb); + if (ret) + return ret; + } + + return 0; +} + +void genimg_print_size(uint32_t size) +{ + printf("%d Bytes = ", size); + print_size(size, "\n"); +} + +void genimg_print_time(time_t timestamp) +{ + struct rtc_time tm; + + rtc_to_tm(timestamp, &tm); + printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n", + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); +} diff --git a/common/image-fdt.c b/common/image-fdt.c index b698e961fe..7aad6d57b8 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -252,59 +252,29 @@ error: } /** - * 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 - * - * boot_get_fdt() is responsible for finding a valid flat device tree image. - * Curently supported are the following ramdisk sources: - * - multicomponent kernel/ramdisk image, - * - commandline provided address of decicated ramdisk image. - * - * returns: - * 0, if fdt image was found and valid, or skipped - * of_flat_tree and of_size are set to fdt start address and length if - * fdt image is found and valid + * select_fdt() - Select and locate the FDT to use * - * 1, if fdt image is found but corrupted - * of_flat_tree and of_size are set to 0 if no fdt exists + * @images: pointer to the bootm images structure + * @select: name of FDT to select, or NULL for any + * @arch: expected FDT architecture + * @fdt_addrp: pointer to a ulong variable, will hold FDT pointer + * @return 0 if OK, -ENOPKG if no FDT (but an error should not be reported), + * other -ve value on other error */ -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) -{ -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - const image_header_t *fdt_hdr; - ulong load, load_end; - ulong image_start, image_data, image_end; -#endif - ulong img_addr; - ulong fdt_addr; - char *fdt_blob = NULL; - void *buf; -#if CONFIG_IS_ENABLED(FIT) - const char *fit_uname_config = images->fit_uname_cfg; - const char *fit_uname_fdt = NULL; - ulong default_addr; - int fdt_noffset; -#endif - const char *select = NULL; - *of_flat_tree = NULL; - *of_size = 0; - - img_addr = (argc == 0) ? image_load_addr : - hextoul(argv[0], NULL); - buf = map_sysmem(img_addr, 0); +static int select_fdt(bootm_headers_t *images, const char *select, u8 arch, + ulong *fdt_addrp) +{ + const char *buf; + ulong fdt_addr; - if (argc > 2) - select = argv[2]; - if (select || genimg_has_config(images)) { #if CONFIG_IS_ENABLED(FIT) - if (select) { + const char *fit_uname_config = images->fit_uname_cfg; + const char *fit_uname_fdt = NULL; + ulong default_addr; + int fdt_noffset; + + if (select) { /* * If the FDT blob comes from the FIT image and the * FIT image address is omitted in the command line @@ -318,54 +288,57 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, else default_addr = image_load_addr; - if (fit_parse_conf(select, default_addr, - &fdt_addr, &fit_uname_config)) { + if (fit_parse_conf(select, default_addr, &fdt_addr, + &fit_uname_config)) { debug("* fdt: config '%s' from image at 0x%08lx\n", fit_uname_config, fdt_addr); - } else if (fit_parse_subimage(select, default_addr, - &fdt_addr, &fit_uname_fdt)) { + } else if (fit_parse_subimage(select, default_addr, &fdt_addr, + &fit_uname_fdt)) { debug("* fdt: subimage '%s' from image at 0x%08lx\n", fit_uname_fdt, fdt_addr); } else #endif - { - fdt_addr = hextoul(select, NULL); - debug("* fdt: cmdline image address = 0x%08lx\n", - fdt_addr); - } -#if CONFIG_IS_ENABLED(FIT) - } else { - /* use FIT configuration provided in first bootm - * command argument - */ - fdt_addr = map_to_sysmem(images->fit_hdr_os); - fdt_noffset = fit_get_node_from_config(images, - FIT_FDT_PROP, - fdt_addr); - if (fdt_noffset == -ENOENT) - return 0; - else if (fdt_noffset < 0) - return 1; + { + fdt_addr = hextoul(select, NULL); + debug("* fdt: cmdline image address = 0x%08lx\n", + fdt_addr); } -#endif - debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", - fdt_addr); - - /* - * Check if there is an FDT image at the - * address provided in the second bootm argument - * check image type, for FIT images get a FIT node. +#if CONFIG_IS_ENABLED(FIT) + } else { + /* use FIT configuration provided in first bootm + * command argument */ - buf = map_sysmem(fdt_addr, 0); - switch (genimg_get_format(buf)) { + fdt_addr = map_to_sysmem(images->fit_hdr_os); + fdt_noffset = fit_get_node_from_config(images, FIT_FDT_PROP, + fdt_addr); + if (fdt_noffset == -ENOENT) + return -ENOPKG; + else if (fdt_noffset < 0) + return fdt_noffset; + } +#endif + debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", + fdt_addr); + + /* + * Check if there is an FDT image at the + * address provided in the second bootm argument + * check image type, for FIT images get a FIT node. + */ + buf = map_sysmem(fdt_addr, 0); + switch (genimg_get_format(buf)) { #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - case IMAGE_FORMAT_LEGACY: + case IMAGE_FORMAT_LEGACY: { + const image_header_t *fdt_hdr; + ulong load, load_end; + ulong image_start, image_data, image_end; + /* verify fdt_addr points to a valid image header */ printf("## Flattened Device Tree from Legacy Image at %08lx\n", fdt_addr); fdt_hdr = image_get_fdt(fdt_addr); if (!fdt_hdr) - goto no_fdt; + return -ENOPKG; /* * move image data to the load address, @@ -386,7 +359,7 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, if ((load < image_end) && (load_end > image_start)) { fdt_error("fdt overwritten"); - goto error; + return -EFAULT; } debug(" Loading FDT from 0x%08lx to 0x%08lx\n", @@ -398,25 +371,26 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, fdt_addr = load; break; + } #endif - case IMAGE_FORMAT_FIT: - /* - * This case will catch both: new uImage format - * (libfdt based) and raw FDT blob (also libfdt - * based). - */ + case IMAGE_FORMAT_FIT: + /* + * This case will catch both: new uImage format + * (libfdt based) and raw FDT blob (also libfdt + * based). + */ #if CONFIG_IS_ENABLED(FIT) /* check FDT blob vs FIT blob */ if (!fit_check_format(buf, IMAGE_SIZE_INVAL)) { ulong load, len; - fdt_noffset = boot_get_fdt_fit(images, - fdt_addr, &fit_uname_fdt, - &fit_uname_config, - arch, &load, &len); + fdt_noffset = boot_get_fdt_fit(images, fdt_addr, + &fit_uname_fdt, + &fit_uname_config, + arch, &load, &len); if (fdt_noffset < 0) - goto error; + return -ENOENT; images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); images->fit_uname_fdt = fit_uname_fdt; @@ -424,22 +398,73 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, fdt_addr = load; break; - } else + } else #endif - { - /* - * FDT blob - */ - debug("* fdt: raw FDT blob\n"); - printf("## Flattened Device Tree blob at %08lx\n", - (long)fdt_addr); - } - break; - default: - puts("ERROR: Did not find a cmdline Flattened Device Tree\n"); - goto error; + { + /* + * FDT blob + */ + debug("* fdt: raw FDT blob\n"); + printf("## Flattened Device Tree blob at %08lx\n", + (long)fdt_addr); } + break; + default: + puts("ERROR: Did not find a cmdline Flattened Device Tree\n"); + return -ENOENT; + } + *fdt_addrp = fdt_addr; + + return 0; +} + +/** + * 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 + * + * boot_get_fdt() is responsible for finding a valid flat device tree image. + * Currently supported are the following ramdisk sources: + * - multicomponent kernel/ramdisk image, + * - commandline provided address of decicated ramdisk image. + * + * returns: + * 0, if fdt image was found and valid, or skipped + * of_flat_tree and of_size are set to fdt start address and length if + * fdt image is found and valid + * + * 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[], uint8_t arch, + bootm_headers_t *images, char **of_flat_tree, ulong *of_size) +{ + ulong img_addr; + ulong fdt_addr; + char *fdt_blob = NULL; + void *buf; + const char *select = NULL; + *of_flat_tree = NULL; + *of_size = 0; + + img_addr = (argc == 0) ? image_load_addr : hextoul(argv[0], NULL); + buf = map_sysmem(img_addr, 0); + + if (argc > 2) + select = argv[2]; + if (select || genimg_has_config(images)) { + int ret; + + ret = select_fdt(images, select, arch, &fdt_addr); + if (ret == -ENOPKG) + goto no_fdt; + else if (ret) + return 1; printf(" Booting using the fdt blob at %#08lx\n", fdt_addr); fdt_blob = map_sysmem(fdt_addr, 0); } else if (images->legacy_hdr_valid && @@ -582,7 +607,7 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, /* Append PStore configuration */ fdt_fixup_pstore(blob); #endif - if (IMAGE_OF_BOARD_SETUP) { + if (IS_ENABLED(CONFIG_OF_BOARD_SETUP)) { const char *skip_board_fixup; skip_board_fixup = env_get("skip_board_fixup"); @@ -597,7 +622,7 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, } } } - if (IMAGE_OF_SYSTEM_SETUP) { + if (IS_ENABLED(CONFIG_OF_SYSTEM_SETUP)) { fdt_ret = ft_system_setup(blob, gd->bd); if (fdt_ret) { printf("ERROR: system-specific fdt fixup failed: %s\n", @@ -629,7 +654,7 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, goto err; #if defined(CONFIG_ARCH_KEYSTONE) - if (IMAGE_OF_BOARD_SETUP) + if (IS_ENABLED(CONFIG_OF_BOARD_SETUP)) ft_board_setup_ex(blob, gd->bd); #endif diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c index b979cd2a4b..4edebbf2d3 100644 --- a/common/image-fit-sig.c +++ b/common/image-fit-sig.c @@ -49,10 +49,8 @@ struct image_region *fit_region_make_list(const void *fit, * Use malloc() except in SPL (to save code size). In SPL the caller * must allocate the array. */ -#ifndef CONFIG_SPL_BUILD - if (!region) + if (!IS_ENABLED(CONFIG_SPL_BUILD) && !region) region = calloc(sizeof(*region), count); -#endif if (!region) return NULL; for (i = 0; i < count; i++) { @@ -72,11 +70,10 @@ static int fit_image_setup_verify(struct image_sign_info *info, char *algo_name; const char *padding_name; - if (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) { + if (fdt_totalsize(fit) > CONFIG_VAL(FIT_SIGNATURE_MAX_SIZE)) { *err_msgp = "Total size too large"; return 1; } - if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { *err_msgp = "Can't get hash algo property"; return -1; diff --git a/common/image-fit.c b/common/image-fit.c index 5a0a0cc200..33b4a46028 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -170,7 +170,6 @@ int fit_get_subimage_count(const void *fit, int images_noffset) return count; } -#if CONFIG_IS_ENABLED(FIT_PRINT) || CONFIG_IS_ENABLED(SPL_FIT_PRINT) /** * fit_image_print_data() - prints out the hash node details * @fit: pointer to the FIT format image header @@ -380,6 +379,9 @@ void fit_print_contents(const void *fit) const char *p; time_t timestamp; + if (!CONFIG_IS_ENABLED(FIT_PRINT)) + return; + /* Indent string is defined in header image.h */ p = IMAGE_INDENT_STRING; @@ -482,6 +484,9 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) int ndepth; int ret; + if (!CONFIG_IS_ENABLED(FIT_PRINT)) + return; + /* Mandatory properties */ ret = fit_get_desc(fit, image_noffset, &desc); printf("%s Description: ", p); @@ -509,7 +514,7 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) ret = fit_image_get_data_and_size(fit, image_noffset, &data, &size); - if (!host_build()) { + if (!tools_build()) { printf("%s Data Start: ", p); if (ret) { printf("unavailable\n"); @@ -575,10 +580,6 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) } } } -#else -void fit_print_contents(const void *fit) { } -void fit_image_print(const void *fit, int image_noffset, const char *p) { } -#endif /* CONFIG_IS_ENABLED(FIR_PRINT) || CONFIG_IS_ENABLED(SPL_FIT_PRINT) */ /** * fit_get_desc - get node description property @@ -1277,7 +1278,7 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data, } printf("%s", algo); - if (IMAGE_ENABLE_IGNORE) { + if (!tools_build()) { fit_image_hash_get_ignore(fit, noffset, &ignore); if (ignore) { printf("-skipped "); @@ -1845,7 +1846,7 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) if (conf_uname == NULL) { /* get configuration unit name from the default property */ debug("No configuration specified, trying default...\n"); - if (!host_build() && IS_ENABLED(CONFIG_MULTI_DTB_FIT)) { + if (!tools_build() && IS_ENABLED(CONFIG_MULTI_DTB_FIT)) { noffset = fit_find_config_node(fit); if (noffset < 0) return noffset; @@ -2008,9 +2009,6 @@ int fit_image_load(bootm_headers_t *images, ulong addr, int type_ok, os_ok; ulong load, load_end, data, len; uint8_t os, comp; -#ifndef USE_HOSTCC - uint8_t os_arch; -#endif const char *prop_name; int ret; @@ -2093,7 +2091,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr, } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); - if (!host_build() && IS_ENABLED(CONFIG_SANDBOX)) { + if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) { if (!fit_image_check_target_arch(fit, noffset)) { puts("Unsupported Architecture\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); @@ -2102,8 +2100,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr, } #ifndef USE_HOSTCC + { + uint8_t os_arch; + fit_image_get_arch(fit, noffset, &os_arch); images->os.arch = os_arch; + } #endif bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); @@ -2158,7 +2160,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr, } /* perform any post-processing on the image data */ - if (!host_build() && IS_ENABLED(CONFIG_FIT_IMAGE_POST_PROCESS)) + if (!tools_build() && IS_ENABLED(CONFIG_FIT_IMAGE_POST_PROCESS)) board_fit_image_post_process(fit, noffset, &buf, &size); len = (ulong)size; diff --git a/common/image-host.c b/common/image-host.c new file mode 100644 index 0000000000..20a9521948 --- /dev/null +++ b/common/image-host.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Image code used by host tools (and not boards) + * + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +#include <time.h> + +void memmove_wd(void *to, void *from, size_t len, ulong chunksz) +{ + memmove(to, from, len); +} + +void genimg_print_size(uint32_t size) +{ + printf("%d Bytes = %.2f KiB = %.2f MiB\n", size, (double)size / 1.024e3, + (double)size / 1.048576e6); +} + +void genimg_print_time(time_t timestamp) +{ + printf("%s", ctime(×tamp)); +} diff --git a/common/image-sig.c b/common/image-sig.c index fa9407bb30..1aa0b58645 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -9,6 +9,7 @@ #include <asm/global_data.h> DECLARE_GLOBAL_DATA_PTR; #include <image.h> +#include <relocate.h> #include <u-boot/ecdsa.h> #include <u-boot/rsa.h> #include <u-boot/hash-checksum.h> @@ -56,17 +57,19 @@ struct checksum_algo *image_get_checksum_algo(const char *full_name) int i; const char *name; -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - static bool done; + if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) { + static bool done; - if (!done) { - done = true; - for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) { - checksum_algos[i].name += gd->reloc_off; - checksum_algos[i].calculate += gd->reloc_off; + if (!done) { + done = true; + for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) { + struct checksum_algo *algo = &checksum_algos[i]; + + MANUAL_RELOC(algo->name); + MANUAL_RELOC(algo->calculate); + } } } -#endif for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) { name = checksum_algos[i].name; @@ -84,18 +87,19 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name) struct crypto_algo *crypto, *end; const char *name; -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - static bool done; - - if (!done) { - crypto = ll_entry_start(struct crypto_algo, cryptos); - end = ll_entry_end(struct crypto_algo, cryptos); - for (; crypto < end; crypto++) { - crypto->name += gd->reloc_off; - crypto->verify += gd->reloc_off; + if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) { + static bool done; + + if (!done) { + done = true; + crypto = ll_entry_start(struct crypto_algo, cryptos); + end = ll_entry_end(struct crypto_algo, cryptos); + for (; crypto < end; crypto++) { + MANUAL_RELOC(crypto->name); + MANUAL_RELOC(crypto->verify); + } } } -#endif /* Move name to after the comma */ name = strchr(full_name, ','); diff --git a/common/image.c b/common/image.c index e199d61a4c..3fa60b5827 100644 --- a/common/image.c +++ b/common/image.c @@ -8,32 +8,19 @@ #ifndef USE_HOSTCC #include <common.h> -#include <bootstage.h> -#include <cpu_func.h> #include <env.h> #include <lmb.h> #include <log.h> #include <malloc.h> -#include <asm/cache.h> #include <u-boot/crc.h> -#include <watchdog.h> #ifdef CONFIG_SHOW_BOOT_PROGRESS #include <status_led.h> #endif -#include <rtc.h> - -#include <gzip.h> -#include <image.h> -#include <lz4.h> -#include <mapmem.h> - -#if IMAGE_ENABLE_FIT || IMAGE_ENABLE_OF_LIBFDT +#if CONFIG_IS_ENABLED(FIT) || CONFIG_IS_ENABLED(OF_LIBFDT) #include <linux/libfdt.h> #include <fdt_support.h> -#include <fpga.h> -#include <xilinx.h> #endif #include <asm/global_data.h> @@ -42,13 +29,6 @@ #include <linux/errno.h> #include <asm/io.h> -#include <bzlib.h> -#include <linux/lzo.h> -#include <lzma/LzmaTypes.h> -#include <lzma/LzmaDec.h> -#include <lzma/LzmaTools.h> -#include <linux/zstd.h> - #ifdef CONFIG_CMD_BDI extern int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); @@ -56,27 +36,41 @@ extern int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, DECLARE_GLOBAL_DATA_PTR; -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) -static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, - int verify); -#endif +/* Set this if we have less than 4 MB of malloc() space */ +#if CONFIG_SYS_MALLOC_LEN < (4096 * 1024) +#define CONSERVE_MEMORY true #else +#define CONSERVE_MEMORY false +#endif + +#else /* USE_HOSTCC */ #include "mkimage.h" #include <u-boot/md5.h> #include <time.h> -#include <image.h> #ifndef __maybe_unused # define __maybe_unused /* unimplemented */ #endif + +#define CONSERVE_MEMORY false + #endif /* !USE_HOSTCC*/ -#include <u-boot/crc.h> +#include <abuf.h> +#include <bzlib.h> +#include <display_options.h> +#include <gzip.h> +#include <image.h> #include <imximage.h> - -#ifndef CONFIG_SYS_BARGSIZE -#define CONFIG_SYS_BARGSIZE 512 -#endif +#include <relocate.h> +#include <linux/lzo.h> +#include <linux/zstd.h> +#include <linux/kconfig.h> +#include <lzma/LzmaTypes.h> +#include <lzma/LzmaDec.h> +#include <lzma/LzmaTools.h> +#include <u-boot/crc.h> +#include <u-boot/lz4.h> static const table_entry_t uimage_arch[] = { { IH_ARCH_INVALID, "invalid", "Invalid ARCH", }, @@ -445,7 +439,7 @@ int image_decomp(int comp, ulong load, ulong image_start, int type, void *load_buf, void *image_buf, ulong image_len, uint unc_len, ulong *load_end) { - int ret = 0; + int ret = -ENOSYS; *load_end = load; print_decomp_msg(comp, type, load == image_start); @@ -457,6 +451,7 @@ int image_decomp(int comp, ulong load, ulong image_start, int type, */ switch (comp) { case IH_COMP_NONE: + ret = 0; if (load == image_start) break; if (image_len <= unc_len) @@ -464,336 +459,74 @@ int image_decomp(int comp, ulong load, ulong image_start, int type, else ret = -ENOSPC; break; -#ifndef USE_HOSTCC -#if CONFIG_IS_ENABLED(GZIP) - case IH_COMP_GZIP: { - ret = gunzip(load_buf, unc_len, image_buf, &image_len); - break; - } -#endif /* CONFIG_GZIP */ -#endif -#ifndef USE_HOSTCC -#if CONFIG_IS_ENABLED(BZIP2) - case IH_COMP_BZIP2: { - uint size = unc_len; - - /* - * If we've got less than 4 MB of malloc() space, - * use slower decompression algorithm which requires - * at most 2300 KB of memory. - */ - ret = BZ2_bzBuffToBuffDecompress(load_buf, &size, - image_buf, image_len, - CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); - image_len = size; + case IH_COMP_GZIP: + if (!tools_build() && CONFIG_IS_ENABLED(GZIP)) + ret = gunzip(load_buf, unc_len, image_buf, &image_len); break; - } -#endif /* CONFIG_BZIP2 */ -#endif -#ifndef USE_HOSTCC -#if CONFIG_IS_ENABLED(LZMA) - case IH_COMP_LZMA: { - SizeT lzma_len = unc_len; + case IH_COMP_BZIP2: + if (!tools_build() && CONFIG_IS_ENABLED(BZIP2)) { + uint size = unc_len; - ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, - image_buf, image_len); - image_len = lzma_len; + /* + * If we've got less than 4 MB of malloc() space, + * use slower decompression algorithm which requires + * at most 2300 KB of memory. + */ + ret = BZ2_bzBuffToBuffDecompress(load_buf, &size, + image_buf, image_len, CONSERVE_MEMORY, 0); + image_len = size; + } break; - } -#endif /* CONFIG_LZMA */ -#endif -#ifndef USE_HOSTCC -#if CONFIG_IS_ENABLED(LZO) - case IH_COMP_LZO: { - size_t size = unc_len; + case IH_COMP_LZMA: + if (!tools_build() && CONFIG_IS_ENABLED(LZMA)) { + SizeT lzma_len = unc_len; - ret = lzop_decompress(image_buf, image_len, load_buf, &size); - image_len = size; + ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, + image_buf, image_len); + image_len = lzma_len; + } break; - } -#endif /* CONFIG_LZO */ -#endif -#ifndef USE_HOSTCC -#if CONFIG_IS_ENABLED(LZ4) - case IH_COMP_LZ4: { - size_t size = unc_len; + case IH_COMP_LZO: + if (!tools_build() && CONFIG_IS_ENABLED(LZO)) { + size_t size = unc_len; - ret = ulz4fn(image_buf, image_len, load_buf, &size); - image_len = size; - break; - } -#endif /* CONFIG_LZ4 */ -#endif -#ifndef USE_HOSTCC -#if CONFIG_IS_ENABLED(ZSTD) - case IH_COMP_ZSTD: { - size_t size = unc_len; - ZSTD_DStream *dstream; - ZSTD_inBuffer in_buf; - ZSTD_outBuffer out_buf; - void *workspace; - size_t wsize; - - wsize = ZSTD_DStreamWorkspaceBound(image_len); - workspace = malloc(wsize); - if (!workspace) { - debug("%s: cannot allocate workspace of size %zu\n", __func__, - wsize); - return -1; + ret = lzop_decompress(image_buf, image_len, load_buf, &size); + image_len = size; } + break; + case IH_COMP_LZ4: + if (!tools_build() && CONFIG_IS_ENABLED(LZ4)) { + size_t size = unc_len; - dstream = ZSTD_initDStream(image_len, workspace, wsize); - if (!dstream) { - printf("%s: ZSTD_initDStream failed\n", __func__); - return ZSTD_getErrorCode(ret); + ret = ulz4fn(image_buf, image_len, load_buf, &size); + image_len = size; } - - in_buf.src = image_buf; - in_buf.pos = 0; - in_buf.size = image_len; - - out_buf.dst = load_buf; - out_buf.pos = 0; - out_buf.size = size; - - while (1) { - size_t ret; - - ret = ZSTD_decompressStream(dstream, &out_buf, &in_buf); - if (ZSTD_isError(ret)) { - printf("%s: ZSTD_decompressStream error %d\n", __func__, - ZSTD_getErrorCode(ret)); - return ZSTD_getErrorCode(ret); + break; + case IH_COMP_ZSTD: + if (!tools_build() && CONFIG_IS_ENABLED(ZSTD)) { + struct abuf in, out; + + abuf_init_set(&in, image_buf, image_len); + abuf_init_set(&in, load_buf, unc_len); + ret = zstd_decompress(&in, &out); + if (ret >= 0) { + image_len = ret; + ret = 0; } - - if (in_buf.pos >= image_len || !ret) - break; } - - image_len = out_buf.pos; - break; } -#endif /* CONFIG_ZSTD */ -#endif - default: + if (ret == -ENOSYS) { printf("Unimplemented compression type %d\n", comp); - return -ENOSYS; + return ret; } + if (ret) + return ret; *load_end = load + image_len; - return ret; -} - - -#ifndef USE_HOSTCC -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) -/** - * image_get_ramdisk - get and verify ramdisk image - * @rd_addr: ramdisk image start address - * @arch: expected ramdisk architecture - * @verify: checksum verification flag - * - * image_get_ramdisk() returns a pointer to the verified ramdisk image - * header. Routine receives image start address and expected architecture - * flag. Verification done covers data and header integrity and os/type/arch - * fields checking. - * - * returns: - * pointer to a ramdisk image header, if image was found and valid - * otherwise, return NULL - */ -static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, - int verify) -{ - const image_header_t *rd_hdr = (const image_header_t *)rd_addr; - - if (!image_check_magic(rd_hdr)) { - puts("Bad Magic Number\n"); - bootstage_error(BOOTSTAGE_ID_RD_MAGIC); - return NULL; - } - - if (!image_check_hcrc(rd_hdr)) { - puts("Bad Header Checksum\n"); - bootstage_error(BOOTSTAGE_ID_RD_HDR_CHECKSUM); - return NULL; - } - - bootstage_mark(BOOTSTAGE_ID_RD_MAGIC); - image_print_contents(rd_hdr); - - if (verify) { - puts(" Verifying Checksum ... "); - if (!image_check_dcrc(rd_hdr)) { - puts("Bad Data CRC\n"); - bootstage_error(BOOTSTAGE_ID_RD_CHECKSUM); - return NULL; - } - puts("OK\n"); - } - - bootstage_mark(BOOTSTAGE_ID_RD_HDR_CHECKSUM); - - if (!image_check_os(rd_hdr, IH_OS_LINUX) || - !image_check_arch(rd_hdr, arch) || - !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) { - printf("No Linux %s Ramdisk Image\n", - genimg_get_arch_name(arch)); - bootstage_error(BOOTSTAGE_ID_RAMDISK); - return NULL; - } - - return rd_hdr; -} -#endif -#endif /* !USE_HOSTCC */ - -/*****************************************************************************/ -/* Shared dual-format routines */ -/*****************************************************************************/ -#ifndef USE_HOSTCC -ulong image_load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ -ulong image_save_addr; /* Default Save Address */ -ulong image_save_size; /* Default Save Size (in bytes) */ - -static int on_loadaddr(const char *name, const char *value, enum env_op op, - int flags) -{ - switch (op) { - case env_op_create: - case env_op_overwrite: - image_load_addr = hextoul(value, NULL); - break; - default: - break; - } - - return 0; -} -U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr); - -ulong env_get_bootm_low(void) -{ - char *s = env_get("bootm_low"); - if (s) { - ulong tmp = hextoul(s, NULL); - return tmp; - } - -#if defined(CONFIG_SYS_SDRAM_BASE) - return CONFIG_SYS_SDRAM_BASE; -#elif defined(CONFIG_ARM) || defined(CONFIG_MICROBLAZE) - return gd->bd->bi_dram[0].start; -#else return 0; -#endif -} - -phys_size_t env_get_bootm_size(void) -{ - phys_size_t tmp, size; - phys_addr_t start; - char *s = env_get("bootm_size"); - if (s) { - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - return tmp; - } - - start = gd->ram_base; - size = gd->ram_size; - - if (start + size > gd->ram_top) - size = gd->ram_top - start; - - s = env_get("bootm_low"); - if (s) - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - else - tmp = start; - - return size - (tmp - start); -} - -phys_size_t env_get_bootm_mapsize(void) -{ - phys_size_t tmp; - char *s = env_get("bootm_mapsize"); - if (s) { - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - return tmp; - } - -#if defined(CONFIG_SYS_BOOTMAPSZ) - return CONFIG_SYS_BOOTMAPSZ; -#else - return env_get_bootm_size(); -#endif -} - -void memmove_wd(void *to, void *from, size_t len, ulong chunksz) -{ - if (to == from) - return; - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - if (to > from) { - from += len; - to += len; - } - while (len > 0) { - size_t tail = (len > chunksz) ? chunksz : len; - WATCHDOG_RESET(); - if (to > from) { - to -= tail; - from -= tail; - } - memmove(to, from, tail); - if (to < from) { - to += tail; - from += tail; - } - len -= tail; - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove(to, from, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ -} -#else /* USE_HOSTCC */ -void memmove_wd(void *to, void *from, size_t len, ulong chunksz) -{ - memmove(to, from, len); -} -#endif /* !USE_HOSTCC */ - -void genimg_print_size(uint32_t size) -{ -#ifndef USE_HOSTCC - printf("%d Bytes = ", size); - print_size(size, "\n"); -#else - printf("%d Bytes = %.2f KiB = %.2f MiB\n", - size, (double)size / 1.024e3, - (double)size / 1.048576e6); -#endif -} - -#if IMAGE_ENABLE_TIMESTAMP -void genimg_print_time(time_t timestamp) -{ -#ifndef USE_HOSTCC - struct rtc_time tm; - - rtc_to_tm(timestamp, &tm); - printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n", - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); -#else - printf("%s", ctime(×tamp)); -#endif } -#endif const table_entry_t *get_table_entry(const table_entry_t *table, int id) { @@ -833,11 +566,7 @@ const char *genimg_get_cat_name(enum ih_category category, uint id) entry = get_table_entry(table_info[category].table, id); if (!entry) return unknown_msg(category); -#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) - return entry->lname; -#else - return entry->lname + gd->reloc_off; -#endif + return manual_reloc(entry->lname); } /** @@ -857,11 +586,7 @@ const char *genimg_get_cat_short_name(enum ih_category category, uint id) entry = get_table_entry(table_info[category].table, id); if (!entry) return unknown_msg(category); -#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) - return entry->sname; -#else - return entry->sname + gd->reloc_off; -#endif + return manual_reloc(entry->sname); } int genimg_get_cat_count(enum ih_category category) @@ -911,11 +636,7 @@ char *get_table_entry_name(const table_entry_t *table, char *msg, int id) table = get_table_entry(table, id); if (!table) return msg; -#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) - return table->lname; -#else - return table->lname + gd->reloc_off; -#endif + return manual_reloc(table->lname); } const char *genimg_get_os_name(uint8_t os) @@ -945,11 +666,7 @@ static const char *genimg_get_short_name(const table_entry_t *table, int val) table = get_table_entry(table, val); if (!table) return "unknown"; -#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) - return table->sname; -#else - return table->sname + gd->reloc_off; -#endif + return manual_reloc(table->sname); } const char *genimg_get_type_short_name(uint8_t type) @@ -992,12 +709,8 @@ int get_table_entry_id(const table_entry_t *table, const table_entry_t *t; for (t = table; t->id >= 0; ++t) { -#ifdef CONFIG_NEEDS_MANUAL_RELOC - if (t->sname && strcasecmp(t->sname + gd->reloc_off, name) == 0) -#else - if (t->sname && strcasecmp(t->sname, name) == 0) -#endif - return (t->id); + if (t->sname && !strcasecmp(manual_reloc(t->sname), name)) + return t->id; } debug("Invalid %s Type: %s\n", table_name, name); @@ -1023,733 +736,3 @@ int genimg_get_comp_id(const char *name) { return (get_table_entry_id(uimage_comp, "Compression", name)); } - -#ifndef USE_HOSTCC -/** - * genimg_get_kernel_addr_fit - get the real kernel address and return 2 - * FIT strings - * @img_addr: a string might contain real image address - * @fit_uname_config: double pointer to a char, will hold pointer to a - * configuration unit name - * @fit_uname_kernel: double pointer to a char, will hold pointer to a subimage - * name - * - * genimg_get_kernel_addr_fit get the real kernel start address from a string - * which is normally the first argv of bootm/bootz - * - * returns: - * kernel start address - */ -ulong genimg_get_kernel_addr_fit(char * const img_addr, - const char **fit_uname_config, - const char **fit_uname_kernel) -{ - ulong kernel_addr; - - /* find out kernel image address */ - if (!img_addr) { - kernel_addr = image_load_addr; - debug("* kernel: default image load address = 0x%08lx\n", - image_load_addr); -#if CONFIG_IS_ENABLED(FIT) - } else if (fit_parse_conf(img_addr, image_load_addr, &kernel_addr, - fit_uname_config)) { - debug("* kernel: config '%s' from image at 0x%08lx\n", - *fit_uname_config, kernel_addr); - } else if (fit_parse_subimage(img_addr, image_load_addr, &kernel_addr, - fit_uname_kernel)) { - debug("* kernel: subimage '%s' from image at 0x%08lx\n", - *fit_uname_kernel, kernel_addr); -#endif - } else { - kernel_addr = hextoul(img_addr, NULL); - debug("* kernel: cmdline image address = 0x%08lx\n", - kernel_addr); - } - - return kernel_addr; -} - -/** - * genimg_get_kernel_addr() is the simple version of - * genimg_get_kernel_addr_fit(). It ignores those return FIT strings - */ -ulong genimg_get_kernel_addr(char * const img_addr) -{ - const char *fit_uname_config = NULL; - const char *fit_uname_kernel = NULL; - - return genimg_get_kernel_addr_fit(img_addr, &fit_uname_config, - &fit_uname_kernel); -} - -/** - * genimg_get_format - get image format type - * @img_addr: image start address - * - * genimg_get_format() checks whether provided address points to a valid - * legacy or FIT image. - * - * New uImage format and FDT blob are based on a libfdt. FDT blob - * may be passed directly or embedded in a FIT image. In both situations - * genimg_get_format() must be able to dectect libfdt header. - * - * returns: - * image format type or IMAGE_FORMAT_INVALID if no image is present - */ -int genimg_get_format(const void *img_addr) -{ -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - const image_header_t *hdr; - - hdr = (const image_header_t *)img_addr; - if (image_check_magic(hdr)) - return IMAGE_FORMAT_LEGACY; -#endif -#if IMAGE_ENABLE_FIT || IMAGE_ENABLE_OF_LIBFDT - if (fdt_check_header(img_addr) == 0) - return IMAGE_FORMAT_FIT; -#endif -#ifdef CONFIG_ANDROID_BOOT_IMAGE - if (android_image_check_header(img_addr) == 0) - return IMAGE_FORMAT_ANDROID; -#endif - - return IMAGE_FORMAT_INVALID; -} - -/** - * fit_has_config - check if there is a valid FIT configuration - * @images: pointer to the bootm command headers structure - * - * fit_has_config() checks if there is a FIT configuration in use - * (if FTI support is present). - * - * returns: - * 0, no FIT support or no configuration found - * 1, configuration found - */ -int genimg_has_config(bootm_headers_t *images) -{ -#if IMAGE_ENABLE_FIT - if (images->fit_uname_cfg) - return 1; -#endif - return 0; -} - -/** - * boot_get_ramdisk - main ramdisk handling routine - * @argc: command argument count - * @argv: command argument list - * @images: pointer to the bootm images structure - * @arch: expected ramdisk architecture - * @rd_start: pointer to a ulong variable, will hold ramdisk start address - * @rd_end: pointer to a ulong variable, will hold ramdisk end - * - * boot_get_ramdisk() is responsible for finding a valid ramdisk image. - * Curently supported are the following ramdisk sources: - * - multicomponent kernel/ramdisk image, - * - commandline provided address of decicated ramdisk image. - * - * returns: - * 0, if ramdisk image was found and valid, or skiped - * rd_start and rd_end are set to ramdisk start/end addresses if - * ramdisk image is found and valid - * - * 1, if ramdisk image is found but corrupted, or invalid - * rd_start and rd_end are set to 0 if no ramdisk exists - */ -int boot_get_ramdisk(int argc, char *const argv[], bootm_headers_t *images, - uint8_t arch, ulong *rd_start, ulong *rd_end) -{ - ulong rd_addr, rd_load; - ulong rd_data, rd_len; -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - const image_header_t *rd_hdr; -#endif - void *buf; -#ifdef CONFIG_SUPPORT_RAW_INITRD - char *end; -#endif -#if IMAGE_ENABLE_FIT - const char *fit_uname_config = images->fit_uname_cfg; - const char *fit_uname_ramdisk = NULL; - ulong default_addr; - int rd_noffset; -#endif - const char *select = NULL; - - *rd_start = 0; - *rd_end = 0; - -#ifdef CONFIG_ANDROID_BOOT_IMAGE - /* - * Look for an Android boot image. - */ - buf = map_sysmem(images->os.start, 0); - if (buf && genimg_get_format(buf) == IMAGE_FORMAT_ANDROID) - select = (argc == 0) ? env_get("loadaddr") : argv[0]; -#endif - - if (argc >= 2) - select = argv[1]; - - /* - * Look for a '-' which indicates to ignore the - * ramdisk argument - */ - if (select && strcmp(select, "-") == 0) { - debug("## Skipping init Ramdisk\n"); - rd_len = rd_data = 0; - } else if (select || genimg_has_config(images)) { -#if IMAGE_ENABLE_FIT - if (select) { - /* - * If the init ramdisk comes from the FIT image and - * the FIT image address is omitted in the command - * line argument, try to use os FIT image address or - * default load address. - */ - if (images->fit_uname_os) - default_addr = (ulong)images->fit_hdr_os; - else - default_addr = image_load_addr; - - if (fit_parse_conf(select, default_addr, - &rd_addr, &fit_uname_config)) { - debug("* ramdisk: config '%s' from image at " - "0x%08lx\n", - fit_uname_config, rd_addr); - } else if (fit_parse_subimage(select, default_addr, - &rd_addr, &fit_uname_ramdisk)) { - debug("* ramdisk: subimage '%s' from image at " - "0x%08lx\n", - fit_uname_ramdisk, rd_addr); - } else -#endif - { - rd_addr = hextoul(select, NULL); - debug("* ramdisk: cmdline image address = " - "0x%08lx\n", - rd_addr); - } -#if IMAGE_ENABLE_FIT - } else { - /* use FIT configuration provided in first bootm - * command argument. If the property is not defined, - * quit silently. - */ - rd_addr = map_to_sysmem(images->fit_hdr_os); - rd_noffset = fit_get_node_from_config(images, - FIT_RAMDISK_PROP, rd_addr); - if (rd_noffset == -ENOENT) - return 0; - else if (rd_noffset < 0) - return 1; - } -#endif - - /* - * Check if there is an initrd image at the - * address provided in the second bootm argument - * check image type, for FIT images get FIT node. - */ - buf = map_sysmem(rd_addr, 0); - switch (genimg_get_format(buf)) { -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - case IMAGE_FORMAT_LEGACY: - printf("## Loading init Ramdisk from Legacy " - "Image at %08lx ...\n", rd_addr); - - bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK); - rd_hdr = image_get_ramdisk(rd_addr, arch, - images->verify); - - if (rd_hdr == NULL) - return 1; - - rd_data = image_get_data(rd_hdr); - rd_len = image_get_data_size(rd_hdr); - rd_load = image_get_load(rd_hdr); - break; -#endif -#if IMAGE_ENABLE_FIT - case IMAGE_FORMAT_FIT: - rd_noffset = fit_image_load(images, - rd_addr, &fit_uname_ramdisk, - &fit_uname_config, arch, - IH_TYPE_RAMDISK, - BOOTSTAGE_ID_FIT_RD_START, - FIT_LOAD_OPTIONAL_NON_ZERO, - &rd_data, &rd_len); - if (rd_noffset < 0) - return 1; - - images->fit_hdr_rd = map_sysmem(rd_addr, 0); - images->fit_uname_rd = fit_uname_ramdisk; - images->fit_noffset_rd = rd_noffset; - break; -#endif -#ifdef CONFIG_ANDROID_BOOT_IMAGE - case IMAGE_FORMAT_ANDROID: - android_image_get_ramdisk((void *)images->os.start, - &rd_data, &rd_len); - break; -#endif - default: -#ifdef CONFIG_SUPPORT_RAW_INITRD - end = NULL; - if (select) - end = strchr(select, ':'); - if (end) { - rd_len = hextoul(++end, NULL); - rd_data = rd_addr; - } else -#endif - { - puts("Wrong Ramdisk Image Format\n"); - rd_data = rd_len = rd_load = 0; - return 1; - } - } - } else if (images->legacy_hdr_valid && - image_check_type(&images->legacy_hdr_os_copy, - IH_TYPE_MULTI)) { - - /* - * Now check if we have a legacy mult-component image, - * get second entry data start address and len. - */ - bootstage_mark(BOOTSTAGE_ID_RAMDISK); - printf("## Loading init Ramdisk from multi component " - "Legacy Image at %08lx ...\n", - (ulong)images->legacy_hdr_os); - - image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len); - } else { - /* - * no initrd image - */ - bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK); - rd_len = rd_data = 0; - } - - if (!rd_data) { - debug("## No init Ramdisk\n"); - } else { - *rd_start = rd_data; - *rd_end = rd_data + rd_len; - } - debug(" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", - *rd_start, *rd_end); - - return 0; -} - -#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH -/** - * boot_ramdisk_high - relocate init ramdisk - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @rd_data: ramdisk data start address - * @rd_len: ramdisk data length - * @initrd_start: pointer to a ulong variable, will hold final init ramdisk - * start address (after possible relocation) - * @initrd_end: pointer to a ulong variable, will hold final init ramdisk - * end address (after possible relocation) - * - * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment - * variable and if requested ramdisk data is moved to a specified location. - * - * Initrd_start and initrd_end are set to final (after relocation) ramdisk - * start/end addresses if ramdisk image start and len were provided, - * otherwise set initrd_start and initrd_end set to zeros. - * - * returns: - * 0 - success - * -1 - failure - */ -int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, - ulong *initrd_start, ulong *initrd_end) -{ - char *s; - ulong initrd_high; - int initrd_copy_to_ram = 1; - - s = env_get("initrd_high"); - if (s) { - /* a value of "no" or a similar string will act like 0, - * turning the "load high" feature off. This is intentional. - */ - initrd_high = hextoul(s, NULL); - if (initrd_high == ~0) - initrd_copy_to_ram = 0; - } else { - initrd_high = env_get_bootm_mapsize() + env_get_bootm_low(); - } - - - debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n", - initrd_high, initrd_copy_to_ram); - - if (rd_data) { - if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ - debug(" in-place initrd\n"); - *initrd_start = rd_data; - *initrd_end = rd_data + rd_len; - lmb_reserve(lmb, rd_data, rd_len); - } else { - if (initrd_high) - *initrd_start = (ulong)lmb_alloc_base(lmb, - rd_len, 0x1000, initrd_high); - else - *initrd_start = (ulong)lmb_alloc(lmb, rd_len, - 0x1000); - - if (*initrd_start == 0) { - puts("ramdisk - allocation error\n"); - goto error; - } - bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK); - - *initrd_end = *initrd_start + rd_len; - printf(" Loading Ramdisk to %08lx, end %08lx ... ", - *initrd_start, *initrd_end); - - memmove_wd((void *)*initrd_start, - (void *)rd_data, rd_len, CHUNKSZ); - -#ifdef CONFIG_MP - /* - * Ensure the image is flushed to memory to handle - * AMP boot scenarios in which we might not be - * HW cache coherent - */ - flush_cache((unsigned long)*initrd_start, - ALIGN(rd_len, ARCH_DMA_MINALIGN)); -#endif - puts("OK\n"); - } - } else { - *initrd_start = 0; - *initrd_end = 0; - } - debug(" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", - *initrd_start, *initrd_end); - - return 0; - -error: - return -1; -} -#endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */ - -int boot_get_setup(bootm_headers_t *images, uint8_t arch, - ulong *setup_start, ulong *setup_len) -{ -#if IMAGE_ENABLE_FIT - return boot_get_setup_fit(images, arch, setup_start, setup_len); -#else - return -ENOENT; -#endif -} - -#if IMAGE_ENABLE_FIT -#if defined(CONFIG_FPGA) -int boot_get_fpga(int argc, char *const argv[], bootm_headers_t *images, - uint8_t arch, const ulong *ld_start, ulong * const ld_len) -{ - ulong tmp_img_addr, img_data, img_len; - void *buf; - int conf_noffset; - int fit_img_result; - const char *uname, *name; - int err; - int devnum = 0; /* TODO support multi fpga platforms */ - - /* 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 - */ - tmp_img_addr = map_to_sysmem(images->fit_hdr_os); - 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); - - uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0, - NULL); - if (!uname) { - debug("## FPGA image is not specified\n"); - return 0; - } - fit_img_result = fit_image_load(images, - tmp_img_addr, - (const char **)&uname, - &(images->fit_uname_cfg), - arch, - IH_TYPE_FPGA, - BOOTSTAGE_ID_FPGA_INIT, - FIT_LOAD_OPTIONAL_NON_ZERO, - &img_data, &img_len); - - debug("FPGA image (%s) loaded to 0x%lx/size 0x%lx\n", - uname, img_data, img_len); - - if (fit_img_result < 0) { - /* Something went wrong! */ - return fit_img_result; - } - - if (!fpga_is_partial_data(devnum, img_len)) { - name = "full"; - err = fpga_loadbitstream(devnum, (char *)img_data, - img_len, BIT_FULL); - if (err) - err = fpga_load(devnum, (const void *)img_data, - img_len, BIT_FULL); - } else { - name = "partial"; - err = fpga_loadbitstream(devnum, (char *)img_data, - img_len, BIT_PARTIAL); - if (err) - err = fpga_load(devnum, (const void *)img_data, - img_len, BIT_PARTIAL); - } - - if (err) - return err; - - printf(" Programming %s bitstream... OK\n", name); - break; - default: - printf("The given image format is not supported (corrupt?)\n"); - return 1; - } - - return 0; -} -#endif - -static void fit_loadable_process(uint8_t img_type, - ulong img_data, - ulong img_len) -{ - int i; - const unsigned int count = - ll_entry_count(struct fit_loadable_tbl, fit_loadable); - struct fit_loadable_tbl *fit_loadable_handler = - ll_entry_start(struct fit_loadable_tbl, fit_loadable); - /* For each loadable handler */ - for (i = 0; i < count; i++, fit_loadable_handler++) - /* matching this type */ - if (fit_loadable_handler->type == img_type) - /* call that handler with this image data */ - fit_loadable_handler->handler(img_data, img_len); -} - -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; - const char *uname; - uint8_t img_type; - - /* 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 - */ - tmp_img_addr = map_to_sysmem(images->fit_hdr_os); - 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; - uname = fdt_stringlist_get(buf, conf_noffset, - FIT_LOADABLE_PROP, loadables_index, - NULL), uname; - loadables_index++) - { - fit_img_result = fit_image_load(images, - tmp_img_addr, - &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; - } - - fit_img_result = fit_image_get_node(buf, uname); - if (fit_img_result < 0) { - /* Something went wrong! */ - return fit_img_result; - } - fit_img_result = fit_image_get_type(buf, - fit_img_result, - &img_type); - if (fit_img_result < 0) { - /* Something went wrong! */ - return fit_img_result; - } - - fit_loadable_process(img_type, img_data, img_len); - } - break; - default: - printf("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 - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @cmd_start: pointer to a ulong variable, will hold cmdline start - * @cmd_end: pointer to a ulong variable, will hold cmdline end - * - * boot_get_cmdline() allocates space for kernel command line below - * BOOTMAPSZ + env_get_bootm_low() address. If "bootargs" U-Boot environment - * variable is present its contents is copied to allocated kernel - * command line. - * - * returns: - * 0 - success - * -1 - failure - */ -int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end) -{ - char *cmdline; - char *s; - - cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf, - env_get_bootm_mapsize() + env_get_bootm_low()); - - if (cmdline == NULL) - return -1; - - s = env_get("bootargs"); - if (!s) - s = ""; - - strcpy(cmdline, s); - - *cmd_start = (ulong) & cmdline[0]; - *cmd_end = *cmd_start + strlen(cmdline); - - debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); - - return 0; -} -#endif /* CONFIG_SYS_BOOT_GET_CMDLINE */ - -#ifdef CONFIG_SYS_BOOT_GET_KBD -/** - * boot_get_kbd - allocate and initialize kernel copy of board info - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @kbd: double pointer to board info data - * - * boot_get_kbd() allocates space for kernel copy of board info data below - * BOOTMAPSZ + env_get_bootm_low() address and kernel board info is initialized - * with the current u-boot board info data. - * - * returns: - * 0 - success - * -1 - failure - */ -int boot_get_kbd(struct lmb *lmb, struct bd_info **kbd) -{ - *kbd = (struct bd_info *)(ulong)lmb_alloc_base(lmb, - sizeof(struct bd_info), - 0xf, - env_get_bootm_mapsize() + env_get_bootm_low()); - if (*kbd == NULL) - return -1; - - **kbd = *(gd->bd); - - debug("## kernel board info at 0x%08lx\n", (ulong)*kbd); - -#if defined(DEBUG) && defined(CONFIG_CMD_BDI) - do_bdinfo(NULL, 0, 0, NULL); -#endif - - return 0; -} -#endif /* CONFIG_SYS_BOOT_GET_KBD */ - -#ifdef CONFIG_LMB -int image_setup_linux(bootm_headers_t *images) -{ - ulong of_size = images->ft_len; - char **of_flat_tree = &images->ft_addr; - struct lmb *lmb = &images->lmb; - int ret; - - if (IMAGE_ENABLE_OF_LIBFDT) - boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); - - if (IMAGE_BOOT_GET_CMDLINE) { - ret = boot_get_cmdline(lmb, &images->cmdline_start, - &images->cmdline_end); - if (ret) { - puts("ERROR with allocation of cmdline\n"); - return ret; - } - } - - if (IMAGE_ENABLE_OF_LIBFDT) { - ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); - if (ret) - return ret; - } - - if (IMAGE_ENABLE_OF_LIBFDT && of_size) { - ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb); - if (ret) - return ret; - } - - return 0; -} -#endif /* CONFIG_LMB */ -#endif /* !USE_HOSTCC */ diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 8a8a971a91..17ce2f6b61 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -419,7 +419,8 @@ config SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION config SPL_CRC32 bool "Support CRC32" - default y if SPL_LEGACY_IMAGE_SUPPORT + default y if SPL_LEGACY_IMAGE_SUPPORT || SPL_EFI_PARTITION + default y if SPL_ENV_SUPPORT || TPL_BLOBLIST help Enable this to support CRC32 in uImages or FIT images within SPL. This is a 32-bit checksum value that can be used to verify images. @@ -1419,6 +1420,16 @@ config TPL_BOOTROM_SUPPORT BOOT_DEVICE_BOOTROM (or fall-through to the next boot device in the boot device list, if not implemented for a given board) +config TPL_CRC32 + bool "Support CRC32 in TPL" + default y if TPL_ENV_SUPPORT || TPL_BLOBLIST + help + Enable this to support CRC32 in uImages or FIT images within SPL. + This is a 32-bit checksum value that can be used to verify images. + For FIT images, this is the least secure type of checksum, suitable + for detected accidental image corruption. For secure applications you + should consider SHA1 or SHA256. + config TPL_DRIVERS_MISC bool "Support misc drivers in TPL" help |