From a85a71d3960d8183fc7ec2bc775693dee940021c Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Thu, 21 Oct 2021 16:46:06 +0200 Subject: tools: kwboot: Align UART baudrate change code in BIN header to 128-bit boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ARM executable code inside the BIN header on some mvebu platforms (e.g. A370, AXP) must always be aligned with the 128-bit boundary. This requirement can be met by inserting dummy arguments into BIN header. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- tools/kwboot.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/kwboot.c b/tools/kwboot.c index 6a1a030308e..eb4f5ab8791 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -255,7 +255,7 @@ static unsigned char kwboot_baud_code[] = { }; #define KWBOOT_BAUDRATE_BIN_HEADER_SZ (sizeof(kwboot_baud_code) + \ - sizeof(struct opt_hdr_v1) + 8) + sizeof(struct opt_hdr_v1) + 8 + 16) static const char kwb_baud_magic[16] = "$baudratechange"; @@ -1328,11 +1328,10 @@ kwboot_add_bin_ohdr_v1(void *img, size_t *size, uint32_t binsz) { struct main_hdr_v1 *hdr = img; struct opt_hdr_v1 *ohdr; + uint32_t num_args; + uint32_t offset; uint32_t ohdrsz; - ohdrsz = binsz + 8 + sizeof(*ohdr); - kwboot_img_grow_hdr(img, size, ohdrsz); - if (hdr->ext & 0x1) { for_each_opt_hdr_v1 (ohdr, img) if (opt_hdr_v1_next(ohdr) == NULL) @@ -1345,13 +1344,26 @@ kwboot_add_bin_ohdr_v1(void *img, size_t *size, uint32_t binsz) ohdr = (void *)(hdr + 1); } + /* + * ARM executable code inside the BIN header on some mvebu platforms + * (e.g. A370, AXP) must always be aligned with the 128-bit boundary. + * This requirement can be met by inserting dummy arguments into + * BIN header, if needed. + */ + offset = &ohdr->data[4] - (char *)img; + num_args = ((16 - offset % 16) % 16) / sizeof(uint32_t); + + ohdrsz = sizeof(*ohdr) + 4 + 4 * num_args + binsz + 4; + kwboot_img_grow_hdr(hdr, size, ohdrsz); + ohdr->headertype = OPT_HDR_V1_BINARY_TYPE; ohdr->headersz_msb = ohdrsz >> 16; ohdr->headersz_lsb = cpu_to_le16(ohdrsz & 0xffff); memset(&ohdr->data[0], 0, ohdrsz - sizeof(*ohdr)); + *(uint32_t *)&ohdr->data[0] = cpu_to_le32(num_args); - return &ohdr->data[4]; + return &ohdr->data[4 + 4 * num_args]; } static void -- cgit v1.3.1 From e58f08b479bb512e4976fc2481657f6cfaf7e7b5 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Thu, 21 Oct 2021 16:46:07 +0200 Subject: tools: kwbimage: Align BIN header executable code to 128-bit boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ARM executable code inside the BIN header on some mvebu platforms (e.g. A370, AXP) must always be aligned with the 128-bit boundary. This requirement can be met by inserting dummy arguments into BIN header. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- tools/kwbimage.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'tools') diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 77bf4dd8865..e9324baddba 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -932,6 +932,12 @@ static size_t image_headersz_v1(int *hasext) */ headersz = sizeof(struct main_hdr_v1); + if (image_get_csk_index() >= 0) { + headersz += sizeof(struct secure_hdr_v1); + if (hasext) + *hasext = 1; + } + count = image_count_options(IMAGE_CFG_DATA); if (count > 0) headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4; @@ -963,15 +969,10 @@ static size_t image_headersz_v1(int *hasext) return 0; } - headersz += sizeof(struct opt_hdr_v1) + - ALIGN(s.st_size, 4) + - (binarye->binary.nargs + 2) * sizeof(uint32_t); - if (hasext) - *hasext = 1; - } - - if (image_get_csk_index() >= 0) { - headersz += sizeof(struct secure_hdr_v1); + headersz += sizeof(struct opt_hdr_v1) + sizeof(uint32_t) + + (binarye->binary.nargs) * sizeof(uint32_t); + headersz = ALIGN(headersz, 16); + headersz += ALIGN(s.st_size, 4) + sizeof(uint32_t); if (hasext) *hasext = 1; } @@ -984,9 +985,12 @@ static size_t image_headersz_v1(int *hasext) } int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext, - struct image_cfg_element *binarye) + struct image_cfg_element *binarye, + struct main_hdr_v1 *main_hdr) { struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)*cur; + uint32_t add_args; + uint32_t offset; uint32_t *args; size_t binhdrsz; struct stat s; @@ -1009,12 +1013,6 @@ int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext, goto err_close; } - binhdrsz = sizeof(struct opt_hdr_v1) + - (binarye->binary.nargs + 2) * sizeof(uint32_t) + - ALIGN(s.st_size, 4); - hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF); - hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; - *cur += sizeof(struct opt_hdr_v1); args = (uint32_t *)*cur; @@ -1025,6 +1023,19 @@ int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext, *cur += (binarye->binary.nargs + 1) * sizeof(uint32_t); + /* + * ARM executable code inside the BIN header on some mvebu platforms + * (e.g. A370, AXP) must always be aligned with the 128-bit boundary. + * This requirement can be met by inserting dummy arguments into + * BIN header, if needed. + */ + offset = *cur - (uint8_t *)main_hdr; + add_args = ((16 - offset % 16) % 16) / sizeof(uint32_t); + if (add_args) { + *(args - 1) = cpu_to_le32(binarye->binary.nargs + add_args); + *cur += add_args * sizeof(uint32_t); + } + ret = fread(*cur, s.st_size, 1, bin); if (ret != 1) { fprintf(stderr, @@ -1043,6 +1054,12 @@ int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext, *cur += sizeof(uint32_t); + binhdrsz = sizeof(struct opt_hdr_v1) + + (binarye->binary.nargs + add_args + 2) * sizeof(uint32_t) + + ALIGN(s.st_size, 4); + hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF); + hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; + return 0; err_close: @@ -1299,7 +1316,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, if (e->type != IMAGE_CFG_BINARY) continue; - if (add_binary_header_v1(&cur, &next_ext, e)) + if (add_binary_header_v1(&cur, &next_ext, e, main_hdr)) return NULL; } -- cgit v1.3.1 From 2fdba4f6585c31da748eee69a8dea1cf0a11d311 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Fri, 22 Oct 2021 12:37:46 +0200 Subject: tools: kwbimage: Add support for NAND_PAGE_SIZE command also for v1 images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The NAND_PAGE_SIZE command is already supported by mkimage for v0 images, but not for v1 images. A38x and A39x BootROM supports reading NAND flash page size from v1 image in the same way as Kirkwood BootROM from v0 image. It it documented in A38x and A39x Functional Specification. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- tools/kwbimage.c | 3 +++ tools/kwbimage.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/kwbimage.c b/tools/kwbimage.c index e9324baddba..67c0c628ae9 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -1231,6 +1231,9 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, 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; diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 126d482fe72..f1ba95c2fa5 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -73,7 +73,7 @@ struct ext_hdr_v0 { struct main_hdr_v1 { uint8_t blockid; /* 0x0 */ uint8_t flags; /* 0x1 */ - uint16_t reserved2; /* 0x2-0x3 */ + uint16_t nandpagesize; /* 0x2-0x3 */ uint32_t blocksize; /* 0x4-0x7 */ uint8_t version; /* 0x8 */ uint8_t headersz_msb; /* 0x9 */ -- cgit v1.3.1 From 0089f61e2dad50650d848ce8625d2b2141f56984 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Fri, 22 Oct 2021 12:37:47 +0200 Subject: tools: kwboot: Patch nandpagesize to zero also for v1 image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kwbimage v1 has also nandpagesize field. So set it to zero for both image versions when image is not signed. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- tools/kwboot.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/kwboot.c b/tools/kwboot.c index eb4f5ab8791..7e1be296230 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -1428,13 +1428,6 @@ kwboot_img_patch(void *img, size_t *size, int baudrate) if (csum != hdr->checksum) goto err; - if (image_ver == 0) { - struct main_hdr_v0 *hdr_v0 = img; - - hdr_v0->nandeccmode = IBR_HDR_ECC_DISABLED; - hdr_v0->nandpagesize = 0; - } - srcaddr = le32_to_cpu(hdr->srcaddr); switch (hdr->blockid) { @@ -1480,6 +1473,12 @@ kwboot_img_patch(void *img, size_t *size, int baudrate) hdr->blockid = IBR_HDR_UART_ID; } + if (!is_secure) { + if (image_ver == 0) + ((struct main_hdr_v0 *)img)->nandeccmode = IBR_HDR_ECC_DISABLED; + hdr->nandpagesize = 0; + } + if (baudrate) { uint32_t codesz = sizeof(kwboot_baud_code); void *code; -- cgit v1.3.1