uboot/tools/aisimage.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2011
   3 * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24/* Required to obtain the getline prototype from stdio.h */
  25#define _GNU_SOURCE
  26
  27#include "mkimage.h"
  28#include "aisimage.h"
  29#include <image.h>
  30
  31#define IS_FNC_EXEC(c)  (cmd_table[c].AIS_cmd == AIS_CMD_FNLOAD)
  32#define WORD_ALIGN0     4
  33#define WORD_ALIGN(len) (((len)+WORD_ALIGN0-1) & ~(WORD_ALIGN0-1))
  34#define MAX_CMD_BUFFER  4096
  35
  36static uint32_t ais_img_size;
  37
  38/*
  39 * Supported commands for configuration file
  40 */
  41static table_entry_t aisimage_cmds[] = {
  42        {CMD_DATA,              "DATA",         "Reg Write Data"},
  43        {CMD_FILL,              "FILL",         "Fill range with pattern"},
  44        {CMD_CRCON,             "CRCON",        "CRC Enable"},
  45        {CMD_CRCOFF,            "CRCOFF",       "CRC Disable"},
  46        {CMD_CRCCHECK,          "CRCCHECK",     "CRC Validate"},
  47        {CMD_JMPCLOSE,          "JMPCLOSE",     "Jump & Close"},
  48        {CMD_JMP,               "JMP",          "Jump"},
  49        {CMD_SEQREAD,           "SEQREAD",      "Sequential read"},
  50        {CMD_PLL0,              "PLL0",         "PLL0"},
  51        {CMD_PLL1,              "PLL1",         "PLL1"},
  52        {CMD_CLK,               "CLK",          "Clock configuration"},
  53        {CMD_DDR2,              "DDR2",         "DDR2 Configuration"},
  54        {CMD_EMIFA,             "EMIFA",        "EMIFA"},
  55        {CMD_EMIFA_ASYNC,       "EMIFA_ASYNC",  "EMIFA Async"},
  56        {CMD_PLL,               "PLL",          "PLL & Clock configuration"},
  57        {CMD_PSC,               "PSC",          "PSC setup"},
  58        {CMD_PINMUX,            "PINMUX",       "Pinmux setup"},
  59        {CMD_BOOTTABLE,         "BOOT_TABLE",   "Boot table command"},
  60        {-1,                    "",             ""},
  61};
  62
  63static struct ais_func_exec {
  64        uint32_t index;
  65        uint32_t argcnt;
  66} ais_func_table[] = {
  67        [CMD_PLL0] = {0, 2},
  68        [CMD_PLL1] = {1, 2},
  69        [CMD_CLK] = {2, 1},
  70        [CMD_DDR2] = {3, 8},
  71        [CMD_EMIFA] = {4, 5},
  72        [CMD_EMIFA_ASYNC] = {5, 5},
  73        [CMD_PLL] = {6, 3},
  74        [CMD_PSC] = {7, 1},
  75        [CMD_PINMUX] = {8, 3}
  76};
  77
  78static struct cmd_table_t {
  79        uint32_t nargs;
  80        uint32_t AIS_cmd;
  81} cmd_table[] = {
  82        [CMD_FILL]       =      {       4,      AIS_CMD_FILL},
  83        [CMD_CRCON]     =       {       0,      AIS_CMD_ENCRC},
  84        [CMD_CRCOFF]    =       {       0,      AIS_CMD_DISCRC},
  85        [CMD_CRCCHECK]  =       {       2,      AIS_CMD_ENCRC},
  86        [CMD_JMPCLOSE]  =       {       1,      AIS_CMD_JMPCLOSE},
  87        [CMD_JMP]       =       {       1,      AIS_CMD_JMP},
  88        [CMD_SEQREAD]   =       {       0,      AIS_CMD_SEQREAD},
  89        [CMD_PLL0]      =       {       2,      AIS_CMD_FNLOAD},
  90        [CMD_PLL1]      =       {       2,      AIS_CMD_FNLOAD},
  91        [CMD_CLK]       =       {       1,      AIS_CMD_FNLOAD},
  92        [CMD_DDR2]      =       {       8,      AIS_CMD_FNLOAD},
  93        [CMD_EMIFA]     =       {       5,      AIS_CMD_FNLOAD},
  94        [CMD_EMIFA_ASYNC] =     {       5,      AIS_CMD_FNLOAD},
  95        [CMD_PLL]       =       {       3,      AIS_CMD_FNLOAD},
  96        [CMD_PSC]       =       {       1,      AIS_CMD_FNLOAD},
  97        [CMD_PINMUX]    =       {       3,      AIS_CMD_FNLOAD},
  98        [CMD_BOOTTABLE] =       {       4,      AIS_CMD_BOOTTBL},
  99};
 100
 101static uint32_t get_cfg_value(char *token, char *name,  int linenr)
 102{
 103        char *endptr;
 104        uint32_t value;
 105
 106        errno = 0;
 107        value = strtoul(token, &endptr, 16);
 108        if (errno || (token == endptr)) {
 109                fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n",
 110                        name,  linenr, token);
 111                exit(EXIT_FAILURE);
 112        }
 113        return value;
 114}
 115
 116static int get_ais_table_id(uint32_t *ptr)
 117{
 118
 119        int i;
 120        int func_no;
 121
 122        for (i = 0; i < ARRAY_SIZE(cmd_table); i++) {
 123                if (*ptr == cmd_table[i].AIS_cmd) {
 124                        if (cmd_table[i].AIS_cmd != AIS_CMD_FNLOAD)
 125                                return i;
 126
 127                        func_no = ((struct ais_cmd_func *)ptr)->func_args
 128                                & 0xFFFF;
 129                        if (func_no == ais_func_table[i].index)
 130                                return i;
 131                }
 132        }
 133
 134        return -1;
 135}
 136
 137static void aisimage_print_header(const void *hdr)
 138{
 139        struct ais_header *ais_hdr = (struct ais_header *)hdr;
 140        uint32_t *ptr;
 141        struct ais_cmd_load *ais_load;
 142        int id;
 143
 144        if (ais_hdr->magic != AIS_MAGIC_WORD) {
 145                fprintf(stderr, "Error: - AIS Magic Number not found\n");
 146                return;
 147        }
 148        fprintf(stdout, "Image Type:   TI Davinci AIS Boot Image\n");
 149        fprintf(stdout, "AIS magic :   %08x\n", ais_hdr->magic);
 150        ptr = (uint32_t *)&ais_hdr->magic;
 151        ptr++;
 152
 153        while (*ptr != AIS_CMD_JMPCLOSE) {
 154                /* Check if we find the image */
 155                if (*ptr == AIS_CMD_LOAD) {
 156                        ais_load = (struct ais_cmd_load *)ptr;
 157                        fprintf(stdout, "Image at  :   0x%08x size 0x%08x\n",
 158                                ais_load->addr,
 159                                ais_load->size);
 160                        ptr = ais_load->data + ais_load->size / sizeof(*ptr);
 161                        continue;
 162                }
 163
 164                id = get_ais_table_id(ptr);
 165                if (id < 0) {
 166                        fprintf(stderr, "Error: -  AIS Image corrupted\n");
 167                        return;
 168                }
 169                fprintf(stdout, "AIS cmd   :   %s\n",
 170                        get_table_entry_name(aisimage_cmds, NULL, id));
 171                ptr += cmd_table[id].nargs + IS_FNC_EXEC(id) + 1;
 172                if (((void *)ptr - hdr) > ais_img_size) {
 173                        fprintf(stderr,
 174                                "AIS Image not terminated by JMPCLOSE\n");
 175                        return;
 176                }
 177        }
 178}
 179
 180static uint32_t *ais_insert_cmd_header(uint32_t cmd, uint32_t nargs,
 181        uint32_t *parms, struct image_type_params *tparams,
 182        uint32_t *ptr)
 183{
 184        int i;
 185
 186        *ptr++ = cmd_table[cmd].AIS_cmd;
 187        if (IS_FNC_EXEC(cmd))
 188                *ptr++ = ((nargs & 0xFFFF) << 16) + ais_func_table[cmd].index;
 189
 190        /* Copy parameters */
 191        for (i = 0; i < nargs; i++)
 192                *ptr++ = cpu_to_le32(parms[i]);
 193
 194        return ptr;
 195
 196}
 197
 198static uint32_t *ais_alloc_buffer(struct mkimage_params *params)
 199{
 200        int dfd;
 201        struct stat sbuf;
 202        char *datafile = params->datafile;
 203        uint32_t *ptr;
 204
 205        dfd = open(datafile, O_RDONLY|O_BINARY);
 206        if (dfd < 0) {
 207                fprintf(stderr, "%s: Can't open %s: %s\n",
 208                        params->cmdname, datafile, strerror(errno));
 209                exit(EXIT_FAILURE);
 210        }
 211
 212        if (fstat(dfd, &sbuf) < 0) {
 213                fprintf(stderr, "%s: Can't stat %s: %s\n",
 214                        params->cmdname, datafile, strerror(errno));
 215                exit(EXIT_FAILURE);
 216        }
 217
 218        /*
 219         * Place for header is allocated. The size is taken from
 220         * the size of the datafile, that the ais_image_generate()
 221         * will copy into the header. Copying the datafile
 222         * is not left to the main program, because after the datafile
 223         * the header must be terminated with the Jump & Close command.
 224         */
 225        ais_img_size = WORD_ALIGN(sbuf.st_size) + MAX_CMD_BUFFER;
 226        ptr = (uint32_t *)malloc(WORD_ALIGN(sbuf.st_size) + MAX_CMD_BUFFER);
 227        if (!ptr) {
 228                fprintf(stderr, "%s: malloc return failure: %s\n",
 229                        params->cmdname, strerror(errno));
 230                exit(EXIT_FAILURE);
 231        }
 232
 233        close(dfd);
 234
 235        return ptr;
 236}
 237
 238static uint32_t *ais_copy_image(struct mkimage_params *params,
 239        uint32_t *aisptr)
 240
 241{
 242        int dfd;
 243        struct stat sbuf;
 244        char *datafile = params->datafile;
 245        void *ptr;
 246
 247        dfd = open(datafile, O_RDONLY|O_BINARY);
 248        if (dfd < 0) {
 249                fprintf(stderr, "%s: Can't open %s: %s\n",
 250                        params->cmdname, datafile, strerror(errno));
 251                exit(EXIT_FAILURE);
 252        }
 253
 254        if (fstat(dfd, &sbuf) < 0) {
 255                fprintf(stderr, "%s: Can't stat %s: %s\n",
 256                        params->cmdname, datafile, strerror(errno));
 257                exit(EXIT_FAILURE);
 258        }
 259
 260        ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
 261        *aisptr++ = AIS_CMD_LOAD;
 262        *aisptr++ = params->ep;
 263        *aisptr++ = sbuf.st_size;
 264        memcpy((void *)aisptr, ptr, sbuf.st_size);
 265        aisptr += WORD_ALIGN(sbuf.st_size) / sizeof(uint32_t);
 266
 267        (void) munmap((void *)ptr, sbuf.st_size);
 268        (void) close(dfd);
 269
 270        return aisptr;
 271
 272}
 273
 274static int aisimage_generate(struct mkimage_params *params,
 275        struct image_type_params *tparams)
 276{
 277        FILE *fd = NULL;
 278        char *line = NULL;
 279        char *token, *saveptr1, *saveptr2;
 280        int lineno = 0;
 281        int fld;
 282        size_t len;
 283        int32_t cmd;
 284        uint32_t nargs, cmd_parms[10];
 285        uint32_t value, size;
 286        char *name = params->imagename;
 287        uint32_t *aishdr;
 288
 289        fd = fopen(name, "r");
 290        if (fd == 0) {
 291                fprintf(stderr,
 292                        "Error: %s - Can't open AIS configuration\n", name);
 293                exit(EXIT_FAILURE);
 294        }
 295
 296        /*
 297         * the size of the header is variable and is computed
 298         * scanning the configuration file.
 299         */
 300        tparams->header_size = 0;
 301
 302        /*
 303         * Start allocating a buffer suitable for most command
 304         * The buffer is then reallocated if it is too small
 305         */
 306        aishdr = ais_alloc_buffer(params);
 307        tparams->hdr = aishdr;
 308        *aishdr++ = AIS_MAGIC_WORD;
 309
 310        /* Very simple parsing, line starting with # are comments
 311         * and are dropped
 312         */
 313        while ((getline(&line, &len, fd)) > 0) {
 314                lineno++;
 315
 316                token = strtok_r(line, "\r\n", &saveptr1);
 317                if (token == NULL)
 318                        continue;
 319
 320                /* Check inside the single line */
 321                line = token;
 322                fld = CFG_COMMAND;
 323                cmd = CMD_INVALID;
 324                nargs = 0;
 325                while (token != NULL) {
 326                        token = strtok_r(line, " \t", &saveptr2);
 327                        if (token == NULL)
 328                                break;
 329
 330                        /* Drop all text starting with '#' as comments */
 331                        if (token[0] == '#')
 332                                break;
 333
 334                        switch (fld) {
 335                        case CFG_COMMAND:
 336                                cmd = get_table_entry_id(aisimage_cmds,
 337                                        "aisimage commands", token);
 338                                if (cmd < 0) {
 339                                        fprintf(stderr,
 340                                        "Error: %s[%d] - Invalid command"
 341                                        "(%s)\n", name, lineno, token);
 342
 343                                        exit(EXIT_FAILURE);
 344                                }
 345                                break;
 346                        case CFG_VALUE:
 347                                value = get_cfg_value(token, name, lineno);
 348                                cmd_parms[nargs++] = value;
 349                                if (nargs > cmd_table[cmd].nargs) {
 350                                        fprintf(stderr,
 351                                         "Error: %s[%d] - too much arguments:"
 352                                                "(%s) for command %s\n", name,
 353                                                lineno, token,
 354                                                aisimage_cmds[cmd].sname);
 355                                        exit(EXIT_FAILURE);
 356                                }
 357                                break;
 358                        }
 359                        line = NULL;
 360                        fld = CFG_VALUE;
 361                }
 362                if (cmd != CMD_INVALID) {
 363                        /* Now insert the command into the header */
 364                        aishdr = ais_insert_cmd_header(cmd, nargs, cmd_parms,
 365                                tparams, aishdr);
 366                }
 367
 368        }
 369        fclose(fd);
 370
 371        aishdr = ais_copy_image(params, aishdr);
 372
 373        /* Add Jmp & Close */
 374        *aishdr++ = AIS_CMD_JMPCLOSE;
 375        *aishdr++ = params->ep;
 376
 377        size = (aishdr - (uint32_t *)tparams->hdr) * sizeof(uint32_t);
 378        tparams->header_size = size;
 379
 380        return 0;
 381}
 382
 383static int aisimage_check_image_types(uint8_t type)
 384{
 385        if (type == IH_TYPE_AISIMAGE)
 386                return EXIT_SUCCESS;
 387        else
 388                return EXIT_FAILURE;
 389}
 390
 391static int aisimage_verify_header(unsigned char *ptr, int image_size,
 392                        struct mkimage_params *params)
 393{
 394        struct ais_header *ais_hdr = (struct ais_header *)ptr;
 395
 396        if (ais_hdr->magic != AIS_MAGIC_WORD)
 397                return -FDT_ERR_BADSTRUCTURE;
 398
 399        /* Store the total size to remember in print_hdr */
 400        ais_img_size = image_size;
 401
 402        return 0;
 403}
 404
 405static void aisimage_set_header(void *ptr, struct stat *sbuf, int ifd,
 406                                struct mkimage_params *params)
 407{
 408}
 409
 410int aisimage_check_params(struct mkimage_params *params)
 411{
 412        if (!params)
 413                return CFG_INVALID;
 414        if (!strlen(params->imagename)) {
 415                fprintf(stderr, "Error: %s - Configuration file not specified, "
 416                        "it is needed for aisimage generation\n",
 417                        params->cmdname);
 418                return CFG_INVALID;
 419        }
 420        /*
 421         * Check parameters:
 422         * XIP is not allowed and verify that incompatible
 423         * parameters are not sent at the same time
 424         * For example, if list is required a data image must not be provided
 425         */
 426        return  (params->dflag && (params->fflag || params->lflag)) ||
 427                (params->fflag && (params->dflag || params->lflag)) ||
 428                (params->lflag && (params->dflag || params->fflag)) ||
 429                (params->xflag) || !(strlen(params->imagename));
 430}
 431
 432/*
 433 * aisimage parameters
 434 */
 435static struct image_type_params aisimage_params = {
 436        .name           = "TI Davinci AIS Boot Image support",
 437        .header_size    = 0,
 438        .hdr            = NULL,
 439        .check_image_type = aisimage_check_image_types,
 440        .verify_header  = aisimage_verify_header,
 441        .print_header   = aisimage_print_header,
 442        .set_header     = aisimage_set_header,
 443        .check_params   = aisimage_check_params,
 444        .vrec_header    = aisimage_generate,
 445};
 446
 447void init_ais_image_type(void)
 448{
 449        mkimage_register(&aisimage_params);
 450}
 451