Message ID | 1400502221-6955-2-git-send-email-andreas.devel@googlemail.com |
---|---|
State | Accepted, archived |
Delegated to: | Andreas Bießmann |
Headers | show |
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 <andreas.devel@googlemail.com> > Cc: Bo Shen <voice.shen@atmel.com> > Cc: Heiko Schocher <hs@denx.de> Thanks for your great work. For the whole patch set: Tested-by: Bo Shen <voice.shen@atmel.com> Acked-by: Bo Shen <voice.shen@atmel.com> > --- > > 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 <andreas.devel@googlemail.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include "imagetool.h" > +#include "mkimage.h" > + > +#include <image.h> > + > +#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); >
Dear Andreas Bießmann, Andreas Bießmann <andreas.devel@googlemail.com> writes: >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 <andreas.devel@googlemail.com> >Cc: Bo Shen <voice.shen@atmel.com> >Cc: Heiko Schocher <hs@denx.de> >Tested-by: Bo Shen <voice.shen@atmel.com> >Acked-by: Bo Shen <voice.shen@atmel.com> > >--- >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 applied to u-boot-atmel/master, thanks! Best regards, Andreas Bießmann
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 <andreas.devel@googlemail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "imagetool.h" +#include "mkimage.h" + +#include <image.h> + +#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);
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 <andreas.devel@googlemail.com> Cc: Bo Shen <voice.shen@atmel.com> Cc: Heiko Schocher <hs@denx.de> --- 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