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