From e29f1db3dd96901fb54d8faefed8cd2987704b68 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 29 Sep 2015 09:19:59 +0200 Subject: [PATCH] tools: kwboot: Add support for UART boot mode patching for Armada XP/38x Currently, kwboot only allows dynamic UART boot mode patching for SoCs with header version 0 (Orion, Kirkwood). This patch now enables this "-p" feature also for SoCs with header version 1 (Armada XP / 38x etc). With this its possible now to use the UART boot mode without on images that are generated for other boot devices, like SPI. So no need to change BOOT_FROM to "uart" for UART xmodem booting any more. Signed-off-by: Stefan Roese Tested-by: Kevin Smith Cc: Luka Perkov Cc: Dirk Eibach --- tools/kwbimage.c | 94 --------------------------------- tools/kwbimage.h | 133 ++++++++++++++++++++++++++++++++++------------- tools/kwboot.c | 37 +++++++++---- 3 files changed, 125 insertions(+), 139 deletions(-) diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 3fa90d3a75..5e62d08a80 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -17,89 +17,6 @@ #include #include "kwbimage.h" -#define ALIGN_SUP(x, a) (((x) + (a - 1)) & ~(a - 1)) - -/* Structure of the main header, version 0 (Kirkwood, Dove) */ -struct main_hdr_v0 { - uint8_t blockid; /*0 */ - uint8_t nandeccmode; /*1 */ - uint16_t nandpagesize; /*2-3 */ - uint32_t blocksize; /*4-7 */ - uint32_t rsvd1; /*8-11 */ - uint32_t srcaddr; /*12-15 */ - uint32_t destaddr; /*16-19 */ - uint32_t execaddr; /*20-23 */ - uint8_t satapiomode; /*24 */ - uint8_t rsvd3; /*25 */ - uint16_t ddrinitdelay; /*26-27 */ - uint16_t rsvd2; /*28-29 */ - uint8_t ext; /*30 */ - uint8_t checksum; /*31 */ -}; - -struct ext_hdr_v0_reg { - uint32_t raddr; - uint32_t rdata; -}; - -#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg)) - -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; -}; - -/* Structure of the main header, version 1 (Armada 370, Armada XP) */ -struct main_hdr_v1 { - uint8_t blockid; /* 0 */ - uint8_t reserved1; /* 1 */ - uint16_t reserved2; /* 2-3 */ - uint32_t blocksize; /* 4-7 */ - uint8_t version; /* 8 */ - uint8_t headersz_msb; /* 9 */ - uint16_t headersz_lsb; /* A-B */ - uint32_t srcaddr; /* C-F */ - uint32_t destaddr; /* 10-13 */ - uint32_t execaddr; /* 14-17 */ - uint8_t reserved3; /* 18 */ - uint8_t nandblocksize; /* 19 */ - uint8_t nandbadblklocation; /* 1A */ - uint8_t reserved4; /* 1B */ - uint16_t reserved5; /* 1C-1D */ - uint8_t ext; /* 1E */ - uint8_t checksum; /* 1F */ -}; - -/* - * Header for the optional headers, version 1 (Armada 370, Armada XP) - */ -struct opt_hdr_v1 { - uint8_t headertype; - uint8_t headersz_msb; - uint16_t headersz_lsb; - char data[0]; -}; - -/* - * Various values for the opt_hdr_v1->headertype field, describing the - * different types of optional headers. The "secure" header contains - * informations related to secure boot (encryption keys, etc.). The - * "binary" header contains ARM binary code to be executed prior to - * executing the main payload (usually the bootloader). This is - * typically used to execute DDR3 training code. The "register" header - * allows to describe a set of (address, value) tuples that are - * generally used to configure the DRAM controller. - */ -#define OPT_HDR_V1_SECURE_TYPE 0x1 -#define OPT_HDR_V1_BINARY_TYPE 0x2 -#define OPT_HDR_V1_REGISTER_TYPE 0x3 - -#define KWBHEADER_V1_SIZE(hdr) \ - (((hdr)->headersz_msb << 16) | (hdr)->headersz_lsb) - static struct image_cfg_element *image_cfg; static int cfgn; @@ -173,17 +90,6 @@ struct image_cfg_element { #define IMAGE_CFG_ELEMENT_MAX 256 -/* - * Byte 8 of the image header contains the version number. In the v0 - * header, byte 8 was reserved, and always set to 0. In the v1 header, - * byte 8 has been changed to a proper field, set to 1. - */ -static unsigned int image_version(void *header) -{ - unsigned char *ptr = header; - return ptr[8]; -} - /* * Utility functions to manipulate boot mode and ecc modes (convert * them back and forth between description strings and the diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 8e4a4e2810..9d2585c0e7 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -29,57 +29,109 @@ #define IBR_HDR_UART_ID 0x69 #define IBR_DEF_ATTRIB 0x00 -enum kwbimage_cmd { - CMD_INVALID, - CMD_BOOT_FROM, - CMD_NAND_ECC_MODE, - CMD_NAND_PAGE_SIZE, - CMD_SATA_PIO_MODE, - CMD_DDR_INIT_DELAY, - CMD_DATA -}; +#define ALIGN_SUP(x, a) (((x) + (a - 1)) & ~(a - 1)) -enum kwbimage_cmd_types { - CFG_INVALID = -1, - CFG_COMMAND, - CFG_DATA0, - CFG_DATA1 -}; - -/* typedefs */ -typedef struct bhr_t { - uint8_t blockid; /*0 */ - uint8_t nandeccmode; /*1 */ +/* Structure of the main header, version 0 (Kirkwood, Dove) */ +struct main_hdr_v0 { + uint8_t blockid; /*0 */ + uint8_t nandeccmode; /*1 */ uint16_t nandpagesize; /*2-3 */ uint32_t blocksize; /*4-7 */ uint32_t rsvd1; /*8-11 */ uint32_t srcaddr; /*12-15 */ uint32_t destaddr; /*16-19 */ uint32_t execaddr; /*20-23 */ - uint8_t satapiomode; /*24 */ - uint8_t rsvd3; /*25 */ + uint8_t satapiomode; /*24 */ + uint8_t rsvd3; /*25 */ uint16_t ddrinitdelay; /*26-27 */ uint16_t rsvd2; /*28-29 */ - uint8_t ext; /*30 */ - uint8_t checkSum; /*31 */ -} bhr_t, *pbhr_t; + uint8_t ext; /*30 */ + uint8_t checksum; /*31 */ +}; -struct reg_config { +struct ext_hdr_v0_reg { uint32_t raddr; uint32_t rdata; }; -typedef struct extbhr_t { - uint32_t dramregsoffs; - uint8_t rsrvd1[0x20 - sizeof(uint32_t)]; - struct reg_config rcfg[KWBIMAGE_MAX_CONFIG]; - uint8_t rsrvd2[7]; - uint8_t checkSum; -} extbhr_t, *pextbhr_t; +#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg)) + +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; +}; struct kwb_header { - bhr_t kwb_hdr; - extbhr_t kwb_exthdr; + struct main_hdr_v0 kwb_hdr; + struct ext_hdr_v0 kwb_exthdr; +}; + +/* Structure of the main header, version 1 (Armada 370, Armada XP) */ +struct main_hdr_v1 { + uint8_t blockid; /* 0 */ + uint8_t reserved1; /* 1 */ + uint16_t reserved2; /* 2-3 */ + uint32_t blocksize; /* 4-7 */ + uint8_t version; /* 8 */ + uint8_t headersz_msb; /* 9 */ + uint16_t headersz_lsb; /* A-B */ + uint32_t srcaddr; /* C-F */ + uint32_t destaddr; /* 10-13 */ + uint32_t execaddr; /* 14-17 */ + uint8_t reserved3; /* 18 */ + uint8_t nandblocksize; /* 19 */ + uint8_t nandbadblklocation; /* 1A */ + uint8_t reserved4; /* 1B */ + uint16_t reserved5; /* 1C-1D */ + uint8_t ext; /* 1E */ + uint8_t checksum; /* 1F */ +}; + +/* + * Header for the optional headers, version 1 (Armada 370, Armada XP) + */ +struct opt_hdr_v1 { + uint8_t headertype; + uint8_t headersz_msb; + uint16_t headersz_lsb; + char data[0]; +}; + +/* + * Various values for the opt_hdr_v1->headertype field, describing the + * different types of optional headers. The "secure" header contains + * informations related to secure boot (encryption keys, etc.). The + * "binary" header contains ARM binary code to be executed prior to + * executing the main payload (usually the bootloader). This is + * typically used to execute DDR3 training code. The "register" header + * allows to describe a set of (address, value) tuples that are + * generally used to configure the DRAM controller. + */ +#define OPT_HDR_V1_SECURE_TYPE 0x1 +#define OPT_HDR_V1_BINARY_TYPE 0x2 +#define OPT_HDR_V1_REGISTER_TYPE 0x3 + +#define KWBHEADER_V1_SIZE(hdr) \ + (((hdr)->headersz_msb << 16) | (hdr)->headersz_lsb) + +enum kwbimage_cmd { + CMD_INVALID, + CMD_BOOT_FROM, + CMD_NAND_ECC_MODE, + CMD_NAND_PAGE_SIZE, + CMD_SATA_PIO_MODE, + CMD_DDR_INIT_DELAY, + CMD_DATA +}; + +enum kwbimage_cmd_types { + CFG_INVALID = -1, + CFG_COMMAND, + CFG_DATA0, + CFG_DATA1 }; /* @@ -87,4 +139,15 @@ struct kwb_header { */ void init_kwb_image_type (void); +/* + * Byte 8 of the image header contains the version number. In the v0 + * header, byte 8 was reserved, and always set to 0. In the v1 header, + * byte 8 has been changed to a proper field, set to 1. + */ +static inline unsigned int image_version(void *header) +{ + unsigned char *ptr = header; + return ptr[8]; +} + #endif /* _KWBIMAGE_H_ */ diff --git a/tools/kwboot.c b/tools/kwboot.c index af7a6ee3f6..c5f4492b5f 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -614,9 +614,10 @@ static int kwboot_img_patch_hdr(void *img, size_t size) { int rc; - bhr_t *hdr; + struct main_hdr_v1 *hdr; uint8_t csum; - const size_t hdrsz = sizeof(*hdr); + size_t hdrsz = sizeof(*hdr); + int image_ver; rc = -1; hdr = img; @@ -626,8 +627,20 @@ kwboot_img_patch_hdr(void *img, size_t size) goto out; } - csum = kwboot_img_csum8(hdr, hdrsz) - hdr->checkSum; - if (csum != hdr->checkSum) { + image_ver = image_version(img); + if (image_ver < 0) { + fprintf(stderr, "Invalid image header version\n"); + errno = EINVAL; + goto out; + } + + if (image_ver == 0) + hdrsz = sizeof(*hdr); + else + hdrsz = KWBHEADER_V1_SIZE(hdr); + + csum = kwboot_img_csum8(hdr, hdrsz) - hdr->checksum; + if (csum != hdr->checksum) { errno = EINVAL; goto out; } @@ -639,14 +652,18 @@ kwboot_img_patch_hdr(void *img, size_t size) hdr->blockid = IBR_HDR_UART_ID; - hdr->nandeccmode = IBR_HDR_ECC_DISABLED; - hdr->nandpagesize = 0; + if (image_ver == 0) { + struct main_hdr_v0 *hdr_v0 = img; - hdr->srcaddr = hdr->ext - ? sizeof(struct kwb_header) - : sizeof(*hdr); + hdr_v0->nandeccmode = IBR_HDR_ECC_DISABLED; + hdr_v0->nandpagesize = 0; + + hdr_v0->srcaddr = hdr_v0->ext + ? sizeof(struct kwb_header) + : sizeof(*hdr_v0); + } - hdr->checkSum = kwboot_img_csum8(hdr, hdrsz) - csum; + hdr->checksum = kwboot_img_csum8(hdr, hdrsz) - csum; rc = 0; out: -- 2.25.1