From d1c07785fd68def6aa2251a15eed99f2e9c8071f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 23 Sep 2019 10:18:44 +0800 Subject: [PATCH] imx8: Add support to get container image set size To avoid hardcoded offset when adding u-boot.cnt to flash.bin, we use flexible offset which is calculated based on the size of the container image generated int the first stage. And pad u-boot.cnt at 1KB alignment. So add code to get the offset when SPL loading u-boot.cnt. Signed-off-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/mach-imx/Makefile | 9 +- arch/arm/mach-imx/imx8/Makefile | 2 +- arch/arm/mach-imx/imx8/image.c | 246 ++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-imx/imx8/image.c diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 17b241ae99..87fd69706d 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -169,9 +169,16 @@ u-boot.cnt: MKIMAGEOUTPUT = u-boot.cnt.log ifeq ($(CONFIG_SPL_LOAD_IMX_CONTAINER), y) u-boot.cnt: u-boot.bin container.cfg FORCE $(call if_changed,mkimage) -endif flash.bin: spl/u-boot-spl.bin FORCE $(call if_changed,mkimage) + @flashbin_size=`wc -c flash.bin | awk '{print $$1}'`; \ + pad_cnt=$$(((flashbin_size + 0x400 - 1) / 0x400)); \ + echo "append u-boot.cnt at $$pad_cnt KB"; \ + dd if=u-boot.cnt of=flash.bin bs=1K seek=$$pad_cnt; +else +flash.bin: spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) +endif endif else diff --git a/arch/arm/mach-imx/imx8/Makefile b/arch/arm/mach-imx/imx8/Makefile index 97f9d22945..39e384d5c7 100644 --- a/arch/arm/mach-imx/imx8/Makefile +++ b/arch/arm/mach-imx/imx8/Makefile @@ -8,5 +8,5 @@ obj-y += cpu.o iomux.o misc.o lowlevel_init.o obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += parse-container.o +obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image.o parse-container.o endif diff --git a/arch/arm/mach-imx/imx8/image.c b/arch/arm/mach-imx/imx8/image.c new file mode 100644 index 0000000000..58a29e8a03 --- /dev/null +++ b/arch/arm/mach-imx/imx8/image.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MMC_DEV 0 +#define QSPI_DEV 1 +#define NAND_DEV 2 +#define QSPI_NOR_DEV 3 + +static int __get_container_size(ulong addr) +{ + struct container_hdr *phdr; + struct boot_img_t *img_entry; + struct signature_block_hdr *sign_hdr; + u8 i = 0; + u32 max_offset = 0, img_end; + + phdr = (struct container_hdr *)addr; + if (phdr->tag != 0x87 && phdr->version != 0x0) { + debug("Wrong container header\n"); + return -EFAULT; + } + + max_offset = sizeof(struct container_hdr); + + img_entry = (struct boot_img_t *)(addr + sizeof(struct container_hdr)); + for (i = 0; i < phdr->num_images; i++) { + img_end = img_entry->offset + img_entry->size; + if (img_end > max_offset) + max_offset = img_end; + + debug("img[%u], end = 0x%x\n", i, img_end); + + img_entry++; + } + + if (phdr->sig_blk_offset != 0) { + sign_hdr = (struct signature_block_hdr *)(addr + phdr->sig_blk_offset); + u16 len = sign_hdr->length_lsb + (sign_hdr->length_msb << 8); + + if (phdr->sig_blk_offset + len > max_offset) + max_offset = phdr->sig_blk_offset + len; + + debug("sigblk, end = 0x%x\n", phdr->sig_blk_offset + len); + } + + return max_offset; +} + +static int get_container_size(void *dev, int dev_type, unsigned long offset) +{ + u8 *buf = malloc(CONTAINER_HDR_ALIGNMENT); + int ret = 0; + + if (!buf) { + printf("Malloc buffer failed\n"); + return -ENOMEM; + } + +#ifdef CONFIG_SPL_MMC_SUPPORT + if (dev_type == MMC_DEV) { + unsigned long count = 0; + struct mmc *mmc = (struct mmc *)dev; + + count = blk_dread(mmc_get_blk_desc(mmc), + offset / mmc->read_bl_len, + CONTAINER_HDR_ALIGNMENT / mmc->read_bl_len, + buf); + if (count == 0) { + printf("Read container image from MMC/SD failed\n"); + return -EIO; + } + } +#endif + +#ifdef CONFIG_SPL_SPI_LOAD + if (dev_type == QSPI_DEV) { + struct spi_flash *flash = (struct spi_flash *)dev; + + ret = spi_flash_read(flash, offset, + CONTAINER_HDR_ALIGNMENT, buf); + if (ret != 0) { + printf("Read container image from QSPI failed\n"); + return -EIO; + } + } +#endif + +#ifdef CONFIG_SPL_NAND_SUPPORT + if (dev_type == NAND_DEV) { + ret = nand_spl_load_image(offset, CONTAINER_HDR_ALIGNMENT, + buf); + if (ret != 0) { + printf("Read container image from NAND failed\n"); + return -EIO; + } + } +#endif + +#ifdef CONFIG_SPL_NOR_SUPPORT + if (dev_type == QSPI_NOR_DEV) + memcpy(buf, (const void *)offset, CONTAINER_HDR_ALIGNMENT); +#endif + + ret = __get_container_size((ulong)buf); + + free(buf); + + return ret; +} + +static unsigned long get_boot_device_offset(void *dev, int dev_type) +{ + unsigned long offset = 0; + + if (dev_type == MMC_DEV) { + struct mmc *mmc = (struct mmc *)dev; + + if (IS_SD(mmc) || mmc->part_config == MMCPART_NOAVAILABLE) { + offset = CONTAINER_HDR_MMCSD_OFFSET; + } else { + u8 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); + + if (part == 1 || part == 2) { + if (is_imx8qxp() && is_soc_rev(CHIP_REV_B)) + offset = CONTAINER_HDR_MMCSD_OFFSET; + else + offset = CONTAINER_HDR_EMMC_OFFSET; + } else { + offset = CONTAINER_HDR_MMCSD_OFFSET; + } + } + } else if (dev_type == QSPI_DEV) { + offset = CONTAINER_HDR_QSPI_OFFSET; + } else if (dev_type == NAND_DEV) { + offset = CONTAINER_HDR_NAND_OFFSET; + } else if (dev_type == QSPI_NOR_DEV) { + offset = CONTAINER_HDR_QSPI_OFFSET + 0x08000000; + } + + return offset; +} + +static int get_imageset_end(void *dev, int dev_type) +{ + unsigned long offset1 = 0, offset2 = 0; + int value_container[2]; + + offset1 = get_boot_device_offset(dev, dev_type); + offset2 = CONTAINER_HDR_ALIGNMENT + offset1; + + value_container[0] = get_container_size(dev, dev_type, offset1); + if (value_container[0] < 0) { + printf("Parse seco container failed %d\n", value_container[0]); + return value_container[0]; + } + + debug("seco container size 0x%x\n", value_container[0]); + + value_container[1] = get_container_size(dev, dev_type, offset2); + if (value_container[1] < 0) { + debug("Parse scu container failed %d, only seco container\n", + value_container[1]); + /* return seco container total size */ + return value_container[0] + offset1; + } + + debug("scu container size 0x%x\n", value_container[1]); + + return value_container[1] + offset2; +} + +#ifdef CONFIG_SPL_SPI_LOAD +unsigned long spl_spi_get_uboot_offs(struct spi_flash *flash) +{ + int end; + + end = get_imageset_end(flash, QSPI_DEV); + end = ROUND(end, SZ_1K); + + printf("Load image from QSPI 0x%x\n", end); + + return end; +} +#endif + +#ifdef CONFIG_SPL_MMC_SUPPORT +unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc) +{ + int end; + + end = get_imageset_end(mmc, MMC_DEV); + end = ROUND(end, SZ_1K); + + printf("Load image from MMC/SD 0x%x\n", end); + + return end / mmc->read_bl_len; +} +#endif + +#ifdef CONFIG_SPL_NAND_SUPPORT +uint32_t spl_nand_get_uboot_raw_page(void) +{ + int end; + + end = get_imageset_end((void *)NULL, NAND_DEV); + end = ROUND(end, SZ_16K); + + printf("Load image from NAND 0x%x\n", end); + + return end; +} +#endif + +#ifdef CONFIG_SPL_NOR_SUPPORT +unsigned long spl_nor_get_uboot_base(void) +{ + int end; + + /* Calculate the image set end, + * if it is less than CONFIG_SYS_UBOOT_BASE(0x8281000), + * we use CONFIG_SYS_UBOOT_BASE + * Otherwise, use the calculated address + */ + end = get_imageset_end((void *)NULL, QSPI_NOR_DEV); + if (end <= CONFIG_SYS_UBOOT_BASE) + end = CONFIG_SYS_UBOOT_BASE; + else + end = ROUND(end, SZ_1K); + + printf("Load image from NOR 0x%x\n", end); + + return end; +} +#endif -- 2.25.1