[U-Boot] [PATCH v3] socfpga: Add a signer that is integrated into mkimage

This adds a signer for the socfpga preloader built from SPL.
Instead of using the arcane Altera signing tool, this automatically creates a signed version of the SPL in the u-boot root directory.
Changes since previous submissions: * This version is integrated into mkimage, with image type socfpgaimage. * This version passes checkpatch too :-)
Signed-off-by: Charles Manning cdhmanning@gmail.com --- common/image.c | 1 + include/image.h | 1 + spl/Makefile | 8 ++ tools/Makefile | 2 + tools/mkimage.c | 2 + tools/mkimage.h | 1 + tools/socfpgaimage.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 363 insertions(+) create mode 100644 tools/socfpgaimage.c
diff --git a/common/image.c b/common/image.c index 95498e6..1a2e107 100644 --- a/common/image.c +++ b/common/image.c @@ -144,6 +144,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_INVALID, NULL, "Invalid Image", }, { IH_TYPE_MULTI, "multi", "Multi-File Image", }, { IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",}, + { IH_TYPE_SOCFPGAIMAGE, "socfpgaimage", "Altera SOCFPGA preloader",}, { IH_TYPE_PBLIMAGE, "pblimage", "Freescale PBL Boot Image",}, { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, { IH_TYPE_SCRIPT, "script", "Script", }, diff --git a/include/image.h b/include/image.h index f5adc50..95a0bf7 100644 --- a/include/image.h +++ b/include/image.h @@ -166,6 +166,7 @@ #define IH_TYPE_AISIMAGE 13 /* TI Davinci AIS Image */ #define IH_TYPE_KERNEL_NOLOAD 14 /* OS Kernel Image, can run from any load address */ #define IH_TYPE_PBLIMAGE 15 /* Freescale PBL Boot Image */ +#define IH_TYPE_SOCFPGAIMAGE 16 /* Altera SOCFPGA Preloader Image */
/* * Compression Types diff --git a/spl/Makefile b/spl/Makefile index c0abe3d..8f061b0 100644 --- a/spl/Makefile +++ b/spl/Makefile @@ -144,8 +144,12 @@ $(OBJTREE)/MLO: $(obj)u-boot-spl.bin
$(OBJTREE)/MLO.byteswap: $(obj)u-boot-spl.bin $(OBJTREE)/tools/mkimage -T omapimage -n byteswap \ + -a $(CONFIG_SPL_TEXT_BASE) -d $< $@
+$(OBJTREE)/socfpga-signed-preloader.bin: $(obj)u-boot-spl.bin + $(OBJTREE)/tools/mkimage -T socfpgaimage -d $< $@ + ifneq ($(CONFIG_IMX_CONFIG),) $(OBJTREE)/SPL: $(obj)u-boot-spl.bin $(OBJTREE)/tools/mkimage -n $(SRCTREE)/$(CONFIG_IMX_CONFIG) -T imximage \ @@ -154,6 +158,10 @@ endif
ALL-y += $(obj)u-boot-spl.bin
+ifdef CONFIG_SOCFPGA +ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin +endif + ifdef CONFIG_SAMSUNG ALL-y += $(obj)$(BOARD)-spl.bin endif diff --git a/tools/Makefile b/tools/Makefile index 686840a..52f4bfc 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -95,6 +95,7 @@ NOPED_OBJ_FILES-y += kwbimage.o NOPED_OBJ_FILES-y += pblimage.o NOPED_OBJ_FILES-y += imximage.o NOPED_OBJ_FILES-y += omapimage.o +NOPED_OBJ_FILES-y += socfpgaimage.o NOPED_OBJ_FILES-y += mkenvimage.o NOPED_OBJ_FILES-y += mkimage.o OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o @@ -214,6 +215,7 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(obj)mkimage.o \ $(obj)os_support.o \ $(obj)omapimage.o \ + $(obj)socfpgaimage.o \ $(obj)sha1.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS) diff --git a/tools/mkimage.c b/tools/mkimage.c index e43b09f..87bacc0 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -167,6 +167,8 @@ main (int argc, char **argv) init_ubl_image_type(); /* Init Davinci AIS support */ init_ais_image_type(); + /* Init Altera SOCFPGA image generation/list support */ + init_socfpga_image_type();
params.cmdname = *argv; params.addr = params.ep = 0; diff --git a/tools/mkimage.h b/tools/mkimage.h index ea45f5c..eda4832 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -157,5 +157,6 @@ void init_default_image_type (void); void init_fit_image_type (void); void init_ubl_image_type(void); void init_omap_image_type(void); +void init_socfpga_image_type(void);
#endif /* _MKIIMAGE_H_ */ diff --git a/tools/socfpgaimage.c b/tools/socfpgaimage.c new file mode 100644 index 0000000..9944c78 --- /dev/null +++ b/tools/socfpgaimage.c @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2014 Charles Manning cdhmanning@gmail.com + * + * Use as you see fit. + * + * Reference doc http://www.altera.com.cn/literature/hb/cyclone-v/cv_5400A.pdf + * Note this doc is not entirely accurate. + * + * "Header" is a structure of the following format. + * this is positioned at 0x40. + * + * Endian is LSB. + * + * Offset Length Usage + * ----------------------- + * 0 4 Validation word 0x31305341 + * 4 1 Version (whatever, zero is fine) + * 5 1 Flags (unused, zero is fine) + * 6 2 Length (in units of u32, including the end checksum). + * 8 2 Zero + * 0x0A 2 Checksum over the heder. NB Not CRC32 + * + * At the end of the code we have a 32-bit CRC checksum over whole binary + * excluding the CRC. + * + * This uses the CRC32 calc out of the well known Apple + * crc32.c code. Copyright for the CRC code: + * + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + * + */ + +#include "mkimage.h" +#include <image.h> + +#define HEADER_OFFSET 0x40 +#define HEADER_SIZE 0x0C +#define BUFFER_SIZE (0x10000) +#define MAX_IMAGE_SIZE 0xFF00 +#define VALIDATION_WORD 0x31305341 +#define FILL_BYTE 0x00 +#define PADDED_SIZE (0x10000) + + +static uint8_t buffer[PADDED_SIZE]; + +static uint16_t hdr_checksum(const uint8_t *buf, int len) +{ + uint16_t ret = 0; + int i; + + for (i = 0; i < len; i++) { + ret += (((uint16_t) *buf) & 0xff); + buf++; + } + return ret; +} + + +static void le16(uint8_t *buf, uint16_t v) +{ + buf[0] = (v >> 0) & 0xff; + buf[1] = (v >> 8) & 0xff; +} + +static void le32(uint8_t *buf, uint32_t v) +{ + buf[0] = (v >> 0) & 0xff; + buf[1] = (v >> 8) & 0xff; + buf[2] = (v >> 16) & 0xff; + buf[3] = (v >> 24) & 0xff; +} + +static uint16_t get_le16(const uint8_t *buf) +{ + uint16_t retval; + + retval = (((uint16_t) buf[0]) << 0) | + (((uint16_t) buf[1]) << 8); + return retval; +} + +static uint32_t get_le32(const uint8_t *buf) +{ + uint32_t retval; + + retval = (((uint32_t) buf[0]) << 0) | + (((uint32_t) buf[1]) << 8) | + (((uint32_t) buf[2]) << 16) | + (((uint32_t) buf[3]) << 24); + return retval; +} + +static int align4(int v) +{ + return ((v + 3) / 4) * 4; +} + +static void build_header(uint8_t *buf, + uint8_t version, + uint8_t flags, + uint16_t length_bytes) +{ + memset(buf, 0, HEADER_SIZE); + + le32(buf + 0, VALIDATION_WORD); + buf[4] = version; + buf[5] = flags; + le16(buf + 6, length_bytes/4); + le16(buf + 10, hdr_checksum(buf, 10)); +} + +static int verify_header(const uint8_t *buf) +{ + + if (get_le32(buf) != VALIDATION_WORD) + return -1; + if (get_le16(buf + 10) != hdr_checksum(buf, 10)) + return -1; + + return get_le16(buf+6) * 4; +} + +static uint32_t crc_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +uint32_t local_crc32(uint32_t crc, const void *_buf, int length) +{ + const uint8_t *buf = _buf; + + crc ^= ~0; + + while (length--) { + crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *buf) & 0xff]; + buf++; + } + + crc ^= ~0; + + return crc; +} + +static int sign_buffer(uint8_t *buf, + uint8_t version, uint8_t flags, + int len, int pad_64k) +{ + uint32_t crcval; + + /* Align the length up */ + len = align4(len); + + /* Build header, adding 4 bytes to length to hold the CRC32. */ + build_header(buf + HEADER_OFFSET, version, flags, len + 4); + + crcval = local_crc32(0, buf, len); + + le32(buf + len, crcval); + + if (!pad_64k) + return len + 4; + + return PADDED_SIZE; +} + +static int verify_buffer(const uint8_t *buf) +{ + int len; /* Including 32bit CRC */ + uint32_t crccalc; + + len = verify_header(buf + HEADER_OFFSET); + if (len < 0) + return -1; + if (len < HEADER_OFFSET || len > PADDED_SIZE) + return -1; + + /* Adjust length, removing CRC */ + len -= 4; + + crccalc = local_crc32(0, buf, len); + + if (get_le32(buf + len) != crccalc) + return -1; + + return 0; +} + + +static int socfpgaimage_verify_header(unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + if (image_size != PADDED_SIZE) + return -1; + + return verify_buffer(ptr); +} + +static void socfpgaimage_print_header(const void *ptr) +{ + if (verify_buffer(ptr) == 0) + printf("Looks like a sane SOCFPGA preloader\n"); + else + printf("Not a sane SOCFPGA preloader\n"); +} + +int socfpgaimage_check_params(struct mkimage_params *params) +{ + /* Not sure if we should be accepting fflags */ + return (params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag)); +} + +static int socfpgaimage_check_image_types(uint8_t type) +{ + if (type == IH_TYPE_SOCFPGAIMAGE) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +/* To work in with the mkimage framework, we do some ugly stuff... + * + * First we prepend a fake header big enough to make the file 64k. + * When set_header is called, we fix this up by moving the image + * around in the buffer. + */ + +static int data_size; +#define fake_header_size (PADDED_SIZE - data_size) + +/* Use vrec_header to set up the fake header */ + +static int socfpgaimage_vrec_header(struct mkimage_params *params, + struct image_type_params *tparams) +{ + struct stat sbuf; + + if (!params->datafile || stat(params->datafile, &sbuf) < 0) + return 0; + + data_size = sbuf.st_size; + tparams->header_size = fake_header_size; + + return fake_header_size; +} + +static void socfpgaimage_set_header(void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + uint8_t *buf = (uint8_t *)ptr; + + /* At this stage we have the header_size dummy bytes followed by + * PADDED_SIZE-header_size image bytes. + * We need to fix the buffer by moving the image bytes back to + * the beginning of the buffer, then actually do the signing stuff... + */ + memmove(buf, buf + fake_header_size, data_size); + memset(buf + data_size, 0, fake_header_size); + + sign_buffer(buf, 0, 0, data_size, 0); + +} + +/* + * socfpgaimage parameters + */ +static struct image_type_params socfpgaimage_params = { + .name = "Altera SOCFPGA preloader support", + .vrec_header = socfpgaimage_vrec_header, + .header_size = 0, + .hdr = (void *)buffer, + .check_image_type = socfpgaimage_check_image_types, + .verify_header = socfpgaimage_verify_header, + .print_header = socfpgaimage_print_header, + .set_header = socfpgaimage_set_header, + .check_params = socfpgaimage_check_params, +}; + +void init_socfpga_image_type(void) +{ + mkimage_register(&socfpgaimage_params); +} +

Dear Charles,
would you please start following the established rules? Especially after having been asked before to to so?
In http://article.gmane.org/gmane.comp.boot-loaders.u-boot/180904 I asked you:
| Would you please read [1] and especially [2], the section about | posting modified versions of patches ? | | You are posting multiple patches with the same subject but different | content. Do you think we have time to figure out what might be the | difference? Please make sure to include a version tagin the Subject: | line, and to add a history oof changes in the comment section. | | And - do you think that "This one passes checkpatch too :-)" is a | helpful and descriptive commit message? [No, it is not.] | | [1] http://www.denx.de/wiki/U-Boot/Patches | [2] http://www.denx.de/wiki/view/U-Boot/Patches#Sending_updated_patch_versions
In message 1393114104-7301-1-git-send-email-cdhmanning@gmail.com you wrote:
This adds a signer for the socfpga preloader built from SPL.
Instead of using the arcane Altera signing tool, this automatically creates a signed version of the SPL in the u-boot root directory.
Changes since previous submissions:
- This version is integrated into mkimage, with image type socfpgaimage.
- This version passes checkpatch too :-)
This belongs into the comment section, i. e. below the "---" line.
Signed-off-by: Charles Manning cdhmanning@gmail.com
This is the place where comments go.
--- a/common/image.c +++ b/common/image.c @@ -144,6 +144,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_INVALID, NULL, "Invalid Image", }, { IH_TYPE_MULTI, "multi", "Multi-File Image", }, { IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",},
- { IH_TYPE_SOCFPGAIMAGE, "socfpgaimage", "Altera SOCFPGA preloader",}, { IH_TYPE_PBLIMAGE, "pblimage", "Freescale PBL Boot Image",}, { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, { IH_TYPE_SCRIPT, "script", "Script", },
I asked before:
| Please always keep such lists sorted.
Why do you ignore review comments?
+++ b/spl/Makefile @@ -144,8 +144,12 @@ $(OBJTREE)/MLO: $(obj)u-boot-spl.bin
$(OBJTREE)/MLO.byteswap: $(obj)u-boot-spl.bin $(OBJTREE)/tools/mkimage -T omapimage -n byteswap \
- -a $(CONFIG_SPL_TEXT_BASE) -d $< $@
Me and Gerhard have asked you about this. Is this eve working? I doubt that. But you ignore all such comments.
+ifdef CONFIG_SOCFPGA +ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin +endif
I commented on this - you ignored it.
@@ -95,6 +95,7 @@ NOPED_OBJ_FILES-y += kwbimage.o NOPED_OBJ_FILES-y += pblimage.o NOPED_OBJ_FILES-y += imximage.o NOPED_OBJ_FILES-y += omapimage.o +NOPED_OBJ_FILES-y += socfpgaimage.o NOPED_OBJ_FILES-y += mkenvimage.o NOPED_OBJ_FILES-y += mkimage.o OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o
I commented on this - you ignored it.
@@ -214,6 +215,7 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(obj)mkimage.o \ $(obj)os_support.o \ $(obj)omapimage.o \
$(obj)socfpgaimage.o \ $(obj)sha1.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS)
I commented on this - you ignored it.
...
- Note this doc is not entirely accurate.
I asked for more information which parts of the doc are not correct. You ignored this.
- This uses the CRC32 calc out of the well known Apple
- crc32.c code. Copyright for the CRC code:
- COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- code or tables extracted from it, as desired without restriction.
Many more ignored review comments folow.
Sorry, but this is not the way how code reviews are supposed to work.
NAK!!!
Wolfgang Denk

Hello All, but mainly a message to Wolfgang and Gerhard.
I would like to apologise for my recent flurry of postings causing some confusion and gnashing of teeth.
I only read some of the comments (relating to adding a version number on the patch). I had read that far then assumed the patch had already been NAKed at that point and did not read further.
I shall now read all the comments from Wolfgang and Gerhard again and resubmit another version which I hope is closer to the mark.
Thank you for my ongoing education.
Regards
Charles
participants (2)
-
Charles Manning
-
Wolfgang Denk