From b55e4f48db372b53568c196ce979f2364f3e8da4 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 11 Oct 2016 14:29:09 +0800 Subject: [PATCH] tools: imximage: add plugin support Add plugin support for imximage. Define CONFIG_USE_IMXIMG_PLUGIN in defconfig to enable using plugin. Signed-off-by: Peng Fan Cc: Stefano Babic Cc: Eric Nelson Cc: Ye Li Reviewed-by: Tom Rini --- tools/imximage.c | 283 +++++++++++++++++++++++++++++++++++++---------- tools/imximage.h | 7 +- 2 files changed, 230 insertions(+), 60 deletions(-) diff --git a/tools/imximage.c b/tools/imximage.c index 092d550002..615a64e727 100644 --- a/tools/imximage.c +++ b/tools/imximage.c @@ -27,6 +27,7 @@ static table_entry_t imximage_cmds[] = { {CMD_CHECK_BITS_CLR, "CHECK_BITS_CLR", "Reg Check bits clr", }, {CMD_CSF, "CSF", "Command Sequence File", }, {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, + {CMD_PLUGIN, "PLUGIN", "file plugin_addr", }, {-1, "", "", }, }; @@ -80,6 +81,9 @@ 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 uint32_t plugin_image; static set_dcd_val_t set_dcd_val; static set_dcd_param_t set_dcd_param; @@ -118,7 +122,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; @@ -165,7 +173,7 @@ static struct dcd_v2_cmd *gd_last_cmd; static void set_dcd_param_v2(struct imx_header *imxhdr, uint32_t dcd_len, int32_t cmd) { - dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; + dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table; struct dcd_v2_cmd *d = gd_last_cmd; struct dcd_v2_cmd *d2; int len; @@ -261,21 +269,23 @@ 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; - struct dcd_v2_cmd *d = gd_last_cmd; - int len; - - if (!d) - d = &dcd_v2->dcd_cmd; - len = be16_to_cpu(d->write_dcd_command.length); - if (len > 4) - d = (struct dcd_v2_cmd *)(((char *)d) + len); - - len = (char *)d - (char *)&dcd_v2->header; - - dcd_v2->header.tag = DCD_HEADER_TAG; - dcd_v2->header.length = cpu_to_be16(len); - dcd_v2->header.version = DCD_VERSION; + if (!imxhdr->header.hdr_v2.boot_data.plugin) { + dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table; + struct dcd_v2_cmd *d = gd_last_cmd; + int len; + + if (!d) + d = &dcd_v2->dcd_cmd; + len = be16_to_cpu(d->write_dcd_command.length); + if (len > 4) + d = (struct dcd_v2_cmd *)(((char *)d) + len); + + len = (char *)d - (char *)&dcd_v2->header; + + dcd_v2->header.tag = DCD_HEADER_TAG; + dcd_v2->header.length = cpu_to_be16(len); + dcd_v2->header.version = DCD_VERSION; + } } static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len, @@ -317,24 +327,94 @@ 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; - if (dcd_len > 0) - fhdr_v2->dcd_ptr = hdr_base - + offsetof(imx_header_v2_t, dcd_table); - else + if (!hdr_v2->boot_data.plugin) { + fhdr_v2->entry = entry_point; + fhdr_v2->reserved1 = 0; + fhdr_v2->reserved1 = 0; + hdr_base = entry_point - imximage_init_loadsize + + flash_offset; + fhdr_v2->self = hdr_base; + if (dcd_len > 0) + fhdr_v2->dcd_ptr = hdr_base + + offsetof(imx_header_v2_t, data); + else + fhdr_v2->dcd_ptr = 0; + 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 = 0; + fhdr_v2->reserved2 = 0; + fhdr_v2->self = imximage_iram_free_start + flash_offset; + fhdr_v2->dcd_ptr = 0; - 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; + fhdr_v2->boot_data_ptr = fhdr_v2->self + + offsetof(imx_header_v2_t, boot_data); + + 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 MAX_PLUGIN_CODE_SIZE(64KB) 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 */ + + next_fhdr_v2->entry = entry_point; + hdr_base = entry_point - sizeof(struct imx_header); + next_fhdr_v2->reserved1 = 0; + 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; - header_size_ptr = &hdr_v2->boot_data.size; - csf_ptr = &fhdr_v2->csf; + next_hdr_v2->boot_data.plugin = 0; + + next_fhdr_v2->csf = 0; + } } static void set_hdr_func(void) @@ -393,16 +473,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); - if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t)) + 8) { - 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); + plugin = hdr_v2->boot_data.plugin; + if (!plugin) { + size = be16_to_cpu(dcd_v2->header.length); + 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); @@ -410,19 +493,81 @@ 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); } } +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; +} + static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, char *name, int lineno, int fld, int dcd_len) { @@ -497,6 +642,10 @@ 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; + case CMD_PLUGIN: + plugin_image = 1; + copy_plugin_code(imxhdr, token); + break; } } @@ -542,6 +691,10 @@ static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd, } } break; + case CMD_PLUGIN: + value = get_cfg_value(token, name, lineno); + imximage_iram_free_start = value; + break; default: break; } @@ -649,6 +802,7 @@ static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, { struct imx_header *imxhdr = (struct imx_header *)ptr; uint32_t dcd_len; + uint32_t header_size; /* * In order to not change the old imx cfg file @@ -665,10 +819,15 @@ static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, dcd_len = parse_cfg_file(imxhdr, params->imagename); if (imximage_version == IMXIMAGE_V2) { - if (imximage_init_loadsize < imximage_ivt_offset + - sizeof(imx_header_v2_t)) + header_size = sizeof(flash_header_v2_t) + sizeof(boot_data_t); + if (!plugin_image) + header_size += sizeof(dcd_v2_t); + else + header_size += MAX_PLUGIN_CODE_SIZE; + + if (imximage_init_loadsize < imximage_ivt_offset + header_size) imximage_init_loadsize = imximage_ivt_offset + - sizeof(imx_header_v2_t); + header_size; } /* Set the imx header */ @@ -721,7 +880,7 @@ static int imximage_generate(struct image_tool_params *params, size_t alloc_len; struct stat sbuf; char *datafile = params->datafile; - uint32_t pad_len; + uint32_t pad_len, header_size; memset(&imximage_header, 0, sizeof(imximage_header)); @@ -742,15 +901,21 @@ static int imximage_generate(struct image_tool_params *params, /* TODO: check i.MX image V1 handling, for now use 'old' style */ if (imximage_version == IMXIMAGE_V1) { alloc_len = 4096; + header_size = 4096; } else { - if (imximage_init_loadsize < imximage_ivt_offset + - sizeof(imx_header_v2_t)) + header_size = sizeof(flash_header_v2_t) + sizeof(boot_data_t); + if (!plugin_image) + header_size += sizeof(dcd_v2_t); + else + header_size += MAX_PLUGIN_CODE_SIZE; + + if (imximage_init_loadsize < imximage_ivt_offset + header_size) imximage_init_loadsize = imximage_ivt_offset + - sizeof(imx_header_v2_t); + header_size; alloc_len = imximage_init_loadsize - imximage_ivt_offset; } - if (alloc_len < sizeof(struct imx_header)) { + if (alloc_len < header_size) { fprintf(stderr, "%s: header error\n", params->cmdname); exit(EXIT_FAILURE); diff --git a/tools/imximage.h b/tools/imximage.h index c7b9b5c8cc..db8b9a3dd4 100644 --- a/tools/imximage.h +++ b/tools/imximage.h @@ -9,6 +9,7 @@ #define _IMXIMAGE_H_ #define MAX_HW_CFG_SIZE_V2 220 /* Max number of registers imx can set for v2 */ +#define MAX_PLUGIN_CODE_SIZE (64 * 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 @@ -64,6 +65,7 @@ enum imximage_cmd { CMD_CHECK_BITS_SET, CMD_CHECK_BITS_CLR, CMD_CSF, + CMD_PLUGIN, }; enum imximage_fld_types { @@ -164,7 +166,10 @@ 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; + char plugin_code[MAX_PLUGIN_CODE_SIZE]; + } data; } imx_header_v2_t; /* The header must be aligned to 4k on MX53 for NAND boot */ -- 2.25.1