]> git.sur5r.net Git - u-boot/blobdiff - tools/kwbimage.c
tools: kwbimage: Fix arithmetic with void pointers
[u-boot] / tools / kwbimage.c
index 5e62d08a80799ac1f5d707d81589d35982574ce8..edc5d3453ac04f9f705f9f248bdcf5dcb82b3c4f 100644 (file)
@@ -68,6 +68,8 @@ struct image_cfg_element {
                IMAGE_CFG_BINARY,
                IMAGE_CFG_PAYLOAD,
                IMAGE_CFG_DATA,
+               IMAGE_CFG_BAUDRATE,
+               IMAGE_CFG_DEBUG,
        } type;
        union {
                unsigned int version;
@@ -85,6 +87,8 @@ struct image_cfg_element {
                unsigned int nandeccmode;
                unsigned int nandpagesz;
                struct ext_hdr_v0_reg regdata;
+               unsigned int baudrate;
+               unsigned int debug;
        };
 };
 
@@ -99,6 +103,7 @@ struct image_cfg_element {
 static const char *image_boot_mode_name(unsigned int id)
 {
        int i;
+
        for (i = 0; boot_modes[i].name; i++)
                if (boot_modes[i].id == id)
                        return boot_modes[i].name;
@@ -108,6 +113,7 @@ static const char *image_boot_mode_name(unsigned int id)
 int image_boot_mode_id(const char *boot_mode_name)
 {
        int i;
+
        for (i = 0; boot_modes[i].name; i++)
                if (!strcmp(boot_modes[i].name, boot_mode_name))
                        return boot_modes[i].id;
@@ -118,6 +124,7 @@ int image_boot_mode_id(const char *boot_mode_name)
 int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
 {
        int i;
+
        for (i = 0; nand_ecc_modes[i].name; i++)
                if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
                        return nand_ecc_modes[i].id;
@@ -195,6 +202,28 @@ static uint32_t image_checksum32(void *start, uint32_t len)
        return csum;
 }
 
+static uint8_t baudrate_to_option(unsigned int baudrate)
+{
+       switch (baudrate) {
+       case 2400:
+               return MAIN_HDR_V1_OPT_BAUD_2400;
+       case 4800:
+               return MAIN_HDR_V1_OPT_BAUD_4800;
+       case 9600:
+               return MAIN_HDR_V1_OPT_BAUD_9600;
+       case 19200:
+               return MAIN_HDR_V1_OPT_BAUD_19200;
+       case 38400:
+               return MAIN_HDR_V1_OPT_BAUD_38400;
+       case 57600:
+               return MAIN_HDR_V1_OPT_BAUD_57600;
+       case 115200:
+               return MAIN_HDR_V1_OPT_BAUD_115200;
+       default:
+               return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
+       }
+}
+
 static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
                             int payloadsz)
 {
@@ -202,7 +231,7 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
        size_t headersz;
        struct main_hdr_v0 *main_hdr;
        struct ext_hdr_v0 *ext_hdr;
-       void *image;
+       uint8_t *image;
        int has_ext = 0;
 
        /*
@@ -229,14 +258,15 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
 
        memset(image, 0, headersz);
 
-       main_hdr = image;
+       main_hdr = (struct main_hdr_v0 *)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)
@@ -246,7 +276,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));
 
@@ -254,16 +284,19 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
        if (has_ext) {
                int cfgi, datai;
 
-               ext_hdr = image + sizeof(struct main_hdr_v0);
-               ext_hdr->offset = 0x40;
+               ext_hdr = (struct ext_hdr_v0 *)
+                               (image + sizeof(struct main_hdr_v0));
+               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++;
                }
 
@@ -321,22 +354,23 @@ 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,
+                       "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;
        }
+       headersz = CONFIG_SYS_U_BOOT_OFFS;
 #endif
 
        /*
@@ -352,7 +386,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
        struct image_cfg_element *e, *binarye;
        struct main_hdr_v1 *main_hdr;
        size_t headersz;
-       void *image, *cur;
+       uint8_t *image, *cur;
        int hasext = 0;
        int ret;
 
@@ -372,16 +406,18 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 
        memset(image, 0, headersz);
 
-       cur = main_hdr = image;
-       cur += sizeof(struct main_hdr_v1);
+       main_hdr = (struct main_hdr_v1 *)image;
+       cur = image + 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)
+                                - sizeof(image_header_t);
+       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);
@@ -393,11 +429,17 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
        e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
        if (e)
                main_hdr->nandbadblklocation = e->nandbadblklocation;
+       e = image_find_option(IMAGE_CFG_BAUDRATE);
+       if (e)
+               main_hdr->options = baudrate_to_option(e->baudrate);
+       e = image_find_option(IMAGE_CFG_DEBUG);
+       if (e)
+               main_hdr->flags = e->debug ? 0x1 : 0;
 
        binarye = image_find_option(IMAGE_CFG_BINARY);
        if (binarye) {
-               struct opt_hdr_v1 *hdr = cur;
-               unsigned int *args;
+               struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
+               uint32_t *args;
                size_t binhdrsz;
                struct stat s;
                int argi;
@@ -415,21 +457,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;
-               binhdrsz = ALIGN_SUP(binhdrsz, 32);
-               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 = (uint32_t *)cur;
+               *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) {
@@ -441,7 +489,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
@@ -449,7 +497,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);
        }
@@ -470,11 +518,13 @@ static int image_create_config_parse_oneline(char *line,
        keyword = strtok_r(line, deliminiters, &saveptr);
        if (!strcmp(keyword, "VERSION")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
+
                el->type = IMAGE_CFG_VERSION;
                el->version = atoi(value);
        } else if (!strcmp(keyword, "BOOT_FROM")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
                int ret = image_boot_mode_id(value);
+
                if (ret < 0) {
                        fprintf(stderr,
                                "Invalid boot media '%s'\n", value);
@@ -484,16 +534,19 @@ static int image_create_config_parse_oneline(char *line,
                el->bootfrom = ret;
        } else if (!strcmp(keyword, "NAND_BLKSZ")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
+
                el->type = IMAGE_CFG_NAND_BLKSZ;
                el->nandblksz = strtoul(value, NULL, 16);
        } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
+
                el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
                el->nandbadblklocation =
                        strtoul(value, NULL, 16);
        } else if (!strcmp(keyword, "NAND_ECC_MODE")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
                int ret = image_nand_ecc_mode_id(value);
+
                if (ret < 0) {
                        fprintf(stderr,
                                "Invalid NAND ECC mode '%s'\n", value);
@@ -503,6 +556,7 @@ static int image_create_config_parse_oneline(char *line,
                el->nandeccmode = ret;
        } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
                char *value = strtok_r(NULL, deliminiters, &saveptr);
+
                el->type = IMAGE_CFG_NAND_PAGESZ;
                el->nandpagesz = strtoul(value, NULL, 16);
        } else if (!strcmp(keyword, "BINARY")) {
@@ -537,6 +591,14 @@ static int image_create_config_parse_oneline(char *line,
                el->type = IMAGE_CFG_DATA;
                el->regdata.raddr = strtoul(value1, NULL, 16);
                el->regdata.rdata = strtoul(value2, NULL, 16);
+       } else if (!strcmp(keyword, "BAUDRATE")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_BAUDRATE;
+               el->baudrate = strtoul(value, NULL, 10);
+       } else if (!strcmp(keyword, "DEBUG")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_DEBUG;
+               el->debug = strtoul(value, NULL, 10);
        } else {
                fprintf(stderr, "Ignoring unknown line '%s'\n", line);
        }
@@ -681,6 +743,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) {
                /*
@@ -711,7 +776,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",
@@ -744,8 +810,8 @@ static int kwbimage_check_image_types(uint8_t type)
 {
        if (type == IH_TYPE_KWBIMAGE)
                return EXIT_SUCCESS;
-       else
-               return EXIT_FAILURE;
+
+       return EXIT_FAILURE;
 }
 
 static int kwbimage_verify_header(unsigned char *ptr, int image_size,
@@ -755,7 +821,7 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,
        struct ext_hdr_v0 *ext_hdr;
        uint8_t checksum;
 
-       main_hdr = (void *)ptr;
+       main_hdr = (struct main_hdr_v0 *)ptr;
        checksum = image_checksum8(ptr,
                                   sizeof(struct main_hdr_v0)
                                   - sizeof(uint8_t));
@@ -764,7 +830,8 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,
 
        /* Only version 0 extended header has checksum */
        if (image_version((void *)ptr) == 0) {
-               ext_hdr = (void *)ptr + sizeof(struct main_hdr_v0);
+               ext_hdr = (struct ext_hdr_v0 *)
+                               (ptr + sizeof(struct main_hdr_v0));
                checksum = image_checksum8(ext_hdr,
                                           sizeof(struct ext_hdr_v0)
                                           - sizeof(uint8_t));
@@ -801,7 +868,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;
 }
 
 /*
@@ -810,9 +885,9 @@ static int kwbimage_generate(struct image_tool_params *params,
 static int kwbimage_check_params(struct image_tool_params *params)
 {
        if (!strlen(params->imagename)) {
-               fprintf(stderr, "Error:%s - Configuration file not specified, "
-                       "it is needed for kwbimage generation\n",
-                       params->cmdname);
+               char *msg = "Configuration file for kwbimage creation omitted";
+
+               fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
                return CFG_INVALID;
        }