From patchwork Wed Sep 19 00:03:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Troy Kisky X-Patchwork-Id: 184881 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 588882C0094 for ; Wed, 19 Sep 2012 10:04:18 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2CC0128193; Wed, 19 Sep 2012 02:03:53 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 HmmX-k5tWKwC; Wed, 19 Sep 2012 02:03:52 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 533C6281C5; Wed, 19 Sep 2012 02:03:15 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9B97F2810C for ; Wed, 19 Sep 2012 02:03:05 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 vsViaW-GXyjn for ; Wed, 19 Sep 2012 02:03:05 +0200 (CEST) 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 mail-pb0-f44.google.com (mail-pb0-f44.google.com [209.85.160.44]) by theia.denx.de (Postfix) with ESMTPS id D520A2817D for ; Wed, 19 Sep 2012 02:03:03 +0200 (CEST) Received: by pbbrr4 with SMTP id rr4so1124274pbb.3 for ; Tue, 18 Sep 2012 17:03:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=BkxBU7HR/4W1Peg1++ar8Mtxx/3VYJgHWsIACLdG1+c=; b=f2rKlgLEleC9Jb0K2Hy+6bW+HkqlT5kNeYJvnX/Zwyz1h/nVvaicfCPt2QgyUdl089 w3EJRtwVTS75bFiSw5AUM7mjfDZ+7limaZczPkurg7YLQkuZzVJ2bjNY7tSXUubBGW3/ 2LJDzHcEOOFTllXvYwArrpSiC5lRFPxTI0HdB9Xy1HjWtA68RDG52/5FkdRK77MgLcDY s0ufchqVBnSllYgJOo3NrTE7BXDd9dHdpm74+nccSfp9OOlmWb1slwtstPtiBVLgLTdk pc0sBBm/tRdd8DY5AZrxtijgIsBUfkuT8aRyG+SLiElQIUb1S6YLt8na5WrFSbXz3h7r VHQw== Received: by 10.66.81.231 with SMTP id d7mr2500345pay.50.1348012982001; Tue, 18 Sep 2012 17:03:02 -0700 (PDT) Received: from officeserver-2 ([70.96.116.236]) by mx.google.com with ESMTPS id it10sm761848pbc.53.2012.09.18.17.02.57 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 18 Sep 2012 17:03:00 -0700 (PDT) Received: from tkisky by officeserver-2 with local (Exim 4.76) (envelope-from ) id 1TE7l5-00058e-3I; Tue, 18 Sep 2012 17:03:15 -0700 From: Troy Kisky To: sbabic@denx.de Date: Tue, 18 Sep 2012 17:03:04 -0700 Message-Id: <1348012989-19674-7-git-send-email-troy.kisky@boundarydevices.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1348012989-19674-1-git-send-email-troy.kisky@boundarydevices.com> References: <1348012989-19674-1-git-send-email-troy.kisky@boundarydevices.com> X-Gm-Message-State: ALoCoQmZSDPeLUf0DmRyrhDCXkoSMAoIa2r9WgMcLEjD/Gk3bYS91HTIoj+QjjT1Izp2JTKdOlXD Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH 06/11] imximage: add plugin commands X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add commands plugin address filename iomux_entry addr, data1 [, data2, [, data3]] write_entry addr, data1 [, data2, [, data3]] Signed-off-by: Troy Kisky --- tools/imximage.c | 338 ++++++++++++++++++++++++++++++++++++++++++++---------- tools/imximage.h | 11 +- 2 files changed, 287 insertions(+), 62 deletions(-) diff --git a/tools/imximage.c b/tools/imximage.c index 2c5a622..63252be 100644 --- a/tools/imximage.c +++ b/tools/imximage.c @@ -31,7 +31,6 @@ #include "mkimage.h" #include #include "imximage.h" - /* * Supported commands for configuration file */ @@ -39,6 +38,9 @@ static table_entry_t imximage_cmds[] = { {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, {CMD_DATA, "DATA", "Reg Write Data", }, {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, + {CMD_PLUGIN, "plugin", "plugin addr,file", }, + {CMD_IOMUX_ENTRY, "iomux_entry", "Write iomux reg", }, + {CMD_WRITE_ENTRY, "write_entry", "Write register", }, {-1, "", "", }, }; @@ -69,8 +71,8 @@ static uint32_t imximage_version; static set_dcd_val_t set_dcd_val; static set_imx_hdr_t set_imx_hdr; -static set_imx_size_t set_imx_size; static uint32_t *p_max_dcd; +static uint32_t *header_size_ptr; static uint32_t g_flash_offset; static struct image_type_params imximage_params; @@ -88,8 +90,7 @@ static uint32_t detect_imximage_version(struct imx_header *imx_hdr) return IMXIMAGE_V1; /* Try to detect V2 */ - if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && - (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG)) + if ((fhdr_v2->header.tag == IVT_HEADER_TAG)) return IMXIMAGE_V2; return IMXIMAGE_VER_INVALID; @@ -160,7 +161,7 @@ static int set_dcd_val_v2(struct imx_header *imxhdr, uint32_t *data) } static int set_imx_hdr_v1(struct imx_header *imxhdr, - uint32_t entry_point, uint32_t flash_offset) + uint32_t entry_point, uint32_t flash_offset, int plugin) { imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1; flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; @@ -180,22 +181,12 @@ static int set_imx_hdr_v1(struct imx_header *imxhdr, /* Security feature are not supported */ fhdr_v1->app_code_csf = 0; fhdr_v1->super_root_key = 0; + header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4); return header_length; } -static void set_imx_size_v1(struct imx_header *imxhdr, uint32_t file_size, - uint32_t flash_offset) -{ - uint32_t *p = (uint32_t *)(((char *)imxhdr) - + imximage_params.header_size); - - /* The external flash header must be at the end of the DCD table */ - /* file_size includes header */ - p[-1] = file_size + flash_offset; -} - static int set_imx_hdr_v2(struct imx_header *imxhdr, - uint32_t entry_point, uint32_t flash_offset) + uint32_t entry_point, uint32_t flash_offset, int plugin) { imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; @@ -216,27 +207,20 @@ static int set_imx_hdr_v2(struct imx_header *imxhdr, fhdr_v2->boot_data_ptr = hdr_base + offsetof(imx_header_v2_t, boot_data); hdr_v2->boot_data.start = hdr_base - flash_offset; + hdr_v2->boot_data.plugin = plugin; /* Security feature are not supported */ fhdr_v2->csf = 0; + header_size_ptr = &hdr_v2->boot_data.size; return header_length; } -static void set_imx_size_v2(struct imx_header *imxhdr, uint32_t file_size, - uint32_t flash_offset) -{ - imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; - /* file_size includes header */ - hdr_v2->boot_data.size = file_size + flash_offset; -} - static void set_hdr_func(struct imx_header *imxhdr) { switch (imximage_version) { case IMXIMAGE_V1: set_dcd_val = set_dcd_val_v1; set_imx_hdr = set_imx_hdr_v1; - set_imx_size = set_imx_size_v1; p_entry = &imxhdr->header.hdr_v1.dcd_table.addr_data[0].type; p_max_dcd = &imxhdr->header.hdr_v1.dcd_table .addr_data[MAX_HW_CFG_SIZE_V1].type; @@ -245,7 +229,6 @@ static void set_hdr_func(struct imx_header *imxhdr) case IMXIMAGE_V2: set_dcd_val = set_dcd_val_v2; set_imx_hdr = set_imx_hdr_v2; - set_imx_size = set_imx_size_v2; p_entry = (uint32_t *)&imxhdr->header.hdr_v2.dcd_table; p_max_dcd = (uint32_t *)((char *)imxhdr + MAX_HEADER_SIZE); break; @@ -283,31 +266,49 @@ static void print_hdr_v1(struct imx_header *imx_hdr) printf("Entry Point: %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector); } -static void print_hdr_v2(struct imx_header *imx_hdr) +static void print_header_info2(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; + + 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); +} + +static void print_hdr_v2(struct imx_header *imxhdr) +{ + imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table; uint32_t size, version; - 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); + if (hdr_v2->fhdr.dcd_ptr) { + 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); + version = detect_imximage_version(imxhdr); 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); + print_header_info2(imxhdr); + if (hdr_v2->boot_data.plugin) { + uint32_t flash_offset = + hdr_v2->fhdr.self - hdr_v2->boot_data.start; + /* The 1st size includes flash offset and the next header */ + uint32_t plugin_length = hdr_v2->boot_data.size - flash_offset + - offsetof(imx_header_v2_t, dcd_table); + + imxhdr = (struct imx_header *)((char *)imxhdr + plugin_length); + print_header_info2(imxhdr); + } } static int cmd_cnt; @@ -363,6 +364,24 @@ int skip_separators(struct data_src *ds) } } +int skip_comma(struct data_src *ds) +{ + char *p = ds->p; + + for (;;) { + char c = *p++; + if ((c == '#') || (c == '\r') || (c == '\n') || !c) + return 0; + if (c == ',') { + ds->p = p; + skip_separators(ds); + return 1; + } + if ((c != ' ') && (c == '\t')) + return 0; + } +} + char *grab_token(char *dest, int size, char *src) { while (size) { @@ -551,16 +570,18 @@ do_unary: static int parse_cmd_data(struct data_src *ds) { uint32_t data[3]; - int ret = get_cfg_value(ds, &data[0]); + int ret, i; - if (ret) - return ret; - ret = get_cfg_value(ds, &data[1]); - if (ret) - return ret; - ret = get_cfg_value(ds, &data[2]); - if (ret) - return ret; + if (ds->plugin) { + fprintf(stderr, "DATA should be before plug command\n"); + return -1; + } + for (i = 0; i < 3; i++) { + int ret = get_cfg_value(ds, &data[i]); + if (ret) + return ret; + skip_comma(ds); /* comma is optional */ + } ret = (*set_dcd_val)(ds->imxhdr, data); if (ret) return ret; @@ -573,6 +594,103 @@ static int parse_cmd_data(struct data_src *ds) return 0; } +static int get_data(struct data_src *ds, uint32_t *data, int cnt) +{ + int i = 0; + + if (!ds->plugin) { + fprintf(stderr, "missing plug command\n"); + return -1; + } + for (;;) { + int ret = get_cfg_value(ds, &data[i++]); + if (ret) + return ret; + if (i >= cnt) + break; + if (!skip_comma(ds)) + break; + } + if (i < 2) { + fprintf(stderr, "missing ','\n"); + return -1; + } + while (i < 4) { + data[i] = data[i - 1]; + i++; + } + return 0; +} + +static int store_data(struct data_src *ds, uint32_t *data, int cnt) +{ + int i; + + for (i = 0; i < cnt; i++) + *p_entry++ = data[i]; + + ds->prev[1] = data[1]; + ds->prev[2] = data[2]; + ds->prev[3] = data[3]; + if (p_entry > p_max_dcd) { + uint32_t size = (char *)p_max_dcd - (char *)ds->imxhdr; + fprintf(stderr, "Error: header exceeds maximum size(%d)\n", + size); + return -1; + } + return 0; +} + +static int parse_iomux_entry(struct data_src *ds) +{ + uint32_t data[4]; + int ret, i, j; + + ret = get_data(ds, data, 4); + if (ret) + return ret; + if (data[0] & (3 << 30)) { + fprintf(stderr, "bad 1st value\n"); + return -1; + } + if ((data[1] == ds->prev[1]) && (data[2] == ds->prev[2]) + && (data[3] == ds->prev[3])) { + i = j = 1; + } else if ((data[1] == data[2]) && (data[2] == data[3])) { + i = j = 2; + } else { + i = 3; + j = 4; + } + data[0] |= (i << 30); + return store_data(ds, data, j); +} + +static int parse_write_entry(struct data_src *ds) +{ + uint32_t data[4]; + int ret, i; + + ret = get_data(ds, data, 4); + if (ret) + return ret; + if (data[0] & 3) { + fprintf(stderr, "Address must be aligned on word boundary\n"); + return -1; + } + if ((data[1] == ds->prev[1]) && (data[2] == ds->prev[2]) + && (data[3] == ds->prev[3])) + i = 0; + else if ((data[1] == data[2]) && (data[2] == data[3])) + i = 1; + else if (data[2] == data[3]) + i = 2; + else + i = 3; + data[0] |= i; + return store_data(ds, data, i + 1); +} + static int parse_image_version(struct data_src *ds) { int ret; @@ -618,8 +736,82 @@ static int parse_boot_from(struct data_src *ds) return 0; } +static int parse_plugin(struct data_src *ds) +{ + struct stat sbuf; + int plug_file; + unsigned char *ptr; + char *p; + char c; + int ret; + uint32_t plug_base; + uint32_t header_length; + + if (g_flash_offset == FLASH_OFFSET_UNDEFINED) { + fprintf(stderr, "Error: Place BOOT_FROM before plugin\n"); + return -1; + } + ret = get_cfg_value(ds, &plug_base); + if (ret) + return ret; + + if (skip_separators(ds)) + return -1; + p = ds->p; + for (;;) { + c = *p; + if (!c) + break; + if ((c == ' ') || (c == '\t') || (c == ';') || (c == '#') + || (c == '\r') || (c == '\n')) { + *p = 0; + break; + } + p++; + } + plug_file = open(ds->p, O_RDONLY|O_BINARY); + if (plug_file < 0) { + fprintf(stderr, "Can't open plugin file %s: %s\n", + ds->p, strerror(errno)); + *p = c; + return -1; + } + if (fstat(plug_file, &sbuf) < 0) { + fprintf(stderr, "Can't stat %s: %s\n", + ds->p, strerror(errno)); + close(plug_file); + return -1; + } + ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, plug_file, 0); + if (ptr == MAP_FAILED) { + fprintf(stderr, "Can't read %s: %s\n", + ds->p, strerror(errno)); + return -1; + } + *p = c; + ds->p = p; + /* Set the plugin header */ + header_length = (*set_imx_hdr)(ds->imxhdr, plug_base, + g_flash_offset, 1); + + p = ((char *)ds->imxhdr) + header_length; + if ((p + sbuf.st_size) >= (char *)p_max_dcd) { + fprintf(stderr, "Out of space\n"); + return -1; + } + + ds->plugin = 1; + memcpy(p, ptr, sbuf.st_size); + munmap((void *)ptr, sbuf.st_size); + close(plug_file); + + p_entry = (uint32_t *)(p + sbuf.st_size); + return 0; +} + parse_fld_t cmd_table[] = { - parse_image_version, parse_boot_from, parse_cmd_data + parse_image_version, parse_boot_from, parse_cmd_data, parse_plugin, + parse_iomux_entry, parse_write_entry }; static int parse_command(struct data_src *ds) @@ -630,9 +822,11 @@ static int parse_command(struct data_src *ds) return cmd_table[cmd](ds); } -static void parse_cfg_file(struct imx_header *imxhdr, char *name) +static void parse_cfg_file(struct imx_header *imxhdr, char *name, + uint32_t entry_point) { struct data_src ds; + uint32_t plugin_length = 0; ds.line = NULL; ds.len = 0; @@ -662,6 +856,35 @@ static void parse_cfg_file(struct imx_header *imxhdr, char *name) cmd_cnt++; } fclose(ds.fd); + + if (ds.plugin) { + uint32_t header_length, more; + struct imx_header *next_imxhdr; + + *p_entry++ = 0; + header_length = ((char *)p_entry) - ((char *)imxhdr); + plugin_length = ((header_length - 1) | 0x3f) + 1; + more = plugin_length - header_length; + if (more) + memset(p_entry, 0, more); + next_imxhdr = (struct imx_header *) + (((char *)imxhdr) + plugin_length); + p_entry = (imximage_version == IMXIMAGE_V1) ? (uint32_t *) + &next_imxhdr->header.hdr_v1.dcd_table.addr_data[0].type + : (uint32_t *)&next_imxhdr->header.hdr_v2.dcd_table; + if (p_entry > p_max_dcd) { + fprintf(stderr, "Out of space\n"); + exit(EXIT_FAILURE); + } + + /* Set the plugin size in header to include next header */ + *header_size_ptr = ((char *)p_entry) - ((char *)imxhdr) + + g_flash_offset; + imxhdr = next_imxhdr; + } + /* Set the imx header */ + imximage_params.header_size = (*set_imx_hdr)(imxhdr, entry_point, + g_flash_offset + plugin_length, 0) + plugin_length; return; } @@ -727,7 +950,7 @@ int imximage_vrec_header(struct mkimage_params *params, set_hdr_func(imxhdr); /* Parse dcd configuration file */ - parse_cfg_file(imxhdr, params->imagename); + parse_cfg_file(imxhdr, params->imagename, params->ep); /* Exit if there is no BOOT_FROM field specifying the flash_offset */ if (g_flash_offset == FLASH_OFFSET_UNDEFINED) { @@ -735,9 +958,6 @@ int imximage_vrec_header(struct mkimage_params *params, params->imagename); exit(EXIT_FAILURE); } - /* Set the imx header */ - imximage_params.header_size = (*set_imx_hdr)(imxhdr, params->ep, - g_flash_offset); imximage_params.hdr = imxhdr; return 0; } @@ -746,8 +966,10 @@ static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, struct mkimage_params *params) { /* Set the size in header */ - (*set_imx_size)((struct imx_header *)ptr, sbuf->st_size, - g_flash_offset); + uint32_t offset = (char *)header_size_ptr - (char *)imximage_params.hdr; + uint32_t *p = (uint32_t *)((char *)ptr + offset); + + *p = sbuf->st_size + g_flash_offset; } int imximage_check_params(struct mkimage_params *params) diff --git a/tools/imximage.h b/tools/imximage.h index efd249b..79f0156 100644 --- a/tools/imximage.h +++ b/tools/imximage.h @@ -51,7 +51,10 @@ enum imximage_cmd { CMD_IMAGE_VERSION, CMD_BOOT_FROM, - CMD_DATA + CMD_DATA, + CMD_PLUGIN, + CMD_IOMUX_ENTRY, + CMD_WRITE_ENTRY, }; enum imximage_version { @@ -158,6 +161,8 @@ struct data_src { char *filename; struct imx_header *imxhdr; char *p; + int plugin; + uint32_t prev[4]; }; typedef int (*parse_fld_t)(struct data_src *ds); @@ -165,8 +170,6 @@ typedef int (*parse_fld_t)(struct data_src *ds); typedef int (*set_dcd_val_t)(struct imx_header *imxhdr, uint32_t *data); typedef int (*set_imx_hdr_t)(struct imx_header *imxhdr, uint32_t entry_point, - uint32_t flash_offset); -typedef void (*set_imx_size_t)(struct imx_header *imxhdr, uint32_t file_size, - uint32_t flash_offset); + uint32_t flash_offset, int plugin); #endif /* _IMXIMAGE_H_ */