]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - tools/kwbimage.c
arc/cache: really do invalidate_dcache_all() even if IOC exists
[people/ms/u-boot.git] / tools / kwbimage.c
index 2c302e5d4981e94c1969f47703da03062495fd01..369aba7bcab9d00e6c965354ff05bb579d420809 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;
 
@@ -115,6 +32,7 @@ struct boot_mode boot_modes[] = {
        { 0x78, "sata" },
        { 0x9C, "pex"  },
        { 0x69, "uart" },
+       { 0xAE, "sdio" },
        {},
 };
 
@@ -172,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
@@ -325,11 +232,12 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
        main_hdr = image;
 
        /* Fill in the main header */
-       main_hdr->blocksize = payloadsz + sizeof(uint32_t) - headersz;
-       main_hdr->srcaddr   = headersz;
+       main_hdr->blocksize =
+               cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz);
+       main_hdr->srcaddr   = cpu_to_le32(headersz);
        main_hdr->ext       = has_ext;
-       main_hdr->destaddr  = params->addr;
-       main_hdr->execaddr  = params->ep;
+       main_hdr->destaddr  = cpu_to_le32(params->addr);
+       main_hdr->execaddr  = cpu_to_le32(params->ep);
 
        e = image_find_option(IMAGE_CFG_BOOT_FROM);
        if (e)
@@ -339,7 +247,7 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
                main_hdr->nandeccmode = e->nandeccmode;
        e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
        if (e)
-               main_hdr->nandpagesize = e->nandpagesz;
+               main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
        main_hdr->checksum = image_checksum8(image,
                                             sizeof(struct main_hdr_v0));
 
@@ -348,15 +256,17 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
                int cfgi, datai;
 
                ext_hdr = image + sizeof(struct main_hdr_v0);
-               ext_hdr->offset = 0x40;
+               ext_hdr->offset = cpu_to_le32(0x40);
 
                for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
                        e = &image_cfg[cfgi];
                        if (e->type != IMAGE_CFG_DATA)
                                continue;
 
-                       ext_hdr->rcfg[datai].raddr = e->regdata.raddr;
-                       ext_hdr->rcfg[datai].rdata = e->regdata.rdata;
+                       ext_hdr->rcfg[datai].raddr =
+                               cpu_to_le32(e->regdata.raddr);
+                       ext_hdr->rcfg[datai].rdata =
+                               cpu_to_le32(e->regdata.rdata);
                        datai++;
                }
 
@@ -414,12 +324,25 @@ static size_t image_headersz_v1(struct image_tool_params *params,
                        return 0;
                }
 
-               headersz += s.st_size +
-                       binarye->binary.nargs * sizeof(unsigned int);
+               headersz += sizeof(struct opt_hdr_v1) +
+                       s.st_size +
+                       (binarye->binary.nargs + 2) * sizeof(uint32_t);
                if (hasext)
                        *hasext = 1;
        }
 
+#if defined(CONFIG_SYS_U_BOOT_OFFS)
+       if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
+               fprintf(stderr, "Error: Image header (incl. SPL image) too big!\n");
+               fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
+                       (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
+               fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
+               return 0;
+       } else {
+               headersz = CONFIG_SYS_U_BOOT_OFFS;
+       }
+#endif
+
        /*
         * The payload should be aligned on some reasonable
         * boundary
@@ -457,12 +380,13 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
        cur += sizeof(struct main_hdr_v1);
 
        /* Fill the main header */
-       main_hdr->blocksize    = payloadsz - headersz + sizeof(uint32_t);
-       main_hdr->headersz_lsb = headersz & 0xFFFF;
+       main_hdr->blocksize    =
+               cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
+       main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
        main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
-       main_hdr->destaddr     = params->addr;
-       main_hdr->execaddr     = params->ep;
-       main_hdr->srcaddr      = headersz;
+       main_hdr->destaddr     = cpu_to_le32(params->addr);
+       main_hdr->execaddr     = cpu_to_le32(params->ep);
+       main_hdr->srcaddr      = cpu_to_le32(headersz);
        main_hdr->ext          = hasext;
        main_hdr->version      = 1;
        e = image_find_option(IMAGE_CFG_BOOT_FROM);
@@ -478,7 +402,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
        binarye = image_find_option(IMAGE_CFG_BINARY);
        if (binarye) {
                struct opt_hdr_v1 *hdr = cur;
-               unsigned int *args;
+               uint32_t *args;
                size_t binhdrsz;
                struct stat s;
                int argi;
@@ -496,20 +420,27 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
                fstat(fileno(bin), &s);
 
                binhdrsz = sizeof(struct opt_hdr_v1) +
-                       (binarye->binary.nargs + 1) * sizeof(unsigned int) +
+                       (binarye->binary.nargs + 2) * sizeof(uint32_t) +
                        s.st_size;
-               hdr->headersz_lsb = binhdrsz & 0xFFFF;
+
+               /*
+                * The size includes the binary image size, rounded
+                * up to a 4-byte boundary. Plus 4 bytes for the
+                * next-header byte and 3-byte alignment at the end.
+                */
+               binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
+               hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
                hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
 
                cur += sizeof(struct opt_hdr_v1);
 
                args = cur;
-               *args = binarye->binary.nargs;
+               *args = cpu_to_le32(binarye->binary.nargs);
                args++;
                for (argi = 0; argi < binarye->binary.nargs; argi++)
-                       args[argi] = binarye->binary.args[argi];
+                       args[argi] = cpu_to_le32(binarye->binary.args[argi]);
 
-               cur += (binarye->binary.nargs + 1) * sizeof(unsigned int);
+               cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
 
                ret = fread(cur, s.st_size, 1, bin);
                if (ret != 1) {
@@ -521,7 +452,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 
                fclose(bin);
 
-               cur += s.st_size;
+               cur += ALIGN_SUP(s.st_size, 4);
 
                /*
                 * For now, we don't support more than one binary
@@ -529,7 +460,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
                 * supported. So, the binary header is necessarily the
                 * last one
                 */
-               *((unsigned char *)cur) = 0;
+               *((uint32_t *)cur) = 0x00000000;
 
                cur += sizeof(uint32_t);
        }
@@ -554,13 +485,14 @@ static int image_create_config_parse_oneline(char *line,
                el->version = atoi(value);
        } else if (!strcmp(keyword, "BOOT_FROM")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
-               el->type = IMAGE_CFG_BOOT_FROM;
-               el->bootfrom = image_boot_mode_id(value);
-               if (el->bootfrom < 0) {
+               int ret = image_boot_mode_id(value);
+               if (ret < 0) {
                        fprintf(stderr,
                                "Invalid boot media '%s'\n", value);
                        return -1;
                }
+               el->type = IMAGE_CFG_BOOT_FROM;
+               el->bootfrom = ret;
        } else if (!strcmp(keyword, "NAND_BLKSZ")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
                el->type = IMAGE_CFG_NAND_BLKSZ;
@@ -572,13 +504,14 @@ static int image_create_config_parse_oneline(char *line,
                        strtoul(value, NULL, 16);
        } else if (!strcmp(keyword, "NAND_ECC_MODE")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
-               el->type = IMAGE_CFG_NAND_ECC_MODE;
-               el->nandeccmode = image_nand_ecc_mode_id(value);
-               if (el->nandeccmode < 0) {
+               int ret = image_nand_ecc_mode_id(value);
+               if (ret < 0) {
                        fprintf(stderr,
                                "Invalid NAND ECC mode '%s'\n", value);
                        return -1;
                }
+               el->type = IMAGE_CFG_NAND_ECC_MODE;
+               el->nandeccmode = ret;
        } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
                el->type = IMAGE_CFG_NAND_PAGESZ;
@@ -759,6 +692,9 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
                exit(EXIT_FAILURE);
        }
 
+       /* The MVEBU BootROM does not allow non word aligned payloads */
+       sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4);
+
        version = image_get_version();
        switch (version) {
                /*
@@ -789,7 +725,8 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
        free(image_cfg);
 
        /* Build and add image checksum header */
-       checksum = image_checksum32((uint32_t *)ptr, sbuf->st_size);
+       checksum =
+               cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size));
        size = write(ifd, &checksum, sizeof(uint32_t));
        if (size != sizeof(uint32_t)) {
                fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n",
@@ -879,7 +816,15 @@ static int kwbimage_generate(struct image_tool_params *params,
        tparams->header_size = alloc_len;
        tparams->hdr = hdr;
 
-       return 0;
+       /*
+        * The resulting image needs to be 4-byte aligned. At least
+        * the Marvell hdrparser tool complains if its unaligned.
+        * By returning 1 here in this function, called via
+        * tparams->vrec_header() in mkimage.c, mkimage will
+        * automatically pad the the resulting image to a 4-byte
+        * size if necessary.
+        */
+       return 1;
 }
 
 /*
@@ -903,19 +848,17 @@ static int kwbimage_check_params(struct image_tool_params *params)
 /*
  * kwbimage type parameters definition
  */
-static struct image_type_params kwbimage_params = {
-       .name           = "Marvell MVEBU Boot Image support",
-       .header_size    = 0,            /* no fixed header size */
-       .hdr            = NULL,
-       .vrec_header    = kwbimage_generate,
-       .check_image_type = kwbimage_check_image_types,
-       .verify_header  = kwbimage_verify_header,
-       .print_header   = kwbimage_print_header,
-       .set_header     = kwbimage_set_header,
-       .check_params   = kwbimage_check_params,
-};
-
-void init_kwb_image_type (void)
-{
-       register_image_type(&kwbimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+       kwbimage,
+       "Marvell MVEBU Boot Image support",
+       0,
+       NULL,
+       kwbimage_check_params,
+       kwbimage_verify_header,
+       kwbimage_print_header,
+       kwbimage_set_header,
+       NULL,
+       kwbimage_check_image_types,
+       NULL,
+       kwbimage_generate
+);