From patchwork Wed Nov 5 08:13:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ye.Li" X-Patchwork-Id: 406898 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 4908414003E for ; Wed, 5 Nov 2014 19:13:46 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0BB9B4BBDE; Wed, 5 Nov 2014 09:13:45 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id WGBGUCtoOLtO; Wed, 5 Nov 2014 09:13:44 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 56C584BBAA; Wed, 5 Nov 2014 09:13:44 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0BACF4BB98 for ; Wed, 5 Nov 2014 09:13:39 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id M5yyHVNGGawg for ; Wed, 5 Nov 2014 09:13:38 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from na01-bl2-obe.outbound.protection.outlook.com (mail-bl2on0116.outbound.protection.outlook.com [65.55.169.116]) by theia.denx.de (Postfix) with ESMTPS id 3F03D4BB8D for ; Wed, 5 Nov 2014 09:13:35 +0100 (CET) Received: from BY2PR03CA041.namprd03.prod.outlook.com (10.141.249.14) by BY2PR03MB363.namprd03.prod.outlook.com (10.242.237.16) with Microsoft SMTP Server (TLS) id 15.1.11.14; Wed, 5 Nov 2014 08:13:31 +0000 Received: from BL2FFO11FD024.protection.gbl (2a01:111:f400:7c09::135) by BY2PR03CA041.outlook.office365.com (2a01:111:e400:2c5d::14) with Microsoft SMTP Server (TLS) id 15.1.16.15 via Frontend Transport; Wed, 5 Nov 2014 08:13:31 +0000 Received: from tx30smr01.am.freescale.net (192.88.168.50) by BL2FFO11FD024.mail.protection.outlook.com (10.173.161.103) with Microsoft SMTP Server (TLS) id 15.1.6.13 via Frontend Transport; Wed, 5 Nov 2014 08:13:31 +0000 Received: from leyoen-ubuntu.localdomain (B37916-01.ap.freescale.net [10.192.242.234]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id sA58DRqo015999; Wed, 5 Nov 2014 01:13:28 -0700 From: Ye.Li To: , Date: Wed, 5 Nov 2014 16:13:12 +0800 Message-ID: <1415175195-9800-1-git-send-email-B37916@freescale.com> X-Mailer: git-send-email 1.7.4.1 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:CAL; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(199003)(189002)(48376002)(104166001)(44976005)(21056001)(102836001)(68736004)(6806004)(19580405001)(92726001)(92566001)(87936001)(26826002)(87286001)(50466002)(36756003)(104016003)(4396001)(50226001)(89996001)(88136002)(84676001)(97736003)(19580395003)(50986999)(77156002)(120916001)(31966008)(93916002)(229853001)(47776003)(107046002)(46102003)(575784001)(64706001)(20776003)(106466001)(95666004)(62966003)(105606002)(99396003)(2004002); DIR:OUT; SFP:1102; SCL:1; SRVR:BY2PR03MB363; H:tx30smr01.am.freescale.net; FPR:; MLV:ovrnspm; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;SRVR:BY2PR03MB363; X-Exchange-Antispam-Report-Test: UriScan:; X-Forefront-PRVS: 0386B406AA Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=Ye.Li@freescale.com; X-OriginatorOrg: freescale.com Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2] imx: mx6: Add support for MX6 plugin images X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Plugin image is a firmware which can be executed during booting. Unlike device configuration data (DCD) which is static and interpretative configuration, plugin can be used to implement rich logics more than the peripherals configuration. Customers may consider to use the plugin, for the cases including but not limited to: 1) Need runtime condition judging. 2) Add delay to booting. 3) Apply custom settings to boot device and memory system. 4) Need more perpherals other than the boot device to work during booting. The boot ROM detects the image type using the plugin flag of the boot data structure. If the plugin flag is 1, then the ROM uses the image as a plugin function. The function must initialize the boot device and copy the program image to the final location. At the end the plugin function must return with the program image parameters. This patch supports generating plugin images and implement a framework for plugin code entry and exit. For any board to generate the plugin image, the macros below must be implemented: imx6_ddr_setting imx6_clock_gating imx6_qos_setting Signed-off-by: Ye.Li --- Changes since v1: - Improve the patch message to explicate more about the usage of plugin image. arch/arm/include/asm/arch-mx6/mx6_plugin.S | 145 +++++++++++++++ tools/imximage.c | 263 ++++++++++++++++++++++------ tools/imximage.h | 10 +- 3 files changed, 366 insertions(+), 52 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx6/mx6_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..1f5ae83 --- /dev/null +++ b/arch/arm/include/asm/arch-mx6/mx6_plugin.S @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2012-2014 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 + +#ifdef CONFIG_ROM_UNIFIED_SECTIONS +#define ROM_API_TABLE_BASE_ADDR_LEGACY 0x180 +#define ROM_VERSION_OFFSET 0x80 +#else +#define ROM_API_TABLE_BASE_ADDR_LEGACY 0xC0 +#define ROM_VERSION_OFFSET 0x48 +#endif +#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_TO10 0x10 +#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 +#ifdef CONFIG_MX6SX + ldr r3, =ROM_VERSION_OFFSET + ldr r4, [r3] + cmp r4, #ROM_VERSION_TO10 + bgt before_calling_rom___pu_irom_hwcnfg_setup + ldr r3, =0x00900b00 + ldr r4, =0x50000000 + str r4, [r3, #0x5c] +#else + ldr r3, =0x00900800 + ldr r4, =0x08000000 + str r4, [r3, #0xc0] +#endif +#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} + push {r5} + 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 + pop {r5} + + /* return back to ROM code */ + bx lr + +/* make the following data right in the end of the output*/ +.ltorg + +#if (defined(CONFIG_SYS_BOOT_EIMNOR) || defined(CONFIG_SYS_BOOT_QSPI)) +#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/tools/imximage.c b/tools/imximage.c index 526b7d4..70a988e 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 5b5ad0e..ef41d52 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 220 /* 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 */