uboot/cmd/fpga.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2000, 2001
   4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
   5 */
   6
   7/*
   8 *  FPGA support
   9 */
  10#include <common.h>
  11#include <command.h>
  12#include <fpga.h>
  13#include <fs.h>
  14#include <malloc.h>
  15
  16static long do_fpga_get_device(char *arg)
  17{
  18        long dev = FPGA_INVALID_DEVICE;
  19        char *devstr = env_get("fpga");
  20
  21        if (devstr)
  22                /* Should be strtol to handle -1 cases */
  23                dev = simple_strtol(devstr, NULL, 16);
  24
  25        if (dev == FPGA_INVALID_DEVICE && arg)
  26                dev = simple_strtol(arg, NULL, 16);
  27
  28        debug("%s: device = %ld\n", __func__, dev);
  29
  30        return dev;
  31}
  32
  33static int do_fpga_check_params(long *dev, long *fpga_data, size_t *data_size,
  34                                cmd_tbl_t *cmdtp, int argc, char *const argv[])
  35{
  36        size_t local_data_size;
  37        long local_fpga_data;
  38
  39        debug("%s %d, %d\n", __func__, argc, cmdtp->maxargs);
  40
  41        if (argc != cmdtp->maxargs) {
  42                debug("fpga: incorrect parameters passed\n");
  43                return CMD_RET_USAGE;
  44        }
  45
  46        *dev = do_fpga_get_device(argv[0]);
  47
  48        local_fpga_data = simple_strtol(argv[1], NULL, 16);
  49        if (!local_fpga_data) {
  50                debug("fpga: zero fpga_data address\n");
  51                return CMD_RET_USAGE;
  52        }
  53        *fpga_data = local_fpga_data;
  54
  55        local_data_size = simple_strtoul(argv[2], NULL, 16);
  56        if (!local_data_size) {
  57                debug("fpga: zero size\n");
  58                return CMD_RET_USAGE;
  59        }
  60        *data_size = local_data_size;
  61
  62        return 0;
  63}
  64
  65#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
  66int do_fpga_loads(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  67{
  68        size_t data_size = 0;
  69        long fpga_data, dev;
  70        int ret;
  71        struct fpga_secure_info fpga_sec_info;
  72
  73        memset(&fpga_sec_info, 0, sizeof(fpga_sec_info));
  74
  75        if (argc < 5) {
  76                debug("fpga: incorrect parameters passed\n");
  77                return CMD_RET_USAGE;
  78        }
  79
  80        if (argc == 6)
  81                fpga_sec_info.userkey_addr = (u8 *)(uintptr_t)
  82                                              simple_strtoull(argv[5],
  83                                                              NULL, 16);
  84        else
  85                /*
  86                 * If 6th parameter is not passed then do_fpga_check_params
  87                 * will get 5 instead of expected 6 which means that function
  88                 * return CMD_RET_USAGE. Increase number of params +1 to pass
  89                 * this.
  90                 */
  91                argc++;
  92
  93        fpga_sec_info.encflag = (u8)simple_strtoul(argv[4], NULL, 16);
  94        fpga_sec_info.authflag = (u8)simple_strtoul(argv[3], NULL, 16);
  95
  96        if (fpga_sec_info.authflag >= FPGA_NO_ENC_OR_NO_AUTH &&
  97            fpga_sec_info.encflag >= FPGA_NO_ENC_OR_NO_AUTH) {
  98                debug("fpga: Use <fpga load> for NonSecure bitstream\n");
  99                return CMD_RET_USAGE;
 100        }
 101
 102        if (fpga_sec_info.encflag == FPGA_ENC_USR_KEY &&
 103            !fpga_sec_info.userkey_addr) {
 104                debug("fpga: User key not provided\n");
 105                return CMD_RET_USAGE;
 106        }
 107
 108        ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
 109                                   cmdtp, argc, argv);
 110        if (ret)
 111                return ret;
 112
 113        return fpga_loads(dev, (void *)fpga_data, data_size, &fpga_sec_info);
 114}
 115#endif
 116
 117#if defined(CONFIG_CMD_FPGA_LOADFS)
 118static int do_fpga_loadfs(cmd_tbl_t *cmdtp, int flag, int argc,
 119                          char *const argv[])
 120{
 121        size_t data_size = 0;
 122        long fpga_data, dev;
 123        int ret;
 124        fpga_fs_info fpga_fsinfo;
 125
 126        ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
 127                                   cmdtp, argc, argv);
 128        if (ret)
 129                return ret;
 130
 131        fpga_fsinfo.fstype = FS_TYPE_ANY;
 132        fpga_fsinfo.blocksize = (unsigned int)simple_strtoul(argv[3], NULL, 16);
 133        fpga_fsinfo.interface = argv[4];
 134        fpga_fsinfo.dev_part = argv[5];
 135        fpga_fsinfo.filename = argv[6];
 136
 137        return fpga_fsload(dev, (void *)fpga_data, data_size, &fpga_fsinfo);
 138}
 139#endif
 140
 141static int do_fpga_info(cmd_tbl_t *cmdtp, int flag, int argc,
 142                        char * const argv[])
 143{
 144        long dev = do_fpga_get_device(argv[0]);
 145
 146        return fpga_info(dev);
 147}
 148
 149static int do_fpga_dump(cmd_tbl_t *cmdtp, int flag, int argc,
 150                        char * const argv[])
 151{
 152        size_t data_size = 0;
 153        long fpga_data, dev;
 154        int ret;
 155
 156        ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
 157                                   cmdtp, argc, argv);
 158        if (ret)
 159                return ret;
 160
 161        return fpga_dump(dev, (void *)fpga_data, data_size);
 162}
 163
 164static int do_fpga_load(cmd_tbl_t *cmdtp, int flag, int argc,
 165                        char * const argv[])
 166{
 167        size_t data_size = 0;
 168        long fpga_data, dev;
 169        int ret;
 170
 171        ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
 172                                   cmdtp, argc, argv);
 173        if (ret)
 174                return ret;
 175
 176        return fpga_load(dev, (void *)fpga_data, data_size, BIT_FULL);
 177}
 178
 179static int do_fpga_loadb(cmd_tbl_t *cmdtp, int flag, int argc,
 180                         char * const argv[])
 181{
 182        size_t data_size = 0;
 183        long fpga_data, dev;
 184        int ret;
 185
 186        ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
 187                                   cmdtp, argc, argv);
 188        if (ret)
 189                return ret;
 190
 191        return fpga_loadbitstream(dev, (void *)fpga_data, data_size, BIT_FULL);
 192}
 193
 194#if defined(CONFIG_CMD_FPGA_LOADP)
 195static int do_fpga_loadp(cmd_tbl_t *cmdtp, int flag, int argc,
 196                         char * const argv[])
 197{
 198        size_t data_size = 0;
 199        long fpga_data, dev;
 200        int ret;
 201
 202        ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
 203                                   cmdtp, argc, argv);
 204        if (ret)
 205                return ret;
 206
 207        return fpga_load(dev, (void *)fpga_data, data_size, BIT_PARTIAL);
 208}
 209#endif
 210
 211#if defined(CONFIG_CMD_FPGA_LOADBP)
 212static int do_fpga_loadbp(cmd_tbl_t *cmdtp, int flag, int argc,
 213                          char * const argv[])
 214{
 215        size_t data_size = 0;
 216        long fpga_data, dev;
 217        int ret;
 218
 219        ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
 220                                   cmdtp, argc, argv);
 221        if (ret)
 222                return ret;
 223
 224        return fpga_loadbitstream(dev, (void *)fpga_data, data_size,
 225                                  BIT_PARTIAL);
 226}
 227#endif
 228
 229#if defined(CONFIG_CMD_FPGA_LOADMK)
 230static int do_fpga_loadmk(cmd_tbl_t *cmdtp, int flag, int argc,
 231                          char * const argv[])
 232{
 233        size_t data_size = 0;
 234        void *fpga_data = NULL;
 235#if defined(CONFIG_FIT)
 236        const char *fit_uname = NULL;
 237        ulong fit_addr;
 238#endif
 239        ulong dev = do_fpga_get_device(argv[0]);
 240        char *datastr = env_get("fpgadata");
 241
 242        debug("fpga: argc %x, dev %lx, datastr %s\n", argc, dev, datastr);
 243
 244        if (dev == FPGA_INVALID_DEVICE) {
 245                debug("fpga: Invalid fpga device\n");
 246                return CMD_RET_USAGE;
 247        }
 248
 249        if (argc == 0 && !datastr) {
 250                debug("fpga: No datastr passed\n");
 251                return CMD_RET_USAGE;
 252        }
 253
 254        if (argc == 2) {
 255                datastr = argv[1];
 256                debug("fpga: Full command with two args\n");
 257        } else if (argc == 1 && !datastr) {
 258                debug("fpga: Dev is setup - fpgadata passed\n");
 259                datastr = argv[0];
 260        }
 261
 262#if defined(CONFIG_FIT)
 263        if (fit_parse_subimage(datastr, (ulong)fpga_data,
 264                               &fit_addr, &fit_uname)) {
 265                fpga_data = (void *)fit_addr;
 266                debug("*  fpga: subimage '%s' from FIT image ",
 267                      fit_uname);
 268                debug("at 0x%08lx\n", fit_addr);
 269        } else
 270#endif
 271        {
 272                fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
 273                debug("*  fpga: cmdline image address = 0x%08lx\n",
 274                      (ulong)fpga_data);
 275        }
 276        debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data);
 277        if (!fpga_data) {
 278                puts("Zero fpga_data address\n");
 279                return CMD_RET_USAGE;
 280        }
 281
 282        switch (genimg_get_format(fpga_data)) {
 283#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
 284        case IMAGE_FORMAT_LEGACY:
 285        {
 286                image_header_t *hdr = (image_header_t *)fpga_data;
 287                ulong data;
 288                u8 comp;
 289
 290                comp = image_get_comp(hdr);
 291                if (comp == IH_COMP_GZIP) {
 292#if defined(CONFIG_GZIP)
 293                        ulong image_buf = image_get_data(hdr);
 294                        ulong image_size = ~0UL;
 295
 296                        data = image_get_load(hdr);
 297
 298                        if (gunzip((void *)data, ~0UL, (void *)image_buf,
 299                                   &image_size) != 0) {
 300                                puts("GUNZIP: error\n");
 301                                return CMD_RET_FAILURE;
 302                        }
 303                        data_size = image_size;
 304#else
 305                        puts("Gunzip image is not supported\n");
 306                        return 1;
 307#endif
 308                } else {
 309                        data = (ulong)image_get_data(hdr);
 310                        data_size = image_get_data_size(hdr);
 311                }
 312                return fpga_load(dev, (void *)data, data_size,
 313                                  BIT_FULL);
 314        }
 315#endif
 316#if defined(CONFIG_FIT)
 317        case IMAGE_FORMAT_FIT:
 318        {
 319                const void *fit_hdr = (const void *)fpga_data;
 320                int noffset;
 321                const void *fit_data;
 322
 323                if (!fit_uname) {
 324                        puts("No FIT subimage unit name\n");
 325                        return CMD_RET_FAILURE;
 326                }
 327
 328                if (!fit_check_format(fit_hdr)) {
 329                        puts("Bad FIT image format\n");
 330                        return CMD_RET_FAILURE;
 331                }
 332
 333                /* get fpga component image node offset */
 334                noffset = fit_image_get_node(fit_hdr, fit_uname);
 335                if (noffset < 0) {
 336                        printf("Can't find '%s' FIT subimage\n", fit_uname);
 337                        return CMD_RET_FAILURE;
 338                }
 339
 340                /* verify integrity */
 341                if (!fit_image_verify(fit_hdr, noffset)) {
 342                        puts("Bad Data Hash\n");
 343                        return CMD_RET_FAILURE;
 344                }
 345
 346                /* get fpga subimage data address and length */
 347                if (fit_image_get_data(fit_hdr, noffset, &fit_data,
 348                                       &data_size)) {
 349                        puts("Fpga subimage data not found\n");
 350                        return CMD_RET_FAILURE;
 351                }
 352
 353                return fpga_load(dev, fit_data, data_size, BIT_FULL);
 354        }
 355#endif
 356        default:
 357                puts("** Unknown image type\n");
 358                return CMD_RET_FAILURE;
 359        }
 360}
 361#endif
 362
 363static cmd_tbl_t fpga_commands[] = {
 364        U_BOOT_CMD_MKENT(info, 1, 1, do_fpga_info, "", ""),
 365        U_BOOT_CMD_MKENT(dump, 3, 1, do_fpga_dump, "", ""),
 366        U_BOOT_CMD_MKENT(load, 3, 1, do_fpga_load, "", ""),
 367        U_BOOT_CMD_MKENT(loadb, 3, 1, do_fpga_loadb, "", ""),
 368#if defined(CONFIG_CMD_FPGA_LOADP)
 369        U_BOOT_CMD_MKENT(loadp, 3, 1, do_fpga_loadp, "", ""),
 370#endif
 371#if defined(CONFIG_CMD_FPGA_LOADBP)
 372        U_BOOT_CMD_MKENT(loadbp, 3, 1, do_fpga_loadbp, "", ""),
 373#endif
 374#if defined(CONFIG_CMD_FPGA_LOADFS)
 375        U_BOOT_CMD_MKENT(loadfs, 7, 1, do_fpga_loadfs, "", ""),
 376#endif
 377#if defined(CONFIG_CMD_FPGA_LOADMK)
 378        U_BOOT_CMD_MKENT(loadmk, 2, 1, do_fpga_loadmk, "", ""),
 379#endif
 380#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
 381        U_BOOT_CMD_MKENT(loads, 6, 1, do_fpga_loads, "", ""),
 382#endif
 383};
 384
 385static int do_fpga_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
 386                           char *const argv[])
 387{
 388        cmd_tbl_t *fpga_cmd;
 389        int ret;
 390
 391        if (argc < 2)
 392                return CMD_RET_USAGE;
 393
 394        fpga_cmd = find_cmd_tbl(argv[1], fpga_commands,
 395                                ARRAY_SIZE(fpga_commands));
 396        if (!fpga_cmd) {
 397                debug("fpga: non existing command\n");
 398                return CMD_RET_USAGE;
 399        }
 400
 401        argc -= 2;
 402        argv += 2;
 403
 404        if (argc > fpga_cmd->maxargs) {
 405                debug("fpga: more parameters passed\n");
 406                return CMD_RET_USAGE;
 407        }
 408
 409        ret = fpga_cmd->cmd(fpga_cmd, flag, argc, argv);
 410
 411        return cmd_process_error(fpga_cmd, ret);
 412}
 413
 414#if defined(CONFIG_CMD_FPGA_LOADFS) || defined(CONFIG_CMD_FPGA_LOAD_SECURE)
 415U_BOOT_CMD(fpga, 9, 1, do_fpga_wrapper,
 416#else
 417U_BOOT_CMD(fpga, 6, 1, do_fpga_wrapper,
 418#endif
 419           "loadable FPGA image support",
 420           "[operation type] [device number] [image address] [image size]\n"
 421           "fpga operations:\n"
 422           "  dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
 423           "  info\t[dev]\t\t\tlist known device information\n"
 424           "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
 425#if defined(CONFIG_CMD_FPGA_LOADP)
 426           "  loadp\t[dev] [address] [size]\t"
 427           "Load device from memory buffer with partial bitstream\n"
 428#endif
 429           "  loadb\t[dev] [address] [size]\t"
 430           "Load device from bitstream buffer (Xilinx only)\n"
 431#if defined(CONFIG_CMD_FPGA_LOADBP)
 432           "  loadbp\t[dev] [address] [size]\t"
 433           "Load device from bitstream buffer with partial bitstream"
 434           "(Xilinx only)\n"
 435#endif
 436#if defined(CONFIG_CMD_FPGA_LOADFS)
 437           "Load device from filesystem (FAT by default) (Xilinx only)\n"
 438           "  loadfs [dev] [address] [image size] [blocksize] <interface>\n"
 439           "        [<dev[:part]>] <filename>\n"
 440#endif
 441#if defined(CONFIG_CMD_FPGA_LOADMK)
 442           "  loadmk [dev] [address]\tLoad device generated with mkimage"
 443#if defined(CONFIG_FIT)
 444           "\n"
 445           "\tFor loadmk operating on FIT format uImage address must include\n"
 446           "\tsubimage unit name in the form of addr:<subimg_uname>"
 447#endif
 448#endif
 449#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
 450           "Load encrypted bitstream (Xilinx only)\n"
 451           "  loads [dev] [address] [size] [auth-OCM-0/DDR-1/noauth-2]\n"
 452           "        [enc-devkey(0)/userkey(1)/nenc(2) [Userkey address]\n"
 453           "Loads the secure bistreams(authenticated/encrypted/both\n"
 454           "authenticated and encrypted) of [size] from [address].\n"
 455           "The auth-OCM/DDR flag specifies to perform authentication\n"
 456           "in OCM or in DDR. 0 for OCM, 1 for DDR, 2 for no authentication.\n"
 457           "The enc flag specifies which key to be used for decryption\n"
 458           "0-device key, 1-user key, 2-no encryption.\n"
 459           "The optional Userkey address specifies from which address key\n"
 460           "has to be used for decryption if user key is selected.\n"
 461           "NOTE: the sceure bitstream has to be created using xilinx\n"
 462           "bootgen tool only.\n"
 463#endif
 464);
 465