From 441fd86d055c57b79257943449a8101b83e98c61 Mon Sep 17 00:00:00 2001 From: Nitin Garg Date: Tue, 27 May 2014 08:30:30 -0500 Subject: ENGR00315499-4: Add support for i.MX6 Plugin images Support generating plugin images. Make sure not to effect the size of DCD images. Signed-off-by: Nitin Garg --- arch/arm/include/asm/arch-mx6/mx6_plugin.S | 127 +++++++ board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg | 8 + board/freescale/mx6sabresd/Makefile | 4 + board/freescale/mx6sabresd/plugin.S | 491 +++++++++++++++++++++++++++ include/configs/mx6sabre_common.h | 2 + tools/imximage.c | 263 +++++++++++--- tools/imximage.h | 10 +- 7 files changed, 853 insertions(+), 52 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx6/mx6_plugin.S create mode 100644 board/freescale/mx6sabresd/plugin.S diff --git a/arch/arm/include/asm/arch-mx6/mx6_plugin.S b/arch/arm/include/asm/arch-mx6/mx6_plugin.S new file mode 100644 index 0000000..6ee5645 --- /dev/null +++ b/arch/arm/include/asm/arch-mx6/mx6_plugin.S @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#define ROM_API_TABLE_BASE_ADDR_LEGACY 0xC0 +#define ROM_API_TABLE_BASE_ADDR_MX6DQ_TO15 0xC4 +#define ROM_API_TABLE_BASE_ADDR_MX6DL_TO12 0xC4 +#define ROM_API_HWCNFG_SETUP_OFFSET 0x08 +#define ROM_VERSION_OFFSET 0x48 +#define ROM_VERSION_TO12 0x12 +#define ROM_VERSION_TO15 0x15 + +plugin_start: + + push {r0-r4, lr} + + imx6_ddr_setting + imx6_clock_gating + imx6_qos_setting + +/* + * The following is to fill in those arguments for this ROM function + * pu_irom_hwcnfg_setup(void **start, size_t *bytes, const void *boot_data) + * This function is used to copy data from the storage media into DDR. + * start - Initial (possibly partial) image load address on entry. + * Final image load address on exit. + * bytes - Initial (possibly partial) image size on entry. + * Final image size on exit. + * boot_data - Initial @ref ivt Boot Data load address. + */ + adr r0, boot_data2 + adr r1, image_len2 + adr r2, boot_data2 + +#ifdef CONFIG_SYS_BOOT_EIMNOR + ldr r3, =0x00900800 + ldr r4, =0x08000000 + str r4, [r3, #0xc0] +#endif + +/* + * check the _pu_irom_api_table for the address + */ +before_calling_rom___pu_irom_hwcnfg_setup: + ldr r3, =ROM_VERSION_OFFSET + ldr r4, [r3] +#if defined(CONFIG_MX6SOLO) || defined(CONFIG_MX6DL) + ldr r3, =ROM_VERSION_TO12 + cmp r4, r3 + ldrge r3, =ROM_API_TABLE_BASE_ADDR_MX6DL_TO12 + ldrlt r3, =ROM_API_TABLE_BASE_ADDR_LEGACY +#elif defined(CONFIG_MX6Q) + ldr r3, =ROM_VERSION_TO15 + cmp r4, r3 + ldrge r3, =ROM_API_TABLE_BASE_ADDR_MX6DQ_TO15 + ldrlt r3, =ROM_API_TABLE_BASE_ADDR_LEGACY +#else + ldr r3, =ROM_API_TABLE_BASE_ADDR_LEGACY +#endif + ldr r4, [r3, #ROM_API_HWCNFG_SETUP_OFFSET] + blx r4 +after_calling_rom___pu_irom_hwcnfg_setup: + + +/* To return to ROM from plugin, we need to fill in these argument. + * Here is what need to do: + * Need to construct the paramters for this function before return to ROM: + * plugin_download(void **start, size_t *bytes, UINT32 *ivt_offset) + */ + pop {r0-r4, lr} + ldr r5, boot_data2 + str r5, [r0] + ldr r5, image_len2 + str r5, [r1] + ldr r5, second_ivt_offset + str r5, [r2] + mov r0, #1 + + /* return back to ROM code */ + bx lr + +/* make the following data right in the end of the output*/ +.ltorg + +#ifdef CONFIG_SYS_BOOT_EIMNOR +#define FLASH_OFFSET 0x1000 +#else +#define FLASH_OFFSET 0x400 +#endif + +/* + * second_ivt_offset is the offset from the "second_ivt_header" to + * "image_copy_start", which involves FLASH_OFFSET, plus the first + * ivt_header, the plugin code size itself recorded by "ivt2_header" + */ + +second_ivt_offset: .long (ivt2_header + 0x2C + FLASH_OFFSET) + +/* + * The following is the second IVT header plus the second boot data + */ +ivt2_header: .long 0x0 +app2_code_jump_v: .long 0x0 +reserv3: .long 0x0 +dcd2_ptr: .long 0x0 +boot_data2_ptr: .long 0x0 +self_ptr2: .long 0x0 +app_code_csf2: .long 0x0 +reserv4: .long 0x0 +boot_data2: .long 0x0 +image_len2: .long 0x0 +plugin2: .long 0x0 diff --git a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg index bb6c60b..93d6209 100644 --- a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg +++ b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg @@ -10,6 +10,8 @@ * The syntax is taken as close as possible with the kwbimage */ +#define __ASSEMBLY__ +#include /* image version */ IMAGE_VERSION 2 @@ -19,6 +21,11 @@ IMAGE_VERSION 2 */ BOOT_FROM sd +#ifdef CONFIG_USE_PLUGIN +/*PLUGIN plugin-binary-file IRAM_FREE_START_ADDR*/ +PLUGIN board/freescale/mx6sabresd/plugin.bin 0x00907000 +#else + /* * Device Configuration Data (DCD) * @@ -167,3 +174,4 @@ DATA 4 0x020e001c 0x007F007F * This sets CKO1 at ahb_clk_root/8 = 132/8 = 16.5 MHz */ DATA 4 0x020c4060 0x000000fb +#endif diff --git a/board/freescale/mx6sabresd/Makefile b/board/freescale/mx6sabresd/Makefile index cfca2ef..c5446c9 100644 --- a/board/freescale/mx6sabresd/Makefile +++ b/board/freescale/mx6sabresd/Makefile @@ -7,3 +7,7 @@ # obj-y := mx6sabresd.o + +extra-$(CONFIG_USE_PLUGIN) := plugin.bin +$(obj)/plugin.bin: $(obj)/plugin.o + $(OBJCOPY) -O binary --gap-fill 0xff $< $@ diff --git a/board/freescale/mx6sabresd/plugin.S b/board/freescale/mx6sabresd/plugin.S new file mode 100644 index 0000000..e743cda --- /dev/null +++ b/board/freescale/mx6sabresd/plugin.S @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* DDR script */ +.macro imx6dqsabresd_ddr_setting + ldr r0, =IOMUXC_BASE_ADDR + ldr r1, =0x000c0000 + str r1, [r0, #0x798] + ldr r1, =0x00000000 + str r1, [r0, #0x758] + + ldr r1, =0x00000030 + str r1, [r0, #0x588] + str r1, [r0, #0x594] + str r1, [r0, #0x56c] + str r1, [r0, #0x578] + str r1, [r0, #0x74c] + str r1, [r0, #0x57c] + + ldr r1, =0x00000000 + str r1, [r0, #0x58c] + + ldr r1, =0x00000030 + str r1, [r0, #0x59c] + str r1, [r0, #0x5a0] + str r1, [r0, #0x78c] + + ldr r1, =0x00020000 + str r1, [r0, #0x750] + + ldr r1, =0x00000030 + str r1, [r0, #0x5a8] + str r1, [r0, #0x5b0] + str r1, [r0, #0x524] + str r1, [r0, #0x51c] + str r1, [r0, #0x518] + str r1, [r0, #0x50c] + str r1, [r0, #0x5b8] + str r1, [r0, #0x5c0] + + ldr r1, =0x00020000 + str r1, [r0, #0x774] + + ldr r1, =0x00000030 + str r1, [r0, #0x784] + str r1, [r0, #0x788] + str r1, [r0, #0x794] + str r1, [r0, #0x79c] + str r1, [r0, #0x7a0] + str r1, [r0, #0x7a4] + str r1, [r0, #0x7a8] + str r1, [r0, #0x748] + str r1, [r0, #0x5ac] + str r1, [r0, #0x5b4] + str r1, [r0, #0x528] + str r1, [r0, #0x520] + str r1, [r0, #0x514] + str r1, [r0, #0x510] + str r1, [r0, #0x5bc] + str r1, [r0, #0x5c4] + + ldr r0, =MMDC_P0_BASE_ADDR + ldr r2, =0xa1390003 + str r2, [r0, #0x800] + + ldr r2, =0x001F001F + str r2, [r0, #0x80c] + str r2, [r0, #0x810] + ldr r1, =MMDC_P1_BASE_ADDR + str r2, [r1, #0x80c] + str r2, [r1, #0x810] + + ldr r2, =0x43270338 + str r2, [r0, #0x83c] + ldr r2, =0x03200314 + str r2, [r0, #0x840] + + ldr r2, =0x431A032F + str r2, [r1, #0x83c] + ldr r2, =0x03200263 + str r2, [r1, #0x840] + + ldr r2, =0x4B434748 + str r2, [r0, #0x848] + ldr r2, =0x4445404C + str r2, [r1, #0x848] + + ldr r2, =0x38444542 + str r2, [r0, #0x850] + ldr r2, =0x4935493A + str r2, [r1, #0x850] + + ldr r2, =0x33333333 + str r2, [r0, #0x81c] + str r2, [r0, #0x820] + str r2, [r0, #0x824] + str r2, [r0, #0x828] + str r2, [r1, #0x81c] + str r2, [r1, #0x820] + str r2, [r1, #0x824] + str r2, [r1, #0x828] + + ldr r2, =0x00000800 + str r2, [r0, #0x8b8] + str r2, [r1, #0x8b8] + + ldr r2, =0x00020036 + str r2, [r0, #0x004] + ldr r2, =0x09444040 + str r2, [r0, #0x008] + + ldr r2, =0x555A7975 + str r2, [r0, #0x00c] + ldr r2, =0xFF538F64 + str r2, [r0, #0x010] + + ldr r2, =0x01FF00DB + str r2, [r0, #0x014] + ldr r2, =0x00001740 + str r2, [r0, #0x018] + + ldr r2, =0x00008000 + str r2, [r0, #0x01c] + ldr r2, =0x000026d2 + str r2, [r0, #0x02c] + ldr r2, =0x005A1023 + str r2, [r0, #0x030] + ldr r2, =0x00000027 + str r2, [r0, #0x040] + + ldr r2, =0x831A0000 + str r2, [r0, #0x000] + + ldr r2, =0x04088032 + str r2, [r0, #0x01c] + ldr r2, =0x00008033 + str r2, [r0, #0x01c] + ldr r2, =0x00048031 + str r2, [r0, #0x01c] + ldr r2, =0x09408030 + str r2, [r0, #0x01c] + ldr r2, =0x04008040 + str r2, [r0, #0x01c] + + ldr r2, =0x00005800 + str r2, [r0, #0x020] + ldr r2, =0x00011117 + str r2, [r0, #0x818] + str r2, [r1, #0x818] + ldr r2, =0x00025576 + str r2, [r0, #0x004] + ldr r2, =0x00011006 + str r2, [r0, #0x404] + ldr r2, =0x00000000 + str r2, [r0, #0x01c] +.endm + +.macro imx6dlsabresd_ddr_setting + ldr r0, =IOMUXC_BASE_ADDR + ldr r1, =0x000c0000 + str r1, [r0, #0x774] + ldr r1, =0x00000000 + str r1, [r0, #0x754] + + ldr r1, =0x00000030 + str r1, [r0, #0x4ac] + str r1, [r0, #0x4b0] + str r1, [r0, #0x464] + str r1, [r0, #0x490] + str r1, [r0, #0x74c] + str r1, [r0, #0x494] + + ldr r1, =0x00000000 + str r1, [r0, #0x4a0] + + ldr r1, =0x00000030 + str r1, [r0, #0x4b4] + str r1, [r0, #0x4b8] + str r1, [r0, #0x76c] + + ldr r1, =0x00020000 + str r1, [r0, #0x750] + + ldr r1, =0x00000030 + str r1, [r0, #0x4bc] + str r1, [r0, #0x4c0] + str r1, [r0, #0x4c4] + str r1, [r0, #0x4c8] + str r1, [r0, #0x4cc] + str r1, [r0, #0x4d0] + str r1, [r0, #0x4d4] + str r1, [r0, #0x4d8] + + ldr r1, =0x00020000 + str r1, [r0, #0x760] + + ldr r1, =0x00000030 + str r1, [r0, #0x764] + str r1, [r0, #0x770] + str r1, [r0, #0x778] + str r1, [r0, #0x77c] + str r1, [r0, #0x780] + str r1, [r0, #0x784] + str r1, [r0, #0x78c] + str r1, [r0, #0x748] + str r1, [r0, #0x470] + str r1, [r0, #0x474] + str r1, [r0, #0x478] + str r1, [r0, #0x47c] + str r1, [r0, #0x480] + str r1, [r0, #0x484] + str r1, [r0, #0x488] + str r1, [r0, #0x48c] + + ldr r0, =MMDC_P0_BASE_ADDR + ldr r2, =0xa1390003 + str r2, [r0, #0x800] + + ldr r2, =0x001f001f + str r2, [r0, #0x80c] + str r2, [r0, #0x810] + ldr r1, =MMDC_P1_BASE_ADDR + str r2, [r1, #0x80c] + str r2, [r1, #0x810] + + ldr r2, =0x4220021F + str r2, [r0, #0x83c] + ldr r2, =0x0207017E + str r2, [r0, #0x840] + + ldr r2, =0x4201020C + str r2, [r1, #0x83c] + ldr r2, =0x01660172 + str r2, [r1, #0x840] + + ldr r2, =0x4A4D4E4D + str r2, [r0, #0x848] + ldr r2, =0x4A4F5049 + str r2, [r1, #0x848] + + ldr r2, =0x3F3C3D31 + str r2, [r0, #0x850] + ldr r2, =0x3238372B + str r2, [r1, #0x850] + + ldr r2, =0x33333333 + str r2, [r0, #0x81c] + str r2, [r0, #0x820] + str r2, [r0, #0x824] + str r2, [r0, #0x828] + str r2, [r1, #0x81c] + str r2, [r1, #0x820] + str r2, [r1, #0x824] + str r2, [r1, #0x828] + + ldr r2, =0x00000800 + str r2, [r0, #0x8b8] + str r2, [r1, #0x8b8] + + ldr r2, =0x0002002D + str r2, [r0, #0x004] + ldr r2, =0x00333030 + str r2, [r0, #0x008] + + ldr r2, =0x3F435313 + str r2, [r0, #0x00c] + ldr r2, =0xB66E8B63 + str r2, [r0, #0x010] + + ldr r2, =0x01FF00DB + str r2, [r0, #0x014] + ldr r2, =0x00001740 + str r2, [r0, #0x018] + + ldr r2, =0x00008000 + str r2, [r0, #0x01c] + ldr r2, =0x000026d2 + str r2, [r0, #0x02c] + ldr r2, =0x00431023 + str r2, [r0, #0x030] + ldr r2, =0x00000027 + str r2, [r0, #0x040] + + ldr r2, =0x831A0000 + str r2, [r0, #0x000] + + ldr r2, =0x04008032 + str r2, [r0, #0x01c] + ldr r2, =0x00008033 + str r2, [r0, #0x01c] + ldr r2, =0x00048031 + str r2, [r0, #0x01c] + ldr r2, =0x05208030 + str r2, [r0, #0x01c] + ldr r2, =0x04008040 + str r2, [r0, #0x01c] + + ldr r2, =0x00005800 + str r2, [r0, #0x020] + ldr r2, =0x00011117 + str r2, [r0, #0x818] + str r2, [r1, #0x818] + ldr r2, =0x0002556D + str r2, [r0, #0x004] + ldr r2, =0x00011006 + str r2, [r0, #0x404] + ldr r2, =0x00000000 + str r2, [r0, #0x01c] +.endm + +.macro imx6solosabresd_ddr_setting + ldr r0, =IOMUXC_BASE_ADDR + ldr r1, =0x000c0000 + str r1, [r0, #0x774] + ldr r1, =0x00000000 + str r1, [r0, #0x754] + + ldr r1, =0x00000030 + str r1, [r0, #0x4ac] + str r1, [r0, #0x4b0] + str r1, [r0, #0x464] + str r1, [r0, #0x490] + str r1, [r0, #0x74c] + str r1, [r0, #0x494] + + ldr r1, =0x00000000 + str r1, [r0, #0x4a0] + + ldr r1, =0x00000030 + str r1, [r0, #0x4b4] + str r1, [r0, #0x4b8] + str r1, [r0, #0x76c] + + ldr r1, =0x00020000 + str r1, [r0, #0x750] + + ldr r1, =0x00000030 + str r1, [r0, #0x4bc] + str r1, [r0, #0x4c0] + str r1, [r0, #0x4c4] + str r1, [r0, #0x4c8] + + ldr r1, =0x00020000 + str r1, [r0, #0x760] + + ldr r1, =0x00000030 + str r1, [r0, #0x764] + str r1, [r0, #0x770] + str r1, [r0, #0x778] + str r1, [r0, #0x77c] + str r1, [r0, #0x470] + str r1, [r0, #0x474] + str r1, [r0, #0x478] + str r1, [r0, #0x47c] + + ldr r0, =MMDC_P0_BASE_ADDR + ldr r2, =0xa1390003 + str r2, [r0, #0x800] + + ldr r2, =0x001F001F + str r2, [r0, #0x80c] + str r2, [r0, #0x810] + + ldr r2, =0x42190219 + str r2, [r0, #0x83c] + ldr r2, =0x017B0177 + str r2, [r0, #0x840] + + ldr r2, =0x4B4D4E4D + str r2, [r0, #0x848] + + ldr r2, =0x3F3E2D36 + str r2, [r0, #0x850] + + ldr r2, =0x33333333 + str r2, [r0, #0x81c] + str r2, [r0, #0x820] + str r2, [r0, #0x824] + str r2, [r0, #0x828] + + ldr r2, =0x00000800 + str r2, [r0, #0x8b8] + + ldr r2, =0x0002002D + str r2, [r0, #0x004] + ldr r2, =0x00333030 + str r2, [r0, #0x008] + + ldr r2, =0x3F435313 + str r2, [r0, #0x00c] + ldr r2, =0xB66E8B63 + str r2, [r0, #0x010] + + ldr r2, =0x01FF00DB + str r2, [r0, #0x014] + ldr r2, =0x00001740 + str r2, [r0, #0x018] + + ldr r2, =0x00008000 + str r2, [r0, #0x01c] + ldr r2, =0x000026d2 + str r2, [r0, #0x02c] + ldr r2, =0x00431023 + str r2, [r0, #0x030] + ldr r2, =0x00000017 + str r2, [r0, #0x040] + + ldr r2, =0x83190000 + str r2, [r0, #0x000] + + ldr r2, =0x04008032 + str r2, [r0, #0x01c] + ldr r2, =0x00008033 + str r2, [r0, #0x01c] + ldr r2, =0x00048031 + str r2, [r0, #0x01c] + ldr r2, =0x05208030 + str r2, [r0, #0x01c] + ldr r2, =0x04008040 + str r2, [r0, #0x01c] + + ldr r2, =0x00005800 + str r2, [r0, #0x020] + ldr r2, =0x00011117 + str r2, [r0, #0x818] + ldr r2, =0x0002556D + str r2, [r0, #0x004] + ldr r2, =0x00011006 + str r2, [r0, #0x404] + ldr r2, =0x00000000 + str r2, [r0, #0x01c] +.endm +.macro imx6_clock_gating + ldr r0, =CCM_BASE_ADDR + ldr r1, =0x00C03F3F + str r1, [r0, #0x068] + ldr r1, =0x0030FC03 + str r1, [r0, #0x06c] + ldr r1, =0x0FFFC000 + str r1, [r0, #0x070] + ldr r1, =0x3FF00000 + str r1, [r0, #0x074] + ldr r1, =0x00FFF300 + str r1, [r0, #0x078] + ldr r1, =0x0F0000C3 + str r1, [r0, #0x07c] + ldr r1, =0x000003FF + str r1, [r0, #0x080] +.endm + +.macro imx6_qos_setting + ldr r0, =IOMUXC_BASE_ADDR + ldr r1, =0xF00000CF + str r1, [r0, #0x10] + + ldr r1, =0x007F007F + str r1, [r0, #0x18] + str r1, [r0, #0x1c] +.endm + +.macro imx6_ddr_setting +#if defined (CONFIG_MX6SOLO) + imx6solosabresd_ddr_setting +#elif defined (CONFIG_MX6DL) + imx6dlsabresd_ddr_setting +#elif defined (CONFIG_MX6Q) + imx6dqsabresd_ddr_setting +#else + #error "SOC not configured" +#endif + +.endm + +/* include the common plugin code here */ +#include diff --git a/include/configs/mx6sabre_common.h b/include/configs/mx6sabre_common.h index d1bf3bc..9686588 100644 --- a/include/configs/mx6sabre_common.h +++ b/include/configs/mx6sabre_common.h @@ -33,6 +33,8 @@ #define CONFIG_BOARD_LATE_INIT #define CONFIG_MXC_GPIO +/* #define CONFIG_USE_PLUGIN */ + #define CONFIG_MXC_UART #define CONFIG_CMD_FUSE diff --git a/tools/imximage.c b/tools/imximage.c index 18dc051..91b2e8e 100644 --- a/tools/imximage.c +++ b/tools/imximage.c @@ -24,6 +24,9 @@ static table_entry_t imximage_cmds[] = { {CMD_DATA, "DATA", "Reg Write Data", }, {CMD_CSF, "CSF", "Command Sequence File", }, {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, +#ifdef CONFIG_USE_PLUGIN + {CMD_PLUGIN, "PLUGIN", "file plugin_addr", }, +#endif {-1, "", "", }, }; @@ -75,6 +78,8 @@ static uint32_t imximage_ivt_offset = UNDEFINED; static uint32_t imximage_csf_size = UNDEFINED; /* Initial Load Region Size */ static uint32_t imximage_init_loadsize; +static uint32_t imximage_iram_free_start; +static uint32_t imximage_plugin_size; static set_dcd_val_t set_dcd_val; static set_dcd_rst_t set_dcd_rst; @@ -112,7 +117,11 @@ static uint32_t detect_imximage_version(struct imx_header *imx_hdr) /* Try to detect V2 */ if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && - (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG)) + (hdr_v2->data.dcd_table.header.tag == DCD_HEADER_TAG)) + return IMXIMAGE_V2; + + if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && + hdr_v2->boot_data.plugin) return IMXIMAGE_V2; return IMXIMAGE_VER_INVALID; @@ -157,7 +166,7 @@ static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno, static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno, int fld, uint32_t value, uint32_t off) { - dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; + dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table; switch (fld) { case CFG_REG_ADDRESS: @@ -192,16 +201,18 @@ static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len, static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len, char *name, int lineno) { - dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; - - dcd_v2->header.tag = DCD_HEADER_TAG; - dcd_v2->header.length = cpu_to_be16( - dcd_len * sizeof(dcd_addr_data_t) + 8); - dcd_v2->header.version = DCD_VERSION; - dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG; - dcd_v2->write_dcd_command.length = cpu_to_be16( - dcd_len * sizeof(dcd_addr_data_t) + 4); - dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM; + if (!imxhdr->header.hdr_v2.boot_data.plugin) { + dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table; + + dcd_v2->header.tag = DCD_HEADER_TAG; + dcd_v2->header.length = cpu_to_be16( + dcd_len * sizeof(dcd_addr_data_t) + 8); + dcd_v2->header.version = DCD_VERSION; + dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG; + dcd_v2->write_dcd_command.length = cpu_to_be16( + dcd_len * sizeof(dcd_addr_data_t) + 4); + dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM; + } } static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len, @@ -243,20 +254,87 @@ static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len, fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t)); fhdr_v2->header.version = IVT_VERSION; /* 0x40 */ - fhdr_v2->entry = entry_point; - fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; - hdr_base = entry_point - imximage_init_loadsize + - flash_offset; - fhdr_v2->self = hdr_base; - fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table); - fhdr_v2->boot_data_ptr = hdr_base - + offsetof(imx_header_v2_t, boot_data); - hdr_v2->boot_data.start = entry_point - imximage_init_loadsize; + if (!hdr_v2->boot_data.plugin) { + fhdr_v2->entry = entry_point; + fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; + hdr_base = entry_point - imximage_init_loadsize + + flash_offset; + fhdr_v2->self = hdr_base; + fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, data); + fhdr_v2->boot_data_ptr = hdr_base + + offsetof(imx_header_v2_t, boot_data); + hdr_v2->boot_data.start = entry_point - imximage_init_loadsize; + + fhdr_v2->csf = 0; + + header_size_ptr = &hdr_v2->boot_data.size; + csf_ptr = &fhdr_v2->csf; + } else { + imx_header_v2_t *next_hdr_v2; + flash_header_v2_t *next_fhdr_v2; + + if(imximage_csf_size != 0) { + fprintf(stderr, "Error: Header v2: SECURE_BOOT" + "is only supported in DCD mode!"); + exit(EXIT_FAILURE); + } + + fhdr_v2->entry = imximage_iram_free_start + + flash_offset + sizeof(flash_header_v2_t) + + sizeof(boot_data_t); + + fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; + fhdr_v2->self = imximage_iram_free_start + flash_offset; + + fhdr_v2->dcd_ptr = 0; + + fhdr_v2->boot_data_ptr = fhdr_v2->self + + offsetof(imx_header_v2_t, boot_data); - fhdr_v2->csf = 0; + hdr_v2->boot_data.start = imximage_iram_free_start; + /* + * The actural size of plugin image is "imximage_plugin_size + + * sizeof(flash_header_v2_t) + sizeof(boot_data_t)", plus the + * flash_offset space.The ROM code only need to copy this size + * to run the plugin code. However, later when copy the whole + * U-Boot image to DDR, the ROM code use memcpy to copy the + * first part of the image, and use the storage read function + * to get the remaining part. This requires the dividing point + * must be multiple of storage sector size. Here we set the + * first section to be 16KB for this purpose. + */ + hdr_v2->boot_data.size = MAX_PLUGIN_CODE_SIZE; + + /* Security feature are not supported */ + fhdr_v2->csf = 0; + + next_hdr_v2 = (imx_header_v2_t *)((char*)hdr_v2 + + imximage_plugin_size); + + next_fhdr_v2 = &next_hdr_v2->fhdr; + + next_fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */ + next_fhdr_v2->header.length = + cpu_to_be16(sizeof(flash_header_v2_t)); + next_fhdr_v2->header.version = IVT_VERSION; /* 0x40 */ - header_size_ptr = &hdr_v2->boot_data.size; - csf_ptr = &fhdr_v2->csf; + next_fhdr_v2->entry = entry_point; + hdr_base = entry_point - sizeof(struct imx_header); + next_fhdr_v2->reserved1 = next_fhdr_v2->reserved2 = 0; + next_fhdr_v2->self = hdr_base + imximage_plugin_size; + + next_fhdr_v2->dcd_ptr = 0; + next_fhdr_v2->boot_data_ptr = next_fhdr_v2->self + + offsetof(imx_header_v2_t, boot_data); + + next_hdr_v2->boot_data.start = hdr_base - flash_offset; + + header_size_ptr = &next_hdr_v2->boot_data.size; + + next_hdr_v2->boot_data.plugin = 0; + + next_fhdr_v2->csf = 0; + } } static void set_hdr_func(void) @@ -312,16 +390,19 @@ static void print_hdr_v2(struct imx_header *imx_hdr) { imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; - dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table; - uint32_t size, version; + dcd_v2_t *dcd_v2 = &hdr_v2->data.dcd_table; + uint32_t size, version, plugin; - size = be16_to_cpu(dcd_v2->header.length) - 8; - if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) { + plugin = hdr_v2->boot_data.plugin; + if (!plugin) { + size = be16_to_cpu(dcd_v2->header.length) - 8; + if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) { fprintf(stderr, "Error: Image corrupt DCD size %d exceed maximum %d\n", (uint32_t)(size / sizeof(dcd_addr_data_t)), MAX_HW_CFG_SIZE_V2); exit(EXIT_FAILURE); + } } version = detect_imximage_version(imx_hdr); @@ -329,18 +410,82 @@ static void print_hdr_v2(struct imx_header *imx_hdr) printf("Image Type: Freescale IMX Boot Image\n"); printf("Image Ver: %x", version); printf("%s\n", get_table_entry_name(imximage_versions, NULL, version)); - printf("Data Size: "); - genimg_print_size(hdr_v2->boot_data.size); - printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr); - printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry); - if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) && - (imximage_csf_size != UNDEFINED)) { - printf("HAB Blocks: %08x %08x %08x\n", - (uint32_t)fhdr_v2->self, 0, - hdr_v2->boot_data.size - imximage_ivt_offset - - imximage_csf_size); + printf("Mode: %s\n", plugin ? "PLUGIN" : "DCD"); + if (!plugin) { + printf("Data Size: "); + genimg_print_size(hdr_v2->boot_data.size); + printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr); + printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry); + if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) && + (imximage_csf_size != UNDEFINED)) { + printf("HAB Blocks: %08x %08x %08x\n", + (uint32_t)fhdr_v2->self, 0, + hdr_v2->boot_data.size - imximage_ivt_offset - + imximage_csf_size); + } + } else { + imx_header_v2_t *next_hdr_v2; + flash_header_v2_t *next_fhdr_v2; + + /*First Header*/ + printf("Plugin Data Size: "); + genimg_print_size(hdr_v2->boot_data.size); + printf("Plugin Code Size: "); + genimg_print_size(imximage_plugin_size); + printf("Plugin Load Address: %08x\n", hdr_v2->boot_data.start); + printf("Plugin Entry Point: %08x\n", + (uint32_t)fhdr_v2->entry); + + /*Second Header*/ + next_hdr_v2 = (imx_header_v2_t *)((char*)hdr_v2 + + imximage_plugin_size); + next_fhdr_v2 = &next_hdr_v2->fhdr; + printf("U-Boot Data Size: "); + genimg_print_size(next_hdr_v2->boot_data.size); + printf("U-Boot Load Address: %08x\n", next_hdr_v2->boot_data.start); + printf("U-Boot Entry Point: %08x\n", + (uint32_t)next_fhdr_v2->entry); + } +} + +#ifdef CONFIG_USE_PLUGIN +static void copy_plugin_code(struct imx_header *imxhdr, char *plugin_file) +{ + int ifd = -1; + struct stat sbuf; + char *plugin_buf = imxhdr->header.hdr_v2.data.plugin_code; + char *ptr; + + ifd = open(plugin_file, O_RDONLY|O_BINARY); + if (fstat(ifd, &sbuf) < 0) { + fprintf(stderr, "Can't stat %s: %s\n", + plugin_file, + strerror(errno)); + exit(EXIT_FAILURE); + } + + ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0); + if (ptr == MAP_FAILED) { + fprintf(stderr, "Can't read %s: %s\n", + plugin_file, + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (sbuf.st_size > MAX_PLUGIN_CODE_SIZE) { + printf("plugin binary size too large\n"); + exit(EXIT_FAILURE); } + + memcpy(plugin_buf, ptr, sbuf.st_size); + imximage_plugin_size = sbuf.st_size; + + (void) munmap((void *)ptr, sbuf.st_size); + (void) close(ifd); + + imxhdr->header.hdr_v2.boot_data.plugin = 1; } +#endif static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, char *name, int lineno, int fld, int dcd_len) @@ -411,6 +556,11 @@ static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, if (unlikely(cmd_ver_first != 1)) cmd_ver_first = 0; break; +#ifdef CONFIG_USE_PLUGIN + case CMD_PLUGIN: + copy_plugin_code(imxhdr, token); + break; +#endif } } @@ -434,20 +584,31 @@ static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd, break; case CFG_REG_ADDRESS: case CFG_REG_VALUE: - if (*cmd != CMD_DATA) - return; - - value = get_cfg_value(token, name, lineno); - (*set_dcd_val)(imxhdr, name, lineno, fld, value, *dcd_len); - - if (fld == CFG_REG_VALUE) { - (*dcd_len)++; - if (*dcd_len > max_dcd_entries) { - fprintf(stderr, "Error: %s[%d] -" - "DCD table exceeds maximum size(%d)\n", - name, lineno, max_dcd_entries); - exit(EXIT_FAILURE); + switch (*cmd) { + case CMD_DATA: + value = get_cfg_value(token, name, lineno); + (*set_dcd_val)(imxhdr, name, lineno, fld, value, + *dcd_len); + + if (fld == CFG_REG_VALUE) { + (*dcd_len)++; + if (*dcd_len > max_dcd_entries) { + fprintf(stderr, "Error: %s[%d] -" + "DCD table exceeds maximum\ + size(%d)\n", + name, lineno, max_dcd_entries); + exit(EXIT_FAILURE); + } } + break; +#ifdef CONFIG_USE_PLUGIN + case CMD_PLUGIN: + value = get_cfg_value(token, name, lineno); + imximage_iram_free_start = value; + break; +#endif + default: + return; } break; default: diff --git a/tools/imximage.h b/tools/imximage.h index 01f861e..28ce671 100644 --- a/tools/imximage.h +++ b/tools/imximage.h @@ -8,7 +8,9 @@ #ifndef _IMXIMAGE_H_ #define _IMXIMAGE_H_ +#include #define MAX_HW_CFG_SIZE_V2 121 /* Max number of registers imx can set for v2 */ +#define MAX_PLUGIN_CODE_SIZE (16*1024) #define MAX_HW_CFG_SIZE_V1 60 /* Max number of registers imx can set for v1 */ #define APP_CODE_BARKER 0xB1 #define DCD_BARKER 0xB17219E9 @@ -54,6 +56,7 @@ enum imximage_cmd { CMD_BOOT_OFFSET, CMD_DATA, CMD_CSF, + CMD_PLUGIN, }; enum imximage_fld_types { @@ -149,7 +152,12 @@ typedef struct { typedef struct { flash_header_v2_t fhdr; boot_data_t boot_data; - dcd_v2_t dcd_table; + union { + dcd_v2_t dcd_table; +#ifdef CONFIG_USE_PLUGIN + char plugin_code[MAX_PLUGIN_CODE_SIZE]; +#endif + } data; } imx_header_v2_t; /* The header must be aligned to 4k on MX53 for NAND boot */ -- cgit v1.1