diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 3fa90d3..5e62d08 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; @@ -174,17 +91,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 * corresponding numerical identifiers). diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 8e4a4e2..9d2585c 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 af7a6ee..c5f4492 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: