Make the function public available so we can reuse it for other boot mediums like QSPI. No functional changes Signed-off-by: Marco Felsch <m.felsch@xxxxxxxxxxxxxx> --- arch/arm/mach-imx/xload-common.c | 120 +++++++++++++++++++++++++++++++++++++++ drivers/mci/imx-esdhc-pbl.c | 118 -------------------------------------- include/mach/imx/xload.h | 5 ++ 3 files changed, 125 insertions(+), 118 deletions(-) diff --git a/arch/arm/mach-imx/xload-common.c b/arch/arm/mach-imx/xload-common.c index 5a437b185d..0d3e6be1b1 100644 --- a/arch/arm/mach-imx/xload-common.c +++ b/arch/arm/mach-imx/xload-common.c @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only #include <common.h> +#include <asm/cache.h> #include <asm/sections.h> #include <linux/sizes.h> #include <mach/imx/xload.h> #include <mach/imx/esdctl.h> #include <mach/imx/imx8m-regs.h> +#include <mach/imx/imx-header.h> #include <asm/barebox-arm.h> int imx_image_size(void) @@ -26,3 +28,121 @@ struct imx_scratch_space *__imx8m_scratch_space(int ddr_buswidth) return (void *)__arm_mem_scratch(endmem); } + +#define HDR_SIZE 512 + +static int +imx_search_header(struct imx_flash_header_v2 **header_pointer, + void *buffer, u32 *offset, u32 ivt_offset, + int (*read)(void *dest, size_t len, void *priv), + void *priv) +{ + int ret; + int i, header_count = 1; + void *buf = buffer; + struct imx_flash_header_v2 *hdr; + + for (i = 0; i < header_count; i++) { + ret = read(buf, *offset + ivt_offset + HDR_SIZE, priv); + if (ret) + return ret; + + hdr = buf + *offset + ivt_offset; + + if (!is_imx_flash_header_v2(hdr)) { + pr_debug("No IVT header! " + "Found tag: 0x%02x length: 0x%04x " + "version: %02x\n", + hdr->header.tag, hdr->header.length, + hdr->header.version); + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_ARCH_IMX8MQ) && + hdr->boot_data.plugin & PLUGIN_HDMI_IMAGE) { + /* + * In images that include signed HDMI + * firmware, first v2 header would be + * dedicated to that and would not contain any + * useful for us information. In order for us + * to pull the rest of the bootloader image + * in, we need to re-read header from SD/MMC, + * this time skipping anything HDMI firmware + * related. + */ + *offset += hdr->boot_data.size + hdr->header.length; + header_count++; + } + } + *header_pointer = hdr; + return 0; +} + +int imx_load_image(ptrdiff_t address, ptrdiff_t entry, u32 offset, + u32 ivt_offset, bool start, unsigned int alignment, + int (*read)(void *dest, size_t len, void *priv), + void *priv) +{ + + void *buf = (void *)address; + struct imx_flash_header_v2 *hdr = NULL; + int ret, len; + void __noreturn (*bb)(void); + unsigned int ofs; + + len = imx_image_size(); + if (alignment) + len = ALIGN(len, alignment); + + ret = imx_search_header(&hdr, buf, &offset, ivt_offset, read, priv); + if (ret) + return ret; + + pr_debug("Check ok, loading image\n"); + + ofs = offset + hdr->entry - hdr->boot_data.start; + + if (entry != address) { + /* + * Passing entry different from address is interpreted + * as a request to place the image such that its entry + * point would be exactly at 'entry', that is: + * + * buf + ofs = entry + * + * solving the above for 'buf' gives us the + * adjustment that needs to be made: + * + * buf = entry - ofs + * + */ + if (WARN_ON(entry - ofs < address)) { + /* + * We want to make sure we won't try to place + * the start of the image before the beginning + * of the memory buffer we were given in + * address. + */ + return -EINVAL; + } + + buf = (void *)(entry - ofs); + } + + ret = read(buf, ofs + len, priv); + if (ret) { + pr_err("Loading image failed with %d\n", ret); + return ret; + } + + pr_debug("Image loaded successfully\n"); + + if (!start) + return 0; + + bb = buf + ofs; + + sync_caches_for_execution(); + + bb(); +} diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c index 4884a68837..7c5febb7a8 100644 --- a/drivers/mci/imx-esdhc-pbl.c +++ b/drivers/mci/imx-esdhc-pbl.c @@ -104,124 +104,6 @@ static int esdhc_read_blocks(struct fsl_esdhc_host *host, void *dst, size_t len) } #ifdef CONFIG_ARCH_IMX -#define HDR_SIZE 512 - -static int -imx_search_header(struct imx_flash_header_v2 **header_pointer, - void *buffer, u32 *offset, u32 ivt_offset, - int (*read)(void *dest, size_t len, void *priv), - void *priv) -{ - int ret; - int i, header_count = 1; - void *buf = buffer; - struct imx_flash_header_v2 *hdr; - - for (i = 0; i < header_count; i++) { - ret = read(buf, *offset + ivt_offset + HDR_SIZE, priv); - if (ret) - return ret; - - hdr = buf + *offset + ivt_offset; - - if (!is_imx_flash_header_v2(hdr)) { - pr_debug("No IVT header! " - "Found tag: 0x%02x length: 0x%04x " - "version: %02x\n", - hdr->header.tag, hdr->header.length, - hdr->header.version); - return -EINVAL; - } - - if (IS_ENABLED(CONFIG_ARCH_IMX8MQ) && - hdr->boot_data.plugin & PLUGIN_HDMI_IMAGE) { - /* - * In images that include signed HDMI - * firmware, first v2 header would be - * dedicated to that and would not contain any - * useful for us information. In order for us - * to pull the rest of the bootloader image - * in, we need to re-read header from SD/MMC, - * this time skipping anything HDMI firmware - * related. - */ - *offset += hdr->boot_data.size + hdr->header.length; - header_count++; - } - } - *header_pointer = hdr; - return 0; -} - -int imx_load_image(ptrdiff_t address, ptrdiff_t entry, u32 offset, - u32 ivt_offset, bool start, unsigned int alignment, - int (*read)(void *dest, size_t len, void *priv), - void *priv) -{ - - void *buf = (void *)address; - struct imx_flash_header_v2 *hdr = NULL; - int ret, len; - void __noreturn (*bb)(void); - unsigned int ofs; - - len = imx_image_size(); - if (alignment) - len = ALIGN(len, alignment); - - ret = imx_search_header(&hdr, buf, &offset, ivt_offset, read, priv); - if (ret) - return ret; - - pr_debug("Check ok, loading image\n"); - - ofs = offset + hdr->entry - hdr->boot_data.start; - - if (entry != address) { - /* - * Passing entry different from address is interpreted - * as a request to place the image such that its entry - * point would be exactly at 'entry', that is: - * - * buf + ofs = entry - * - * solving the above for 'buf' gives us the - * adjustment that needs to be made: - * - * buf = entry - ofs - * - */ - if (WARN_ON(entry - ofs < address)) { - /* - * We want to make sure we won't try to place - * the start of the image before the beginning - * of the memory buffer we were given in - * address. - */ - return -EINVAL; - } - - buf = (void *)(entry - ofs); - } - - ret = read(buf, ofs + len, priv); - if (ret) { - pr_err("Loading image failed with %d\n", ret); - return ret; - } - - pr_debug("Image loaded successfully\n"); - - if (!start) - return 0; - - bb = buf + ofs; - - sync_caches_for_execution(); - - bb(); -} - static int imx_read_blocks(void *dest, size_t len, void *priv) { return esdhc_read_blocks(priv, dest, len); diff --git a/include/mach/imx/xload.h b/include/mach/imx/xload.h index 86270b03dc..e9d41adc97 100644 --- a/include/mach/imx/xload.h +++ b/include/mach/imx/xload.h @@ -25,6 +25,11 @@ void __noreturn imx8mm_load_and_start_image_via_tfa(void); void __noreturn imx8mn_load_and_start_image_via_tfa(void); void __noreturn imx8mp_load_and_start_image_via_tfa(void); +int imx_load_image(ptrdiff_t address, ptrdiff_t entry, u32 offset, + u32 ivt_offset, bool start, unsigned int alignment, + int (*read)(void *dest, size_t len, void *priv), + void *priv); + int imx_image_size(void); int piggydata_size(void); -- 2.30.2