diff --git a/arch/arm/mach-mvebu/kwbimage.cfg.in b/arch/arm/mach-mvebu/kwbimage.cfg.in index 72e67d75c3..049d23c6ef 100644 --- a/arch/arm/mach-mvebu/kwbimage.cfg.in +++ b/arch/arm/mach-mvebu/kwbimage.cfg.in @@ -9,4 +9,4 @@ VERSION 1 #@BOOT_FROM # Binary Header (bin_hdr) with DDR3 training code -BINARY spl/u-boot-spl.bin 0000005b 00000068 +BINARY spl/u-boot-spl.bin diff --git a/arch/arm/mach-mvebu/lowlevel_spl.S b/arch/arm/mach-mvebu/lowlevel_spl.S index dde77b7652..501c239e9d 100644 --- a/arch/arm/mach-mvebu/lowlevel_spl.S +++ b/arch/arm/mach-mvebu/lowlevel_spl.S @@ -3,6 +3,15 @@ #include #include +/* + * BootROM loads the header part of kwbimage into L2 cache. BIN header usually + * contains U-Boot SPL, optionally it can also contain additional arguments. + * The number of these arguments is in r0, pointer to the argument array in r1. + * BootROM expects executable BIN header code to return to address stored in lr. + * Other registers (r2 - r12) must be preserved. We save all registers to + * CONFIG_SPL_BOOTROM_SAVE address. BIN header arguments (passed via r0 and r1) + * are currently not used by U-Boot SPL binary. + */ ENTRY(save_boot_params) stmfd sp!, {r0 - r12, lr} /* @ save registers on stack */ ldr r12, =CONFIG_SPL_BOOTROM_SAVE diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index b798c797cc..cad3f0a488 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -72,11 +72,11 @@ #define IBR_HDR_UART_ID 0x69 #define IBR_HDR_SDIO_ID 0xAE -/* Structure of the main header, version 1 (Armada 370/38x/XP) */ +/* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */ struct kwbimage_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 */ diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 39051a803a..36c596efc5 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -603,7 +603,7 @@ static bool fixup_mtd_partitions(void *blob, int offset, struct mtd_info *mtd) mtd_probe_devices(); - list_for_each_entry(slave, &mtd->partitions, node) { + list_for_each_entry_reverse(slave, &mtd->partitions, node) { char name[32]; int part; diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index d4f381b6ad..a7f3ff3c6f 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -85,11 +85,11 @@ struct mvebu_image_info { }; #endif -/* Structure of the main header, version 1 (Armada 370/38x/XP) */ +/* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */ struct a38x_main_hdr_v1 { u8 blockid; /* 0x0 */ u8 flags; /* 0x1 */ - u16 reserved2; /* 0x2-0x3 */ + u16 nandpagesize; /* 0x2-0x3 */ u32 blocksize; /* 0x4-0x7 */ u8 version; /* 0x8 */ u8 headersz_msb; /* 0x9 */ diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 77bf4dd886..67c0c628ae 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: @@ -1214,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; @@ -1299,7 +1319,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; } diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 126d482fe7..f1ba95c2fa 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 */ diff --git a/tools/kwboot.c b/tools/kwboot.c index 6a1a030308..7e1be29623 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 @@ -1416,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) { @@ -1468,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;