[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