[PATCH u-boot-marvell 0/7] tools: kwbimage: Support for parsing extended v0 format

This patch series extends kwbimage v0 format support by providing ability to dump content of Dove boot images (extension of v0 format). It also fixes recognition of these images in kwboot utility (as it uses macros and inline functions from kwbimage.h header file).
Implementation is based on 88AP510 Functional Specifications, Chapter 5.2 Boot Image Format, which is publicly available at: https://web.archive.org/web/20120130172443/https://www.marvell.com/applicati...
Printing information about image.kwb is possible by:
$ ./tools/dumpimage -l image.kwb
Dumping image.kwb is possible by commands:
$ ./tools/dumpimage -T kwbimage -p -1 -o image.cfg image.kwb $ ./tools/dumpimage -T kwbimage -p 0 -o data.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 1 -o binary1.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 2 -o binary2.bin image.kwb ... (where -p N is Nth binary executable header, e.g. SPL)
Dove images contains more sections which in config file begins with line "MATCH ADDRESS 0xaddr MASK 0xmask VALUE 0xval" and means that section is executed only when check ((readl(addr) & mask) == (val & mask)) passes.
Support for generating these kind of images is not provided. I hope that this patch series helps somebody else to implement it.
Pali Rohár (7): tools: kwbimage: Define structures for extended kwbimage v0 headers tools: kwbimage: Fix calculating size of kwbimage v0 header tools: kwbimage: Add support for dumping extended and binary v0 headers tools: kwbimage: Do not show mkimage error message in dumpimage tools: kwbimage: Add support for NAND_BLKSZ and NAND_BADBLK_LOCATION for v0 images tools: kwbimage: Fix help how to extract DDR3 training code tools: kwbimage: Add me as an author of kwbimage
tools/kwbimage.c | 139 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 116 +++++++++++++++++++++++++++++++++++---- 2 files changed, 231 insertions(+), 24 deletions(-)

They are used by Marvell Dove 88AP510 BootROM.
After the main header is a list of optional extended headers and after that is a list of optional binary executable headers. Between each two extended headers is additional 0x20 byte long padding.
Original Kirkwood SoCs support only one extended header and no binary executable header.
Extension of struct ext_hdr_v0 is backward compatible with the old definition. Only reserved[] fields are changed.
Signed-off-by: Pali Rohár pali@kernel.org --- tools/kwbimage.h | 51 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 9ebc7d72d363..706bebddf4fa 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -48,9 +48,13 @@ struct main_hdr_v0 { uint32_t destaddr; /* 0x10-0x13 */ uint32_t execaddr; /* 0x14-0x17 */ uint8_t satapiomode; /* 0x18 */ - uint8_t rsvd3; /* 0x19 */ + uint8_t nandblocksize; /* 0x19 */ + union { + uint8_t nandbadblklocation; /* 0x1A */ uint16_t ddrinitdelay; /* 0x1A-0x1B */ - uint16_t rsvd2; /* 0x1C-0x1D */ + }; + uint8_t rsvd2; /* 0x1C */ + uint8_t bin; /* 0x1D */ uint8_t ext; /* 0x1E */ uint8_t checksum; /* 0x1F */ } __packed; @@ -60,14 +64,43 @@ struct ext_hdr_v0_reg { uint32_t rdata; } __packed;
-#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg)) - +/* Structure of the extension header, version 0 (Kirkwood, Dove) */ struct ext_hdr_v0 { - uint32_t offset; - uint8_t reserved[0x20 - sizeof(uint32_t)]; - struct ext_hdr_v0_reg rcfg[EXT_HDR_V0_REG_COUNT]; - uint8_t reserved2[7]; - uint8_t checksum; + /* + * Beware that extension header offsets specified in 88AP510 Functional + * Specifications are relative to the start of the main header, not to + * the start of the extension header itself. + */ + uint32_t offset; /* 0x0-0x3 */ + uint8_t rsvd1[8]; /* 0x4-0xB */ + uint32_t enddelay; /* 0xC-0xF */ + uint32_t match_addr; /* 0x10-0x13 */ + uint32_t match_mask; /* 0x14-0x17 */ + uint32_t match_value; /* 0x18-0x1B */ + uint8_t ddrwritetype; /* 0x1C */ + uint8_t ddrresetmpp; /* 0x1D */ + uint8_t ddrclkenmpp; /* 0x1E */ + uint8_t ddrinitdelay; /* 0x1F */ + struct ext_hdr_v0_reg rcfg[55]; /* 0x20-0x1D7 */ + uint8_t rsvd2[7]; /* 0x1D8-0x1DE */ + uint8_t checksum; /* 0x1DF */ +} __packed; + +/* Structure of the binary code header, version 0 (Dove) */ +struct bin_hdr_v0 { + uint32_t match_addr; /* 0x00-0x03 */ + uint32_t match_mask; /* 0x04-0x07 */ + uint32_t match_value; /* 0x08-0x0B */ + uint32_t offset; /* 0x0C-0x0F */ + uint32_t destaddr; /* 0x10-0x13 */ + uint32_t size; /* 0x14-0x17 */ + uint32_t execaddr; /* 0x18-0x1B */ + uint32_t params[4]; /* 0x1C-0x2B */ + uint8_t params_flags; /* 0x2C */ + uint8_t rsvd1; /* 0x2D */ + uint8_t rsvd2; /* 0x2E */ + uint8_t checksum; /* 0x2F */ + uint8_t code[2000]; /* 0x30-0x7FF */ } __packed;
/* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */

On 2/15/22 19:59, Pali Rohár wrote:
They are used by Marvell Dove 88AP510 BootROM.
After the main header is a list of optional extended headers and after that is a list of optional binary executable headers. Between each two extended headers is additional 0x20 byte long padding.
Original Kirkwood SoCs support only one extended header and no binary executable header.
Extension of struct ext_hdr_v0 is backward compatible with the old definition. Only reserved[] fields are changed.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
tools/kwbimage.h | 51 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 9ebc7d72d363..706bebddf4fa 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -48,9 +48,13 @@ struct main_hdr_v0 { uint32_t destaddr; /* 0x10-0x13 */ uint32_t execaddr; /* 0x14-0x17 */ uint8_t satapiomode; /* 0x18 */
- uint8_t rsvd3; /* 0x19 */
- uint8_t nandblocksize; /* 0x19 */
- union {
- uint8_t nandbadblklocation; /* 0x1A */ uint16_t ddrinitdelay; /* 0x1A-0x1B */
- uint16_t rsvd2; /* 0x1C-0x1D */
- };
- uint8_t rsvd2; /* 0x1C */
- uint8_t bin; /* 0x1D */ uint8_t ext; /* 0x1E */ uint8_t checksum; /* 0x1F */ } __packed;
@@ -60,14 +64,43 @@ struct ext_hdr_v0_reg { uint32_t rdata; } __packed;
-#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg))
+/* Structure of the extension header, version 0 (Kirkwood, Dove) */ struct ext_hdr_v0 {
- uint32_t offset;
- uint8_t reserved[0x20 - sizeof(uint32_t)];
- struct ext_hdr_v0_reg rcfg[EXT_HDR_V0_REG_COUNT];
- uint8_t reserved2[7];
- uint8_t checksum;
- /*
* Beware that extension header offsets specified in 88AP510 Functional
* Specifications are relative to the start of the main header, not to
* the start of the extension header itself.
*/
- uint32_t offset; /* 0x0-0x3 */
- uint8_t rsvd1[8]; /* 0x4-0xB */
- uint32_t enddelay; /* 0xC-0xF */
- uint32_t match_addr; /* 0x10-0x13 */
- uint32_t match_mask; /* 0x14-0x17 */
- uint32_t match_value; /* 0x18-0x1B */
- uint8_t ddrwritetype; /* 0x1C */
- uint8_t ddrresetmpp; /* 0x1D */
- uint8_t ddrclkenmpp; /* 0x1E */
- uint8_t ddrinitdelay; /* 0x1F */
- struct ext_hdr_v0_reg rcfg[55]; /* 0x20-0x1D7 */
- uint8_t rsvd2[7]; /* 0x1D8-0x1DE */
- uint8_t checksum; /* 0x1DF */
+} __packed;
+/* Structure of the binary code header, version 0 (Dove) */ +struct bin_hdr_v0 {
uint32_t match_addr; /* 0x00-0x03 */
uint32_t match_mask; /* 0x04-0x07 */
uint32_t match_value; /* 0x08-0x0B */
uint32_t offset; /* 0x0C-0x0F */
uint32_t destaddr; /* 0x10-0x13 */
uint32_t size; /* 0x14-0x17 */
uint32_t execaddr; /* 0x18-0x1B */
uint32_t params[4]; /* 0x1C-0x2B */
uint8_t params_flags; /* 0x2C */
uint8_t rsvd1; /* 0x2D */
uint8_t rsvd2; /* 0x2E */
uint8_t checksum; /* 0x2F */
uint8_t code[2000]; /* 0x30-0x7FF */ } __packed;
/* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */
Viele Grüße, Stefan Roese

Extended and binary headers are optional and are part of the image header.
Fixes kwboot to determinate correct length of Dove images.
Signed-off-by: Pali Rohár pali@kernel.org --- tools/kwbimage.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 706bebddf4fa..502b6d503305 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -240,8 +240,20 @@ static inline size_t kwbheader_size(const void *header) if (kwbimage_version(header) == 0) { const struct main_hdr_v0 *hdr = header;
+ /* + * First extension header starts immediately after the main + * header without any padding. Between extension headers is + * 0x20 byte padding. There is no padding after the last + * extension header. First binary code header starts immediately + * after the last extension header (or immediately after the + * main header if there is no extension header) without any + * padding. There is no padding between binary code headers and + * neither after the last binary code header. + */ return sizeof(*hdr) + - hdr->ext ? sizeof(struct ext_hdr_v0) : 0; + hdr->ext * sizeof(struct ext_hdr_v0) + + ((hdr->ext > 1) ? ((hdr->ext - 1) * 0x20) : 0) + + hdr->bin * sizeof(struct bin_hdr_v0); } else { const struct main_hdr_v1 *hdr = header;

On 2/15/22 19:59, Pali Rohár wrote:
Extended and binary headers are optional and are part of the image header.
Fixes kwboot to determinate correct length of Dove images.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
tools/kwbimage.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 706bebddf4fa..502b6d503305 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -240,8 +240,20 @@ static inline size_t kwbheader_size(const void *header) if (kwbimage_version(header) == 0) { const struct main_hdr_v0 *hdr = header;
/*
* First extension header starts immediately after the main
* header without any padding. Between extension headers is
* 0x20 byte padding. There is no padding after the last
* extension header. First binary code header starts immediately
* after the last extension header (or immediately after the
* main header if there is no extension header) without any
* padding. There is no padding between binary code headers and
* neither after the last binary code header.
return sizeof(*hdr) +*/
hdr->ext ? sizeof(struct ext_hdr_v0) : 0;
hdr->ext * sizeof(struct ext_hdr_v0) +
((hdr->ext > 1) ? ((hdr->ext - 1) * 0x20) : 0) +
} else { const struct main_hdr_v1 *hdr = header;hdr->bin * sizeof(struct bin_hdr_v0);
Viele Grüße, Stefan Roese

dumpimage is now able to successfully parse and dump content of the Dove bootloader image.
Note that support for generating these extended parts of v0 images is not included yet.
Signed-off-by: Pali Rohár pali@kernel.org --- tools/kwbimage.c | 127 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 51 +++++++++++++++++++ 2 files changed, 166 insertions(+), 12 deletions(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 99d38cd1cfb2..22e6a44c561c 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -17,6 +17,8 @@ #include <stdint.h> #include "kwbimage.h"
+#include <asm-generic/bitops/fls.h> + #include <openssl/bn.h> #include <openssl/rsa.h> #include <openssl/pem.h> @@ -1898,6 +1900,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, static void kwbimage_print_header(const void *ptr) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr; + struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr;
printf("Image Type: MVEBU Boot from %s Image\n", @@ -1915,6 +1918,13 @@ static void kwbimage_print_header(const void *ptr) } }
+ for_each_bin_hdr_v0(bhdr, mhdr) { + printf("BIN Img Size: "); + genimg_print_size(le32_to_cpu(bhdr->size)); + printf("BIN Img Addr: %08x\n", le32_to_cpu(bhdr->destaddr)); + printf("BIN Img Entr: %08x\n", le32_to_cpu(bhdr->execaddr)); + } + printf("Data Size: "); genimg_print_size(mhdr->blocksize - sizeof(uint32_t)); printf("Load Address: %08x\n", mhdr->destaddr); @@ -1947,15 +1957,31 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size, /* Only version 0 extended header has checksum */ if (kwbimage_version(ptr) == 0) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr; + struct ext_hdr_v0 *ext_hdr; + struct bin_hdr_v0 *bhdr;
- if (mhdr->ext) { - struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1); - + for_each_ext_hdr_v0(ext_hdr, ptr) { csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1); if (csum != ext_hdr->checksum) return -FDT_ERR_BADSTRUCTURE; }
+ for_each_bin_hdr_v0(bhdr, ptr) { + csum = image_checksum8(bhdr, (uint8_t *)&bhdr->checksum - (uint8_t *)bhdr - 1); + if (csum != bhdr->checksum) + return -FDT_ERR_BADSTRUCTURE; + + if (bhdr->offset > sizeof(*bhdr) || bhdr->offset % 4 != 0) + return -FDT_ERR_BADSTRUCTURE; + + if (bhdr->offset + bhdr->size + 4 > sizeof(*bhdr) || bhdr->size % 4 != 0) + return -FDT_ERR_BADSTRUCTURE; + + if (image_checksum32((uint8_t *)bhdr + bhdr->offset, bhdr->size) != + *(uint32_t *)((uint8_t *)bhdr + bhdr->offset + bhdr->size)) + return -FDT_ERR_BADSTRUCTURE; + } + blockid = mhdr->blockid; offset = le32_to_cpu(mhdr->srcaddr); size = le32_to_cpu(mhdr->blocksize); @@ -2130,8 +2156,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) struct register_set_hdr_v1 *regset_hdr; struct ext_hdr_v0_reg *regdata; struct ext_hdr_v0 *ehdr0; + struct bin_hdr_v0 *bhdr0; struct opt_hdr_v1 *ohdr; + int params_count; unsigned offset; + int is_v0_ext; int cur_idx; int version; FILE *f; @@ -2145,6 +2174,14 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
version = kwbimage_version(ptr);
+ is_v0_ext = 0; + if (version == 0) { + if (mhdr0->ext > 1 || mhdr0->bin || + ((ehdr0 = ext_hdr_v0_first(ptr)) && + (ehdr0->match_addr || ehdr0->match_mask || ehdr0->match_value))) + is_v0_ext = 1; + } + if (version != 0) fprintf(f, "VERSION %d\n", version);
@@ -2156,10 +2193,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if (mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize);
- if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) { + if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize); + + if (mhdr->blockid == IBR_HDR_NAND_ID && (mhdr->nandbadblklocation != 0 || is_v0_ext)) fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation); - }
if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID) fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode); @@ -2222,8 +2260,39 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) } }
- if (version == 0 && mhdr0->ext) { - ehdr0 = (struct ext_hdr_v0 *)(mhdr0 + 1); + if (version == 0 && !is_v0_ext && le16_to_cpu(mhdr0->ddrinitdelay)) + fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay)); + + for_each_ext_hdr_v0(ehdr0, ptr) { + if (is_v0_ext) { + fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n", + le32_to_cpu(ehdr0->match_addr), + le32_to_cpu(ehdr0->match_mask), + le32_to_cpu(ehdr0->match_value)); + if (ehdr0->rsvd1[0] || ehdr0->rsvd1[1] || ehdr0->rsvd1[2] || + ehdr0->rsvd1[3] || ehdr0->rsvd1[4] || ehdr0->rsvd1[5] || + ehdr0->rsvd1[6] || ehdr0->rsvd1[7]) + fprintf(f, "#DDR_RSVD1 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + ehdr0->rsvd1[0], ehdr0->rsvd1[1], ehdr0->rsvd1[2], + ehdr0->rsvd1[3], ehdr0->rsvd1[4], ehdr0->rsvd1[5], + ehdr0->rsvd1[6], ehdr0->rsvd1[7]); + if (ehdr0->rsvd2[0] || ehdr0->rsvd2[1] || ehdr0->rsvd2[2] || + ehdr0->rsvd2[3] || ehdr0->rsvd2[4] || ehdr0->rsvd2[5] || + ehdr0->rsvd2[6]) + fprintf(f, "#DDR_RSVD2 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + ehdr0->rsvd2[0], ehdr0->rsvd2[1], ehdr0->rsvd2[2], + ehdr0->rsvd2[3], ehdr0->rsvd2[4], ehdr0->rsvd2[5], + ehdr0->rsvd2[6]); + if (ehdr0->ddrwritetype) + fprintf(f, "DDR_WRITE_TYPE %u\n", (unsigned)ehdr0->ddrwritetype); + if (ehdr0->ddrresetmpp) + fprintf(f, "DDR_RESET_MPP 0x%x\n", (unsigned)ehdr0->ddrresetmpp); + if (ehdr0->ddrclkenmpp) + fprintf(f, "DDR_CLKEN_MPP 0x%x\n", (unsigned)ehdr0->ddrclkenmpp); + if (ehdr0->ddrinitdelay) + fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)ehdr0->ddrinitdelay); + } + if (ehdr0->offset) { for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset); (uint8_t *)regdata < (uint8_t *)ptr + header_size && @@ -2234,10 +2303,38 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if ((uint8_t *)regdata != (uint8_t *)ptr + ehdr0->offset) fprintf(f, "DATA 0x0 0x0\n"); } + + if (le32_to_cpu(ehdr0->enddelay)) + fprintf(f, "DATA_DELAY %u\n", le32_to_cpu(ehdr0->enddelay)); + else if (is_v0_ext) + fprintf(f, "DATA_DELAY SDRAM_SETUP\n"); }
- if (version == 0 && le16_to_cpu(mhdr0->ddrinitdelay)) - fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay)); + cur_idx = 1; + for_each_bin_hdr_v0(bhdr0, ptr) { + fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n", + le32_to_cpu(bhdr0->match_addr), + le32_to_cpu(bhdr0->match_mask), + le32_to_cpu(bhdr0->match_value)); + + fprintf(f, "BINARY binary%d.bin", cur_idx); + params_count = fls(bhdr0->params_flags & 0xF); + for (i = 0; i < params_count; i++) + fprintf(f, " 0x%x", (bhdr0->params[i] & (1 << i)) ? bhdr0->params[i] : 0); + fprintf(f, " LOAD_ADDRESS 0x%08x", le32_to_cpu(bhdr0->destaddr)); + fprintf(f, " EXEC_ADDRESS 0x%08x", le32_to_cpu(bhdr0->execaddr)); + fprintf(f, "\n"); + + fprintf(f, "#BINARY_OFFSET 0x%x\n", le32_to_cpu(bhdr0->offset)); + fprintf(f, "#BINARY_SIZE 0x%x\n", le32_to_cpu(bhdr0->size)); + + if (bhdr0->rsvd1) + fprintf(f, "#BINARY_RSVD1 0x%x\n", (unsigned)bhdr0->rsvd1); + if (bhdr0->rsvd2) + fprintf(f, "#BINARY_RSVD2 0x%x\n", (unsigned)bhdr0->rsvd2); + + cur_idx++; + }
/* Undocumented reserved fields */
@@ -2245,9 +2342,6 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0], (unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
- if (version == 0 && mhdr0->rsvd3) - fprintf(f, "#RSVD3 0x%x\n", (unsigned)mhdr0->rsvd3); - if (version == 0 && le16_to_cpu(mhdr0->rsvd2)) fprintf(f, "#RSVD2 0x%x\n", (unsigned)le16_to_cpu(mhdr0->rsvd2));
@@ -2266,6 +2360,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params { struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr; size_t header_size = kwbheader_size(ptr); + struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr; int idx = params->pflag; int cur_idx; @@ -2312,6 +2407,14 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params
++cur_idx; } + for_each_bin_hdr_v0(bhdr, ptr) { + if (idx == cur_idx) { + image = (ulong)bhdr + bhdr->offset; + size = bhdr->size; + break; + } + ++cur_idx; + }
if (!image) { fprintf(stderr, "Argument -p %d is invalid\n", idx); diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 502b6d503305..505522332bd4 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -270,6 +270,57 @@ static inline size_t kwbheader_size_for_csum(const void *header) return kwbheader_size(header); }
+static inline struct ext_hdr_v0 *ext_hdr_v0_first(void *img) +{ + struct main_hdr_v0 *mhdr; + + if (kwbimage_version(img) != 0) + return NULL; + + mhdr = img; + if (mhdr->ext) + return (struct ext_hdr_v0 *)(mhdr + 1); + else + return NULL; +} + +static inline void *_ext_hdr_v0_end(struct main_hdr_v0 *mhdr) +{ + return (uint8_t *)mhdr + kwbheader_size(mhdr) - mhdr->bin * sizeof(struct bin_hdr_v0); +} + +static inline struct ext_hdr_v0 *ext_hdr_v0_next(void *img, struct ext_hdr_v0 *cur) +{ + if ((void *)(cur + 1) < _ext_hdr_v0_end(img)) + return (struct ext_hdr_v0 *)((uint8_t *)(cur + 1) + 0x20); + else + return NULL; +} + +#define for_each_ext_hdr_v0(ehdr, img) \ + for ((ehdr) = ext_hdr_v0_first((img)); \ + (ehdr) != NULL; \ + (ehdr) = ext_hdr_v0_next((img), (ehdr))) + +static inline struct bin_hdr_v0 *bin_hdr_v0_first(void *img) +{ + struct main_hdr_v0 *mhdr; + + if (kwbimage_version(img) != 0) + return NULL; + + mhdr = img; + if (mhdr->bin) + return _ext_hdr_v0_end(mhdr); + else + return NULL; +} + +#define for_each_bin_hdr_v0(bhdr, img) \ + for ((bhdr) = bin_hdr_v0_first((img)); \ + (bhdr) && (void *)(bhdr) < (void *)((uint8_t *)img + kwbheader_size(img)); \ + (bhdr) = (struct bin_hdr_v0 *)((bhdr))+1) + static inline uint32_t opt_hdr_v1_size(const struct opt_hdr_v1 *ohdr) { return (ohdr->headersz_msb << 16) | le16_to_cpu(ohdr->headersz_lsb);

On 2/15/22 19:59, Pali Rohár wrote:
dumpimage is now able to successfully parse and dump content of the Dove bootloader image.
Note that support for generating these extended parts of v0 images is not included yet.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
tools/kwbimage.c | 127 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 51 +++++++++++++++++++ 2 files changed, 166 insertions(+), 12 deletions(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 99d38cd1cfb2..22e6a44c561c 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -17,6 +17,8 @@ #include <stdint.h> #include "kwbimage.h"
+#include <asm-generic/bitops/fls.h>
- #include <openssl/bn.h> #include <openssl/rsa.h> #include <openssl/pem.h>
@@ -1898,6 +1900,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, static void kwbimage_print_header(const void *ptr) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr;
printf("Image Type: MVEBU Boot from %s Image\n",
@@ -1915,6 +1918,13 @@ static void kwbimage_print_header(const void *ptr) } }
- for_each_bin_hdr_v0(bhdr, mhdr) {
printf("BIN Img Size: ");
genimg_print_size(le32_to_cpu(bhdr->size));
printf("BIN Img Addr: %08x\n", le32_to_cpu(bhdr->destaddr));
printf("BIN Img Entr: %08x\n", le32_to_cpu(bhdr->execaddr));
- }
- printf("Data Size: "); genimg_print_size(mhdr->blocksize - sizeof(uint32_t)); printf("Load Address: %08x\n", mhdr->destaddr);
@@ -1947,15 +1957,31 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size, /* Only version 0 extended header has checksum */ if (kwbimage_version(ptr) == 0) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
struct ext_hdr_v0 *ext_hdr;
struct bin_hdr_v0 *bhdr;
if (mhdr->ext) {
struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1);
for_each_ext_hdr_v0(ext_hdr, ptr) { csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1); if (csum != ext_hdr->checksum) return -FDT_ERR_BADSTRUCTURE;
}
for_each_bin_hdr_v0(bhdr, ptr) {
csum = image_checksum8(bhdr, (uint8_t *)&bhdr->checksum - (uint8_t *)bhdr - 1);
if (csum != bhdr->checksum)
return -FDT_ERR_BADSTRUCTURE;
if (bhdr->offset > sizeof(*bhdr) || bhdr->offset % 4 != 0)
return -FDT_ERR_BADSTRUCTURE;
if (bhdr->offset + bhdr->size + 4 > sizeof(*bhdr) || bhdr->size % 4 != 0)
return -FDT_ERR_BADSTRUCTURE;
if (image_checksum32((uint8_t *)bhdr + bhdr->offset, bhdr->size) !=
*(uint32_t *)((uint8_t *)bhdr + bhdr->offset + bhdr->size))
return -FDT_ERR_BADSTRUCTURE;
}
blockid = mhdr->blockid; offset = le32_to_cpu(mhdr->srcaddr); size = le32_to_cpu(mhdr->blocksize);
@@ -2130,8 +2156,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) struct register_set_hdr_v1 *regset_hdr; struct ext_hdr_v0_reg *regdata; struct ext_hdr_v0 *ehdr0;
- struct bin_hdr_v0 *bhdr0; struct opt_hdr_v1 *ohdr;
- int params_count; unsigned offset;
- int is_v0_ext; int cur_idx; int version; FILE *f;
@@ -2145,6 +2174,14 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
version = kwbimage_version(ptr);
- is_v0_ext = 0;
- if (version == 0) {
if (mhdr0->ext > 1 || mhdr0->bin ||
((ehdr0 = ext_hdr_v0_first(ptr)) &&
(ehdr0->match_addr || ehdr0->match_mask || ehdr0->match_value)))
is_v0_ext = 1;
- }
- if (version != 0) fprintf(f, "VERSION %d\n", version);
@@ -2156,10 +2193,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if (mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize);
- if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) {
- if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize);
- if (mhdr->blockid == IBR_HDR_NAND_ID && (mhdr->nandbadblklocation != 0 || is_v0_ext)) fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation);
}
if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID) fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode);
@@ -2222,8 +2260,39 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) } }
- if (version == 0 && mhdr0->ext) {
ehdr0 = (struct ext_hdr_v0 *)(mhdr0 + 1);
- if (version == 0 && !is_v0_ext && le16_to_cpu(mhdr0->ddrinitdelay))
fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
- for_each_ext_hdr_v0(ehdr0, ptr) {
if (is_v0_ext) {
fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
le32_to_cpu(ehdr0->match_addr),
le32_to_cpu(ehdr0->match_mask),
le32_to_cpu(ehdr0->match_value));
if (ehdr0->rsvd1[0] || ehdr0->rsvd1[1] || ehdr0->rsvd1[2] ||
ehdr0->rsvd1[3] || ehdr0->rsvd1[4] || ehdr0->rsvd1[5] ||
ehdr0->rsvd1[6] || ehdr0->rsvd1[7])
fprintf(f, "#DDR_RSVD1 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
ehdr0->rsvd1[0], ehdr0->rsvd1[1], ehdr0->rsvd1[2],
ehdr0->rsvd1[3], ehdr0->rsvd1[4], ehdr0->rsvd1[5],
ehdr0->rsvd1[6], ehdr0->rsvd1[7]);
if (ehdr0->rsvd2[0] || ehdr0->rsvd2[1] || ehdr0->rsvd2[2] ||
ehdr0->rsvd2[3] || ehdr0->rsvd2[4] || ehdr0->rsvd2[5] ||
ehdr0->rsvd2[6])
fprintf(f, "#DDR_RSVD2 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
ehdr0->rsvd2[0], ehdr0->rsvd2[1], ehdr0->rsvd2[2],
ehdr0->rsvd2[3], ehdr0->rsvd2[4], ehdr0->rsvd2[5],
ehdr0->rsvd2[6]);
if (ehdr0->ddrwritetype)
fprintf(f, "DDR_WRITE_TYPE %u\n", (unsigned)ehdr0->ddrwritetype);
if (ehdr0->ddrresetmpp)
fprintf(f, "DDR_RESET_MPP 0x%x\n", (unsigned)ehdr0->ddrresetmpp);
if (ehdr0->ddrclkenmpp)
fprintf(f, "DDR_CLKEN_MPP 0x%x\n", (unsigned)ehdr0->ddrclkenmpp);
if (ehdr0->ddrinitdelay)
fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)ehdr0->ddrinitdelay);
}
- if (ehdr0->offset) { for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset); (uint8_t *)regdata < (uint8_t *)ptr + header_size &&
@@ -2234,10 +2303,38 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if ((uint8_t *)regdata != (uint8_t *)ptr + ehdr0->offset) fprintf(f, "DATA 0x0 0x0\n"); }
if (le32_to_cpu(ehdr0->enddelay))
fprintf(f, "DATA_DELAY %u\n", le32_to_cpu(ehdr0->enddelay));
else if (is_v0_ext)
}fprintf(f, "DATA_DELAY SDRAM_SETUP\n");
- if (version == 0 && le16_to_cpu(mhdr0->ddrinitdelay))
fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
cur_idx = 1;
for_each_bin_hdr_v0(bhdr0, ptr) {
fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
le32_to_cpu(bhdr0->match_addr),
le32_to_cpu(bhdr0->match_mask),
le32_to_cpu(bhdr0->match_value));
fprintf(f, "BINARY binary%d.bin", cur_idx);
params_count = fls(bhdr0->params_flags & 0xF);
for (i = 0; i < params_count; i++)
fprintf(f, " 0x%x", (bhdr0->params[i] & (1 << i)) ? bhdr0->params[i] : 0);
fprintf(f, " LOAD_ADDRESS 0x%08x", le32_to_cpu(bhdr0->destaddr));
fprintf(f, " EXEC_ADDRESS 0x%08x", le32_to_cpu(bhdr0->execaddr));
fprintf(f, "\n");
fprintf(f, "#BINARY_OFFSET 0x%x\n", le32_to_cpu(bhdr0->offset));
fprintf(f, "#BINARY_SIZE 0x%x\n", le32_to_cpu(bhdr0->size));
if (bhdr0->rsvd1)
fprintf(f, "#BINARY_RSVD1 0x%x\n", (unsigned)bhdr0->rsvd1);
if (bhdr0->rsvd2)
fprintf(f, "#BINARY_RSVD2 0x%x\n", (unsigned)bhdr0->rsvd2);
cur_idx++;
}
/* Undocumented reserved fields */
@@ -2245,9 +2342,6 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0], (unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
- if (version == 0 && mhdr0->rsvd3)
fprintf(f, "#RSVD3 0x%x\n", (unsigned)mhdr0->rsvd3);
- if (version == 0 && le16_to_cpu(mhdr0->rsvd2)) fprintf(f, "#RSVD2 0x%x\n", (unsigned)le16_to_cpu(mhdr0->rsvd2));
@@ -2266,6 +2360,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params { struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr; size_t header_size = kwbheader_size(ptr);
- struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr; int idx = params->pflag; int cur_idx;
@@ -2312,6 +2407,14 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params
++cur_idx; }
for_each_bin_hdr_v0(bhdr, ptr) {
if (idx == cur_idx) {
image = (ulong)bhdr + bhdr->offset;
size = bhdr->size;
break;
}
++cur_idx;
}
if (!image) { fprintf(stderr, "Argument -p %d is invalid\n", idx);
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 502b6d503305..505522332bd4 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -270,6 +270,57 @@ static inline size_t kwbheader_size_for_csum(const void *header) return kwbheader_size(header); }
+static inline struct ext_hdr_v0 *ext_hdr_v0_first(void *img) +{
- struct main_hdr_v0 *mhdr;
- if (kwbimage_version(img) != 0)
return NULL;
- mhdr = img;
- if (mhdr->ext)
return (struct ext_hdr_v0 *)(mhdr + 1);
- else
return NULL;
+}
+static inline void *_ext_hdr_v0_end(struct main_hdr_v0 *mhdr) +{
- return (uint8_t *)mhdr + kwbheader_size(mhdr) - mhdr->bin * sizeof(struct bin_hdr_v0);
+}
+static inline struct ext_hdr_v0 *ext_hdr_v0_next(void *img, struct ext_hdr_v0 *cur) +{
- if ((void *)(cur + 1) < _ext_hdr_v0_end(img))
return (struct ext_hdr_v0 *)((uint8_t *)(cur + 1) + 0x20);
- else
return NULL;
+}
+#define for_each_ext_hdr_v0(ehdr, img) \
- for ((ehdr) = ext_hdr_v0_first((img)); \
(ehdr) != NULL; \
(ehdr) = ext_hdr_v0_next((img), (ehdr)))
+static inline struct bin_hdr_v0 *bin_hdr_v0_first(void *img) +{
- struct main_hdr_v0 *mhdr;
- if (kwbimage_version(img) != 0)
return NULL;
- mhdr = img;
- if (mhdr->bin)
return _ext_hdr_v0_end(mhdr);
- else
return NULL;
+}
+#define for_each_bin_hdr_v0(bhdr, img) \
- for ((bhdr) = bin_hdr_v0_first((img)); \
(bhdr) && (void *)(bhdr) < (void *)((uint8_t *)img + kwbheader_size(img)); \
(bhdr) = (struct bin_hdr_v0 *)((bhdr))+1)
- static inline uint32_t opt_hdr_v1_size(const struct opt_hdr_v1 *ohdr) { return (ohdr->headersz_msb << 16) | le16_to_cpu(ohdr->headersz_lsb);
Viele Grüße, Stefan Roese

When pflag is set then kwbimage was invoked by dumpimage and not mkimage. So do not show mkimage error message in this case.
Signed-off-by: Pali Rohár pali@kernel.org --- tools/kwbimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 22e6a44c561c..8fd30516c9d4 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -2436,7 +2436,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params */ static int kwbimage_check_params(struct image_tool_params *params) { - if (!params->lflag && !params->iflag && + if (!params->lflag && !params->iflag && !params->pflag && (!params->imagename || !strlen(params->imagename))) { char *msg = "Configuration file for kwbimage creation omitted";

On 2/15/22 19:59, Pali Rohár wrote:
When pflag is set then kwbimage was invoked by dumpimage and not mkimage. So do not show mkimage error message in this case.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
tools/kwbimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 22e6a44c561c..8fd30516c9d4 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -2436,7 +2436,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params */ static int kwbimage_check_params(struct image_tool_params *params) {
- if (!params->lflag && !params->iflag &&
- if (!params->lflag && !params->iflag && !params->pflag && (!params->imagename || !strlen(params->imagename))) { char *msg = "Configuration file for kwbimage creation omitted";
Viele Grüße, Stefan Roese

These two commands are currently not processed when generating v0 images.
Signed-off-by: Pali Rohár pali@kernel.org --- tools/kwbimage.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 8fd30516c9d4..e455c10dc744 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -985,9 +985,15 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, e = image_find_option(IMAGE_CFG_NAND_ECC_MODE); if (e) main_hdr->nandeccmode = e->nandeccmode; + e = image_find_option(IMAGE_CFG_NAND_BLKSZ); + if (e) + main_hdr->nandblocksize = e->nandblksz / (64 * 1024); e = image_find_option(IMAGE_CFG_NAND_PAGESZ); if (e) main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz); + e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION); + if (e) + main_hdr->nandbadblklocation = e->nandbadblklocation; main_hdr->checksum = image_checksum8(image, sizeof(struct main_hdr_v0));

On 2/15/22 19:59, Pali Rohár wrote:
These two commands are currently not processed when generating v0 images.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
tools/kwbimage.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 8fd30516c9d4..e455c10dc744 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -985,9 +985,15 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, e = image_find_option(IMAGE_CFG_NAND_ECC_MODE); if (e) main_hdr->nandeccmode = e->nandeccmode;
- e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
- if (e)
e = image_find_option(IMAGE_CFG_NAND_PAGESZ); if (e) main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
- e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
- if (e)
main_hdr->checksum = image_checksum8(image, sizeof(struct main_hdr_v0));main_hdr->nandbadblklocation = e->nandbadblklocation;
Viele Grüße, Stefan Roese

First binary executable header is extracted by '-p 1' argument.
Signed-off-by: Pali Rohár pali@kernel.org --- tools/kwbimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index e455c10dc744..d82f04bea7c3 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -1102,7 +1102,7 @@ static size_t image_headersz_v1(int *hasext) fprintf(stderr, "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n" - "image for your board. Use 'dumpimage -T kwbimage -p 0' to extract it from an existing image.\n", + "image for your board. Use 'dumpimage -T kwbimage -p 1' to extract it from an existing image.\n", e->binary.file, dir); return 0; }

On 2/15/22 19:59, Pali Rohár wrote:
First binary executable header is extracted by '-p 1' argument.
Signed-off-by: Pali Rohár pali@kernel.org
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
tools/kwbimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index e455c10dc744..d82f04bea7c3 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -1102,7 +1102,7 @@ static size_t image_headersz_v1(int *hasext) fprintf(stderr, "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
"image for your board. Use 'dumpimage -T kwbimage -p 0' to extract it from an existing image.\n",
}"image for your board. Use 'dumpimage -T kwbimage -p 1' to extract it from an existing image.\n", e->binary.file, dir); return 0;
Viele Grüße, Stefan Roese

Signed-off-by: Pali Rohár pali@kernel.org --- tools/kwbimage.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index d82f04bea7c3..a3c1592b8140 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -6,6 +6,8 @@ * * (C) Copyright 2013 Thomas Petazzoni * thomas.petazzoni@free-electrons.com + * + * (C) Copyright 2022 Pali Rohár pali@kernel.org */
#define OPENSSL_API_COMPAT 0x10101000L

On 2/15/22 19:59, Pali Rohár wrote:
Signed-off-by: Pali Rohár pali@kernel.org
tools/kwbimage.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index d82f04bea7c3..a3c1592b8140 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -6,6 +6,8 @@
- (C) Copyright 2013 Thomas Petazzoni
- thomas.petazzoni@free-electrons.com
- (C) Copyright 2022 Pali Rohár pali@kernel.org
*/
#define OPENSSL_API_COMPAT 0x10101000L
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Hi Pali,
Works great! I've tested this patch using dumpimage for the following boards:
HP Thin Client T5335z Marvell Dove board: RD-88AP510-Avengers SoC: 88AP510 (A1) 1Ghz CPU, 1GB RAM
Dell Kace M300 Marvell Kirkwood board: DB-88F6282A-BP LE SoC: Armada 300 ( aka 88F6282) 2GHz CPU, 2GB RAM
Thanks!
Tested-by: Tony Dinh mibodhi@gmail.com
On Tue, Feb 15, 2022 at 10:59 AM Pali Rohár pali@kernel.org wrote:
This patch series extends kwbimage v0 format support by providing ability to dump content of Dove boot images (extension of v0 format). It also fixes recognition of these images in kwboot utility (as it uses macros and inline functions from kwbimage.h header file).
Implementation is based on 88AP510 Functional Specifications, Chapter 5.2 Boot Image Format, which is publicly available at: https://web.archive.org/web/20120130172443/https://www.marvell.com/applicati...
Printing information about image.kwb is possible by:
$ ./tools/dumpimage -l image.kwb
Dumping image.kwb is possible by commands:
$ ./tools/dumpimage -T kwbimage -p -1 -o image.cfg image.kwb $ ./tools/dumpimage -T kwbimage -p 0 -o data.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 1 -o binary1.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 2 -o binary2.bin image.kwb ... (where -p N is Nth binary executable header, e.g. SPL)
Dove images contains more sections which in config file begins with line "MATCH ADDRESS 0xaddr MASK 0xmask VALUE 0xval" and means that section is executed only when check ((readl(addr) & mask) == (val & mask)) passes.
Support for generating these kind of images is not provided. I hope that this patch series helps somebody else to implement it.
Pali Rohár (7): tools: kwbimage: Define structures for extended kwbimage v0 headers tools: kwbimage: Fix calculating size of kwbimage v0 header tools: kwbimage: Add support for dumping extended and binary v0 headers tools: kwbimage: Do not show mkimage error message in dumpimage tools: kwbimage: Add support for NAND_BLKSZ and NAND_BADBLK_LOCATION for v0 images tools: kwbimage: Fix help how to extract DDR3 training code tools: kwbimage: Add me as an author of kwbimage
tools/kwbimage.c | 139 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 116 +++++++++++++++++++++++++++++++++++---- 2 files changed, 231 insertions(+), 24 deletions(-)
-- 2.20.1

Hi Pali,
On 2/15/22 19:59, Pali Rohár wrote:
This patch series extends kwbimage v0 format support by providing ability to dump content of Dove boot images (extension of v0 format). It also fixes recognition of these images in kwboot utility (as it uses macros and inline functions from kwbimage.h header file).
This patchset seems to cause some problems with world / azure building. Please see here for details:
https://dev.azure.com/sr0718/u-boot/_build/results?buildId=159&view=resu...
Could you please take a look and address this issue?
Thanks, Stefan
Implementation is based on 88AP510 Functional Specifications, Chapter 5.2 Boot Image Format, which is publicly available at: https://web.archive.org/web/20120130172443/https://www.marvell.com/applicati...
Printing information about image.kwb is possible by:
$ ./tools/dumpimage -l image.kwb
Dumping image.kwb is possible by commands:
$ ./tools/dumpimage -T kwbimage -p -1 -o image.cfg image.kwb $ ./tools/dumpimage -T kwbimage -p 0 -o data.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 1 -o binary1.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 2 -o binary2.bin image.kwb ... (where -p N is Nth binary executable header, e.g. SPL)
Dove images contains more sections which in config file begins with line "MATCH ADDRESS 0xaddr MASK 0xmask VALUE 0xval" and means that section is executed only when check ((readl(addr) & mask) == (val & mask)) passes.
Support for generating these kind of images is not provided. I hope that this patch series helps somebody else to implement it.
Pali Rohár (7): tools: kwbimage: Define structures for extended kwbimage v0 headers tools: kwbimage: Fix calculating size of kwbimage v0 header tools: kwbimage: Add support for dumping extended and binary v0 headers tools: kwbimage: Do not show mkimage error message in dumpimage tools: kwbimage: Add support for NAND_BLKSZ and NAND_BADBLK_LOCATION for v0 images tools: kwbimage: Fix help how to extract DDR3 training code tools: kwbimage: Add me as an author of kwbimage
tools/kwbimage.c | 139 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 116 +++++++++++++++++++++++++++++++++++---- 2 files changed, 231 insertions(+), 24 deletions(-)
Viele Grüße, Stefan Roese

On Thursday 17 February 2022 08:10:57 Stefan Roese wrote:
Hi Pali,
On 2/15/22 19:59, Pali Rohár wrote:
This patch series extends kwbimage v0 format support by providing ability to dump content of Dove boot images (extension of v0 format). It also fixes recognition of these images in kwboot utility (as it uses macros and inline functions from kwbimage.h header file).
This patchset seems to cause some problems with world / azure building. Please see here for details:
https://dev.azure.com/sr0718/u-boot/_build/results?buildId=159&view=resu...
Could you please take a look and address this issue?
In file included from tools/kwbimage.c:22: include/asm-generic/bitops/fls.h:12:8: error: unknown type name '__always_inline' static __always_inline int fls(int x) ^ HOSTCC tools/omapimage.o 1 error generated.
It looks like that it is not possible to use fls() function from U-Boot bitops/fls.h header file. I will rewrite code to not use that header file.
Thanks, Stefan
Implementation is based on 88AP510 Functional Specifications, Chapter 5.2 Boot Image Format, which is publicly available at: https://web.archive.org/web/20120130172443/https://www.marvell.com/applicati...
Printing information about image.kwb is possible by:
$ ./tools/dumpimage -l image.kwb
Dumping image.kwb is possible by commands:
$ ./tools/dumpimage -T kwbimage -p -1 -o image.cfg image.kwb $ ./tools/dumpimage -T kwbimage -p 0 -o data.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 1 -o binary1.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 2 -o binary2.bin image.kwb ... (where -p N is Nth binary executable header, e.g. SPL)
Dove images contains more sections which in config file begins with line "MATCH ADDRESS 0xaddr MASK 0xmask VALUE 0xval" and means that section is executed only when check ((readl(addr) & mask) == (val & mask)) passes.
Support for generating these kind of images is not provided. I hope that this patch series helps somebody else to implement it.
Pali Rohár (7): tools: kwbimage: Define structures for extended kwbimage v0 headers tools: kwbimage: Fix calculating size of kwbimage v0 header tools: kwbimage: Add support for dumping extended and binary v0 headers tools: kwbimage: Do not show mkimage error message in dumpimage tools: kwbimage: Add support for NAND_BLKSZ and NAND_BADBLK_LOCATION for v0 images tools: kwbimage: Fix help how to extract DDR3 training code tools: kwbimage: Add me as an author of kwbimage
tools/kwbimage.c | 139 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 116 +++++++++++++++++++++++++++++++++++---- 2 files changed, 231 insertions(+), 24 deletions(-)
Viele Grüße, Stefan Roese
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de

This patch series extends kwbimage v0 format support by providing ability to dump content of Dove boot images (extension of v0 format). It also fixes recognition of these images in kwboot utility (as it uses macros and inline functions from kwbimage.h header file).
Implementation is based on 88AP510 Functional Specifications, Chapter 5.2 Boot Image Format, which is publicly available at: https://web.archive.org/web/20120130172443/https://www.marvell.com/applicati...
Printing information about image.kwb is possible by:
$ ./tools/dumpimage -l image.kwb
Dumping image.kwb is possible by commands:
$ ./tools/dumpimage -T kwbimage -p -1 -o image.cfg image.kwb $ ./tools/dumpimage -T kwbimage -p 0 -o data.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 1 -o binary1.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 2 -o binary2.bin image.kwb ... (where -p N is Nth binary executable header, e.g. SPL)
Dove images contains more sections which in config file begins with line "MATCH ADDRESS 0xaddr MASK 0xmask VALUE 0xval" and means that section is executed only when check ((readl(addr) & mask) == (val & mask)) passes.
Support for generating these kind of images is not provided. I hope that this patch series helps somebody else to implement it.
Changes in v2: * Implement custom function fls4() as it is not possible to use U-Boot's fls() from asm-generic/bitsops/fls.h file when compling for Mac or Win.
Pali Rohár (7): tools: kwbimage: Define structures for extended kwbimage v0 headers tools: kwbimage: Fix calculating size of kwbimage v0 header tools: kwbimage: Add support for dumping extended and binary v0 headers tools: kwbimage: Do not show mkimage error message in dumpimage tools: kwbimage: Add support for NAND_BLKSZ and NAND_BADBLK_LOCATION for v0 images tools: kwbimage: Fix help how to extract DDR3 training code tools: kwbimage: Add me as an author of kwbimage
tools/kwbimage.c | 152 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 116 ++++++++++++++++++++++++++++++++---- 2 files changed, 244 insertions(+), 24 deletions(-)

They are used by Marvell Dove 88AP510 BootROM.
After the main header is a list of optional extended headers and after that is a list of optional binary executable headers. Between each two extended headers is additional 0x20 byte long padding.
Original Kirkwood SoCs support only one extended header and no binary executable header.
Extension of struct ext_hdr_v0 is backward compatible with the old definition. Only reserved[] fields are changed.
Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com Reviewed-by: Stefan Roese sr@denx.de --- tools/kwbimage.h | 51 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 9ebc7d72d363..706bebddf4fa 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -48,9 +48,13 @@ struct main_hdr_v0 { uint32_t destaddr; /* 0x10-0x13 */ uint32_t execaddr; /* 0x14-0x17 */ uint8_t satapiomode; /* 0x18 */ - uint8_t rsvd3; /* 0x19 */ + uint8_t nandblocksize; /* 0x19 */ + union { + uint8_t nandbadblklocation; /* 0x1A */ uint16_t ddrinitdelay; /* 0x1A-0x1B */ - uint16_t rsvd2; /* 0x1C-0x1D */ + }; + uint8_t rsvd2; /* 0x1C */ + uint8_t bin; /* 0x1D */ uint8_t ext; /* 0x1E */ uint8_t checksum; /* 0x1F */ } __packed; @@ -60,14 +64,43 @@ struct ext_hdr_v0_reg { uint32_t rdata; } __packed;
-#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg)) - +/* Structure of the extension header, version 0 (Kirkwood, Dove) */ struct ext_hdr_v0 { - uint32_t offset; - uint8_t reserved[0x20 - sizeof(uint32_t)]; - struct ext_hdr_v0_reg rcfg[EXT_HDR_V0_REG_COUNT]; - uint8_t reserved2[7]; - uint8_t checksum; + /* + * Beware that extension header offsets specified in 88AP510 Functional + * Specifications are relative to the start of the main header, not to + * the start of the extension header itself. + */ + uint32_t offset; /* 0x0-0x3 */ + uint8_t rsvd1[8]; /* 0x4-0xB */ + uint32_t enddelay; /* 0xC-0xF */ + uint32_t match_addr; /* 0x10-0x13 */ + uint32_t match_mask; /* 0x14-0x17 */ + uint32_t match_value; /* 0x18-0x1B */ + uint8_t ddrwritetype; /* 0x1C */ + uint8_t ddrresetmpp; /* 0x1D */ + uint8_t ddrclkenmpp; /* 0x1E */ + uint8_t ddrinitdelay; /* 0x1F */ + struct ext_hdr_v0_reg rcfg[55]; /* 0x20-0x1D7 */ + uint8_t rsvd2[7]; /* 0x1D8-0x1DE */ + uint8_t checksum; /* 0x1DF */ +} __packed; + +/* Structure of the binary code header, version 0 (Dove) */ +struct bin_hdr_v0 { + uint32_t match_addr; /* 0x00-0x03 */ + uint32_t match_mask; /* 0x04-0x07 */ + uint32_t match_value; /* 0x08-0x0B */ + uint32_t offset; /* 0x0C-0x0F */ + uint32_t destaddr; /* 0x10-0x13 */ + uint32_t size; /* 0x14-0x17 */ + uint32_t execaddr; /* 0x18-0x1B */ + uint32_t params[4]; /* 0x1C-0x2B */ + uint8_t params_flags; /* 0x2C */ + uint8_t rsvd1; /* 0x2D */ + uint8_t rsvd2; /* 0x2E */ + uint8_t checksum; /* 0x2F */ + uint8_t code[2000]; /* 0x30-0x7FF */ } __packed;
/* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */

Extended and binary headers are optional and are part of the image header.
Fixes kwboot to determinate correct length of Dove images.
Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com Reviewed-by: Stefan Roese sr@denx.de --- tools/kwbimage.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 706bebddf4fa..502b6d503305 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -240,8 +240,20 @@ static inline size_t kwbheader_size(const void *header) if (kwbimage_version(header) == 0) { const struct main_hdr_v0 *hdr = header;
+ /* + * First extension header starts immediately after the main + * header without any padding. Between extension headers is + * 0x20 byte padding. There is no padding after the last + * extension header. First binary code header starts immediately + * after the last extension header (or immediately after the + * main header if there is no extension header) without any + * padding. There is no padding between binary code headers and + * neither after the last binary code header. + */ return sizeof(*hdr) + - hdr->ext ? sizeof(struct ext_hdr_v0) : 0; + hdr->ext * sizeof(struct ext_hdr_v0) + + ((hdr->ext > 1) ? ((hdr->ext - 1) * 0x20) : 0) + + hdr->bin * sizeof(struct bin_hdr_v0); } else { const struct main_hdr_v1 *hdr = header;

dumpimage is now able to successfully parse and dump content of the Dove bootloader image.
Note that support for generating these extended parts of v0 images is not included yet.
Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com
-- Changes in v2: * Implement custom function fls4() as it is not possible to use U-Boot's fls() from asm-generic/bitsops/fls.h file when compling for Mac or Win. --- tools/kwbimage.c | 140 +++++++++++++++++++++++++++++++++++++++++++---- tools/kwbimage.h | 51 +++++++++++++++++ 2 files changed, 179 insertions(+), 12 deletions(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 99d38cd1cfb2..5a717e5354bf 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -43,6 +43,21 @@ void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) } #endif
+/* fls - find last (most-significant) bit set in 4-bit integer */ +static inline int fls4(int num) +{ + if (num & 0x8) + return 4; + else if (num & 0x4) + return 3; + else if (num & 0x2) + return 2; + else if (num & 0x1) + return 1; + else + return 0; +} + static struct image_cfg_element *image_cfg; static int cfgn; static int verbose_mode; @@ -1898,6 +1913,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, static void kwbimage_print_header(const void *ptr) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr; + struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr;
printf("Image Type: MVEBU Boot from %s Image\n", @@ -1915,6 +1931,13 @@ static void kwbimage_print_header(const void *ptr) } }
+ for_each_bin_hdr_v0(bhdr, mhdr) { + printf("BIN Img Size: "); + genimg_print_size(le32_to_cpu(bhdr->size)); + printf("BIN Img Addr: %08x\n", le32_to_cpu(bhdr->destaddr)); + printf("BIN Img Entr: %08x\n", le32_to_cpu(bhdr->execaddr)); + } + printf("Data Size: "); genimg_print_size(mhdr->blocksize - sizeof(uint32_t)); printf("Load Address: %08x\n", mhdr->destaddr); @@ -1947,15 +1970,31 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size, /* Only version 0 extended header has checksum */ if (kwbimage_version(ptr) == 0) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr; + struct ext_hdr_v0 *ext_hdr; + struct bin_hdr_v0 *bhdr;
- if (mhdr->ext) { - struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1); - + for_each_ext_hdr_v0(ext_hdr, ptr) { csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1); if (csum != ext_hdr->checksum) return -FDT_ERR_BADSTRUCTURE; }
+ for_each_bin_hdr_v0(bhdr, ptr) { + csum = image_checksum8(bhdr, (uint8_t *)&bhdr->checksum - (uint8_t *)bhdr - 1); + if (csum != bhdr->checksum) + return -FDT_ERR_BADSTRUCTURE; + + if (bhdr->offset > sizeof(*bhdr) || bhdr->offset % 4 != 0) + return -FDT_ERR_BADSTRUCTURE; + + if (bhdr->offset + bhdr->size + 4 > sizeof(*bhdr) || bhdr->size % 4 != 0) + return -FDT_ERR_BADSTRUCTURE; + + if (image_checksum32((uint8_t *)bhdr + bhdr->offset, bhdr->size) != + *(uint32_t *)((uint8_t *)bhdr + bhdr->offset + bhdr->size)) + return -FDT_ERR_BADSTRUCTURE; + } + blockid = mhdr->blockid; offset = le32_to_cpu(mhdr->srcaddr); size = le32_to_cpu(mhdr->blocksize); @@ -2130,8 +2169,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) struct register_set_hdr_v1 *regset_hdr; struct ext_hdr_v0_reg *regdata; struct ext_hdr_v0 *ehdr0; + struct bin_hdr_v0 *bhdr0; struct opt_hdr_v1 *ohdr; + int params_count; unsigned offset; + int is_v0_ext; int cur_idx; int version; FILE *f; @@ -2145,6 +2187,14 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
version = kwbimage_version(ptr);
+ is_v0_ext = 0; + if (version == 0) { + if (mhdr0->ext > 1 || mhdr0->bin || + ((ehdr0 = ext_hdr_v0_first(ptr)) && + (ehdr0->match_addr || ehdr0->match_mask || ehdr0->match_value))) + is_v0_ext = 1; + } + if (version != 0) fprintf(f, "VERSION %d\n", version);
@@ -2156,10 +2206,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if (mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize);
- if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) { + if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize); + + if (mhdr->blockid == IBR_HDR_NAND_ID && (mhdr->nandbadblklocation != 0 || is_v0_ext)) fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation); - }
if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID) fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode); @@ -2222,8 +2273,39 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) } }
- if (version == 0 && mhdr0->ext) { - ehdr0 = (struct ext_hdr_v0 *)(mhdr0 + 1); + if (version == 0 && !is_v0_ext && le16_to_cpu(mhdr0->ddrinitdelay)) + fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay)); + + for_each_ext_hdr_v0(ehdr0, ptr) { + if (is_v0_ext) { + fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n", + le32_to_cpu(ehdr0->match_addr), + le32_to_cpu(ehdr0->match_mask), + le32_to_cpu(ehdr0->match_value)); + if (ehdr0->rsvd1[0] || ehdr0->rsvd1[1] || ehdr0->rsvd1[2] || + ehdr0->rsvd1[3] || ehdr0->rsvd1[4] || ehdr0->rsvd1[5] || + ehdr0->rsvd1[6] || ehdr0->rsvd1[7]) + fprintf(f, "#DDR_RSVD1 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + ehdr0->rsvd1[0], ehdr0->rsvd1[1], ehdr0->rsvd1[2], + ehdr0->rsvd1[3], ehdr0->rsvd1[4], ehdr0->rsvd1[5], + ehdr0->rsvd1[6], ehdr0->rsvd1[7]); + if (ehdr0->rsvd2[0] || ehdr0->rsvd2[1] || ehdr0->rsvd2[2] || + ehdr0->rsvd2[3] || ehdr0->rsvd2[4] || ehdr0->rsvd2[5] || + ehdr0->rsvd2[6]) + fprintf(f, "#DDR_RSVD2 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + ehdr0->rsvd2[0], ehdr0->rsvd2[1], ehdr0->rsvd2[2], + ehdr0->rsvd2[3], ehdr0->rsvd2[4], ehdr0->rsvd2[5], + ehdr0->rsvd2[6]); + if (ehdr0->ddrwritetype) + fprintf(f, "DDR_WRITE_TYPE %u\n", (unsigned)ehdr0->ddrwritetype); + if (ehdr0->ddrresetmpp) + fprintf(f, "DDR_RESET_MPP 0x%x\n", (unsigned)ehdr0->ddrresetmpp); + if (ehdr0->ddrclkenmpp) + fprintf(f, "DDR_CLKEN_MPP 0x%x\n", (unsigned)ehdr0->ddrclkenmpp); + if (ehdr0->ddrinitdelay) + fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)ehdr0->ddrinitdelay); + } + if (ehdr0->offset) { for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset); (uint8_t *)regdata < (uint8_t *)ptr + header_size && @@ -2234,10 +2316,38 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if ((uint8_t *)regdata != (uint8_t *)ptr + ehdr0->offset) fprintf(f, "DATA 0x0 0x0\n"); } + + if (le32_to_cpu(ehdr0->enddelay)) + fprintf(f, "DATA_DELAY %u\n", le32_to_cpu(ehdr0->enddelay)); + else if (is_v0_ext) + fprintf(f, "DATA_DELAY SDRAM_SETUP\n"); }
- if (version == 0 && le16_to_cpu(mhdr0->ddrinitdelay)) - fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay)); + cur_idx = 1; + for_each_bin_hdr_v0(bhdr0, ptr) { + fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n", + le32_to_cpu(bhdr0->match_addr), + le32_to_cpu(bhdr0->match_mask), + le32_to_cpu(bhdr0->match_value)); + + fprintf(f, "BINARY binary%d.bin", cur_idx); + params_count = fls4(bhdr0->params_flags & 0xF); + for (i = 0; i < params_count; i++) + fprintf(f, " 0x%x", (bhdr0->params[i] & (1 << i)) ? bhdr0->params[i] : 0); + fprintf(f, " LOAD_ADDRESS 0x%08x", le32_to_cpu(bhdr0->destaddr)); + fprintf(f, " EXEC_ADDRESS 0x%08x", le32_to_cpu(bhdr0->execaddr)); + fprintf(f, "\n"); + + fprintf(f, "#BINARY_OFFSET 0x%x\n", le32_to_cpu(bhdr0->offset)); + fprintf(f, "#BINARY_SIZE 0x%x\n", le32_to_cpu(bhdr0->size)); + + if (bhdr0->rsvd1) + fprintf(f, "#BINARY_RSVD1 0x%x\n", (unsigned)bhdr0->rsvd1); + if (bhdr0->rsvd2) + fprintf(f, "#BINARY_RSVD2 0x%x\n", (unsigned)bhdr0->rsvd2); + + cur_idx++; + }
/* Undocumented reserved fields */
@@ -2245,9 +2355,6 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0], (unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
- if (version == 0 && mhdr0->rsvd3) - fprintf(f, "#RSVD3 0x%x\n", (unsigned)mhdr0->rsvd3); - if (version == 0 && le16_to_cpu(mhdr0->rsvd2)) fprintf(f, "#RSVD2 0x%x\n", (unsigned)le16_to_cpu(mhdr0->rsvd2));
@@ -2266,6 +2373,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params { struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr; size_t header_size = kwbheader_size(ptr); + struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr; int idx = params->pflag; int cur_idx; @@ -2312,6 +2420,14 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params
++cur_idx; } + for_each_bin_hdr_v0(bhdr, ptr) { + if (idx == cur_idx) { + image = (ulong)bhdr + bhdr->offset; + size = bhdr->size; + break; + } + ++cur_idx; + }
if (!image) { fprintf(stderr, "Argument -p %d is invalid\n", idx); diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 502b6d503305..505522332bd4 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -270,6 +270,57 @@ static inline size_t kwbheader_size_for_csum(const void *header) return kwbheader_size(header); }
+static inline struct ext_hdr_v0 *ext_hdr_v0_first(void *img) +{ + struct main_hdr_v0 *mhdr; + + if (kwbimage_version(img) != 0) + return NULL; + + mhdr = img; + if (mhdr->ext) + return (struct ext_hdr_v0 *)(mhdr + 1); + else + return NULL; +} + +static inline void *_ext_hdr_v0_end(struct main_hdr_v0 *mhdr) +{ + return (uint8_t *)mhdr + kwbheader_size(mhdr) - mhdr->bin * sizeof(struct bin_hdr_v0); +} + +static inline struct ext_hdr_v0 *ext_hdr_v0_next(void *img, struct ext_hdr_v0 *cur) +{ + if ((void *)(cur + 1) < _ext_hdr_v0_end(img)) + return (struct ext_hdr_v0 *)((uint8_t *)(cur + 1) + 0x20); + else + return NULL; +} + +#define for_each_ext_hdr_v0(ehdr, img) \ + for ((ehdr) = ext_hdr_v0_first((img)); \ + (ehdr) != NULL; \ + (ehdr) = ext_hdr_v0_next((img), (ehdr))) + +static inline struct bin_hdr_v0 *bin_hdr_v0_first(void *img) +{ + struct main_hdr_v0 *mhdr; + + if (kwbimage_version(img) != 0) + return NULL; + + mhdr = img; + if (mhdr->bin) + return _ext_hdr_v0_end(mhdr); + else + return NULL; +} + +#define for_each_bin_hdr_v0(bhdr, img) \ + for ((bhdr) = bin_hdr_v0_first((img)); \ + (bhdr) && (void *)(bhdr) < (void *)((uint8_t *)img + kwbheader_size(img)); \ + (bhdr) = (struct bin_hdr_v0 *)((bhdr))+1) + static inline uint32_t opt_hdr_v1_size(const struct opt_hdr_v1 *ohdr) { return (ohdr->headersz_msb << 16) | le16_to_cpu(ohdr->headersz_lsb);

On 2/17/22 10:43, Pali Rohár wrote:
dumpimage is now able to successfully parse and dump content of the Dove bootloader image.
Note that support for generating these extended parts of v0 images is not included yet.
Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com
-- Changes in v2:
- Implement custom function fls4() as it is not possible to use U-Boot's fls() from asm-generic/bitsops/fls.h file when compling for Mac or Win.
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
tools/kwbimage.c | 140 +++++++++++++++++++++++++++++++++++++++++++---- tools/kwbimage.h | 51 +++++++++++++++++ 2 files changed, 179 insertions(+), 12 deletions(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 99d38cd1cfb2..5a717e5354bf 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -43,6 +43,21 @@ void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) } #endif
+/* fls - find last (most-significant) bit set in 4-bit integer */ +static inline int fls4(int num) +{
- if (num & 0x8)
return 4;
- else if (num & 0x4)
return 3;
- else if (num & 0x2)
return 2;
- else if (num & 0x1)
return 1;
- else
return 0;
+}
- static struct image_cfg_element *image_cfg; static int cfgn; static int verbose_mode;
@@ -1898,6 +1913,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, static void kwbimage_print_header(const void *ptr) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr;
printf("Image Type: MVEBU Boot from %s Image\n",
@@ -1915,6 +1931,13 @@ static void kwbimage_print_header(const void *ptr) } }
- for_each_bin_hdr_v0(bhdr, mhdr) {
printf("BIN Img Size: ");
genimg_print_size(le32_to_cpu(bhdr->size));
printf("BIN Img Addr: %08x\n", le32_to_cpu(bhdr->destaddr));
printf("BIN Img Entr: %08x\n", le32_to_cpu(bhdr->execaddr));
- }
- printf("Data Size: "); genimg_print_size(mhdr->blocksize - sizeof(uint32_t)); printf("Load Address: %08x\n", mhdr->destaddr);
@@ -1947,15 +1970,31 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size, /* Only version 0 extended header has checksum */ if (kwbimage_version(ptr) == 0) { struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
struct ext_hdr_v0 *ext_hdr;
struct bin_hdr_v0 *bhdr;
if (mhdr->ext) {
struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1);
for_each_ext_hdr_v0(ext_hdr, ptr) { csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1); if (csum != ext_hdr->checksum) return -FDT_ERR_BADSTRUCTURE;
}
for_each_bin_hdr_v0(bhdr, ptr) {
csum = image_checksum8(bhdr, (uint8_t *)&bhdr->checksum - (uint8_t *)bhdr - 1);
if (csum != bhdr->checksum)
return -FDT_ERR_BADSTRUCTURE;
if (bhdr->offset > sizeof(*bhdr) || bhdr->offset % 4 != 0)
return -FDT_ERR_BADSTRUCTURE;
if (bhdr->offset + bhdr->size + 4 > sizeof(*bhdr) || bhdr->size % 4 != 0)
return -FDT_ERR_BADSTRUCTURE;
if (image_checksum32((uint8_t *)bhdr + bhdr->offset, bhdr->size) !=
*(uint32_t *)((uint8_t *)bhdr + bhdr->offset + bhdr->size))
return -FDT_ERR_BADSTRUCTURE;
}
blockid = mhdr->blockid; offset = le32_to_cpu(mhdr->srcaddr); size = le32_to_cpu(mhdr->blocksize);
@@ -2130,8 +2169,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) struct register_set_hdr_v1 *regset_hdr; struct ext_hdr_v0_reg *regdata; struct ext_hdr_v0 *ehdr0;
- struct bin_hdr_v0 *bhdr0; struct opt_hdr_v1 *ohdr;
- int params_count; unsigned offset;
- int is_v0_ext; int cur_idx; int version; FILE *f;
@@ -2145,6 +2187,14 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
version = kwbimage_version(ptr);
- is_v0_ext = 0;
- if (version == 0) {
if (mhdr0->ext > 1 || mhdr0->bin ||
((ehdr0 = ext_hdr_v0_first(ptr)) &&
(ehdr0->match_addr || ehdr0->match_mask || ehdr0->match_value)))
is_v0_ext = 1;
- }
- if (version != 0) fprintf(f, "VERSION %d\n", version);
@@ -2156,10 +2206,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if (mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize);
- if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) {
- if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize);
- if (mhdr->blockid == IBR_HDR_NAND_ID && (mhdr->nandbadblklocation != 0 || is_v0_ext)) fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation);
}
if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID) fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode);
@@ -2222,8 +2273,39 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) } }
- if (version == 0 && mhdr0->ext) {
ehdr0 = (struct ext_hdr_v0 *)(mhdr0 + 1);
- if (version == 0 && !is_v0_ext && le16_to_cpu(mhdr0->ddrinitdelay))
fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
- for_each_ext_hdr_v0(ehdr0, ptr) {
if (is_v0_ext) {
fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
le32_to_cpu(ehdr0->match_addr),
le32_to_cpu(ehdr0->match_mask),
le32_to_cpu(ehdr0->match_value));
if (ehdr0->rsvd1[0] || ehdr0->rsvd1[1] || ehdr0->rsvd1[2] ||
ehdr0->rsvd1[3] || ehdr0->rsvd1[4] || ehdr0->rsvd1[5] ||
ehdr0->rsvd1[6] || ehdr0->rsvd1[7])
fprintf(f, "#DDR_RSVD1 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
ehdr0->rsvd1[0], ehdr0->rsvd1[1], ehdr0->rsvd1[2],
ehdr0->rsvd1[3], ehdr0->rsvd1[4], ehdr0->rsvd1[5],
ehdr0->rsvd1[6], ehdr0->rsvd1[7]);
if (ehdr0->rsvd2[0] || ehdr0->rsvd2[1] || ehdr0->rsvd2[2] ||
ehdr0->rsvd2[3] || ehdr0->rsvd2[4] || ehdr0->rsvd2[5] ||
ehdr0->rsvd2[6])
fprintf(f, "#DDR_RSVD2 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
ehdr0->rsvd2[0], ehdr0->rsvd2[1], ehdr0->rsvd2[2],
ehdr0->rsvd2[3], ehdr0->rsvd2[4], ehdr0->rsvd2[5],
ehdr0->rsvd2[6]);
if (ehdr0->ddrwritetype)
fprintf(f, "DDR_WRITE_TYPE %u\n", (unsigned)ehdr0->ddrwritetype);
if (ehdr0->ddrresetmpp)
fprintf(f, "DDR_RESET_MPP 0x%x\n", (unsigned)ehdr0->ddrresetmpp);
if (ehdr0->ddrclkenmpp)
fprintf(f, "DDR_CLKEN_MPP 0x%x\n", (unsigned)ehdr0->ddrclkenmpp);
if (ehdr0->ddrinitdelay)
fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)ehdr0->ddrinitdelay);
}
- if (ehdr0->offset) { for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset); (uint8_t *)regdata < (uint8_t *)ptr + header_size &&
@@ -2234,10 +2316,38 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) if ((uint8_t *)regdata != (uint8_t *)ptr + ehdr0->offset) fprintf(f, "DATA 0x0 0x0\n"); }
if (le32_to_cpu(ehdr0->enddelay))
fprintf(f, "DATA_DELAY %u\n", le32_to_cpu(ehdr0->enddelay));
else if (is_v0_ext)
}fprintf(f, "DATA_DELAY SDRAM_SETUP\n");
- if (version == 0 && le16_to_cpu(mhdr0->ddrinitdelay))
fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
cur_idx = 1;
for_each_bin_hdr_v0(bhdr0, ptr) {
fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
le32_to_cpu(bhdr0->match_addr),
le32_to_cpu(bhdr0->match_mask),
le32_to_cpu(bhdr0->match_value));
fprintf(f, "BINARY binary%d.bin", cur_idx);
params_count = fls4(bhdr0->params_flags & 0xF);
for (i = 0; i < params_count; i++)
fprintf(f, " 0x%x", (bhdr0->params[i] & (1 << i)) ? bhdr0->params[i] : 0);
fprintf(f, " LOAD_ADDRESS 0x%08x", le32_to_cpu(bhdr0->destaddr));
fprintf(f, " EXEC_ADDRESS 0x%08x", le32_to_cpu(bhdr0->execaddr));
fprintf(f, "\n");
fprintf(f, "#BINARY_OFFSET 0x%x\n", le32_to_cpu(bhdr0->offset));
fprintf(f, "#BINARY_SIZE 0x%x\n", le32_to_cpu(bhdr0->size));
if (bhdr0->rsvd1)
fprintf(f, "#BINARY_RSVD1 0x%x\n", (unsigned)bhdr0->rsvd1);
if (bhdr0->rsvd2)
fprintf(f, "#BINARY_RSVD2 0x%x\n", (unsigned)bhdr0->rsvd2);
cur_idx++;
}
/* Undocumented reserved fields */
@@ -2245,9 +2355,6 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0], (unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
- if (version == 0 && mhdr0->rsvd3)
fprintf(f, "#RSVD3 0x%x\n", (unsigned)mhdr0->rsvd3);
- if (version == 0 && le16_to_cpu(mhdr0->rsvd2)) fprintf(f, "#RSVD2 0x%x\n", (unsigned)le16_to_cpu(mhdr0->rsvd2));
@@ -2266,6 +2373,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params { struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr; size_t header_size = kwbheader_size(ptr);
- struct bin_hdr_v0 *bhdr; struct opt_hdr_v1 *ohdr; int idx = params->pflag; int cur_idx;
@@ -2312,6 +2420,14 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params
++cur_idx; }
for_each_bin_hdr_v0(bhdr, ptr) {
if (idx == cur_idx) {
image = (ulong)bhdr + bhdr->offset;
size = bhdr->size;
break;
}
++cur_idx;
}
if (!image) { fprintf(stderr, "Argument -p %d is invalid\n", idx);
diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 502b6d503305..505522332bd4 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -270,6 +270,57 @@ static inline size_t kwbheader_size_for_csum(const void *header) return kwbheader_size(header); }
+static inline struct ext_hdr_v0 *ext_hdr_v0_first(void *img) +{
- struct main_hdr_v0 *mhdr;
- if (kwbimage_version(img) != 0)
return NULL;
- mhdr = img;
- if (mhdr->ext)
return (struct ext_hdr_v0 *)(mhdr + 1);
- else
return NULL;
+}
+static inline void *_ext_hdr_v0_end(struct main_hdr_v0 *mhdr) +{
- return (uint8_t *)mhdr + kwbheader_size(mhdr) - mhdr->bin * sizeof(struct bin_hdr_v0);
+}
+static inline struct ext_hdr_v0 *ext_hdr_v0_next(void *img, struct ext_hdr_v0 *cur) +{
- if ((void *)(cur + 1) < _ext_hdr_v0_end(img))
return (struct ext_hdr_v0 *)((uint8_t *)(cur + 1) + 0x20);
- else
return NULL;
+}
+#define for_each_ext_hdr_v0(ehdr, img) \
- for ((ehdr) = ext_hdr_v0_first((img)); \
(ehdr) != NULL; \
(ehdr) = ext_hdr_v0_next((img), (ehdr)))
+static inline struct bin_hdr_v0 *bin_hdr_v0_first(void *img) +{
- struct main_hdr_v0 *mhdr;
- if (kwbimage_version(img) != 0)
return NULL;
- mhdr = img;
- if (mhdr->bin)
return _ext_hdr_v0_end(mhdr);
- else
return NULL;
+}
+#define for_each_bin_hdr_v0(bhdr, img) \
- for ((bhdr) = bin_hdr_v0_first((img)); \
(bhdr) && (void *)(bhdr) < (void *)((uint8_t *)img + kwbheader_size(img)); \
(bhdr) = (struct bin_hdr_v0 *)((bhdr))+1)
- static inline uint32_t opt_hdr_v1_size(const struct opt_hdr_v1 *ohdr) { return (ohdr->headersz_msb << 16) | le16_to_cpu(ohdr->headersz_lsb);
Viele Grüße, Stefan Roese

When pflag is set then kwbimage was invoked by dumpimage and not mkimage. So do not show mkimage error message in this case.
Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com Reviewed-by: Stefan Roese sr@denx.de --- tools/kwbimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 5a717e5354bf..73788d8d892f 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -2449,7 +2449,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params */ static int kwbimage_check_params(struct image_tool_params *params) { - if (!params->lflag && !params->iflag && + if (!params->lflag && !params->iflag && !params->pflag && (!params->imagename || !strlen(params->imagename))) { char *msg = "Configuration file for kwbimage creation omitted";

These two commands are currently not processed when generating v0 images.
Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com Reviewed-by: Stefan Roese sr@denx.de --- tools/kwbimage.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 73788d8d892f..bf8ab0f19251 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -998,9 +998,15 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, e = image_find_option(IMAGE_CFG_NAND_ECC_MODE); if (e) main_hdr->nandeccmode = e->nandeccmode; + e = image_find_option(IMAGE_CFG_NAND_BLKSZ); + if (e) + main_hdr->nandblocksize = e->nandblksz / (64 * 1024); e = image_find_option(IMAGE_CFG_NAND_PAGESZ); if (e) main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz); + e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION); + if (e) + main_hdr->nandbadblklocation = e->nandbadblklocation; main_hdr->checksum = image_checksum8(image, sizeof(struct main_hdr_v0));

First binary executable header is extracted by '-p 1' argument.
Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com Reviewed-by: Stefan Roese sr@denx.de --- tools/kwbimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index bf8ab0f19251..f270dcf242b6 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -1115,7 +1115,7 @@ static size_t image_headersz_v1(int *hasext) fprintf(stderr, "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n" - "image for your board. Use 'dumpimage -T kwbimage -p 0' to extract it from an existing image.\n", + "image for your board. Use 'dumpimage -T kwbimage -p 1' to extract it from an existing image.\n", e->binary.file, dir); return 0; }

Signed-off-by: Pali Rohár pali@kernel.org Tested-by: Tony Dinh mibodhi@gmail.com Reviewed-by: Stefan Roese sr@denx.de --- tools/kwbimage.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c index f270dcf242b6..94b768539222 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -6,6 +6,8 @@ * * (C) Copyright 2013 Thomas Petazzoni * thomas.petazzoni@free-electrons.com + * + * (C) Copyright 2022 Pali Rohár pali@kernel.org */
#define OPENSSL_API_COMPAT 0x10101000L

On 2/17/22 10:43, Pali Rohár wrote:
This patch series extends kwbimage v0 format support by providing ability to dump content of Dove boot images (extension of v0 format). It also fixes recognition of these images in kwboot utility (as it uses macros and inline functions from kwbimage.h header file).
Implementation is based on 88AP510 Functional Specifications, Chapter 5.2 Boot Image Format, which is publicly available at: https://web.archive.org/web/20120130172443/https://www.marvell.com/applicati...
Printing information about image.kwb is possible by:
$ ./tools/dumpimage -l image.kwb
Dumping image.kwb is possible by commands:
$ ./tools/dumpimage -T kwbimage -p -1 -o image.cfg image.kwb $ ./tools/dumpimage -T kwbimage -p 0 -o data.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 1 -o binary1.bin image.kwb $ ./tools/dumpimage -T kwbimage -p 2 -o binary2.bin image.kwb ... (where -p N is Nth binary executable header, e.g. SPL)
Dove images contains more sections which in config file begins with line "MATCH ADDRESS 0xaddr MASK 0xmask VALUE 0xval" and means that section is executed only when check ((readl(addr) & mask) == (val & mask)) passes.
Support for generating these kind of images is not provided. I hope that this patch series helps somebody else to implement it.
Changes in v2:
- Implement custom function fls4() as it is not possible to use U-Boot's fls() from asm-generic/bitsops/fls.h file when compling for Mac or Win.
Pali Rohár (7): tools: kwbimage: Define structures for extended kwbimage v0 headers tools: kwbimage: Fix calculating size of kwbimage v0 header tools: kwbimage: Add support for dumping extended and binary v0 headers tools: kwbimage: Do not show mkimage error message in dumpimage tools: kwbimage: Add support for NAND_BLKSZ and NAND_BADBLK_LOCATION for v0 images tools: kwbimage: Fix help how to extract DDR3 training code tools: kwbimage: Add me as an author of kwbimage
tools/kwbimage.c | 152 ++++++++++++++++++++++++++++++++++++++++++----- tools/kwbimage.h | 116 ++++++++++++++++++++++++++++++++---- 2 files changed, 244 insertions(+), 24 deletions(-)
Applied to u-boot-marvell/master
Thanks, Stefan
participants (3)
-
Pali Rohár
-
Stefan Roese
-
Tony Dinh