
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);