diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 2 | ||||
-rw-r--r-- | common/bloblist.c | 17 | ||||
-rw-r--r-- | common/board_f.c | 9 | ||||
-rw-r--r-- | common/board_r.c | 2 | ||||
-rw-r--r-- | common/cyclic.c | 6 | ||||
-rw-r--r-- | common/hash.c | 17 | ||||
-rw-r--r-- | common/log.c | 33 | ||||
-rw-r--r-- | common/spl/Kconfig | 8 | ||||
-rw-r--r-- | common/spl/Kconfig.tpl | 8 | ||||
-rw-r--r-- | common/spl/Kconfig.vpl | 21 | ||||
-rw-r--r-- | common/spl/Makefile | 1 | ||||
-rw-r--r-- | common/spl/spl.c | 45 | ||||
-rw-r--r-- | common/spl/spl_fit.c | 42 | ||||
-rw-r--r-- | common/spl/spl_reloc.c | 183 | ||||
-rw-r--r-- | common/splash_source.c | 17 |
15 files changed, 357 insertions, 54 deletions
diff --git a/common/Kconfig b/common/Kconfig index 0e8c44f3f74..7685914fa6f 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1047,6 +1047,8 @@ if BLOBLIST choice prompt "Bloblist location" + default BLOBLIST_FIXED if SANDBOX + default BLOBLIST_ALLOC help Select the location of the bloblist, via various means. diff --git a/common/bloblist.c b/common/bloblist.c index 110bb9dc44a..ab48a3cdb98 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -223,13 +223,26 @@ static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size, void *bloblist_find(uint tag, int size) { + void *blob = NULL; + int blob_size; + + blob = bloblist_get_blob(tag, &blob_size); + + if (size && size != blob_size) + return NULL; + + return blob; +} + +void *bloblist_get_blob(uint tag, int *sizep) +{ struct bloblist_rec *rec; rec = bloblist_findrec(tag); if (!rec) return NULL; - if (size && size != rec->size) - return NULL; + + *sizep = rec->size; return (void *)rec + rec_hdr_size(rec); } diff --git a/common/board_f.c b/common/board_f.c index 54c48d42ee9..6c5c3bfab48 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -815,21 +815,26 @@ static int initf_bootstage(void) static int initf_dm(void) { -#if defined(CONFIG_DM) && CONFIG_IS_ENABLED(SYS_MALLOC_F) int ret; + if (!CONFIG_IS_ENABLED(SYS_MALLOC_F)) + return 0; + bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f"); ret = dm_init_and_scan(true); bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F); if (ret) return ret; + ret = dm_autoprobe(); + if (ret) + return ret; + if (IS_ENABLED(CONFIG_TIMER_EARLY)) { ret = dm_timer_init(); if (ret) return ret; } -#endif return 0; } diff --git a/common/board_r.c b/common/board_r.c index f63c6aed4d5..179259b00de 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -250,7 +250,7 @@ static int initr_dm(void) if (ret) return ret; - return 0; + return dm_autoprobe(); } #endif diff --git a/common/cyclic.c b/common/cyclic.c index 196797fd61e..fad071a39c6 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -36,7 +36,7 @@ void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, cyclic->func = func; cyclic->name = name; cyclic->delay_us = delay_us; - cyclic->start_time_us = timer_get_us(); + cyclic->start_time_us = get_timer_us(0); hlist_add_head(&cyclic->list, cyclic_get_list()); } @@ -61,13 +61,13 @@ static void cyclic_run(void) * Check if this cyclic function needs to get called, e.g. * do not call the cyclic func too often */ - now = timer_get_us(); + now = get_timer_us(0); if (time_after_eq64(now, cyclic->next_call)) { /* Call cyclic function and account it's cpu-time */ cyclic->next_call = now + cyclic->delay_us; cyclic->func(cyclic); cyclic->run_cnt++; - cpu_time = timer_get_us() - now; + cpu_time = get_timer_us(0) - now; cyclic->cpu_time_us += cpu_time; /* Check if cpu-time exceeds max allowed time */ diff --git a/common/hash.c b/common/hash.c index 8dd9da85768..0c45992d5c7 100644 --- a/common/hash.c +++ b/common/hash.c @@ -143,7 +143,8 @@ static int __maybe_unused hash_finish_sha512(struct hash_algo *algo, void *ctx, return 0; } -static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp) +static int __maybe_unused hash_init_crc16_ccitt(struct hash_algo *algo, + void **ctxp) { uint16_t *ctx = malloc(sizeof(uint16_t)); *ctx = 0; @@ -151,16 +152,18 @@ static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp) return 0; } -static int hash_update_crc16_ccitt(struct hash_algo *algo, void *ctx, - const void *buf, unsigned int size, - int is_last) +static int __maybe_unused hash_update_crc16_ccitt(struct hash_algo *algo, + void *ctx, const void *buf, + unsigned int size, + int is_last) { *((uint16_t *)ctx) = crc16_ccitt(*((uint16_t *)ctx), buf, size); return 0; } -static int hash_finish_crc16_ccitt(struct hash_algo *algo, void *ctx, - void *dest_buf, int size) +static int __maybe_unused hash_finish_crc16_ccitt(struct hash_algo *algo, + void *ctx, void *dest_buf, + int size) { if (size < algo->digest_size) return -1; @@ -295,6 +298,7 @@ static struct hash_algo hash_algo[] = { #endif }, #endif +#if CONFIG_IS_ENABLED(CRC16) { .name = "crc16-ccitt", .digest_size = 2, @@ -304,6 +308,7 @@ static struct hash_algo hash_algo[] = { .hash_update = hash_update_crc16_ccitt, .hash_finish = hash_finish_crc16_ccitt, }, +#endif #if CONFIG_IS_ENABLED(CRC8) && IS_ENABLED(CONFIG_HASH_CRC8) { .name = "crc8", diff --git a/common/log.c b/common/log.c index c9fe35230d6..b75e404420b 100644 --- a/common/log.c +++ b/common/log.c @@ -130,17 +130,25 @@ bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat) return false; } -bool log_has_file(const char *file_list, const char *file) +/** + * log_has_member() - check if a string is in a comma separated list + * + * @list: Comma separated list of strings + * @member: String to find + * + * Return: ``true`` if @member is in @list, else ``false`` + */ +static bool log_has_member(const char *list, const char *member) { - int file_len = strlen(file); + int member_len = strlen(member); const char *s, *p; int substr_len; - for (s = file_list; *s; s = p + (*p != '\0')) { + for (s = list; *s; s = p + (*p != '\0')) { p = strchrnul(s, ','); substr_len = p - s; - if (file_len >= substr_len && - !strncmp(file + file_len - substr_len, s, substr_len)) + if (member_len >= substr_len && + !strncmp(member + member_len - substr_len, s, substr_len)) return true; } @@ -181,7 +189,11 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec) continue; if (filt->file_list && - !log_has_file(filt->file_list, rec->file)) + !log_has_member(filt->file_list, rec->file)) + continue; + + if (filt->func_list && + !log_has_member(filt->func_list, rec->func)) continue; if (filt->flags & LOGFF_DENY) @@ -321,7 +333,7 @@ int _log_buffer(enum log_category_t cat, enum log_level_t level, int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[], enum log_level_t level, const char *file_list, - int flags) + const char *func_list, int flags) { struct log_filter *filt; struct log_device *ldev; @@ -356,6 +368,13 @@ int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[], goto err; } } + if (func_list) { + filt->func_list = strdup(func_list); + if (!filt->func_list) { + ret = -ENOMEM; + goto err; + } + } filt->filter_num = ldev->next_filter_num++; /* Add deny filters to the beginning of the list */ if (flags & LOGFF_DENY) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 4e56d9909c8..94e118f8465 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -983,6 +983,14 @@ config SPL_NAND_IDENT help SPL uses the chip ID list to identify the NAND flash. +config SPL_RELOC_LOADER + bool "Allow relocating the next phase" + help + In some cases multiple U-Boot phases need to run in SRAM, typically + at the same address. Enable this to support loading the next phase + to temporary memory, then copying it into place afterwards, then + jumping to it. + config SPL_UBI bool "Support UBI" help diff --git a/common/spl/Kconfig.tpl b/common/spl/Kconfig.tpl index 92d4d43ec87..22ca7016453 100644 --- a/common/spl/Kconfig.tpl +++ b/common/spl/Kconfig.tpl @@ -268,6 +268,14 @@ config TPL_RAM_DEVICE be already in memory when TPL takes over, e.g. loaded by the boot ROM. +config TPL_RELOC_LOADER + bool "Allow relocating the next phase" + help + In some cases multiple U-Boot phases need to run in SRAM, typically + at the same address. Enable this to support loading the next phase + to temporary memory, then copying it into place afterwards, then + jumping to it. + config TPL_RTC bool "Support RTC drivers" help diff --git a/common/spl/Kconfig.vpl b/common/spl/Kconfig.vpl index eb57dfabea5..cf6b36c8e38 100644 --- a/common/spl/Kconfig.vpl +++ b/common/spl/Kconfig.vpl @@ -9,6 +9,19 @@ config VPL_BANNER_PRINT info. Disabling this option could be useful to reduce VPL boot time (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud). +config VPL_LDSCRIPT + string "Linker script for the VPL stage" + default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARM64 + default "arch/\$(ARCH)/cpu/u-boot-spl.lds" + help + The TPL stage will usually require a different linker-script + (as it runs from a different memory region) than the regular + U-Boot stage. Set this to the path of the linker-script to + be used for TPL. + + May be left empty to trigger the Makefile infrastructure to + fall back to the linker-script used for the SPL stage. + config VPL_BOARD_INIT bool "Call board-specific initialization in VPL" help @@ -181,6 +194,14 @@ config VPL_PCI necessary driver support. This enables the drivers in drivers/pci as part of a VPL build. +config VPL_RELOC_LOADER + bool "Allow relocating the next phase" + help + In some cases multiple U-Boot phases need to run in SRAM, typically + at the same address. Enable this to support loading the next phase + to temporary memory, then copying it into place afterwards, then + jumping to it. + config VPL_RTC bool "Support RTC drivers" help diff --git a/common/spl/Makefile b/common/spl/Makefile index 75123eb666b..4c9482bd309 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_$(PHASE_)BOOTROM_SUPPORT) += spl_bootrom.o obj-$(CONFIG_$(PHASE_)LOAD_FIT) += spl_fit.o obj-$(CONFIG_$(PHASE_)BLK_FS) += spl_blk_fs.o obj-$(CONFIG_$(PHASE_)LEGACY_IMAGE_FORMAT) += spl_legacy.o +obj-$(CONFIG_$(PHASE_)RELOC_LOADER) += spl_reloc.o obj-$(CONFIG_$(PHASE_)NOR_SUPPORT) += spl_nor.o obj-$(CONFIG_$(PHASE_)XIP_SUPPORT) += spl_xip.o obj-$(CONFIG_$(PHASE_)YMODEM_SUPPORT) += spl_ymodem.o diff --git a/common/spl/spl.c b/common/spl/spl.c index ad31a2f8b6c..76fd56dfe4b 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -50,8 +50,10 @@ u32 *boot_params_ptr = NULL; #if CONFIG_IS_ENABLED(BINMAN_UBOOT_SYMBOLS) /* See spl.h for information about this */ +#if defined(CONFIG_SPL_BUILD) binman_sym_declare(ulong, u_boot_any, image_pos); binman_sym_declare(ulong, u_boot_any, size); +#endif #ifdef CONFIG_TPL binman_sym_declare(ulong, u_boot_spl_any, image_pos); @@ -179,9 +181,15 @@ ulong spl_get_image_pos(void) if (xpl_next_phase() == PHASE_VPL) return binman_sym(ulong, u_boot_vpl_any, image_pos); #endif - return xpl_next_phase() == PHASE_SPL ? - binman_sym(ulong, u_boot_spl_any, image_pos) : - binman_sym(ulong, u_boot_any, image_pos); +#if defined(CONFIG_TPL) && !defined(CONFIG_VPL) + if (xpl_next_phase() == PHASE_SPL) + return binman_sym(ulong, u_boot_spl_any, image_pos); +#endif +#if defined(CONFIG_SPL_BUILD) + return binman_sym(ulong, u_boot_any, image_pos); +#endif + + return BINMAN_SYM_MISSING; } ulong spl_get_image_size(void) @@ -263,14 +271,20 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) */ if (u_boot_pos && u_boot_pos != BINMAN_SYM_MISSING) { /* Binman does not support separated entry addresses */ - spl_image->entry_point = u_boot_pos; - spl_image->load_addr = u_boot_pos; + spl_image->entry_point = spl_get_image_text_base(); + spl_image->load_addr = spl_get_image_text_base(); + spl_image->size = spl_get_image_size(); + log_debug("Next load addr %lx\n", spl_image->load_addr); } else { spl_image->entry_point = CONFIG_SYS_UBOOT_START; spl_image->load_addr = CONFIG_TEXT_BASE; + log_debug("Default load addr %x (u_boot_pos=%lx)\n", + CONFIG_TEXT_BASE, u_boot_pos); } spl_image->os = IH_OS_U_BOOT; - spl_image->name = "U-Boot"; + spl_image->name = xpl_name(xpl_next_phase()); + log_debug("Next phase: %s at %lx size %lx\n", spl_image->name, + spl_image->load_addr, (ulong)spl_image->size); } __weak int spl_parse_board_header(struct spl_image_info *spl_image, @@ -500,6 +514,10 @@ static int spl_common_init(bool setup_malloc) debug("dm_init_and_scan() returned error %d\n", ret); return ret; } + + ret = dm_autoprobe(); + if (ret) + return ret; } return 0; @@ -671,8 +689,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) BOOT_DEVICE_NONE, BOOT_DEVICE_NONE, }; - typedef void __noreturn (*jump_to_image_t)(struct spl_image_info *); - jump_to_image_t jump_to_image = &jump_to_image_no_args; + spl_jump_to_image_t jump_to_image = &jump_to_image_no_args; struct spl_image_info spl_image; int ret, os; @@ -827,6 +844,18 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } spl_board_prepare_for_boot(); + + if (CONFIG_IS_ENABLED(RELOC_LOADER)) { + int ret; + + ret = spl_reloc_jump(&spl_image, jump_to_image); + if (ret) { + if (xpl_phase() == PHASE_VPL) + printf("jump failed %d\n", ret); + hang(); + } + } + jump_to_image(&spl_image); } diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ac8462577ff..49b4df60560 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -199,7 +199,9 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, * the image gets loaded to the address pointed to by the * load_addr member in this struct, if load_addr is not 0 * - * Return: 0 on success or a negative error number. + * Return: 0 on success, -EPERM if this image is not the correct phase + * (for CONFIG_BOOTMETH_VBE_SIMPLE_FW), or another negative error number on + * other error. */ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, const struct spl_fit_info *ctx, int node, @@ -218,6 +220,25 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, const void *fit = ctx->fit; bool external_data = false; + log_debug("starting\n"); + if (CONFIG_IS_ENABLED(BOOTMETH_VBE) && + xpl_get_phase(info) != IH_PHASE_NONE) { + enum image_phase_t phase; + int ret; + + ret = fit_image_get_phase(fit, node, &phase); + /* if the image is for any phase, let's use it */ + if (ret == -ENOENT || phase == xpl_get_phase(info)) { + log_debug("found\n"); + } else if (ret < 0) { + log_debug("err=%d\n", ret); + return ret; + } else { + log_debug("- phase mismatch, skipping this image\n"); + return -EPERM; + } + } + if (IS_ENABLED(CONFIG_SPL_FPGA) || (IS_ENABLED(CONFIG_SPL_OS_BOOT) && spl_decompression_enabled())) { if (fit_image_get_type(fit, node, &type)) @@ -278,10 +299,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, log_debug("reading from offset %x / %lx size %lx to %p: ", offset, read_offset, size, src_ptr); - if (info->read(info, - fit_offset + - get_aligned_image_offset(info, offset), size, - src_ptr) < length) + if (info->read(info, read_offset, size, src_ptr) < length) return -EIO; debug("External data: dst=%p, offset=%x, size=%lx\n", @@ -289,7 +307,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, src = src_ptr + overhead; } else { /* Embedded data */ - if (fit_image_get_data(fit, node, &data, &length)) { + if (fit_image_get_emb_data(fit, node, &data, &length)) { puts("Cannot get image data/size\n"); return -ENOENT; } @@ -456,7 +474,9 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, image_info.load_addr = (ulong)tmpbuffer; ret = load_simple_fit(info, offset, ctx, node, &image_info); - if (ret < 0) + if (ret == -EPERM) + continue; + else if (ret < 0) break; /* Make room in FDT for changes from the overlay */ @@ -495,9 +515,6 @@ static int spl_fit_record_loadable(const struct spl_fit_info *ctx, int index, const char *name; int node; - if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY)) - return 0; - ret = spl_fit_get_image_name(ctx, "loadables", index, &name); if (ret < 0) return ret; @@ -817,7 +834,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, image_info.load_addr = 0; ret = load_simple_fit(info, offset, &ctx, node, &image_info); - if (ret < 0) { + if (ret < 0 && ret != -EPERM) { printf("%s: can't load image loadables index %d (ret = %d)\n", __func__, index, ret); return ret; @@ -843,7 +860,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, spl_image->entry_point = image_info.entry_point; /* Record our loadables into the FDT */ - if (spl_image->fdt_addr) + if (!CONFIG_IS_ENABLED(FIT_IMAGE_TINY) && + xpl_get_fdt_update(info) && spl_image->fdt_addr) spl_fit_record_loadable(&ctx, index, spl_image->fdt_addr, &image_info); diff --git a/common/spl/spl_reloc.c b/common/spl/spl_reloc.c new file mode 100644 index 00000000000..324b98eaf98 --- /dev/null +++ b/common/spl/spl_reloc.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <gzip.h> +#include <image.h> +#include <log.h> +#include <mapmem.h> +#include <spl.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/sections.h> +#include <asm/unaligned.h> +#include <linux/types.h> +#include <lzma/LzmaTypes.h> +#include <lzma/LzmaDec.h> +#include <lzma/LzmaTools.h> +#include <u-boot/crc.h> +#include <u-boot/lz4.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* provide a way to jump straight into the relocation code, for debugging */ +#define DEBUG_JUMP 0 + +enum { + /* margin to allow for stack growth */ + RELOC_STACK_MARGIN = 0x800, + + /* align base address for DMA controllers which require it */ + BASE_ALIGN = 0x200, + + STACK_PROT_VALUE = 0x51ce4697, +}; + +typedef int (*rcode_func)(struct spl_image_info *image); + +static int setup_layout(struct spl_image_info *image, ulong *addrp) +{ + ulong base, fdt_size; + ulong limit, rcode_base; + uint rcode_size; + int buf_size, margin; + char *rcode_buf; + + limit = ALIGN(map_to_sysmem(&limit) - RELOC_STACK_MARGIN, 8); + image->stack_prot = map_sysmem(limit, sizeof(uint)); + *image->stack_prot = STACK_PROT_VALUE; + + fdt_size = fdt_totalsize(gd->fdt_blob); + base = ALIGN(map_to_sysmem(gd->fdt_blob) + fdt_size + BASE_ALIGN - 1, + BASE_ALIGN); + + rcode_size = _rcode_end - _rcode_start; + rcode_base = limit - rcode_size; + buf_size = rcode_base - base; + uint need_size = image->size + image->fdt_size; + margin = buf_size - need_size; + log_debug("spl_reloc %s->%s: margin%s%lx limit %lx fdt_size %lx base %lx avail %x image %x fdt %lx need %x\n", + spl_phase_name(spl_phase()), spl_phase_name(spl_phase() + 1), + margin >= 0 ? " " : " -", abs(margin), limit, fdt_size, base, + buf_size, image->size, image->fdt_size, need_size); + if (margin < 0) { + log_err("Image size %x but buffer is only %x\n", need_size, + buf_size); + return -ENOSPC; + } + + rcode_buf = map_sysmem(rcode_base, rcode_size); + log_debug("_rcode_start %p: %x -- func %p %x\n", _rcode_start, + *(uint *)_rcode_start, setup_layout, *(uint *)setup_layout); + + image->reloc_offset = rcode_buf - _rcode_start; + log_debug("_rcode start %lx base %lx size %x offset %lx\n", + (ulong)map_to_sysmem(_rcode_start), rcode_base, rcode_size, + image->reloc_offset); + + memcpy(rcode_buf, _rcode_start, rcode_size); + + image->buf = map_sysmem(base, need_size); + image->fdt_buf = image->buf + image->size; + image->rcode_buf = rcode_buf; + *addrp = base; + + return 0; +} + +int spl_reloc_prepare(struct spl_image_info *image, ulong *addrp) +{ + int ret; + + ret = setup_layout(image, addrp); + if (ret) + return ret; + + return 0; +} + +typedef void __noreturn (*image_entry_noargs_t)(uint crc, uint unc_len); + +/* this is the relocation + jump code that is copied to the top of memory */ +__rcode int rcode_reloc_and_jump(struct spl_image_info *image) +{ + image_entry_noargs_t entry = (image_entry_noargs_t)image->entry_point; + u32 *dst; + ulong image_len; + size_t unc_len; + int ret, crc; + uint magic; + + dst = map_sysmem(image->load_addr, image->size); + unc_len = (void *)image->rcode_buf - (void *)dst; + image_len = image->size; + if (*image->stack_prot != STACK_PROT_VALUE) + return -EFAULT; + magic = get_unaligned_le32(image->buf); + if (CONFIG_IS_ENABLED(LZMA)) { + SizeT lzma_len = unc_len; + + ret = lzmaBuffToBuffDecompress((u8 *)dst, &lzma_len, + image->buf, image_len); + unc_len = lzma_len; + } else if (CONFIG_IS_ENABLED(GZIP)) { + ret = gunzip(dst, unc_len, image->buf, &image_len); + } else if (CONFIG_IS_ENABLED(LZ4) && magic == LZ4F_MAGIC) { + ret = ulz4fn(image->buf, image_len, dst, &unc_len); + if (ret) + return ret; + } else { + u32 *src, *end, *ptr; + + unc_len = image->size; + for (src = image->buf, end = (void *)src + image->size, + ptr = dst; src < end;) + *ptr++ = *src++; + } + if (*image->stack_prot != STACK_PROT_VALUE) + return -EFAULT; + + /* copy in the FDT if needed */ + if (image->fdt_size) + memcpy(image->fdt_start, image->fdt_buf, image->fdt_size); + + crc = crc8(0, (u8 *)dst, unc_len); + + /* jump to the entry point */ + entry(crc, unc_len); +} + +int spl_reloc_jump(struct spl_image_info *image, spl_jump_to_image_t jump) +{ + rcode_func loader; + int ret; + + log_debug("malloc usage %x bytes (%d KB of %d KB)\n", gd->malloc_ptr, + gd->malloc_ptr / 1024, CONFIG_VAL(SYS_MALLOC_F_LEN) / 1024); + + if (*image->stack_prot != STACK_PROT_VALUE) { + log_err("stack busted, cannot continue\n"); + return -EFAULT; + } + loader = (rcode_func)(void *)rcode_reloc_and_jump + image->reloc_offset; + log_debug("Jumping via %p to %lx - image %p size %x load %lx\n", loader, + image->entry_point, image, image->size, image->load_addr); + + log_debug("unc_len %lx\n", + image->rcode_buf - map_sysmem(image->load_addr, image->size)); + if (DEBUG_JUMP) { + rcode_reloc_and_jump(image); + } else { + /* + * Must disable LOG_DEBUG since the decompressor cannot call + * log functions, printf(), etc. + */ + _Static_assert(DEBUG_JUMP || !_DEBUG, + "Cannot have debug output from decompressor"); + ret = loader(image); + } + + return -EFAULT; +} diff --git a/common/splash_source.c b/common/splash_source.c index f43e7cc1be7..2df78a4f2d7 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -395,19 +395,10 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) } /* Extract the splash data from FIT */ - /* 1. Test if splash is in FIT internal data. */ - if (!fit_image_get_data(fit_header, node_offset, &internal_splash_data, &internal_splash_size)) - memmove((void *)(uintptr_t)bmp_load_addr, internal_splash_data, internal_splash_size); - /* 2. Test if splash is in FIT external data with fixed position. */ - else if (!fit_image_get_data_position(fit_header, node_offset, &external_splash_addr)) - is_splash_external = true; - /* 3. Test if splash is in FIT external data with offset. */ - else if (!fit_image_get_data_offset(fit_header, node_offset, &external_splash_addr)) { - /* Align data offset to 4-byte boundary */ - fit_size = ALIGN(fdt_totalsize(fit_header), 4); - /* External splash offset means the offset by end of FIT header */ - external_splash_addr += location->offset + fit_size; - is_splash_external = true; + if (!fit_image_get_data(fit_header, node_offset, &internal_splash_data, + &internal_splash_size)) { + memmove((void *)(uintptr_t)bmp_load_addr, internal_splash_data, + internal_splash_size); } else { printf("Failed to get splash image from FIT\n"); return -ENODATA; |