X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cmd%2Ffpga.c;h=b1c7b5453b3b12b5fb339f819f6244bd190e9a51;hb=c7a86d1645325697372b404f0b8cadac8a722ce9;hp=016349f5608695ebdd6ec2f48bad36f018a35278;hpb=f253f2933b7373556329c0174dd5b101039a4056;p=oweals%2Fu-boot.git diff --git a/cmd/fpga.c b/cmd/fpga.c index 016349f560..b1c7b5453b 100644 --- a/cmd/fpga.c +++ b/cmd/fpga.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2000, 2001 * Rich Ireland, Enterasys Networks, rireland@enterasys.com. - * - * SPDX-License-Identifier: GPL-2.0+ */ /* @@ -10,340 +9,414 @@ */ #include #include +#include #include #include +#include #include -/* Local functions */ -static int fpga_get_op(char *opstr); - -/* Local defines */ -enum { - FPGA_NONE = -1, - FPGA_INFO, - FPGA_LOAD, - FPGA_LOADB, - FPGA_DUMP, - FPGA_LOADMK, - FPGA_LOADP, - FPGA_LOADBP, - FPGA_LOADFS, -}; +static long do_fpga_get_device(char *arg) +{ + long dev = FPGA_INVALID_DEVICE; + char *devstr = env_get("fpga"); -/* ------------------------------------------------------------------------- */ -/* command form: - * fpga - * where op is 'load', 'dump', or 'info' - * If there is no device number field, the fpga environment variable is used. - * If there is no data addr field, the fpgadata environment variable is used. - * The info command requires no data address field. - */ -int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) + if (devstr) + /* Should be strtol to handle -1 cases */ + dev = simple_strtol(devstr, NULL, 16); + + if (dev == FPGA_INVALID_DEVICE && arg) + dev = simple_strtol(arg, NULL, 16); + + debug("%s: device = %ld\n", __func__, dev); + + return dev; +} + +static int do_fpga_check_params(long *dev, long *fpga_data, size_t *data_size, + cmd_tbl_t *cmdtp, int argc, char *const argv[]) +{ + size_t local_data_size; + long local_fpga_data; + + debug("%s %d, %d\n", __func__, argc, cmdtp->maxargs); + + if (argc != cmdtp->maxargs) { + debug("fpga: incorrect parameters passed\n"); + return CMD_RET_USAGE; + } + + *dev = do_fpga_get_device(argv[0]); + + local_fpga_data = simple_strtol(argv[1], NULL, 16); + if (!local_fpga_data) { + debug("fpga: zero fpga_data address\n"); + return CMD_RET_USAGE; + } + *fpga_data = local_fpga_data; + + local_data_size = simple_strtoul(argv[2], NULL, 16); + if (!local_data_size) { + debug("fpga: zero size\n"); + return CMD_RET_USAGE; + } + *data_size = local_data_size; + + return 0; +} + +#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) +int do_fpga_loads(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - int op, dev = FPGA_INVALID_DEVICE; size_t data_size = 0; - void *fpga_data = NULL; - char *devstr = getenv("fpga"); - char *datastr = getenv("fpgadata"); - int rc = FPGA_FAIL; - int wrong_parms = 0; -#if defined(CONFIG_FIT) - const char *fit_uname = NULL; - ulong fit_addr; + long fpga_data, dev; + int ret; + struct fpga_secure_info fpga_sec_info; + + memset(&fpga_sec_info, 0, sizeof(fpga_sec_info)); + + if (argc < 5) { + debug("fpga: incorrect parameters passed\n"); + return CMD_RET_USAGE; + } + + if (argc == 6) + fpga_sec_info.userkey_addr = (u8 *)(uintptr_t) + simple_strtoull(argv[5], + NULL, 16); + else + /* + * If 6th parameter is not passed then do_fpga_check_params + * will get 5 instead of expected 6 which means that function + * return CMD_RET_USAGE. Increase number of params +1 to pass + * this. + */ + argc++; + + fpga_sec_info.encflag = (u8)simple_strtoul(argv[4], NULL, 16); + fpga_sec_info.authflag = (u8)simple_strtoul(argv[3], NULL, 16); + + if (fpga_sec_info.authflag >= FPGA_NO_ENC_OR_NO_AUTH && + fpga_sec_info.encflag >= FPGA_NO_ENC_OR_NO_AUTH) { + debug("fpga: Use for NonSecure bitstream\n"); + return CMD_RET_USAGE; + } + + if (fpga_sec_info.encflag == FPGA_ENC_USR_KEY && + !fpga_sec_info.userkey_addr) { + debug("fpga: User key not provided\n"); + return CMD_RET_USAGE; + } + + ret = do_fpga_check_params(&dev, &fpga_data, &data_size, + cmdtp, argc, argv); + if (ret) + return ret; + + return fpga_loads(dev, (void *)fpga_data, data_size, &fpga_sec_info); +} #endif + #if defined(CONFIG_CMD_FPGA_LOADFS) +static int do_fpga_loadfs(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + size_t data_size = 0; + long fpga_data, dev; + int ret; fpga_fs_info fpga_fsinfo; + + ret = do_fpga_check_params(&dev, &fpga_data, &data_size, + cmdtp, argc, argv); + if (ret) + return ret; + fpga_fsinfo.fstype = FS_TYPE_ANY; + fpga_fsinfo.blocksize = (unsigned int)simple_strtoul(argv[3], NULL, 16); + fpga_fsinfo.interface = argv[4]; + fpga_fsinfo.dev_part = argv[5]; + fpga_fsinfo.filename = argv[6]; + + return fpga_fsload(dev, (void *)fpga_data, data_size, &fpga_fsinfo); +} #endif - if (devstr) - dev = (int) simple_strtoul(devstr, NULL, 16); - if (datastr) - fpga_data = (void *)simple_strtoul(datastr, NULL, 16); +static int do_fpga_info(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + long dev = do_fpga_get_device(argv[0]); - switch (argc) { -#if defined(CONFIG_CMD_FPGA_LOADFS) - case 9: - fpga_fsinfo.blocksize = (unsigned int) - simple_strtoul(argv[5], NULL, 16); - fpga_fsinfo.interface = argv[6]; - fpga_fsinfo.dev_part = argv[7]; - fpga_fsinfo.filename = argv[8]; -#endif - case 5: /* fpga */ - data_size = simple_strtoul(argv[4], NULL, 16); + return fpga_info(dev); +} - case 4: /* fpga */ -#if defined(CONFIG_FIT) - if (fit_parse_subimage(argv[3], (ulong)fpga_data, - &fit_addr, &fit_uname)) { - fpga_data = (void *)fit_addr; - debug("* fpga: subimage '%s' from FIT image ", - fit_uname); - debug("at 0x%08lx\n", fit_addr); - } else -#endif - { - fpga_data = (void *)simple_strtoul(argv[3], NULL, 16); - debug("* fpga: cmdline image address = 0x%08lx\n", - (ulong)fpga_data); - } - debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data); +static int do_fpga_dump(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + size_t data_size = 0; + long fpga_data, dev; + int ret; - case 3: /* fpga */ - dev = (int)simple_strtoul(argv[2], NULL, 16); - debug("%s: device = %d\n", __func__, dev); - /* FIXME - this is a really weak test */ - if ((argc == 3) && (dev > fpga_count())) { - /* must be buffer ptr */ - debug("%s: Assuming buffer pointer in arg 3\n", - __func__); + ret = do_fpga_check_params(&dev, &fpga_data, &data_size, + cmdtp, argc, argv); + if (ret) + return ret; -#if defined(CONFIG_FIT) - if (fit_parse_subimage(argv[2], (ulong)fpga_data, - &fit_addr, &fit_uname)) { - fpga_data = (void *)fit_addr; - debug("* fpga: subimage '%s' from FIT image ", - fit_uname); - debug("at 0x%08lx\n", fit_addr); - } else -#endif - { - fpga_data = (void *)(uintptr_t)dev; - debug("* fpga: cmdline image addr = 0x%08lx\n", - (ulong)fpga_data); - } + return fpga_dump(dev, (void *)fpga_data, data_size); +} - debug("%s: fpga_data = 0x%lx\n", - __func__, (ulong)fpga_data); - dev = FPGA_INVALID_DEVICE; /* reset device num */ - } +static int do_fpga_load(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + size_t data_size = 0; + long fpga_data, dev; + int ret; - case 2: /* fpga */ - op = (int)fpga_get_op(argv[1]); - break; + ret = do_fpga_check_params(&dev, &fpga_data, &data_size, + cmdtp, argc, argv); + if (ret) + return ret; - default: - debug("%s: Too many or too few args (%d)\n", __func__, argc); - op = FPGA_NONE; /* force usage display */ - break; - } + return fpga_load(dev, (void *)fpga_data, data_size, BIT_FULL); +} - if (dev == FPGA_INVALID_DEVICE) { - puts("FPGA device not specified\n"); - op = FPGA_NONE; - } +static int do_fpga_loadb(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + size_t data_size = 0; + long fpga_data, dev; + int ret; - switch (op) { - case FPGA_NONE: - case FPGA_INFO: - break; -#if defined(CONFIG_CMD_FPGA_LOADFS) - case FPGA_LOADFS: - /* Blocksize can be zero */ - if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part || - !fpga_fsinfo.filename) - wrong_parms = 1; + ret = do_fpga_check_params(&dev, &fpga_data, &data_size, + cmdtp, argc, argv); + if (ret) + return ret; + + return fpga_loadbitstream(dev, (void *)fpga_data, data_size, BIT_FULL); +} + +#if defined(CONFIG_CMD_FPGA_LOADP) +static int do_fpga_loadp(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + size_t data_size = 0; + long fpga_data, dev; + int ret; + + ret = do_fpga_check_params(&dev, &fpga_data, &data_size, + cmdtp, argc, argv); + if (ret) + return ret; + + return fpga_load(dev, (void *)fpga_data, data_size, BIT_PARTIAL); +} +#endif + +#if defined(CONFIG_CMD_FPGA_LOADBP) +static int do_fpga_loadbp(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + size_t data_size = 0; + long fpga_data, dev; + int ret; + + ret = do_fpga_check_params(&dev, &fpga_data, &data_size, + cmdtp, argc, argv); + if (ret) + return ret; + + return fpga_loadbitstream(dev, (void *)fpga_data, data_size, + BIT_PARTIAL); +} #endif - case FPGA_LOAD: - case FPGA_LOADP: - case FPGA_LOADB: - case FPGA_LOADBP: - case FPGA_DUMP: - if (!fpga_data || !data_size) - wrong_parms = 1; - break; + #if defined(CONFIG_CMD_FPGA_LOADMK) - case FPGA_LOADMK: - if (!fpga_data) - wrong_parms = 1; - break; +static int do_fpga_loadmk(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + size_t data_size = 0; + void *fpga_data = NULL; +#if defined(CONFIG_FIT) + const char *fit_uname = NULL; + ulong fit_addr; #endif - } + ulong dev = do_fpga_get_device(argv[0]); + char *datastr = env_get("fpgadata"); - if (wrong_parms) { - puts("Wrong parameters for FPGA request\n"); - op = FPGA_NONE; - } + debug("fpga: argc %x, dev %lx, datastr %s\n", argc, dev, datastr); - switch (op) { - case FPGA_NONE: + if (dev == FPGA_INVALID_DEVICE) { + debug("fpga: Invalid fpga device\n"); return CMD_RET_USAGE; + } - case FPGA_INFO: - rc = fpga_info(dev); - break; + if (argc == 0 && !datastr) { + debug("fpga: No datastr passed\n"); + return CMD_RET_USAGE; + } - case FPGA_LOAD: - rc = fpga_load(dev, fpga_data, data_size, BIT_FULL); - break; + if (argc == 2) { + datastr = argv[1]; + debug("fpga: Full command with two args\n"); + } else if (argc == 1 && !datastr) { + debug("fpga: Dev is setup - fpgadata passed\n"); + datastr = argv[0]; + } -#if defined(CONFIG_CMD_FPGA_LOADP) - case FPGA_LOADP: - rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL); - break; +#if defined(CONFIG_FIT) + if (fit_parse_subimage(datastr, (ulong)fpga_data, + &fit_addr, &fit_uname)) { + fpga_data = (void *)fit_addr; + debug("* fpga: subimage '%s' from FIT image ", + fit_uname); + debug("at 0x%08lx\n", fit_addr); + } else #endif + { + fpga_data = (void *)simple_strtoul(datastr, NULL, 16); + debug("* fpga: cmdline image address = 0x%08lx\n", + (ulong)fpga_data); + } + debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data); + if (!fpga_data) { + puts("Zero fpga_data address\n"); + return CMD_RET_USAGE; + } - case FPGA_LOADB: - rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL); - break; + switch (genimg_get_format(fpga_data)) { +#if defined(CONFIG_LEGACY_IMAGE_FORMAT) + case IMAGE_FORMAT_LEGACY: + { + image_header_t *hdr = (image_header_t *)fpga_data; + ulong data; + u8 comp; -#if defined(CONFIG_CMD_FPGA_LOADBP) - case FPGA_LOADBP: - rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL); - break; -#endif + comp = image_get_comp(hdr); + if (comp == IH_COMP_GZIP) { +#if defined(CONFIG_GZIP) + ulong image_buf = image_get_data(hdr); + ulong image_size = ~0UL; -#if defined(CONFIG_CMD_FPGA_LOADFS) - case FPGA_LOADFS: - rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo); - break; -#endif + data = image_get_load(hdr); -#if defined(CONFIG_CMD_FPGA_LOADMK) - case FPGA_LOADMK: - switch (genimg_get_format(fpga_data)) { -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - case IMAGE_FORMAT_LEGACY: - { - image_header_t *hdr = - (image_header_t *)fpga_data; - ulong data; - uint8_t comp; - - comp = image_get_comp(hdr); - if (comp == IH_COMP_GZIP) { -#if defined(CONFIG_GZIP) - ulong image_buf = image_get_data(hdr); - data = image_get_load(hdr); - ulong image_size = ~0UL; - - if (gunzip((void *)data, ~0UL, - (void *)image_buf, - &image_size) != 0) { - puts("GUNZIP: error\n"); - return 1; - } - data_size = image_size; + if (gunzip((void *)data, ~0UL, (void *)image_buf, + &image_size) != 0) { + puts("GUNZIP: error\n"); + return CMD_RET_FAILURE; + } + data_size = image_size; #else - puts("Gunzip image is not supported\n"); - return 1; + puts("Gunzip image is not supported\n"); + return 1; #endif - } else { - data = (ulong)image_get_data(hdr); - data_size = image_get_data_size(hdr); - } - rc = fpga_load(dev, (void *)data, data_size, - BIT_FULL); - } - break; + } else { + data = (ulong)image_get_data(hdr); + data_size = image_get_data_size(hdr); + } + return fpga_load(dev, (void *)data, data_size, + BIT_FULL); + } #endif #if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - { - const void *fit_hdr = (const void *)fpga_data; - int noffset; - const void *fit_data; - - if (fit_uname == NULL) { - puts("No FIT subimage unit name\n"); - return 1; - } - - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT image format\n"); - return 1; - } - - /* get fpga component image node offset */ - noffset = fit_image_get_node(fit_hdr, - fit_uname); - if (noffset < 0) { - printf("Can't find '%s' FIT subimage\n", - fit_uname); - return 1; - } - - /* verify integrity */ - if (!fit_image_verify(fit_hdr, noffset)) { - puts ("Bad Data Hash\n"); - return 1; - } - - /* get fpga subimage data address and length */ - if (fit_image_get_data(fit_hdr, noffset, - &fit_data, &data_size)) { - puts("Fpga subimage data not found\n"); - return 1; - } - - rc = fpga_load(dev, fit_data, data_size, - BIT_FULL); - } - break; -#endif - default: - puts("** Unknown image type\n"); - rc = FPGA_FAIL; - break; + case IMAGE_FORMAT_FIT: + { + const void *fit_hdr = (const void *)fpga_data; + int noffset; + const void *fit_data; + + if (!fit_uname) { + puts("No FIT subimage unit name\n"); + return CMD_RET_FAILURE; } - break; -#endif - case FPGA_DUMP: - rc = fpga_dump(dev, fpga_data, data_size); - break; + if (!fit_check_format(fit_hdr)) { + puts("Bad FIT image format\n"); + return CMD_RET_FAILURE; + } + /* get fpga component image node offset */ + noffset = fit_image_get_node(fit_hdr, fit_uname); + if (noffset < 0) { + printf("Can't find '%s' FIT subimage\n", fit_uname); + return CMD_RET_FAILURE; + } + + /* verify integrity */ + if (!fit_image_verify(fit_hdr, noffset)) { + puts("Bad Data Hash\n"); + return CMD_RET_FAILURE; + } + + /* get fpga subimage/external data address and length */ + if (fit_image_get_data_and_size(fit_hdr, noffset, + &fit_data, &data_size)) { + puts("Fpga subimage data not found\n"); + return CMD_RET_FAILURE; + } + + return fpga_load(dev, fit_data, data_size, BIT_FULL); + } +#endif default: - printf("Unknown operation\n"); - return CMD_RET_USAGE; + puts("** Unknown image type\n"); + return CMD_RET_FAILURE; } - return rc; } +#endif -/* - * Map op to supported operations. We don't use a table since we - * would just have to relocate it from flash anyway. - */ -static int fpga_get_op(char *opstr) -{ - int op = FPGA_NONE; - - if (!strcmp("info", opstr)) - op = FPGA_INFO; - else if (!strcmp("loadb", opstr)) - op = FPGA_LOADB; - else if (!strcmp("load", opstr)) - op = FPGA_LOAD; +static cmd_tbl_t fpga_commands[] = { + U_BOOT_CMD_MKENT(info, 1, 1, do_fpga_info, "", ""), + U_BOOT_CMD_MKENT(dump, 3, 1, do_fpga_dump, "", ""), + U_BOOT_CMD_MKENT(load, 3, 1, do_fpga_load, "", ""), + U_BOOT_CMD_MKENT(loadb, 3, 1, do_fpga_loadb, "", ""), #if defined(CONFIG_CMD_FPGA_LOADP) - else if (!strcmp("loadp", opstr)) - op = FPGA_LOADP; + U_BOOT_CMD_MKENT(loadp, 3, 1, do_fpga_loadp, "", ""), #endif #if defined(CONFIG_CMD_FPGA_LOADBP) - else if (!strcmp("loadbp", opstr)) - op = FPGA_LOADBP; + U_BOOT_CMD_MKENT(loadbp, 3, 1, do_fpga_loadbp, "", ""), #endif #if defined(CONFIG_CMD_FPGA_LOADFS) - else if (!strcmp("loadfs", opstr)) - op = FPGA_LOADFS; + U_BOOT_CMD_MKENT(loadfs, 7, 1, do_fpga_loadfs, "", ""), #endif #if defined(CONFIG_CMD_FPGA_LOADMK) - else if (!strcmp("loadmk", opstr)) - op = FPGA_LOADMK; + U_BOOT_CMD_MKENT(loadmk, 2, 1, do_fpga_loadmk, "", ""), +#endif +#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) + U_BOOT_CMD_MKENT(loads, 6, 1, do_fpga_loads, "", ""), #endif - else if (!strcmp("dump", opstr)) - op = FPGA_DUMP; +}; - if (op == FPGA_NONE) - printf("Unknown fpga operation \"%s\"\n", opstr); +static int do_fpga_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + cmd_tbl_t *fpga_cmd; + int ret; - return op; + if (argc < 2) + return CMD_RET_USAGE; + + fpga_cmd = find_cmd_tbl(argv[1], fpga_commands, + ARRAY_SIZE(fpga_commands)); + if (!fpga_cmd) { + debug("fpga: non existing command\n"); + return CMD_RET_USAGE; + } + + argc -= 2; + argv += 2; + + if (argc > fpga_cmd->maxargs) { + debug("fpga: more parameters passed\n"); + return CMD_RET_USAGE; + } + + ret = fpga_cmd->cmd(fpga_cmd, flag, argc, argv); + + return cmd_process_error(fpga_cmd, ret); } -#if defined(CONFIG_CMD_FPGA_LOADFS) -U_BOOT_CMD(fpga, 9, 1, do_fpga, +#if defined(CONFIG_CMD_FPGA_LOADFS) || defined(CONFIG_CMD_FPGA_LOAD_SECURE) +U_BOOT_CMD(fpga, 9, 1, do_fpga_wrapper, #else -U_BOOT_CMD(fpga, 6, 1, do_fpga, +U_BOOT_CMD(fpga, 6, 1, do_fpga_wrapper, #endif "loadable FPGA image support", "[operation type] [device number] [image address] [image size]\n" @@ -375,4 +448,19 @@ U_BOOT_CMD(fpga, 6, 1, do_fpga, "\tsubimage unit name in the form of addr:" #endif #endif +#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) + "Load encrypted bitstream (Xilinx only)\n" + " loads [dev] [address] [size] [auth-OCM-0/DDR-1/noauth-2]\n" + " [enc-devkey(0)/userkey(1)/nenc(2) [Userkey address]\n" + "Loads the secure bistreams(authenticated/encrypted/both\n" + "authenticated and encrypted) of [size] from [address].\n" + "The auth-OCM/DDR flag specifies to perform authentication\n" + "in OCM or in DDR. 0 for OCM, 1 for DDR, 2 for no authentication.\n" + "The enc flag specifies which key to be used for decryption\n" + "0-device key, 1-user key, 2-no encryption.\n" + "The optional Userkey address specifies from which address key\n" + "has to be used for decryption if user key is selected.\n" + "NOTE: the secure bitstream has to be created using Xilinx\n" + "bootgen tool only.\n" +#endif );