From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bo Shen Date: Tue, 20 May 2014 09:42:59 +0800 Subject: [U-Boot] [PATCH v3 1/3] mkimage: add atmelimage In-Reply-To: <1400502221-6955-2-git-send-email-andreas.devel@googlemail.com> References: <1400502221-6955-1-git-send-email-andreas.devel@googlemail.com> <1400502221-6955-2-git-send-email-andreas.devel@googlemail.com> Message-ID: <537AB323.20402@atmel.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Andreas, On 05/19/2014 08:23 PM, Andreas Bie?mann wrote: > The new atmelimage converts a machine code BLOB to bootable ROM image. Atmel > ROM has no sophisticated image format, it only checks the first 7 ARM vectors. > The vectors can contain valid B or LDR opcodes, the 6'th vector contains the > image size to load. > > Additionally the PMECC header can be written by the atmelimage target. The > parameters must be given via the -n switch as a coma separated list. For > example: > > mkimage -T atmelimage \ > -n usePmecc=1,sectorPerPage=4,sectorSize=512,spareSize=64,eccBits=4,eccOffset=36 \ > -d spl/u-boot-spl.bin boot.bin > > A provided image can be checked for correct header setup. It prints out the > PMECC header parameters if it has one and the 6'th interrupt vector content. > > ---8<--- > Image Type: ATMEL ROM-Boot Image with PMECC Header > PMECC header > ==================== > eccOffset: 36 > sectorSize: 512 > eccBitReq: 4 > spareSize: 64 > nbSectorPerPage: 4 > usePmecc: 1 > ==================== > 6'th vector has 17044 set > --->8--- > > A SPL binary modified with the atmelimage mkimage target was succesfully > booted on a sama5d34ek via MMC and NAND. > > Signed-off-by: Andreas Bie?mann > Cc: Bo Shen > Cc: Heiko Schocher Thanks for your great work. For the whole patch set: Tested-by: Bo Shen Acked-by: Bo Shen > --- > > Changes in v3: > * remove check for 'usePmecc=y' > > Changes in v2: > * do not check filesize in atmelimage > * add PMECC header generation and printout > * add printout of 6'th vector > > common/image.c | 1 + > include/image.h | 1 + > tools/Makefile | 1 + > tools/atmelimage.c | 342 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > tools/imagetool.c | 2 + > tools/imagetool.h | 1 + > 6 files changed, 348 insertions(+) > create mode 100644 tools/atmelimage.c > > diff --git a/common/image.c b/common/image.c > index fcc5a9c..7cb0bd7 100644 > --- a/common/image.c > +++ b/common/image.c > @@ -139,6 +139,7 @@ static const table_entry_t uimage_type[] = { > { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, > { IH_TYPE_UBLIMAGE, "ublimage", "Davinci UBL image",}, > { IH_TYPE_MXSIMAGE, "mxsimage", "Freescale MXS Boot Image",}, > + { IH_TYPE_ATMELIMAGE, "atmelimage", "ATMEL ROM-Boot Image",}, > { -1, "", "", }, > }; > > diff --git a/include/image.h b/include/image.h > index b278778..9c3b9b8 100644 > --- a/include/image.h > +++ b/include/image.h > @@ -225,6 +225,7 @@ struct lmb; > #define IH_TYPE_PBLIMAGE 15 /* Freescale PBL Boot Image */ > #define IH_TYPE_MXSIMAGE 16 /* Freescale MXSBoot Image */ > #define IH_TYPE_GPIMAGE 17 /* TI Keystone GPHeader Image */ > +#define IH_TYPE_ATMELIMAGE 18 /* ATMEL ROM bootable Image */ > > /* > * Compression Types > diff --git a/tools/Makefile b/tools/Makefile > index 6e43a01..421ff50 100644 > --- a/tools/Makefile > +++ b/tools/Makefile > @@ -69,6 +69,7 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o rsa-verify.o rsa-checksum.o > > # common objs for dumpimage and mkimage > dumpimage-mkimage-objs := aisimage.o \ > + atmelimage.o \ > $(FIT_SIG_OBJS-y) \ > crc32.o \ > default_image.o \ > diff --git a/tools/atmelimage.c b/tools/atmelimage.c > new file mode 100644 > index 0000000..c8101d2 > --- /dev/null > +++ b/tools/atmelimage.c > @@ -0,0 +1,342 @@ > +/* > + * (C) Copyright 2014 > + * Andreas Bie?mann > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include "imagetool.h" > +#include "mkimage.h" > + > +#include > + > +#define pr_err(fmt, args...) fprintf(stderr, "atmelimage Error: " fmt, ##args) > + > +static int atmel_check_image_type(uint8_t type) > +{ > + if (type == IH_TYPE_ATMELIMAGE) > + return EXIT_SUCCESS; > + else > + return EXIT_FAILURE; > +} > + > +static uint32_t nand_pmecc_header[52]; > + > +/* > + * A helper struct for parsing the mkimage -n parameter > + * > + * Keep in same order as the configs array! > + */ > +static struct pmecc_config { > + int use_pmecc; > + int sector_per_page; > + int spare_size; > + int ecc_bits; > + int sector_size; > + int ecc_offset; > +} pmecc; > + > +/* > + * Strings used for configure the PMECC header via -n mkimage switch > + * > + * We estimate a coma separated list of key=value pairs. The mkimage -n > + * parameter argument should not contain any whitespace. > + * > + * Keep in same order as struct pmecc_config! > + */ > +static const char * const configs[] = { > + "usePmecc", > + "sectorPerPage", > + "spareSize", > + "eccBits", > + "sectorSize", > + "eccOffset" > +}; > + > +static int atmel_find_pmecc_parameter_in_token(const char *token) > +{ > + size_t pos; > + char *param; > + > + debug("token: '%s'\n", token); > + > + for (pos = 0; pos < ARRAY_SIZE(configs); pos++) { > + if (strncmp(token, configs[pos], strlen(configs[pos])) == 0) { > + param = strstr(token, "="); > + if (!param) > + goto err; > + > + param++; > + debug("\t%s parameter: '%s'\n", configs[pos], param); > + > + switch (pos) { > + case 0: > + pmecc.use_pmecc = strtol(param, NULL, 10); > + return EXIT_SUCCESS; > + case 1: > + pmecc.sector_per_page = strtol(param, NULL, 10); > + return EXIT_SUCCESS; > + case 2: > + pmecc.spare_size = strtol(param, NULL, 10); > + return EXIT_SUCCESS; > + case 3: > + pmecc.ecc_bits = strtol(param, NULL, 10); > + return EXIT_SUCCESS; > + case 4: > + pmecc.sector_size = strtol(param, NULL, 10); > + return EXIT_SUCCESS; > + case 5: > + pmecc.ecc_offset = strtol(param, NULL, 10); > + return EXIT_SUCCESS; > + } > + } > + } > + > +err: > + pr_err("Could not find parameter in token '%s'\n", token); > + return EXIT_FAILURE; > +} > + > +static int atmel_parse_pmecc_params(char *txt) > +{ > + char *token; > + > + token = strtok(txt, ","); > + while (token != NULL) { > + if (atmel_find_pmecc_parameter_in_token(token)) > + return EXIT_FAILURE; > + > + token = strtok(NULL, ","); > + } > + > + return EXIT_SUCCESS; > +} > + > +static int atmel_verify_header(unsigned char *ptr, int image_size, > + struct image_tool_params *params) > +{ > + uint32_t *ints = (uint32_t *)ptr; > + size_t pos; > + size_t size = image_size; > + > + /* check if we have an PMECC header attached */ > + for (pos = 0; pos < ARRAY_SIZE(nand_pmecc_header); pos++) > + if (ints[pos] >> 28 != 0xC) > + break; > + > + if (pos == ARRAY_SIZE(nand_pmecc_header)) { > + ints += ARRAY_SIZE(nand_pmecc_header); > + size -= sizeof(nand_pmecc_header); > + } > + > + /* check the seven interrupt vectors of binary */ > + for (pos = 0; pos < 7; pos++) { > + debug("atmelimage: interrupt vector #%d is 0x%08X\n", pos+1, > + ints[pos]); > + /* > + * all vectors except the 6'th one must contain valid > + * LDR or B Opcode > + */ > + if (pos == 5) > + /* 6'th vector has image size set, check later */ > + continue; > + if ((ints[pos] & 0xff000000) == 0xea000000) > + /* valid B Opcode */ > + continue; > + if ((ints[pos] & 0xfffff000) == 0xe59ff000) > + /* valid LDR (I=0, P=1, U=1, B=0, W=0, L=1) */ > + continue; > + /* ouch, one of the checks has missed ... */ > + return 1; > + } > + > + return ints[5] != cpu_to_le32(size); > +} > + > +static void atmel_print_pmecc_header(const uint32_t word) > +{ > + int val; > + > + printf("\t\tPMECC header\n"); > + > + printf("\t\t====================\n"); > + > + val = (word >> 18) & 0x1ff; > + printf("\t\teccOffset: %9i\n", val); > + > + val = (((word >> 16) & 0x3) == 0) ? 512 : 1024; > + printf("\t\tsectorSize: %8i\n", val); > + > + if (((word >> 13) & 0x7) <= 2) > + val = (2 << ((word >> 13) & 0x7)); > + else > + val = (12 << (((word >> 13) & 0x7) - 3)); > + printf("\t\teccBitReq: %9i\n", val); > + > + val = (word >> 4) & 0x1ff; > + printf("\t\tspareSize: %9i\n", val); > + > + val = (1 << ((word >> 1) & 0x3)); > + printf("\t\tnbSectorPerPage: %3i\n", val); > + > + printf("\t\tusePmecc: %10i\n", word & 0x1); > + printf("\t\t====================\n"); > +} > + > +static void atmel_print_header(const void *ptr) > +{ > + uint32_t *ints = (uint32_t *)ptr; > + size_t pos; > + > + /* check if we have an PMECC header attached */ > + for (pos = 0; pos < ARRAY_SIZE(nand_pmecc_header); pos++) > + if (ints[pos] >> 28 != 0xC) > + break; > + > + if (pos == ARRAY_SIZE(nand_pmecc_header)) { > + printf("Image Type:\tATMEL ROM-Boot Image with PMECC Header\n"); > + atmel_print_pmecc_header(ints[0]); > + pos += 5; > + } else { > + printf("Image Type:\tATMEL ROM-Boot Image without PMECC Header\n"); > + pos = 5; > + } > + printf("\t\t6'th vector has %u set\n", le32_to_cpu(ints[pos])); > +} > + > +static void atmel_set_header(void *ptr, struct stat *sbuf, int ifd, > + struct image_tool_params *params) > +{ > + /* just save the image size into 6'th interrupt vector */ > + uint32_t *ints = (uint32_t *)ptr; > + size_t cnt; > + size_t pos = 5; > + size_t size = sbuf->st_size; > + > + for (cnt = 0; cnt < ARRAY_SIZE(nand_pmecc_header); cnt++) > + if (ints[cnt] >> 28 != 0xC) > + break; > + > + if (cnt == ARRAY_SIZE(nand_pmecc_header)) { > + pos += ARRAY_SIZE(nand_pmecc_header); > + size -= sizeof(nand_pmecc_header); > + } > + > + ints[pos] = cpu_to_le32(size); > +} > + > +static int atmel_check_params(struct image_tool_params *params) > +{ > + if (strlen(params->imagename) > 0) > + if (atmel_parse_pmecc_params(params->imagename)) > + return EXIT_FAILURE; > + > + return !(!params->eflag && > + !params->fflag && > + !params->xflag && > + ((params->dflag && !params->lflag) || > + (params->lflag && !params->dflag))); > +} > + > +static int atmel_vrec_header(struct image_tool_params *params, > + struct image_type_params *tparams) > +{ > + uint32_t tmp; > + size_t pos; > + > + if (strlen(params->imagename) == 0) > + return EXIT_SUCCESS; > + > + tmp = 0xC << 28; > + > + tmp |= (pmecc.ecc_offset & 0x1ff) << 18; > + > + switch (pmecc.sector_size) { > + case 512: > + tmp |= 0 << 16; > + break; > + case 1024: > + tmp |= 1 << 16; > + break; > + > + default: > + pr_err("Wrong sectorSize (%i) for PMECC header\n", > + pmecc.sector_size); > + return EXIT_FAILURE; > + } > + > + switch (pmecc.ecc_bits) { > + case 2: > + tmp |= 0 << 13; > + break; > + case 4: > + tmp |= 1 << 13; > + break; > + case 8: > + tmp |= 2 << 13; > + break; > + case 12: > + tmp |= 3 << 13; > + break; > + case 24: > + tmp |= 4 << 13; > + break; > + > + default: > + pr_err("Wrong eccBits (%i) for PMECC header\n", > + pmecc.ecc_bits); > + return EXIT_FAILURE; > + } > + > + tmp |= (pmecc.spare_size & 0x1ff) << 4; > + > + switch (pmecc.sector_per_page) { > + case 1: > + tmp |= 0 << 1; > + break; > + case 2: > + tmp |= 1 << 1; > + break; > + case 4: > + tmp |= 2 << 1; > + break; > + case 8: > + tmp |= 3 << 1; > + break; > + > + default: > + pr_err("Wrong sectorPerPage (%i) for PMECC header\n", > + pmecc.sector_per_page); > + return EXIT_FAILURE; > + } > + > + if (pmecc.use_pmecc) > + tmp |= 1; > + > + for (pos = 0; pos < ARRAY_SIZE(nand_pmecc_header); pos++) > + nand_pmecc_header[pos] = tmp; > + > + debug("PMECC header filled 52 times with 0x%08X\n", tmp); > + > + tparams->header_size = sizeof(nand_pmecc_header); > + tparams->hdr = nand_pmecc_header; > + > + return EXIT_SUCCESS; > +} > + > +static struct image_type_params atmelimage_params = { > + .name = "ATMEL ROM-Boot Image support", > + .header_size = 0, > + .hdr = NULL, > + .check_image_type = atmel_check_image_type, > + .verify_header = atmel_verify_header, > + .print_header = atmel_print_header, > + .set_header = atmel_set_header, > + .check_params = atmel_check_params, > + .vrec_header = atmel_vrec_header, > +}; > + > +void init_atmel_image_type(void) > +{ > + register_image_type(&atmelimage_params); > +} > diff --git a/tools/imagetool.c b/tools/imagetool.c > index da72115..32d6278 100644 > --- a/tools/imagetool.c > +++ b/tools/imagetool.c > @@ -27,6 +27,8 @@ void register_image_tool(imagetool_register_t image_register) > */ > register_func = image_register; > > + /* Init ATMEL ROM Boot Image generation/list support */ > + init_atmel_image_type(); > /* Init Freescale PBL Boot image generation/list support */ > init_pbl_image_type(); > /* Init Kirkwood Boot image generation/list support */ > diff --git a/tools/imagetool.h b/tools/imagetool.h > index a3e9d30..c480687 100644 > --- a/tools/imagetool.h > +++ b/tools/imagetool.h > @@ -159,6 +159,7 @@ void register_image_type(struct image_type_params *tparams); > * Supported image types init functions > */ > void init_default_image_type(void); > +void init_atmel_image_type(void); > void init_pbl_image_type(void); > void init_ais_image_type(void); > void init_kwb_image_type(void); >