uboot/tools/imximage.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2009
   4 * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
   5 *
   6 * (C) Copyright 2008
   7 * Marvell Semiconductor <www.marvell.com>
   8 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
   9 */
  10
  11#include "imagetool.h"
  12#include <image.h>
  13#include "imximage.h"
  14
  15#define UNDEFINED 0xFFFFFFFF
  16
  17/*
  18 * Supported commands for configuration file
  19 */
  20static table_entry_t imximage_cmds[] = {
  21        {CMD_BOOT_FROM,         "BOOT_FROM",            "boot command",   },
  22        {CMD_BOOT_OFFSET,       "BOOT_OFFSET",          "Boot offset",    },
  23        {CMD_WRITE_DATA,        "DATA",                 "Reg Write Data", },
  24        {CMD_WRITE_CLR_BIT,     "CLR_BIT",              "Reg clear bit",  },
  25        {CMD_WRITE_SET_BIT,     "SET_BIT",              "Reg set bit",  },
  26        {CMD_CHECK_BITS_SET,    "CHECK_BITS_SET",   "Reg Check bits set", },
  27        {CMD_CHECK_BITS_CLR,    "CHECK_BITS_CLR",   "Reg Check bits clr", },
  28        {CMD_CSF,               "CSF",           "Command Sequence File", },
  29        {CMD_IMAGE_VERSION,     "IMAGE_VERSION",        "image version",  },
  30        {CMD_PLUGIN,            "PLUGIN",               "file plugin_addr",  },
  31        {-1,                    "",                     "",               },
  32};
  33
  34/*
  35 * Supported Boot options for configuration file
  36 * this is needed to set the correct flash offset
  37 */
  38static table_entry_t imximage_boot_offset[] = {
  39        {FLASH_OFFSET_ONENAND,  "onenand",      "OneNAND Flash",},
  40        {FLASH_OFFSET_NAND,     "nand",         "NAND Flash",   },
  41        {FLASH_OFFSET_NOR,      "nor",          "NOR Flash",    },
  42        {FLASH_OFFSET_SATA,     "sata",         "SATA Disk",    },
  43        {FLASH_OFFSET_SD,       "sd",           "SD Card",      },
  44        {FLASH_OFFSET_SPI,      "spi",          "SPI Flash",    },
  45        {FLASH_OFFSET_QSPI,     "qspi",         "QSPI NOR Flash",},
  46        {-1,                    "",             "Invalid",      },
  47};
  48
  49/*
  50 * Supported Boot options for configuration file
  51 * this is needed to determine the initial load size
  52 */
  53static table_entry_t imximage_boot_loadsize[] = {
  54        {FLASH_LOADSIZE_ONENAND,        "onenand",      "OneNAND Flash",},
  55        {FLASH_LOADSIZE_NAND,           "nand",         "NAND Flash",   },
  56        {FLASH_LOADSIZE_NOR,            "nor",          "NOR Flash",    },
  57        {FLASH_LOADSIZE_SATA,           "sata",         "SATA Disk",    },
  58        {FLASH_LOADSIZE_SD,             "sd",           "SD Card",      },
  59        {FLASH_LOADSIZE_SPI,            "spi",          "SPI Flash",    },
  60        {FLASH_LOADSIZE_QSPI,           "qspi",         "QSPI NOR Flash",},
  61        {-1,                            "",             "Invalid",      },
  62};
  63
  64/*
  65 * IMXIMAGE version definition for i.MX chips
  66 */
  67static table_entry_t imximage_versions[] = {
  68        {IMXIMAGE_V1,   "",     " (i.MX25/35/51 compatible)", },
  69        {IMXIMAGE_V2,   "",     " (i.MX53/6/7 compatible)",   },
  70        {-1,            "",     " (Invalid)",                 },
  71};
  72
  73static struct imx_header imximage_header;
  74static uint32_t imximage_version;
  75/*
  76 * Image Vector Table Offset
  77 * Initialized to a wrong not 4-bytes aligned address to
  78 * check if it is was set by the cfg file.
  79 */
  80static uint32_t imximage_ivt_offset = UNDEFINED;
  81static uint32_t imximage_csf_size = UNDEFINED;
  82/* Initial Load Region Size */
  83static uint32_t imximage_init_loadsize;
  84static uint32_t imximage_iram_free_start;
  85static uint32_t imximage_plugin_size;
  86static uint32_t plugin_image;
  87
  88static set_dcd_val_t set_dcd_val;
  89static set_dcd_param_t set_dcd_param;
  90static set_dcd_rst_t set_dcd_rst;
  91static set_imx_hdr_t set_imx_hdr;
  92static uint32_t max_dcd_entries;
  93static uint32_t *header_size_ptr;
  94static uint32_t *csf_ptr;
  95
  96static uint32_t get_cfg_value(char *token, char *name,  int linenr)
  97{
  98        char *endptr;
  99        uint32_t value;
 100
 101        errno = 0;
 102        value = strtoul(token, &endptr, 16);
 103        if (errno || (token == endptr)) {
 104                fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n",
 105                        name,  linenr, token);
 106                exit(EXIT_FAILURE);
 107        }
 108        return value;
 109}
 110
 111static uint32_t detect_imximage_version(struct imx_header *imx_hdr)
 112{
 113        imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1;
 114        imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2;
 115        flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
 116        flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
 117
 118        /* Try to detect V1 */
 119        if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) &&
 120                (hdr_v1->dcd_table.preamble.barker == DCD_BARKER))
 121                return IMXIMAGE_V1;
 122
 123        /* Try to detect V2 */
 124        if ((fhdr_v2->header.tag == IVT_HEADER_TAG) &&
 125                (hdr_v2->data.dcd_table.header.tag == DCD_HEADER_TAG))
 126                return IMXIMAGE_V2;
 127
 128        if ((fhdr_v2->header.tag == IVT_HEADER_TAG) &&
 129            hdr_v2->boot_data.plugin)
 130                return IMXIMAGE_V2;
 131
 132        return IMXIMAGE_VER_INVALID;
 133}
 134
 135static void err_imximage_version(int version)
 136{
 137        fprintf(stderr,
 138                "Error: Unsupported imximage version:%d\n", version);
 139
 140        exit(EXIT_FAILURE);
 141}
 142
 143static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno,
 144                                        int fld, uint32_t value, uint32_t off)
 145{
 146        dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
 147
 148        switch (fld) {
 149        case CFG_REG_SIZE:
 150                /* Byte, halfword, word */
 151                if ((value != 1) && (value != 2) && (value != 4)) {
 152                        fprintf(stderr, "Error: %s[%d] - "
 153                                "Invalid register size " "(%d)\n",
 154                                name, lineno, value);
 155                        exit(EXIT_FAILURE);
 156                }
 157                dcd_v1->addr_data[off].type = value;
 158                break;
 159        case CFG_REG_ADDRESS:
 160                dcd_v1->addr_data[off].addr = value;
 161                break;
 162        case CFG_REG_VALUE:
 163                dcd_v1->addr_data[off].value = value;
 164                break;
 165        default:
 166                break;
 167
 168        }
 169}
 170
 171static struct dcd_v2_cmd *gd_last_cmd;
 172
 173static void set_dcd_param_v2(struct imx_header *imxhdr, uint32_t dcd_len,
 174                int32_t cmd)
 175{
 176        dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table;
 177        struct dcd_v2_cmd *d = gd_last_cmd;
 178        struct dcd_v2_cmd *d2;
 179        int len;
 180
 181        if (!d)
 182                d = &dcd_v2->dcd_cmd;
 183        d2 = d;
 184        len = be16_to_cpu(d->write_dcd_command.length);
 185        if (len > 4)
 186                d2 = (struct dcd_v2_cmd *)(((char *)d) + len);
 187
 188        switch (cmd) {
 189        case CMD_WRITE_DATA:
 190                if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) &&
 191                    (d->write_dcd_command.param == DCD_WRITE_DATA_PARAM))
 192                        break;
 193                d = d2;
 194                d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG;
 195                d->write_dcd_command.length = cpu_to_be16(4);
 196                d->write_dcd_command.param = DCD_WRITE_DATA_PARAM;
 197                break;
 198        case CMD_WRITE_CLR_BIT:
 199                if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) &&
 200                    (d->write_dcd_command.param == DCD_WRITE_CLR_BIT_PARAM))
 201                        break;
 202                d = d2;
 203                d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG;
 204                d->write_dcd_command.length = cpu_to_be16(4);
 205                d->write_dcd_command.param = DCD_WRITE_CLR_BIT_PARAM;
 206                break;
 207        case CMD_WRITE_SET_BIT:
 208                if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) &&
 209                    (d->write_dcd_command.param == DCD_WRITE_SET_BIT_PARAM))
 210                        break;
 211                d = d2;
 212                d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG;
 213                d->write_dcd_command.length = cpu_to_be16(4);
 214                d->write_dcd_command.param = DCD_WRITE_SET_BIT_PARAM;
 215                break;
 216        /*
 217         * Check data command only supports one entry,
 218         */
 219        case CMD_CHECK_BITS_SET:
 220                d = d2;
 221                d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG;
 222                d->write_dcd_command.length = cpu_to_be16(4);
 223                d->write_dcd_command.param = DCD_CHECK_BITS_SET_PARAM;
 224                break;
 225        case CMD_CHECK_BITS_CLR:
 226                d = d2;
 227                d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG;
 228                d->write_dcd_command.length = cpu_to_be16(4);
 229                d->write_dcd_command.param = DCD_CHECK_BITS_CLR_PARAM;
 230                break;
 231        default:
 232                break;
 233        }
 234        gd_last_cmd = d;
 235}
 236
 237static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno,
 238                                        int fld, uint32_t value, uint32_t off)
 239{
 240        struct dcd_v2_cmd *d = gd_last_cmd;
 241        int len;
 242
 243        len = be16_to_cpu(d->write_dcd_command.length);
 244        off = (len - 4) >> 3;
 245
 246        switch (fld) {
 247        case CFG_REG_ADDRESS:
 248                d->addr_data[off].addr = cpu_to_be32(value);
 249                break;
 250        case CFG_REG_VALUE:
 251                d->addr_data[off].value = cpu_to_be32(value);
 252                off++;
 253                d->write_dcd_command.length = cpu_to_be16((off << 3) + 4);
 254                break;
 255        default:
 256                break;
 257
 258        }
 259}
 260
 261/*
 262 * Complete setting up the rest field of DCD of V1
 263 * such as barker code and DCD data length.
 264 */
 265static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len,
 266                                                char *name, int lineno)
 267{
 268        dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
 269
 270        dcd_v1->preamble.barker = DCD_BARKER;
 271        dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t);
 272}
 273
 274/*
 275 * Complete setting up the reset field of DCD of V2
 276 * such as DCD tag, version, length, etc.
 277 */
 278static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len,
 279                                                char *name, int lineno)
 280{
 281        if (!imxhdr->header.hdr_v2.boot_data.plugin) {
 282                dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table;
 283                struct dcd_v2_cmd *d = gd_last_cmd;
 284                int len;
 285
 286                if (!d)
 287                        d = &dcd_v2->dcd_cmd;
 288                len = be16_to_cpu(d->write_dcd_command.length);
 289                if (len > 4)
 290                        d = (struct dcd_v2_cmd *)(((char *)d) + len);
 291
 292                len = (char *)d - (char *)&dcd_v2->header;
 293                dcd_v2->header.tag = DCD_HEADER_TAG;
 294                dcd_v2->header.length = cpu_to_be16(len);
 295                dcd_v2->header.version = DCD_VERSION;
 296        }
 297}
 298
 299static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len,
 300                uint32_t entry_point, uint32_t flash_offset)
 301{
 302        imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1;
 303        flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
 304        dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
 305        uint32_t hdr_base;
 306        uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr)
 307                        - ((char *)imxhdr));
 308
 309        /* Set magic number */
 310        fhdr_v1->app_code_barker = APP_CODE_BARKER;
 311
 312        hdr_base = entry_point - imximage_init_loadsize + flash_offset;
 313        fhdr_v1->app_dest_ptr = hdr_base - flash_offset;
 314        fhdr_v1->app_code_jump_vector = entry_point;
 315
 316        fhdr_v1->dcd_ptr_ptr = hdr_base + offsetof(flash_header_v1_t, dcd_ptr);
 317        fhdr_v1->dcd_ptr = hdr_base + offsetof(imx_header_v1_t, dcd_table);
 318
 319        /* Security feature are not supported */
 320        fhdr_v1->app_code_csf = 0;
 321        fhdr_v1->super_root_key = 0;
 322        header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4);
 323}
 324
 325static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len,
 326                uint32_t entry_point, uint32_t flash_offset)
 327{
 328        imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2;
 329        flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
 330        uint32_t hdr_base;
 331
 332        /* Set magic number */
 333        fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */
 334        fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t));
 335        fhdr_v2->header.version = IVT_VERSION; /* 0x40 */
 336
 337        if (!hdr_v2->boot_data.plugin) {
 338                fhdr_v2->entry = entry_point;
 339                fhdr_v2->reserved1 = 0;
 340                fhdr_v2->reserved1 = 0;
 341                hdr_base = entry_point - imximage_init_loadsize +
 342                        flash_offset;
 343                fhdr_v2->self = hdr_base;
 344                if (dcd_len > 0)
 345                        fhdr_v2->dcd_ptr = hdr_base +
 346                                offsetof(imx_header_v2_t, data);
 347                else
 348                        fhdr_v2->dcd_ptr = 0;
 349                fhdr_v2->boot_data_ptr = hdr_base
 350                                + offsetof(imx_header_v2_t, boot_data);
 351                hdr_v2->boot_data.start = entry_point - imximage_init_loadsize;
 352
 353                fhdr_v2->csf = 0;
 354
 355                header_size_ptr = &hdr_v2->boot_data.size;
 356                csf_ptr = &fhdr_v2->csf;
 357        } else {
 358                imx_header_v2_t *next_hdr_v2;
 359                flash_header_v2_t *next_fhdr_v2;
 360
 361                if (imximage_csf_size != 0) {
 362                        fprintf(stderr, "Error: Header v2: SECURE_BOOT is only supported in DCD mode!");
 363                        exit(EXIT_FAILURE);
 364                }
 365
 366                fhdr_v2->entry = imximage_iram_free_start +
 367                        flash_offset + sizeof(flash_header_v2_t) +
 368                        sizeof(boot_data_t);
 369
 370                fhdr_v2->reserved1 = 0;
 371                fhdr_v2->reserved2 = 0;
 372                fhdr_v2->self = imximage_iram_free_start + flash_offset;
 373
 374                fhdr_v2->dcd_ptr = 0;
 375
 376                fhdr_v2->boot_data_ptr = fhdr_v2->self +
 377                                offsetof(imx_header_v2_t, boot_data);
 378
 379                hdr_v2->boot_data.start = imximage_iram_free_start;
 380                /*
 381                 * The actural size of plugin image is "imximage_plugin_size +
 382                 * sizeof(flash_header_v2_t) + sizeof(boot_data_t)", plus the
 383                 * flash_offset space.The ROM code only need to copy this size
 384                 * to run the plugin code. However, later when copy the whole
 385                 * U-Boot image to DDR, the ROM code use memcpy to copy the
 386                 * first part of the image, and use the storage read function
 387                 * to get the remaining part. This requires the dividing point
 388                 * must be multiple of storage sector size. Here we set the
 389                 * first section to be MAX_PLUGIN_CODE_SIZE(64KB) for this
 390                 * purpose.
 391                 */
 392                hdr_v2->boot_data.size = MAX_PLUGIN_CODE_SIZE;
 393
 394                /* Security feature are not supported */
 395                fhdr_v2->csf = 0;
 396
 397                next_hdr_v2 = (imx_header_v2_t *)((char *)hdr_v2 +
 398                               imximage_plugin_size);
 399
 400                next_fhdr_v2 = &next_hdr_v2->fhdr;
 401
 402                next_fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */
 403                next_fhdr_v2->header.length =
 404                        cpu_to_be16(sizeof(flash_header_v2_t));
 405                next_fhdr_v2->header.version = IVT_VERSION; /* 0x40 */
 406
 407                next_fhdr_v2->entry = entry_point;
 408                hdr_base = entry_point - sizeof(struct imx_header);
 409                next_fhdr_v2->reserved1 = 0;
 410                next_fhdr_v2->reserved2 = 0;
 411                next_fhdr_v2->self = hdr_base + imximage_plugin_size;
 412
 413                next_fhdr_v2->dcd_ptr = 0;
 414                next_fhdr_v2->boot_data_ptr = next_fhdr_v2->self +
 415                                offsetof(imx_header_v2_t, boot_data);
 416
 417                next_hdr_v2->boot_data.start = hdr_base - flash_offset;
 418
 419                header_size_ptr = &next_hdr_v2->boot_data.size;
 420
 421                next_hdr_v2->boot_data.plugin = 0;
 422
 423                next_fhdr_v2->csf = 0;
 424        }
 425}
 426
 427static void set_hdr_func(void)
 428{
 429        switch (imximage_version) {
 430        case IMXIMAGE_V1:
 431                set_dcd_val = set_dcd_val_v1;
 432                set_dcd_param = NULL;
 433                set_dcd_rst = set_dcd_rst_v1;
 434                set_imx_hdr = set_imx_hdr_v1;
 435                max_dcd_entries = MAX_HW_CFG_SIZE_V1;
 436                break;
 437        case IMXIMAGE_V2:
 438                gd_last_cmd = NULL;
 439                set_dcd_val = set_dcd_val_v2;
 440                set_dcd_param = set_dcd_param_v2;
 441                set_dcd_rst = set_dcd_rst_v2;
 442                set_imx_hdr = set_imx_hdr_v2;
 443                max_dcd_entries = MAX_HW_CFG_SIZE_V2;
 444                break;
 445        default:
 446                err_imximage_version(imximage_version);
 447                break;
 448        }
 449}
 450
 451static void print_hdr_v1(struct imx_header *imx_hdr)
 452{
 453        imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1;
 454        flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
 455        dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
 456        uint32_t size, length, ver;
 457
 458        size = dcd_v1->preamble.length;
 459        if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) {
 460                fprintf(stderr,
 461                        "Error: Image corrupt DCD size %d exceed maximum %d\n",
 462                        (uint32_t)(size / sizeof(dcd_type_addr_data_t)),
 463                        MAX_HW_CFG_SIZE_V1);
 464                exit(EXIT_FAILURE);
 465        }
 466
 467        length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t);
 468        ver = detect_imximage_version(imx_hdr);
 469
 470        printf("Image Type:   Freescale IMX Boot Image\n");
 471        printf("Image Ver:    %x", ver);
 472        printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver));
 473        printf("Data Size:    ");
 474        genimg_print_size(dcd_v1->addr_data[length].type);
 475        printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr);
 476        printf("Entry Point:  %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector);
 477}
 478
 479static void print_hdr_v2(struct imx_header *imx_hdr)
 480{
 481        imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2;
 482        flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
 483        dcd_v2_t *dcd_v2 = &hdr_v2->data.dcd_table;
 484        uint32_t size, version, plugin;
 485
 486        plugin = hdr_v2->boot_data.plugin;
 487        if (!plugin) {
 488                size = be16_to_cpu(dcd_v2->header.length);
 489                if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) {
 490                        fprintf(stderr,
 491                                "Error: Image corrupt DCD size %d exceed maximum %d\n",
 492                                (uint32_t)(size / sizeof(dcd_addr_data_t)),
 493                                MAX_HW_CFG_SIZE_V2);
 494                        exit(EXIT_FAILURE);
 495                }
 496        }
 497
 498        version = detect_imximage_version(imx_hdr);
 499
 500        printf("Image Type:   Freescale IMX Boot Image\n");
 501        printf("Image Ver:    %x", version);
 502        printf("%s\n", get_table_entry_name(imximage_versions, NULL, version));
 503        printf("Mode:         %s\n", plugin ? "PLUGIN" : "DCD");
 504        if (!plugin) {
 505                printf("Data Size:    ");
 506                genimg_print_size(hdr_v2->boot_data.size);
 507                printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr);
 508                printf("Entry Point:  %08x\n", (uint32_t)fhdr_v2->entry);
 509                if (fhdr_v2->csf) {
 510                        uint16_t dcdlen;
 511                        int offs;
 512
 513                        dcdlen = hdr_v2->data.dcd_table.header.length;
 514                        offs = (char *)&hdr_v2->data.dcd_table
 515                                - (char *)hdr_v2;
 516
 517                        /*
 518                         * The HAB block is the first part of the image, from
 519                         * start of IVT header (fhdr_v2->self) to the start of
 520                         * the CSF block (fhdr_v2->csf). So HAB size is
 521                         * calculated as:
 522                         * HAB_size = fhdr_v2->csf - fhdr_v2->self
 523                         */
 524                        printf("HAB Blocks:   0x%08x 0x%08x 0x%08x\n",
 525                               (uint32_t)fhdr_v2->self, 0,
 526                               (uint32_t)(fhdr_v2->csf - fhdr_v2->self));
 527                        printf("DCD Blocks:   0x00910000 0x%08x 0x%08x\n",
 528                               offs, be16_to_cpu(dcdlen));
 529                }
 530        } else {
 531                imx_header_v2_t *next_hdr_v2;
 532                flash_header_v2_t *next_fhdr_v2;
 533
 534                /*First Header*/
 535                printf("Plugin Data Size:     ");
 536                genimg_print_size(hdr_v2->boot_data.size);
 537                printf("Plugin Code Size:     ");
 538                genimg_print_size(imximage_plugin_size);
 539                printf("Plugin Load Address:  %08x\n", hdr_v2->boot_data.start);
 540                printf("Plugin Entry Point:   %08x\n", (uint32_t)fhdr_v2->entry);
 541
 542                /*Second Header*/
 543                next_hdr_v2 = (imx_header_v2_t *)((char *)hdr_v2 +
 544                                imximage_plugin_size);
 545                next_fhdr_v2 = &next_hdr_v2->fhdr;
 546                printf("U-Boot Data Size:     ");
 547                genimg_print_size(next_hdr_v2->boot_data.size);
 548                printf("U-Boot Load Address:  %08x\n",
 549                       next_hdr_v2->boot_data.start);
 550                printf("U-Boot Entry Point:   %08x\n",
 551                       (uint32_t)next_fhdr_v2->entry);
 552        }
 553}
 554
 555static void copy_plugin_code(struct imx_header *imxhdr, char *plugin_file)
 556{
 557        int ifd;
 558        struct stat sbuf;
 559        char *plugin_buf = imxhdr->header.hdr_v2.data.plugin_code;
 560        char *ptr;
 561
 562        ifd = open(plugin_file, O_RDONLY|O_BINARY);
 563        if (ifd < 0) {
 564                fprintf(stderr, "Can't open %s: %s\n",
 565                        plugin_file,
 566                        strerror(errno));
 567                exit(EXIT_FAILURE);
 568        }
 569
 570        if (fstat(ifd, &sbuf) < 0) {
 571                fprintf(stderr, "Can't stat %s: %s\n",
 572                        plugin_file,
 573                        strerror(errno));
 574                exit(EXIT_FAILURE);
 575        }
 576
 577        ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
 578        if (ptr == MAP_FAILED) {
 579                fprintf(stderr, "Can't read %s: %s\n",
 580                        plugin_file,
 581                        strerror(errno));
 582                exit(EXIT_FAILURE);
 583        }
 584
 585        if (sbuf.st_size > MAX_PLUGIN_CODE_SIZE) {
 586                printf("plugin binary size too large\n");
 587                exit(EXIT_FAILURE);
 588        }
 589
 590        memcpy(plugin_buf, ptr, sbuf.st_size);
 591        imximage_plugin_size = sbuf.st_size;
 592
 593        (void) munmap((void *)ptr, sbuf.st_size);
 594        (void) close(ifd);
 595
 596        imxhdr->header.hdr_v2.boot_data.plugin = 1;
 597}
 598
 599static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token,
 600                                char *name, int lineno, int fld, int dcd_len)
 601{
 602        int value;
 603        static int cmd_ver_first = ~0;
 604
 605        switch (cmd) {
 606        case CMD_IMAGE_VERSION:
 607                imximage_version = get_cfg_value(token, name, lineno);
 608                if (cmd_ver_first == 0) {
 609                        fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION "
 610                                "command need be the first before other "
 611                                "valid command in the file\n", name, lineno);
 612                        exit(EXIT_FAILURE);
 613                }
 614                cmd_ver_first = 1;
 615                set_hdr_func();
 616                break;
 617        case CMD_BOOT_FROM:
 618                imximage_ivt_offset = get_table_entry_id(imximage_boot_offset,
 619                                        "imximage boot option", token);
 620                if (imximage_ivt_offset == -1) {
 621                        fprintf(stderr, "Error: %s[%d] -Invalid boot device"
 622                                "(%s)\n", name, lineno, token);
 623                        exit(EXIT_FAILURE);
 624                }
 625
 626                imximage_init_loadsize =
 627                        get_table_entry_id(imximage_boot_loadsize,
 628                                           "imximage boot option", token);
 629
 630                if (imximage_init_loadsize == -1) {
 631                        fprintf(stderr,
 632                                "Error: %s[%d] -Invalid boot device(%s)\n",
 633                                name, lineno, token);
 634                        exit(EXIT_FAILURE);
 635                }
 636
 637                /*
 638                 * The SOC loads from the storage starting at address 0
 639                 * then ensures that the load size contains the offset
 640                 */
 641                if (imximage_init_loadsize < imximage_ivt_offset)
 642                        imximage_init_loadsize = imximage_ivt_offset;
 643                if (unlikely(cmd_ver_first != 1))
 644                        cmd_ver_first = 0;
 645                break;
 646        case CMD_BOOT_OFFSET:
 647                imximage_ivt_offset = get_cfg_value(token, name, lineno);
 648                if (unlikely(cmd_ver_first != 1))
 649                        cmd_ver_first = 0;
 650                break;
 651        case CMD_WRITE_DATA:
 652        case CMD_WRITE_CLR_BIT:
 653        case CMD_WRITE_SET_BIT:
 654        case CMD_CHECK_BITS_SET:
 655        case CMD_CHECK_BITS_CLR:
 656                value = get_cfg_value(token, name, lineno);
 657                if (set_dcd_param)
 658                        (*set_dcd_param)(imxhdr, dcd_len, cmd);
 659                (*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len);
 660                if (unlikely(cmd_ver_first != 1))
 661                        cmd_ver_first = 0;
 662                break;
 663        case CMD_CSF:
 664                if (imximage_version != 2) {
 665                        fprintf(stderr,
 666                                "Error: %s[%d] - CSF only supported for VERSION 2(%s)\n",
 667                                name, lineno, token);
 668                        exit(EXIT_FAILURE);
 669                }
 670                imximage_csf_size = get_cfg_value(token, name, lineno);
 671                if (unlikely(cmd_ver_first != 1))
 672                        cmd_ver_first = 0;
 673                break;
 674        case CMD_PLUGIN:
 675                plugin_image = 1;
 676                copy_plugin_code(imxhdr, token);
 677                break;
 678        }
 679}
 680
 681static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd,
 682                char *token, char *name, int lineno, int fld, int *dcd_len)
 683{
 684        int value;
 685
 686        switch (fld) {
 687        case CFG_COMMAND:
 688                *cmd = get_table_entry_id(imximage_cmds,
 689                        "imximage commands", token);
 690                if (*cmd < 0) {
 691                        fprintf(stderr, "Error: %s[%d] - Invalid command"
 692                        "(%s)\n", name, lineno, token);
 693                        exit(EXIT_FAILURE);
 694                }
 695                break;
 696        case CFG_REG_SIZE:
 697                parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len);
 698                break;
 699        case CFG_REG_ADDRESS:
 700        case CFG_REG_VALUE:
 701                switch(*cmd) {
 702                case CMD_WRITE_DATA:
 703                case CMD_WRITE_CLR_BIT:
 704                case CMD_WRITE_SET_BIT:
 705                case CMD_CHECK_BITS_SET:
 706                case CMD_CHECK_BITS_CLR:
 707
 708                        value = get_cfg_value(token, name, lineno);
 709                        if (set_dcd_param)
 710                                (*set_dcd_param)(imxhdr, *dcd_len, *cmd);
 711                        (*set_dcd_val)(imxhdr, name, lineno, fld, value,
 712                                        *dcd_len);
 713
 714                        if (fld == CFG_REG_VALUE) {
 715                                (*dcd_len)++;
 716                                if (*dcd_len > max_dcd_entries) {
 717                                        fprintf(stderr, "Error: %s[%d] -"
 718                                                "DCD table exceeds maximum size(%d)\n",
 719                                                name, lineno, max_dcd_entries);
 720                                        exit(EXIT_FAILURE);
 721                                }
 722                        }
 723                        break;
 724                case CMD_PLUGIN:
 725                        value = get_cfg_value(token, name, lineno);
 726                        imximage_iram_free_start = value;
 727                        break;
 728                default:
 729                        break;
 730                }
 731                break;
 732        default:
 733                break;
 734        }
 735}
 736static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name)
 737{
 738        FILE *fd = NULL;
 739        char *line = NULL;
 740        char *token, *saveptr1, *saveptr2;
 741        int lineno = 0;
 742        int fld;
 743        size_t len;
 744        int dcd_len = 0;
 745        int32_t cmd;
 746
 747        fd = fopen(name, "r");
 748        if (fd == 0) {
 749                fprintf(stderr, "Error: %s - Can't open DCD file\n", name);
 750                exit(EXIT_FAILURE);
 751        }
 752
 753        /*
 754         * Very simple parsing, line starting with # are comments
 755         * and are dropped
 756         */
 757        while ((getline(&line, &len, fd)) > 0) {
 758                lineno++;
 759
 760                token = strtok_r(line, "\r\n", &saveptr1);
 761                if (token == NULL)
 762                        continue;
 763
 764                /* Check inside the single line */
 765                for (fld = CFG_COMMAND, cmd = CMD_INVALID,
 766                                line = token; ; line = NULL, fld++) {
 767                        token = strtok_r(line, " \t", &saveptr2);
 768                        if (token == NULL)
 769                                break;
 770
 771                        /* Drop all text starting with '#' as comments */
 772                        if (token[0] == '#')
 773                                break;
 774
 775                        parse_cfg_fld(imxhdr, &cmd, token, name,
 776                                        lineno, fld, &dcd_len);
 777                }
 778
 779        }
 780
 781        (*set_dcd_rst)(imxhdr, dcd_len, name, lineno);
 782        fclose(fd);
 783
 784        /* Exit if there is no BOOT_FROM field specifying the flash_offset */
 785        if (imximage_ivt_offset == FLASH_OFFSET_UNDEFINED) {
 786                fprintf(stderr, "Error: No BOOT_FROM tag in %s\n", name);
 787                exit(EXIT_FAILURE);
 788        }
 789        return dcd_len;
 790}
 791
 792
 793static int imximage_check_image_types(uint8_t type)
 794{
 795        if (type == IH_TYPE_IMXIMAGE)
 796                return EXIT_SUCCESS;
 797        else
 798                return EXIT_FAILURE;
 799}
 800
 801static int imximage_verify_header(unsigned char *ptr, int image_size,
 802                        struct image_tool_params *params)
 803{
 804        struct imx_header *imx_hdr = (struct imx_header *) ptr;
 805
 806        if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID)
 807                return -FDT_ERR_BADSTRUCTURE;
 808
 809        return 0;
 810}
 811
 812static void imximage_print_header(const void *ptr)
 813{
 814        struct imx_header *imx_hdr = (struct imx_header *) ptr;
 815        uint32_t version = detect_imximage_version(imx_hdr);
 816
 817        switch (version) {
 818        case IMXIMAGE_V1:
 819                print_hdr_v1(imx_hdr);
 820                break;
 821        case IMXIMAGE_V2:
 822                print_hdr_v2(imx_hdr);
 823                break;
 824        default:
 825                err_imximage_version(version);
 826                break;
 827        }
 828}
 829
 830static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd,
 831                                struct image_tool_params *params)
 832{
 833        struct imx_header *imxhdr = (struct imx_header *)ptr;
 834        uint32_t dcd_len;
 835        uint32_t header_size;
 836
 837        /*
 838         * In order to not change the old imx cfg file
 839         * by adding VERSION command into it, here need
 840         * set up function ptr group to V1 by default.
 841         */
 842        imximage_version = IMXIMAGE_V1;
 843        /* Be able to detect if the cfg file has no BOOT_FROM tag */
 844        imximage_ivt_offset = FLASH_OFFSET_UNDEFINED;
 845        imximage_csf_size = 0;
 846        set_hdr_func();
 847
 848        /* Parse dcd configuration file */
 849        dcd_len = parse_cfg_file(imxhdr, params->imagename);
 850
 851        if (imximage_version == IMXIMAGE_V1)
 852                header_size = sizeof(flash_header_v1_t);
 853        else {
 854                header_size = sizeof(flash_header_v2_t) + sizeof(boot_data_t);
 855                if (!plugin_image)
 856                        header_size += sizeof(dcd_v2_t);
 857                else
 858                        header_size += MAX_PLUGIN_CODE_SIZE;
 859        }
 860
 861        if (imximage_init_loadsize < imximage_ivt_offset + header_size)
 862                        imximage_init_loadsize = imximage_ivt_offset + header_size;
 863
 864        /* Set the imx header */
 865        (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imximage_ivt_offset);
 866
 867        /*
 868         * ROM bug alert
 869         *
 870         * MX53 only loads 512 byte multiples in case of SD boot.
 871         * MX53 only loads NAND page multiples in case of NAND boot and
 872         * supports up to 4096 byte large pages, thus align to 4096.
 873         *
 874         * The remaining fraction of a block bytes would not be loaded!
 875         */
 876        *header_size_ptr = ROUND((sbuf->st_size + imximage_ivt_offset), 4096);
 877
 878        if (csf_ptr && imximage_csf_size) {
 879                *csf_ptr = params->ep - imximage_init_loadsize +
 880                        *header_size_ptr;
 881                *header_size_ptr += imximage_csf_size;
 882        }
 883}
 884
 885int imximage_check_params(struct image_tool_params *params)
 886{
 887        if (!params)
 888                return CFG_INVALID;
 889        if (!strlen(params->imagename)) {
 890                fprintf(stderr, "Error: %s - Configuration file not specified, "
 891                        "it is needed for imximage generation\n",
 892                        params->cmdname);
 893                return CFG_INVALID;
 894        }
 895        /*
 896         * Check parameters:
 897         * XIP is not allowed and verify that incompatible
 898         * parameters are not sent at the same time
 899         * For example, if list is required a data image must not be provided
 900         */
 901        return  (params->dflag && (params->fflag || params->lflag)) ||
 902                (params->fflag && (params->dflag || params->lflag)) ||
 903                (params->lflag && (params->dflag || params->fflag)) ||
 904                (params->xflag) || !(strlen(params->imagename));
 905}
 906
 907static int imximage_generate(struct image_tool_params *params,
 908        struct image_type_params *tparams)
 909{
 910        struct imx_header *imxhdr;
 911        size_t alloc_len;
 912        struct stat sbuf;
 913        char *datafile = params->datafile;
 914        uint32_t pad_len, header_size;
 915
 916        memset(&imximage_header, 0, sizeof(imximage_header));
 917
 918        /*
 919         * In order to not change the old imx cfg file
 920         * by adding VERSION command into it, here need
 921         * set up function ptr group to V1 by default.
 922         */
 923        imximage_version = IMXIMAGE_V1;
 924        /* Be able to detect if the cfg file has no BOOT_FROM tag */
 925        imximage_ivt_offset = FLASH_OFFSET_UNDEFINED;
 926        imximage_csf_size = 0;
 927        set_hdr_func();
 928
 929        /* Parse dcd configuration file */
 930        parse_cfg_file(&imximage_header, params->imagename);
 931
 932        if (imximage_version == IMXIMAGE_V1)
 933                header_size = sizeof(imx_header_v1_t);
 934        else {
 935                header_size = sizeof(flash_header_v2_t) + sizeof(boot_data_t);
 936                if (!plugin_image)
 937                        header_size += sizeof(dcd_v2_t);
 938                else
 939                        header_size += MAX_PLUGIN_CODE_SIZE;
 940        }
 941
 942        if (imximage_init_loadsize < imximage_ivt_offset + header_size)
 943                        imximage_init_loadsize = imximage_ivt_offset + header_size;
 944
 945        alloc_len = imximage_init_loadsize - imximage_ivt_offset;
 946
 947        if (alloc_len < header_size) {
 948                fprintf(stderr, "%s: header error\n",
 949                        params->cmdname);
 950                exit(EXIT_FAILURE);
 951        }
 952
 953        imxhdr = malloc(alloc_len);
 954
 955        if (!imxhdr) {
 956                fprintf(stderr, "%s: malloc return failure: %s\n",
 957                        params->cmdname, strerror(errno));
 958                exit(EXIT_FAILURE);
 959        }
 960
 961        memset(imxhdr, 0, alloc_len);
 962
 963        tparams->header_size = alloc_len;
 964        tparams->hdr         = imxhdr;
 965
 966        /* determine data image file length */
 967
 968        if (stat(datafile, &sbuf) < 0) {
 969                fprintf(stderr, "%s: Can't stat %s: %s\n",
 970                        params->cmdname, datafile, strerror(errno));
 971                exit(EXIT_FAILURE);
 972        }
 973
 974        pad_len = ROUND(sbuf.st_size, 4096) - sbuf.st_size;
 975
 976        return pad_len;
 977}
 978
 979
 980/*
 981 * imximage parameters
 982 */
 983U_BOOT_IMAGE_TYPE(
 984        imximage,
 985        "Freescale i.MX Boot Image support",
 986        0,
 987        NULL,
 988        imximage_check_params,
 989        imximage_verify_header,
 990        imximage_print_header,
 991        imximage_set_header,
 992        NULL,
 993        imximage_check_image_types,
 994        NULL,
 995        imximage_generate
 996);
 997