#include <stdint.h>
#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;
#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
#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
};
/*
*/
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_ */
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;
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;
}
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: