uboot/common/cmd_fpga.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000, 2001
   3 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 *  FPGA support
  10 */
  11#include <common.h>
  12#include <command.h>
  13#include <fpga.h>
  14#include <fs.h>
  15#include <malloc.h>
  16
  17/* Local functions */
  18static int fpga_get_op(char *opstr);
  19
  20/* Local defines */
  21#define FPGA_NONE   -1
  22#define FPGA_INFO   0
  23#define FPGA_LOAD   1
  24#define FPGA_LOADB  2
  25#define FPGA_DUMP   3
  26#define FPGA_LOADMK 4
  27#define FPGA_LOADP  5
  28#define FPGA_LOADBP 6
  29#define FPGA_LOADFS 7
  30
  31/* ------------------------------------------------------------------------- */
  32/* command form:
  33 *   fpga <op> <device number> <data addr> <datasize>
  34 * where op is 'load', 'dump', or 'info'
  35 * If there is no device number field, the fpga environment variable is used.
  36 * If there is no data addr field, the fpgadata environment variable is used.
  37 * The info command requires no data address field.
  38 */
  39int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  40{
  41        int op, dev = FPGA_INVALID_DEVICE;
  42        size_t data_size = 0;
  43        void *fpga_data = NULL;
  44        char *devstr = getenv("fpga");
  45        char *datastr = getenv("fpgadata");
  46        int rc = FPGA_FAIL;
  47        int wrong_parms = 0;
  48#if defined(CONFIG_FIT)
  49        const char *fit_uname = NULL;
  50        ulong fit_addr;
  51#endif
  52#if defined(CONFIG_CMD_FPGA_LOADFS)
  53        fpga_fs_info fpga_fsinfo;
  54        fpga_fsinfo.fstype = FS_TYPE_ANY;
  55#endif
  56
  57        if (devstr)
  58                dev = (int) simple_strtoul(devstr, NULL, 16);
  59        if (datastr)
  60                fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
  61
  62        switch (argc) {
  63#if defined(CONFIG_CMD_FPGA_LOADFS)
  64        case 9:
  65                fpga_fsinfo.blocksize = (unsigned int)
  66                                             simple_strtoul(argv[5], NULL, 16);
  67                fpga_fsinfo.interface = argv[6];
  68                fpga_fsinfo.dev_part = argv[7];
  69                fpga_fsinfo.filename = argv[8];
  70#endif
  71        case 5:         /* fpga <op> <dev> <data> <datasize> */
  72                data_size = simple_strtoul(argv[4], NULL, 16);
  73
  74        case 4:         /* fpga <op> <dev> <data> */
  75#if defined(CONFIG_FIT)
  76                if (fit_parse_subimage(argv[3], (ulong)fpga_data,
  77                                       &fit_addr, &fit_uname)) {
  78                        fpga_data = (void *)fit_addr;
  79                        debug("*  fpga: subimage '%s' from FIT image ",
  80                              fit_uname);
  81                        debug("at 0x%08lx\n", fit_addr);
  82                } else
  83#endif
  84                {
  85                        fpga_data = (void *)simple_strtoul(argv[3], NULL, 16);
  86                        debug("*  fpga: cmdline image address = 0x%08lx\n",
  87                              (ulong)fpga_data);
  88                }
  89                debug("%s: fpga_data = 0x%x\n", __func__, (uint)fpga_data);
  90
  91        case 3:         /* fpga <op> <dev | data addr> */
  92                dev = (int)simple_strtoul(argv[2], NULL, 16);
  93                debug("%s: device = %d\n", __func__, dev);
  94                /* FIXME - this is a really weak test */
  95                if ((argc == 3) && (dev > fpga_count())) {
  96                        /* must be buffer ptr */
  97                        debug("%s: Assuming buffer pointer in arg 3\n",
  98                              __func__);
  99
 100#if defined(CONFIG_FIT)
 101                        if (fit_parse_subimage(argv[2], (ulong)fpga_data,
 102                                               &fit_addr, &fit_uname)) {
 103                                fpga_data = (void *)fit_addr;
 104                                debug("*  fpga: subimage '%s' from FIT image ",
 105                                      fit_uname);
 106                                debug("at 0x%08lx\n", fit_addr);
 107                        } else
 108#endif
 109                        {
 110                                fpga_data = (void *)dev;
 111                                debug("*  fpga: cmdline image addr = 0x%08lx\n",
 112                                      (ulong)fpga_data);
 113                        }
 114
 115                        debug("%s: fpga_data = 0x%x\n",
 116                              __func__, (uint)fpga_data);
 117                        dev = FPGA_INVALID_DEVICE;      /* reset device num */
 118                }
 119
 120        case 2:         /* fpga <op> */
 121                op = (int)fpga_get_op(argv[1]);
 122                break;
 123
 124        default:
 125                debug("%s: Too many or too few args (%d)\n", __func__, argc);
 126                op = FPGA_NONE; /* force usage display */
 127                break;
 128        }
 129
 130        if (dev == FPGA_INVALID_DEVICE) {
 131                puts("FPGA device not specified\n");
 132                op = FPGA_NONE;
 133        }
 134
 135        switch (op) {
 136        case FPGA_NONE:
 137        case FPGA_INFO:
 138                break;
 139#if defined(CONFIG_CMD_FPGA_LOADFS)
 140        case FPGA_LOADFS:
 141                /* Blocksize can be zero */
 142                if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part ||
 143                    !fpga_fsinfo.filename)
 144                        wrong_parms = 1;
 145#endif
 146        case FPGA_LOAD:
 147        case FPGA_LOADP:
 148        case FPGA_LOADB:
 149        case FPGA_LOADBP:
 150        case FPGA_DUMP:
 151                if (!fpga_data || !data_size)
 152                        wrong_parms = 1;
 153                break;
 154#if defined(CONFIG_CMD_FPGA_LOADMK)
 155        case FPGA_LOADMK:
 156                if (!fpga_data)
 157                        wrong_parms = 1;
 158                break;
 159#endif
 160        }
 161
 162        if (wrong_parms) {
 163                puts("Wrong parameters for FPGA request\n");
 164                op = FPGA_NONE;
 165        }
 166
 167        switch (op) {
 168        case FPGA_NONE:
 169                return CMD_RET_USAGE;
 170
 171        case FPGA_INFO:
 172                rc = fpga_info(dev);
 173                break;
 174
 175        case FPGA_LOAD:
 176                rc = fpga_load(dev, fpga_data, data_size, BIT_FULL);
 177                break;
 178
 179#if defined(CONFIG_CMD_FPGA_LOADP)
 180        case FPGA_LOADP:
 181                rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL);
 182                break;
 183#endif
 184
 185        case FPGA_LOADB:
 186                rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL);
 187                break;
 188
 189#if defined(CONFIG_CMD_FPGA_LOADBP)
 190        case FPGA_LOADBP:
 191                rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL);
 192                break;
 193#endif
 194
 195#if defined(CONFIG_CMD_FPGA_LOADFS)
 196        case FPGA_LOADFS:
 197                rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo);
 198                break;
 199#endif
 200
 201#if defined(CONFIG_CMD_FPGA_LOADMK)
 202        case FPGA_LOADMK:
 203                switch (genimg_get_format(fpga_data)) {
 204#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
 205                case IMAGE_FORMAT_LEGACY:
 206                        {
 207                                image_header_t *hdr =
 208                                                (image_header_t *)fpga_data;
 209                                ulong data;
 210                                uint8_t comp;
 211
 212                                comp = image_get_comp(hdr);
 213                                if (comp == IH_COMP_GZIP) {
 214#if defined(CONFIG_GZIP)
 215                                        ulong image_buf = image_get_data(hdr);
 216                                        data = image_get_load(hdr);
 217                                        ulong image_size = ~0UL;
 218
 219                                        if (gunzip((void *)data, ~0UL,
 220                                                   (void *)image_buf,
 221                                                   &image_size) != 0) {
 222                                                puts("GUNZIP: error\n");
 223                                                return 1;
 224                                        }
 225                                        data_size = image_size;
 226#else
 227                                        puts("Gunzip image is not supported\n");
 228                                        return 1;
 229#endif
 230                                } else {
 231                                        data = (ulong)image_get_data(hdr);
 232                                        data_size = image_get_data_size(hdr);
 233                                }
 234                                rc = fpga_load(dev, (void *)data, data_size,
 235                                               BIT_FULL);
 236                        }
 237                        break;
 238#endif
 239#if defined(CONFIG_FIT)
 240                case IMAGE_FORMAT_FIT:
 241                        {
 242                                const void *fit_hdr = (const void *)fpga_data;
 243                                int noffset;
 244                                const void *fit_data;
 245
 246                                if (fit_uname == NULL) {
 247                                        puts("No FIT subimage unit name\n");
 248                                        return 1;
 249                                }
 250
 251                                if (!fit_check_format(fit_hdr)) {
 252                                        puts("Bad FIT image format\n");
 253                                        return 1;
 254                                }
 255
 256                                /* get fpga component image node offset */
 257                                noffset = fit_image_get_node(fit_hdr,
 258                                                             fit_uname);
 259                                if (noffset < 0) {
 260                                        printf("Can't find '%s' FIT subimage\n",
 261                                               fit_uname);
 262                                        return 1;
 263                                }
 264
 265                                /* verify integrity */
 266                                if (!fit_image_verify(fit_hdr, noffset)) {
 267                                        puts ("Bad Data Hash\n");
 268                                        return 1;
 269                                }
 270
 271                                /* get fpga subimage data address and length */
 272                                if (fit_image_get_data(fit_hdr, noffset,
 273                                                       &fit_data, &data_size)) {
 274                                        puts("Fpga subimage data not found\n");
 275                                        return 1;
 276                                }
 277
 278                                rc = fpga_load(dev, fit_data, data_size,
 279                                               BIT_FULL);
 280                        }
 281                        break;
 282#endif
 283                default:
 284                        puts("** Unknown image type\n");
 285                        rc = FPGA_FAIL;
 286                        break;
 287                }
 288                break;
 289#endif
 290
 291        case FPGA_DUMP:
 292                rc = fpga_dump(dev, fpga_data, data_size);
 293                break;
 294
 295        default:
 296                printf("Unknown operation\n");
 297                return CMD_RET_USAGE;
 298        }
 299        return rc;
 300}
 301
 302/*
 303 * Map op to supported operations.  We don't use a table since we
 304 * would just have to relocate it from flash anyway.
 305 */
 306static int fpga_get_op(char *opstr)
 307{
 308        int op = FPGA_NONE;
 309
 310        if (!strcmp("info", opstr))
 311                op = FPGA_INFO;
 312        else if (!strcmp("loadb", opstr))
 313                op = FPGA_LOADB;
 314        else if (!strcmp("load", opstr))
 315                op = FPGA_LOAD;
 316#if defined(CONFIG_CMD_FPGA_LOADP)
 317        else if (!strcmp("loadp", opstr))
 318                op = FPGA_LOADP;
 319#endif
 320#if defined(CONFIG_CMD_FPGA_LOADBP)
 321        else if (!strcmp("loadbp", opstr))
 322                op = FPGA_LOADBP;
 323#endif
 324#if defined(CONFIG_CMD_FPGA_LOADFS)
 325        else if (!strcmp("loadfs", opstr))
 326                op = FPGA_LOADFS;
 327#endif
 328#if defined(CONFIG_CMD_FPGA_LOADMK)
 329        else if (!strcmp("loadmk", opstr))
 330                op = FPGA_LOADMK;
 331#endif
 332        else if (!strcmp("dump", opstr))
 333                op = FPGA_DUMP;
 334
 335        if (op == FPGA_NONE)
 336                printf("Unknown fpga operation \"%s\"\n", opstr);
 337
 338        return op;
 339}
 340
 341#if defined(CONFIG_CMD_FPGA_LOADFS)
 342U_BOOT_CMD(fpga, 9, 1, do_fpga,
 343#else
 344U_BOOT_CMD(fpga, 6, 1, do_fpga,
 345#endif
 346           "loadable FPGA image support",
 347           "[operation type] [device number] [image address] [image size]\n"
 348           "fpga operations:\n"
 349           "  dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
 350           "  info\t[dev]\t\t\tlist known device information\n"
 351           "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
 352#if defined(CONFIG_CMD_FPGA_LOADP)
 353           "  loadp\t[dev] [address] [size]\t"
 354           "Load device from memory buffer with partial bitstream\n"
 355#endif
 356           "  loadb\t[dev] [address] [size]\t"
 357           "Load device from bitstream buffer (Xilinx only)\n"
 358#if defined(CONFIG_CMD_FPGA_LOADBP)
 359           "  loadbp\t[dev] [address] [size]\t"
 360           "Load device from bitstream buffer with partial bitstream"
 361           "(Xilinx only)\n"
 362#endif
 363#if defined(CONFIG_CMD_FPGA_LOADFS)
 364           "Load device from filesystem (FAT by default) (Xilinx only)\n"
 365           "  loadfs [dev] [address] [image size] [blocksize] <interface>\n"
 366           "        [<dev[:part]>] <filename>\n"
 367#endif
 368#if defined(CONFIG_CMD_FPGA_LOADMK)
 369           "  loadmk [dev] [address]\tLoad device generated with mkimage"
 370#if defined(CONFIG_FIT)
 371           "\n"
 372           "\tFor loadmk operating on FIT format uImage address must include\n"
 373           "\tsubimage unit name in the form of addr:<subimg_uname>"
 374#endif
 375#endif
 376);
 377