diff options
Diffstat (limited to 'common/spl')
-rw-r--r-- | common/spl/Makefile | 1 | ||||
-rw-r--r-- | common/spl/spl.c | 56 | ||||
-rw-r--r-- | common/spl/spl_legacy.c | 131 | ||||
-rw-r--r-- | common/spl/spl_nor.c | 27 |
4 files changed, 157 insertions, 58 deletions
diff --git a/common/spl/Makefile b/common/spl/Makefile index eaa57f5ce5e..c576a781268 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -10,6 +10,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_$(SPL_TPL_)FRAMEWORK) += spl.o obj-$(CONFIG_$(SPL_TPL_)BOOTROM_SUPPORT) += spl_bootrom.o obj-$(CONFIG_$(SPL_TPL_)LOAD_FIT) += spl_fit.o +obj-$(CONFIG_$(SPL_TPL_)LEGACY_IMAGE_SUPPORT) += spl_legacy.o obj-$(CONFIG_$(SPL_TPL_)NOR_SUPPORT) += spl_nor.o obj-$(CONFIG_$(SPL_TPL_)XIP_SUPPORT) += spl_xip.o obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += spl_ymodem.o diff --git a/common/spl/spl.c b/common/spl/spl.c index 932e6ab98ac..b0f0e1557b9 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -254,6 +254,14 @@ static int spl_load_fit_image(struct spl_image_info *spl_image, } #endif +__weak int spl_parse_legacy_header(struct spl_image_info *spl_image, + const struct image_header *header) +{ + /* LEGACY image not supported */ + debug("Legacy boot image support not enabled, proceeding to other boot methods\n"); + return -EINVAL; +} + int spl_parse_image_header(struct spl_image_info *spl_image, const struct image_header *header) { @@ -264,51 +272,11 @@ int spl_parse_image_header(struct spl_image_info *spl_image, return ret; #endif if (image_get_magic(header) == IH_MAGIC) { -#ifdef CONFIG_SPL_LEGACY_IMAGE_SUPPORT - u32 header_size = sizeof(struct image_header); - -#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK - /* check uImage header CRC */ - if (!image_check_hcrc(header)) { - puts("SPL: Image header CRC check failed!\n"); - return -EINVAL; - } -#endif - - if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) { - /* - * On some system (e.g. powerpc), the load-address and - * entry-point is located at address 0. We can't load - * to 0-0x40. So skip header in this case. - */ - spl_image->load_addr = image_get_load(header); - spl_image->entry_point = image_get_ep(header); - spl_image->size = image_get_data_size(header); - } else { - spl_image->entry_point = image_get_ep(header); - /* Load including the header */ - spl_image->load_addr = image_get_load(header) - - header_size; - spl_image->size = image_get_data_size(header) + - header_size; - } -#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK - /* store uImage data length and CRC to check later */ - spl_image->dcrc_data = image_get_load(header); - spl_image->dcrc_length = image_get_data_size(header); - spl_image->dcrc = image_get_dcrc(header); -#endif + int ret; - spl_image->os = image_get_os(header); - spl_image->name = image_get_name(header); - debug(SPL_TPL_PROMPT - "payload image: %32s load addr: 0x%lx size: %d\n", - spl_image->name, spl_image->load_addr, spl_image->size); -#else - /* LEGACY image not supported */ - debug("Legacy boot image support not enabled, proceeding to other boot methods\n"); - return -EINVAL; -#endif + ret = spl_parse_legacy_header(spl_image, header); + if (ret) + return ret; } else { #ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE /* diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c new file mode 100644 index 00000000000..29d3ec70734 --- /dev/null +++ b/common/spl/spl_legacy.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Stefan Roese <sr@denx.de> + */ + +#include <common.h> +#include <malloc.h> +#include <spl.h> + +#include <lzma/LzmaTypes.h> +#include <lzma/LzmaDec.h> +#include <lzma/LzmaTools.h> + +#define LZMA_LEN (1 << 20) + +int spl_parse_legacy_header(struct spl_image_info *spl_image, + const struct image_header *header) +{ + u32 header_size = sizeof(struct image_header); + + /* check uImage header CRC */ + if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK) && + !image_check_hcrc(header)) { + puts("SPL: Image header CRC check failed!\n"); + return -EINVAL; + } + + if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) { + /* + * On some system (e.g. powerpc), the load-address and + * entry-point is located at address 0. We can't load + * to 0-0x40. So skip header in this case. + */ + spl_image->load_addr = image_get_load(header); + spl_image->entry_point = image_get_ep(header); + spl_image->size = image_get_data_size(header); + } else { + spl_image->entry_point = image_get_ep(header); + /* Load including the header */ + spl_image->load_addr = image_get_load(header) - + header_size; + spl_image->size = image_get_data_size(header) + + header_size; + } + +#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK + /* store uImage data length and CRC to check later */ + spl_image->dcrc_data = image_get_load(header); + spl_image->dcrc_length = image_get_data_size(header); + spl_image->dcrc = image_get_dcrc(header); +#endif + + spl_image->os = image_get_os(header); + spl_image->name = image_get_name(header); + debug(SPL_TPL_PROMPT + "payload image: %32s load addr: 0x%lx size: %d\n", + spl_image->name, spl_image->load_addr, spl_image->size); + + return 0; +} + +/* + * This function is added explicitly to avoid code size increase, when + * no compression method is enabled. The compiler will optimize the + * following switch/case statement in spl_load_legacy_img() away due to + * Dead Code Elimination. + */ +static inline int spl_image_get_comp(const struct image_header *hdr) +{ + if (IS_ENABLED(CONFIG_SPL_LZMA)) + return image_get_comp(hdr); + + return IH_COMP_NONE; +} + +int spl_load_legacy_img(struct spl_image_info *spl_image, + struct spl_load_info *load, ulong header) +{ + __maybe_unused SizeT lzma_len; + __maybe_unused void *src; + struct image_header hdr; + ulong dataptr; + int ret; + + /* Read header into local struct */ + load->read(load, header, sizeof(hdr), &hdr); + + ret = spl_parse_image_header(spl_image, &hdr); + if (ret) + return ret; + + dataptr = header + sizeof(hdr); + + /* Read image */ + switch (spl_image_get_comp(&hdr)) { + case IH_COMP_NONE: + load->read(load, dataptr, spl_image->size, + (void *)(unsigned long)spl_image->load_addr); + break; + + case IH_COMP_LZMA: + lzma_len = LZMA_LEN; + + debug("LZMA: Decompressing %08lx to %08lx\n", + dataptr, spl_image->load_addr); + src = malloc(spl_image->size); + if (!src) { + printf("Unable to allocate %d bytes for LZMA\n", + spl_image->size); + return -ENOMEM; + } + + load->read(load, dataptr, spl_image->size, src); + ret = lzmaBuffToBuffDecompress((void *)spl_image->load_addr, + &lzma_len, src, spl_image->size); + if (ret) { + printf("LZMA decompression error: %d\n", ret); + return ret; + } + + spl_image->size = lzma_len; + break; + + default: + debug("Compression method %s is not supported\n", + genimg_get_comp_short_name(image_get_comp(&hdr))); + return -EINVAL; + } + + return 0; +} diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index b1e79b9ded6..3f03ffe6a33 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -24,7 +24,6 @@ unsigned long __weak spl_nor_get_uboot_base(void) static int spl_nor_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - int ret; __maybe_unused const struct image_header *header; __maybe_unused struct spl_load_info load; @@ -43,6 +42,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, header = (const struct image_header *)CONFIG_SYS_OS_BASE; #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { + int ret; + debug("Found FIT\n"); load.bl_len = 1; load.read = spl_nor_load_read; @@ -61,6 +62,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, #endif if (image_get_os(header) == IH_OS_LINUX) { /* happy - was a Linux */ + int ret; ret = spl_parse_image_header(spl_image, header); if (ret) @@ -93,11 +95,9 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, debug("Found FIT format U-Boot\n"); load.bl_len = 1; load.read = spl_nor_load_read; - ret = spl_load_simple_fit(spl_image, &load, - spl_nor_get_uboot_base(), - (void *)header); - - return ret; + return spl_load_simple_fit(spl_image, &load, + spl_nor_get_uboot_base(), + (void *)header); } #endif if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { @@ -107,14 +107,13 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, spl_nor_get_uboot_base()); } - ret = spl_parse_image_header(spl_image, - (const struct image_header *)spl_nor_get_uboot_base()); - if (ret) - return ret; - - memcpy((void *)(unsigned long)spl_image->load_addr, - (void *)(spl_nor_get_uboot_base() + sizeof(struct image_header)), - spl_image->size); + /* Legacy image handling */ + if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_SUPPORT)) { + load.bl_len = 1; + load.read = spl_nor_load_read; + return spl_load_legacy_img(spl_image, &load, + spl_nor_get_uboot_base()); + } return 0; } |