FPGA changes for v2018.11

- add fpga tests to cover fpga commands
 - fpga Kconfig cleanup
 - fix cmd/fpga.c
 - add support for missing fpga loadmk commands
 - add fpga fragment to MAINTAINERS
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iEYEABECAAYFAluXlcwACgkQykllyylKDCGqEQCgiqm9BBhYnLugEroL2b3FDUjX
 IfEAn2dPmCF5WfJsiQYXmtO25jiuyDU5
 =lsZ5
 -----END PGP SIGNATURE-----

Merge tag 'fpga-for-v2018.11' of git://git.denx.de/u-boot-microblaze

FPGA changes for v2018.11

- add fpga tests to cover fpga commands
- fpga Kconfig cleanup
- fix cmd/fpga.c
- add support for missing fpga loadmk commands
- add fpga fragment to MAINTAINERS
lime2-spi
Tom Rini 6 years ago
commit 89aa19d092
  1. 8
      MAINTAINERS
  2. 652
      cmd/fpga.c
  3. 16
      drivers/fpga/Kconfig
  4. 552
      test/py/tests/test_fpga.py

@ -391,6 +391,14 @@ F: test/py/tests/test_efi*
F: cmd/bootefi.c
F: tools/file2include.c
FPGA
M: Michal Simek <michal.simek@xilinx.com>
S: Maintained
T: git git://git.denx.de/u-boot-microblaze.git
F: drivers/fpga/
F: cmd/fpga.c
F: include/fpga.h
FLATTENED DEVICE TREE
M: Simon Glass <sjg@chromium.org>
S: Maintained

@ -13,388 +13,408 @@
#include <fs.h>
#include <malloc.h>
/* 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,
FPGA_LOADS,
};
/* ------------------------------------------------------------------------- */
/* command form:
* fpga <op> <device number> <data addr> <datasize>
* 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[])
static long do_fpga_get_device(char *arg)
{
int op, dev = FPGA_INVALID_DEVICE;
size_t data_size = 0;
void *fpga_data = NULL;
long dev = FPGA_INVALID_DEVICE;
char *devstr = env_get("fpga");
char *datastr = env_get("fpgadata");
int rc = FPGA_FAIL;
int wrong_parms = 0;
#if defined(CONFIG_FIT)
const char *fit_uname = NULL;
ulong fit_addr;
#endif
#if defined(CONFIG_CMD_FPGA_LOADFS)
fpga_fs_info fpga_fsinfo;
fpga_fsinfo.fstype = FS_TYPE_ANY;
#endif
#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
struct fpga_secure_info fpga_sec_info;
memset(&fpga_sec_info, 0, sizeof(fpga_sec_info));
#endif
if (devstr)
dev = (int) simple_strtoul(devstr, NULL, 16);
if (datastr)
fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
/* 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);
if (argc > 9 || argc < 2) {
debug("%s: Too many or too few args (%d)\n", __func__, argc);
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;
}
op = (int)fpga_get_op(argv[1]);
*dev = do_fpga_get_device(argv[0]);
switch (op) {
#if defined(CONFIG_CMD_FPGA_LOADFS)
case FPGA_LOADFS:
if (argc < 9)
return CMD_RET_USAGE;
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];
argc = 5;
break;
#endif
#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
case FPGA_LOADS:
if (argc < 7)
return CMD_RET_USAGE;
if (argc == 8)
fpga_sec_info.userkey_addr = (u8 *)(uintptr_t)
simple_strtoull(argv[7],
NULL, 16);
fpga_sec_info.encflag = (u8)simple_strtoul(argv[6], NULL, 16);
fpga_sec_info.authflag = (u8)simple_strtoul(argv[5], NULL, 16);
argc = 5;
break;
#endif
default:
break;
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;
switch (argc) {
case 5: /* fpga <op> <dev> <data> <datasize> */
data_size = simple_strtoul(argv[4], NULL, 16);
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;
case 4: /* fpga <op> <dev> <data> */
#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);
return 0;
}
#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
int do_fpga_loads(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
size_t data_size = 0;
long fpga_data, dev;
int ret;
struct fpga_secure_info fpga_sec_info;
case 3: /* fpga <op> <dev | data addr> */
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__);
memset(&fpga_sec_info, 0, sizeof(fpga_sec_info));
#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);
}
if (argc < 5) {
debug("fpga: incorrect parameters passed\n");
return CMD_RET_USAGE;
}
debug("%s: fpga_data = 0x%lx\n",
__func__, (ulong)fpga_data);
dev = FPGA_INVALID_DEVICE; /* reset device num */
}
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 <fpga load> for NonSecure bitstream\n");
return CMD_RET_USAGE;
}
if (dev == FPGA_INVALID_DEVICE) {
puts("FPGA device not specified\n");
op = FPGA_NONE;
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;
}
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;
break;
#endif
#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
case FPGA_LOADS:
if (fpga_sec_info.authflag >= FPGA_NO_ENC_OR_NO_AUTH &&
fpga_sec_info.encflag >= FPGA_NO_ENC_OR_NO_AUTH) {
puts("ERR: use <fpga load> for NonSecure bitstream\n");
wrong_parms = 1;
}
ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
cmdtp, argc, argv);
if (ret)
return ret;
if (fpga_sec_info.encflag == FPGA_ENC_USR_KEY &&
!fpga_sec_info.userkey_addr) {
wrong_parms = 1;
puts("ERR:User key not provided\n");
}
break;
return fpga_loads(dev, (void *)fpga_data, data_size, &fpga_sec_info);
}
#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;
#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 (wrong_parms) {
puts("Wrong parameters for FPGA request\n");
op = FPGA_NONE;
}
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 (op) {
case FPGA_NONE:
return CMD_RET_USAGE;
return fpga_info(dev);
}
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;
ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
cmdtp, argc, argv);
if (ret)
return ret;
return fpga_dump(dev, (void *)fpga_data, data_size);
}
case FPGA_INFO:
rc = fpga_info(dev);
break;
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;
ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
cmdtp, argc, argv);
if (ret)
return ret;
case FPGA_LOAD:
rc = fpga_load(dev, fpga_data, data_size, BIT_FULL);
break;
return fpga_load(dev, (void *)fpga_data, data_size, BIT_FULL);
}
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;
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)
case FPGA_LOADP:
rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL);
break;
#endif
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;
case FPGA_LOADB:
rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL);
break;
return fpga_load(dev, (void *)fpga_data, data_size, BIT_PARTIAL);
}
#endif
#if defined(CONFIG_CMD_FPGA_LOADBP)
case FPGA_LOADBP:
rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL);
break;
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
#if defined(CONFIG_CMD_FPGA_LOADFS)
case FPGA_LOADFS:
rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo);
break;
#if defined(CONFIG_CMD_FPGA_LOADMK)
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 defined(CONFIG_CMD_FPGA_LOAD_SECURE)
case FPGA_LOADS:
rc = fpga_loads(dev, fpga_data, data_size, &fpga_sec_info);
break;
debug("fpga: argc %x, dev %lx, datastr %s\n", argc, dev, datastr);
if (dev == FPGA_INVALID_DEVICE) {
debug("fpga: Invalid fpga device\n");
return CMD_RET_USAGE;
}
if (argc == 0 && !datastr) {
debug("fpga: No datastr passed\n");
return CMD_RET_USAGE;
}
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_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;
}
#if defined(CONFIG_CMD_FPGA_LOADMK)
case FPGA_LOADMK:
switch (genimg_get_format(fpga_data)) {
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) {
case IMAGE_FORMAT_LEGACY:
{
image_header_t *hdr = (image_header_t *)fpga_data;
ulong data;
u8 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;
ulong image_buf = image_get_data(hdr);
ulong image_size = ~0UL;
data = image_get_load(hdr);
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;
}
if (!fit_check_format(fit_hdr)) {
puts("Bad FIT image format\n");
return CMD_RET_FAILURE;
}
break;
#endif
case FPGA_DUMP:
rc = fpga_dump(dev, fpga_data, data_size);
break;
/* 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 data address and length */
if (fit_image_get_data(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
else if (!strcmp("dump", opstr))
op = FPGA_DUMP;
#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
else if (!strcmp("loads", opstr))
op = FPGA_LOADS;
U_BOOT_CMD_MKENT(loads, 6, 1, do_fpga_loads, "", ""),
#endif
};
static int do_fpga_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
cmd_tbl_t *fpga_cmd;
int ret;
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;
}
if (op == FPGA_NONE)
printf("Unknown fpga operation \"%s\"\n", opstr);
ret = fpga_cmd->cmd(fpga_cmd, flag, argc, argv);
return op;
return cmd_process_error(fpga_cmd, ret);
}
#if defined(CONFIG_CMD_FPGA_LOADFS) || defined(CONFIG_CMD_FPGA_LOAD_SECURE)
U_BOOT_CMD(fpga, 9, 1, do_fpga,
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"

@ -46,15 +46,15 @@ config FPGA_ZYNQMPPL
on Xilinx Zynq UltraScale+ (ZynqMP) device.
config FPGA_SPARTAN3
bool "Enable Spartan3 FPGA driver"
help
Enable Spartan3 FPGA driver for loading in BIT format.
bool "Enable Spartan3 FPGA driver"
help
Enable Spartan3 FPGA driver for loading in BIT format.
config FPGA_ZYNQPL
bool "Enable Xilinx FPGA for Zynq"
depends on ARCH_ZYNQ
help
Enable FPGA driver for loading bitstream in BIT and BIN format
on Xilinx Zynq devices.
bool "Enable Xilinx FPGA for Zynq"
depends on ARCH_ZYNQ
help
Enable FPGA driver for loading bitstream in BIT and BIN format
on Xilinx Zynq devices.
endmenu

@ -0,0 +1,552 @@
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2018, Xilinx Inc.
#
# Michal Simek
# Siva Durga Prasad Paladugu
import pytest
import re
import random
import u_boot_utils
"""
Note: This test relies on boardenv_* containing configuration values to define
the network available and files to be used for testing. Without this, this test
will be automatically skipped.
For example:
# True if a DHCP server is attached to the network, and should be tested.
env__net_dhcp_server = True
# A list of environment variables that should be set in order to configure a
# static IP. In this test case we atleast need serverip for performing tftpb
# to get required files.
env__net_static_env_vars = [
("ipaddr", "10.0.0.100"),
("netmask", "255.255.255.0"),
("serverip", "10.0.0.1"),
]
# Details regarding the files that may be read from a TFTP server. .
env__fpga_secure_readable_file = {
"fn": "auth_bhdr_ppk1_bit.bin",
"enckupfn": "auth_bhdr_enc_kup_load_bit.bin",
"addr": 0x1000000,
"keyaddr": 0x100000,
"keyfn": "key.txt",
}
env__fpga_under_test = {
"dev": 0,
"addr" : 0x1000000,
"bitstream_load": "compress.bin",
"bitstream_load_size": 1831960,
"bitstream_loadp": "compress_pr.bin",
"bitstream_loadp_size": 423352,
"bitstream_loadb": "compress.bit",
"bitstream_loadb_size": 1832086,
"bitstream_loadbp": "compress_pr.bit",
"bitstream_loadbp_size": 423491,
"mkimage_legacy": "download.ub",
"mkimage_legacy_size": 13321468,
"mkimage_legacy_gz": "download.gz.ub",
"mkimage_legacy_gz_size": 53632,
"mkimage_fit": "download-fit.ub",
"mkimage_fit_size": 13322784,
"loadfs": "mmc 0 compress.bin",
"loadfs_size": 1831960,
"loadfs_block_size": 0x10000,
}
"""
import test_net
def check_dev(u_boot_console):
f = u_boot_console.config.env.get('env__fpga_under_test', None)
if not f:
pytest.skip('No FPGA to test')
dev = f.get('dev', -1)
if dev < 0:
pytest.fail('No dev specified via env__fpga_under_test')
return dev, f
def load_file_from_var(u_boot_console, name):
dev, f = check_dev(u_boot_console)
addr = f.get('addr', -1)
if addr < 0:
pytest.fail('No address specified via env__fpga_under_test')
test_net.test_net_dhcp(u_boot_console)
test_net.test_net_setup_static(u_boot_console)
bit = f['%s' % (name)]
bit_size = f['%s_size' % (name)]
expected_tftp = 'Bytes transferred = %d' % bit_size
output = u_boot_console.run_command('tftpboot %x %s' % (addr, bit))
assert expected_tftp in output
return f, dev, addr, bit, bit_size
###### FPGA FAIL test ######
expected_usage = 'fpga - loadable FPGA image support'
@pytest.mark.xfail
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_fail(u_boot_console):
# Test non valid fpga subcommand
expected = 'fpga: non existing command'
output = u_boot_console.run_command('fpga broken 0')
#assert expected in output
assert expected_usage in output
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_help(u_boot_console):
# Just show help
output = u_boot_console.run_command('fpga')
assert expected_usage in output
###### FPGA DUMP tests ######
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_dump(u_boot_console):
pytest.skip('Not implemented now')
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_dump_variable(u_boot_console):
# Same as above but via "fpga" variable
pytest.skip('Not implemented now')
###### FPGA INFO tests ######
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_info_fail(u_boot_console):
# Maybe this can be skipped completely
dev, f = check_dev(u_boot_console)
# Multiple parameters to fpga info should fail
expected = 'fpga: more parameters passed'
output = u_boot_console.run_command('fpga info 0 0')
#assert expected in output
assert expected_usage in output
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_info_list(u_boot_console):
# Maybe this can be skipped completely
dev, f = check_dev(u_boot_console)
# Code is design in a way that if fpga dev is not passed it should
# return list of all fpga devices in the system
u_boot_console.run_command('setenv fpga')
output = u_boot_console.run_command('fpga info')
assert expected_usage not in output
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_info(u_boot_console):
dev, f = check_dev(u_boot_console)
output = u_boot_console.run_command('fpga info %x' % (dev))
assert expected_usage not in output
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_info_variable(u_boot_console):
dev, f = check_dev(u_boot_console)
#
# fpga variable is storing device number which doesn't need to be passed
#
u_boot_console.run_command('setenv fpga %x' % (dev))
output = u_boot_console.run_command('fpga info')
# Variable cleanup
u_boot_console.run_command('setenv fpga')
assert expected_usage not in output
###### FPGA LOAD tests ######
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_load_fail(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_load')
for cmd in ['dump', 'load', 'loadb']:
# missing dev parameter
expected = 'fpga: incorrect parameters passed'
output = u_boot_console.run_command('fpga %s %x $filesize' % (cmd, addr))
#assert expected in output
assert expected_usage in output
# more parameters - 0 at the end
expected = 'fpga: more parameters passed'
output = u_boot_console.run_command('fpga %s %x %x $filesize 0' % (cmd, dev, addr))
#assert expected in output
assert expected_usage in output
# 0 address
expected = 'fpga: zero fpga_data address'
output = u_boot_console.run_command('fpga %s %x 0 $filesize' % (cmd, dev))
#assert expected in output
assert expected_usage in output
# 0 filesize
expected = 'fpga: zero size'
output = u_boot_console.run_command('fpga %s %x %x 0' % (cmd, dev, addr))
#assert expected in output
assert expected_usage in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_load(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_load')
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga load %x %x $filesize && echo %s' % (dev, addr, expected_text))
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadp')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadp(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_load')
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga load %x %x $filesize && echo %s' % (dev, addr, expected_text))
assert expected_text in output
# And load also partial bistream
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadp')
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadp %x %x $filesize && echo %s' % (dev, addr, expected_text))
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadb(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadb')
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadb %x %x $filesize && echo %s' % (dev, addr, expected_text))
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadbp')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadbp(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadb')
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadb %x %x $filesize && echo %s' % (dev, addr, expected_text))
assert expected_text in output
# And load also partial bistream in bit format
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadbp')
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadbp %x %x $filesize && echo %s' % (dev, addr, expected_text))
assert expected_text in output
###### FPGA LOADMK tests ######
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('cmd_echo')
@pytest.mark.buildconfigspec('image_format_legacy')
def test_fpga_loadmk_fail(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
u_boot_console.run_command('imi %x' % (addr))
# load image but pass incorrect address to show error message
expected = 'Unknown image type'
output = u_boot_console.run_command('fpga loadmk %x %x' % (dev, addr + 0x10))
assert expected in output
# Pass more parameters then command expects - 0 at the end
output = u_boot_console.run_command('fpga loadmk %x %x 0' % (dev, addr))
#assert expected in output
assert expected_usage in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('cmd_echo')
@pytest.mark.buildconfigspec('image_format_legacy')
def test_fpga_loadmk_legacy(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
u_boot_console.run_command('imi %x' % (addr))
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk %x %x && echo %s' % (dev, addr, expected_text))
assert expected_text in output
@pytest.mark.xfail
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('cmd_echo')
@pytest.mark.buildconfigspec('image_format_legacy')
def test_fpga_loadmk_legacy_variable_fpga(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
u_boot_console.run_command('imi %x' % (addr))
u_boot_console.run_command('setenv fpga %x' % (dev))
# this testcase should cover case which looks like it is supported but dev pointer is broken by loading mkimage address
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk %x && echo %s' % (addr, expected_text))
u_boot_console.run_command('setenv fpga')
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('cmd_echo')
@pytest.mark.buildconfigspec('image_format_legacy')
def test_fpga_loadmk_legacy_variable_fpgadata(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
u_boot_console.run_command('imi %x' % (addr))
u_boot_console.run_command('setenv fpgadata %x' % (addr))
# this testcase should cover case which looks like it is supported but dev pointer is broken by loading mkimage address
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk %x && echo %s' % (dev, expected_text))
u_boot_console.run_command('setenv fpgadata')
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('cmd_echo')
@pytest.mark.buildconfigspec('image_format_legacy')
def test_fpga_loadmk_legacy_variable(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
u_boot_console.run_command('imi %x' % (addr))
u_boot_console.run_command('setenv fpga %x' % (dev))
u_boot_console.run_command('setenv fpgadata %x' % (addr))
# this testcase should cover case which looks like it is supported but dev pointer is broken by loading mkimage address
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk && echo %s' % (expected_text))
u_boot_console.run_command('setenv fpga')
u_boot_console.run_command('setenv fpgadata')
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('cmd_echo')
@pytest.mark.buildconfigspec('image_format_legacy')
@pytest.mark.buildconfigspec('gzip')
def test_fpga_loadmk_legacy_gz(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy_gz')
u_boot_console.run_command('imi %x' % (addr))
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk %x %x && echo %s' % (dev, addr, expected_text))
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('fit')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadmk_fit(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
u_boot_console.run_command('imi %x' % (addr))
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk %x %x:fpga && echo %s' % (dev, addr, expected_text))
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('fit')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadmk_fit_variable_fpga(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
u_boot_console.run_command('imi %x' % (addr))
# FIXME this should fail - broken support in past
u_boot_console.run_command('setenv fpga %x' % (dev))
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk %x:fpga && echo %s' % (addr, expected_text))
u_boot_console.run_command('setenv fpga')
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('fit')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadmk_fit_variable_fpgadata(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
u_boot_console.run_command('imi %x' % (addr))
# FIXME this should fail - broken support in past
u_boot_console.run_command('setenv fpgadata %x:fpga' % (addr))
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk %x && echo %s' % (dev, expected_text))
u_boot_console.run_command('setenv fpgadata')
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
@pytest.mark.buildconfigspec('fit')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadmk_fit_variable(u_boot_console):
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
u_boot_console.run_command('imi %x' % (addr))
u_boot_console.run_command('setenv fpga %x' % (dev))
u_boot_console.run_command('setenv fpgadata %x:fpga' % (addr))
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadmk && echo %s' % (expected_text))
u_boot_console.run_command('setenv fpga')
u_boot_console.run_command('setenv fpgadata')
assert expected_text in output
###### FPGA LOAD tests ######
@pytest.mark.buildconfigspec('cmd_fpga')
def test_fpga_loadfs_fail(u_boot_console):
dev, f = check_dev(u_boot_console)
addr = f.get('addr', -1)
if addr < 0:
pytest.fail('No address specified via env__fpga_under_test')
bit = f['loadfs']
bit_size = f['loadfs_size']
block_size = f['loadfs_block_size']
# less params - dev number removed
expected = 'fpga: incorrect parameters passed'
output = u_boot_console.run_command('fpga loadfs %x %x %x %s' % (addr, bit_size, block_size, bit))
#assert expected in output
assert expected_usage in output
# one more param - 0 at the end
# This is the longest command that's why there is no message from cmd/fpga.c
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s 0' % (dev, addr, bit_size, block_size, bit))
assert expected_usage in output
# zero address 0
expected = 'fpga: zero fpga_data address'
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s' % (dev, 0, bit_size, block_size, bit))
#assert expected in output
assert expected_usage in output
# bit_size 0
expected = 'fpga: zero size'
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s' % (dev, addr, 0, block_size, bit))
#assert expected in output
assert expected_usage in output
# block size 0
# FIXME this should pass but it failing too
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s' % (dev, addr, bit_size, 0, bit))
assert expected_usage in output
# non existing bitstream name
expected = 'Unable to read file noname'
output = u_boot_console.run_command('fpga loadfs %x %x %x %x mmc 0 noname' % (dev, addr, bit_size, block_size))
assert expected in output
assert expected_usage in output
# -1 dev number
expected = 'fpga_fsload: Invalid device number -1'
output = u_boot_console.run_command('fpga loadfs %d %x %x %x mmc 0 noname' % (-1, addr, bit_size, block_size))
assert expected in output
assert expected_usage in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_echo')
def test_fpga_loadfs(u_boot_console):
dev, f = check_dev(u_boot_console)
addr = f.get('addr', -1)
if addr < 0:
pytest.fail('No address specified via env__fpga_under_test')
bit = f['loadfs']
bit_size = f['loadfs_size']
block_size = f['loadfs_block_size']
# This should be done better
expected_text = 'FPGA loaded successfully'
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s && echo %s' % (dev, addr, bit_size, block_size, bit, expected_text))
assert expected_text in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_load_secure')
@pytest.mark.buildconfigspec('cmd_net')
@pytest.mark.buildconfigspec('cmd_dhcp')
@pytest.mark.buildconfigspec('net')
def test_fpga_secure_bit_auth(u_boot_console):
test_net.test_net_dhcp(u_boot_console)
test_net.test_net_setup_static(u_boot_console)
f = u_boot_console.config.env.get('env__fpga_secure_readable_file', None)
if not f:
pytest.skip('No TFTP readable file to read')
addr = f.get('addr', None)
if not addr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['fn']
output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
assert expected_tftp in output
expected_zynqmpsecure = 'Bitstream successfully loaded'
output = u_boot_console.run_command('fpga loads 0 %x $filesize 0 2' % (addr))
assert expected_zynqmpsecure in output
@pytest.mark.buildconfigspec('cmd_fpga')
@pytest.mark.buildconfigspec('cmd_fpga_load_secure')
@pytest.mark.buildconfigspec('cmd_net')
@pytest.mark.buildconfigspec('cmd_dhcp')
@pytest.mark.buildconfigspec('net')
def test_fpga_secure_bit_img_auth_kup(u_boot_console):
test_net.test_net_dhcp(u_boot_console)
test_net.test_net_setup_static(u_boot_console)
f = u_boot_console.config.env.get('env__fpga_secure_readable_file', None)
if not f:
pytest.skip('No TFTP readable file to read')
keyaddr = f.get('keyaddr', None)
if not keyaddr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
keyfn = f['keyfn']
output = u_boot_console.run_command('tftpboot %x %s' % (keyaddr, keyfn))
assert expected_tftp in output
addr = f.get('addr', None)
if not addr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['enckupfn']
output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
assert expected_tftp in output
expected_zynqmpsecure = 'Bitstream successfully loaded'
output = u_boot_console.run_command('fpga loads 0 %x $filesize 0 1 %x' % (addr, keyaddr))
assert expected_zynqmpsecure in output
Loading…
Cancel
Save