tools: kwboot: Add support for UART boot mode patching for Armada XP/38x
authorStefan Roese <sr@denx.de>
Tue, 29 Sep 2015 07:19:59 +0000 (09:19 +0200)
committerLuka Perkov <luka.perkov@sartura.hr>
Thu, 1 Oct 2015 00:02:06 +0000 (02:02 +0200)
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 <sr@denx.de>
Tested-by: Kevin Smith <kevin.smith@elecsyscorp.com>
Cc: Luka Perkov <luka.perkov@sartura.hr>
Cc: Dirk Eibach <eibach@gdsys.de>
tools/kwbimage.c
tools/kwbimage.h
tools/kwboot.c

index 3fa90d3a758ab407206773fa3fd932d696794a8d..5e62d08a80799ac1f5d707d81589d35982574ce8 100644 (file)
 #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;
 
@@ -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
index 8e4a4e2810e66413fb11d4197869a975e22d4eee..9d2585c0e727238689520cf92747d8da5bfa017c 100644 (file)
 #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_ */
index af7a6ee3f6a12c04ac3782cb8703617d63375b45..c5f4492b5f7ab3d4a3b1a609740316cebcb7dae5 100644 (file)
@@ -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: