[U-Boot] [PATCH v3 1/3] mkimage: add atmelimage
Bo Shen
voice.shen at atmel.com
Tue May 20 03:42:59 CEST 2014
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 at googlemail.com>
> Cc: Bo Shen <voice.shen at atmel.com>
> Cc: Heiko Schocher <hs at denx.de>
Thanks for your great work.
For the whole patch set:
Tested-by: Bo Shen <voice.shen at atmel.com>
Acked-by: Bo Shen <voice.shen at 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 at 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);
>
More information about the U-Boot
mailing list