xref: /openbmc/u-boot/cmd/fpga.c (revision a2d1033b)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
22e192b24SSimon Glass /*
32e192b24SSimon Glass  * (C) Copyright 2000, 2001
42e192b24SSimon Glass  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
52e192b24SSimon Glass  */
62e192b24SSimon Glass 
72e192b24SSimon Glass /*
82e192b24SSimon Glass  *  FPGA support
92e192b24SSimon Glass  */
102e192b24SSimon Glass #include <common.h>
112e192b24SSimon Glass #include <command.h>
122e192b24SSimon Glass #include <fpga.h>
132e192b24SSimon Glass #include <fs.h>
142e192b24SSimon Glass #include <malloc.h>
152e192b24SSimon Glass 
16f4c7a4aeSMichal Simek static long do_fpga_get_device(char *arg)
17f4c7a4aeSMichal Simek {
18f4c7a4aeSMichal Simek 	long dev = FPGA_INVALID_DEVICE;
19f4c7a4aeSMichal Simek 	char *devstr = env_get("fpga");
20f4c7a4aeSMichal Simek 
21f4c7a4aeSMichal Simek 	if (devstr)
22f4c7a4aeSMichal Simek 		/* Should be strtol to handle -1 cases */
23f4c7a4aeSMichal Simek 		dev = simple_strtol(devstr, NULL, 16);
24f4c7a4aeSMichal Simek 
258c75f794SMichal Simek 	if (dev == FPGA_INVALID_DEVICE && arg)
26f4c7a4aeSMichal Simek 		dev = simple_strtol(arg, NULL, 16);
27f4c7a4aeSMichal Simek 
28f4c7a4aeSMichal Simek 	debug("%s: device = %ld\n", __func__, dev);
29f4c7a4aeSMichal Simek 
30f4c7a4aeSMichal Simek 	return dev;
31f4c7a4aeSMichal Simek }
32f4c7a4aeSMichal Simek 
3385754795SMichal Simek static int do_fpga_check_params(long *dev, long *fpga_data, size_t *data_size,
3485754795SMichal Simek 				cmd_tbl_t *cmdtp, int argc, char *const argv[])
3585754795SMichal Simek {
3685754795SMichal Simek 	size_t local_data_size;
3785754795SMichal Simek 	long local_fpga_data;
3885754795SMichal Simek 
3985754795SMichal Simek 	debug("%s %d, %d\n", __func__, argc, cmdtp->maxargs);
4085754795SMichal Simek 
4185754795SMichal Simek 	if (argc != cmdtp->maxargs) {
4285754795SMichal Simek 		debug("fpga: incorrect parameters passed\n");
4385754795SMichal Simek 		return CMD_RET_USAGE;
4485754795SMichal Simek 	}
4585754795SMichal Simek 
4685754795SMichal Simek 	*dev = do_fpga_get_device(argv[0]);
4785754795SMichal Simek 
4885754795SMichal Simek 	local_fpga_data = simple_strtol(argv[1], NULL, 16);
4985754795SMichal Simek 	if (!local_fpga_data) {
5085754795SMichal Simek 		debug("fpga: zero fpga_data address\n");
5185754795SMichal Simek 		return CMD_RET_USAGE;
5285754795SMichal Simek 	}
5385754795SMichal Simek 	*fpga_data = local_fpga_data;
5485754795SMichal Simek 
5585754795SMichal Simek 	local_data_size = simple_strtoul(argv[2], NULL, 16);
5685754795SMichal Simek 	if (!local_data_size) {
5785754795SMichal Simek 		debug("fpga: zero size\n");
5885754795SMichal Simek 		return CMD_RET_USAGE;
5985754795SMichal Simek 	}
6085754795SMichal Simek 	*data_size = local_data_size;
6185754795SMichal Simek 
6285754795SMichal Simek 	return 0;
6385754795SMichal Simek }
6485754795SMichal Simek 
652e192b24SSimon Glass /* Local defines */
665cf22289SMichal Simek enum {
675cf22289SMichal Simek 	FPGA_NONE = -1,
68cedd48e2SSiva Durga Prasad Paladugu 	FPGA_LOADS,
695cf22289SMichal Simek };
702e192b24SSimon Glass 
71323fe38eSMichal Simek /*
72323fe38eSMichal Simek  * Map op to supported operations.  We don't use a table since we
73323fe38eSMichal Simek  * would just have to relocate it from flash anyway.
74323fe38eSMichal Simek  */
75323fe38eSMichal Simek static int fpga_get_op(char *opstr)
76323fe38eSMichal Simek {
77323fe38eSMichal Simek 	int op = FPGA_NONE;
78323fe38eSMichal Simek 
79323fe38eSMichal Simek #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
802892fe80SMichal Simek 	if (!strcmp("loads", opstr))
81323fe38eSMichal Simek 		op = FPGA_LOADS;
82323fe38eSMichal Simek #endif
83323fe38eSMichal Simek 
84323fe38eSMichal Simek 	return op;
85323fe38eSMichal Simek }
86323fe38eSMichal Simek 
872e192b24SSimon Glass /* ------------------------------------------------------------------------- */
882e192b24SSimon Glass /* command form:
892e192b24SSimon Glass  *   fpga <op> <device number> <data addr> <datasize>
902e192b24SSimon Glass  * where op is 'load', 'dump', or 'info'
912e192b24SSimon Glass  * If there is no device number field, the fpga environment variable is used.
922e192b24SSimon Glass  * If there is no data addr field, the fpgadata environment variable is used.
932e192b24SSimon Glass  * The info command requires no data address field.
942e192b24SSimon Glass  */
952e192b24SSimon Glass int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
962e192b24SSimon Glass {
972e192b24SSimon Glass 	int op, dev = FPGA_INVALID_DEVICE;
982e192b24SSimon Glass 	size_t data_size = 0;
992e192b24SSimon Glass 	void *fpga_data = NULL;
1002e192b24SSimon Glass 	int rc = FPGA_FAIL;
101cedd48e2SSiva Durga Prasad Paladugu #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
102cedd48e2SSiva Durga Prasad Paladugu 	struct fpga_secure_info fpga_sec_info;
103cedd48e2SSiva Durga Prasad Paladugu 
104cedd48e2SSiva Durga Prasad Paladugu 	memset(&fpga_sec_info, 0, sizeof(fpga_sec_info));
105cedd48e2SSiva Durga Prasad Paladugu #endif
1062e192b24SSimon Glass 
107f5953610SSiva Durga Prasad Paladugu 	if (argc > 9 || argc < 2) {
108f5953610SSiva Durga Prasad Paladugu 		debug("%s: Too many or too few args (%d)\n", __func__, argc);
109f5953610SSiva Durga Prasad Paladugu 		return CMD_RET_USAGE;
110f5953610SSiva Durga Prasad Paladugu 	}
111f5953610SSiva Durga Prasad Paladugu 
112323fe38eSMichal Simek 	op = fpga_get_op(argv[1]);
113f5953610SSiva Durga Prasad Paladugu 
114f5953610SSiva Durga Prasad Paladugu 	switch (op) {
11555010969SMichal Simek 	case FPGA_NONE:
11655010969SMichal Simek 		printf("Unknown fpga operation \"%s\"\n", argv[1]);
11755010969SMichal Simek 		return CMD_RET_USAGE;
118cedd48e2SSiva Durga Prasad Paladugu #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
119cedd48e2SSiva Durga Prasad Paladugu 	case FPGA_LOADS:
120cedd48e2SSiva Durga Prasad Paladugu 		if (argc < 7)
121cedd48e2SSiva Durga Prasad Paladugu 			return CMD_RET_USAGE;
122cedd48e2SSiva Durga Prasad Paladugu 		if (argc == 8)
123cedd48e2SSiva Durga Prasad Paladugu 			fpga_sec_info.userkey_addr = (u8 *)(uintptr_t)
124cedd48e2SSiva Durga Prasad Paladugu 						     simple_strtoull(argv[7],
125cedd48e2SSiva Durga Prasad Paladugu 								     NULL, 16);
126cedd48e2SSiva Durga Prasad Paladugu 		fpga_sec_info.encflag = (u8)simple_strtoul(argv[6], NULL, 16);
127cedd48e2SSiva Durga Prasad Paladugu 		fpga_sec_info.authflag = (u8)simple_strtoul(argv[5], NULL, 16);
12844d839bdSMichal Simek 
12944d839bdSMichal Simek 		if (fpga_sec_info.authflag >= FPGA_NO_ENC_OR_NO_AUTH &&
13044d839bdSMichal Simek 		    fpga_sec_info.encflag >= FPGA_NO_ENC_OR_NO_AUTH) {
13144d839bdSMichal Simek 			puts("ERR: Use <fpga load> for NonSecure bitstream\n");
13244d839bdSMichal Simek 			return CMD_RET_USAGE;
13344d839bdSMichal Simek 		}
13444d839bdSMichal Simek 
13544d839bdSMichal Simek 		if (fpga_sec_info.encflag == FPGA_ENC_USR_KEY &&
13644d839bdSMichal Simek 		    !fpga_sec_info.userkey_addr) {
13744d839bdSMichal Simek 			puts("ERR: User key not provided\n");
13844d839bdSMichal Simek 			return CMD_RET_USAGE;
13944d839bdSMichal Simek 		}
14044d839bdSMichal Simek 
141cedd48e2SSiva Durga Prasad Paladugu 		argc = 5;
142cedd48e2SSiva Durga Prasad Paladugu 		break;
143cedd48e2SSiva Durga Prasad Paladugu #endif
144f5953610SSiva Durga Prasad Paladugu 	default:
145f5953610SSiva Durga Prasad Paladugu 		break;
146f5953610SSiva Durga Prasad Paladugu 	}
147f5953610SSiva Durga Prasad Paladugu 
148f5953610SSiva Durga Prasad Paladugu 	switch (argc) {
1492e192b24SSimon Glass 	case 5:		/* fpga <op> <dev> <data> <datasize> */
1502e192b24SSimon Glass 		data_size = simple_strtoul(argv[4], NULL, 16);
1515cadab60SMichal Simek 		if (!data_size) {
1525cadab60SMichal Simek 			puts("Zero data_size\n");
1535cadab60SMichal Simek 			return CMD_RET_USAGE;
1545cadab60SMichal Simek 		}
1552e192b24SSimon Glass 	case 4:		/* fpga <op> <dev> <data> */
1562e192b24SSimon Glass 		{
1572e192b24SSimon Glass 			fpga_data = (void *)simple_strtoul(argv[3], NULL, 16);
1582e192b24SSimon Glass 			debug("*  fpga: cmdline image address = 0x%08lx\n",
1592e192b24SSimon Glass 			      (ulong)fpga_data);
1602e192b24SSimon Glass 		}
161455ad585SMichal Simek 		debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data);
1625cadab60SMichal Simek 		if (!fpga_data) {
1635cadab60SMichal Simek 			puts("Zero fpga_data address\n");
1645cadab60SMichal Simek 			return CMD_RET_USAGE;
1655cadab60SMichal Simek 		}
1662e192b24SSimon Glass 	case 3:		/* fpga <op> <dev | data addr> */
1672e192b24SSimon Glass 		dev = (int)simple_strtoul(argv[2], NULL, 16);
1682e192b24SSimon Glass 		debug("%s: device = %d\n", __func__, dev);
1692e192b24SSimon Glass 	}
1702e192b24SSimon Glass 
1712e192b24SSimon Glass 	if (dev == FPGA_INVALID_DEVICE) {
1722e192b24SSimon Glass 		puts("FPGA device not specified\n");
173ccd65203SMichal Simek 		return CMD_RET_USAGE;
1742e192b24SSimon Glass 	}
1752e192b24SSimon Glass 
1762e192b24SSimon Glass 	switch (op) {
177cedd48e2SSiva Durga Prasad Paladugu #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
178cedd48e2SSiva Durga Prasad Paladugu 	case FPGA_LOADS:
179cedd48e2SSiva Durga Prasad Paladugu 		rc = fpga_loads(dev, fpga_data, data_size, &fpga_sec_info);
180cedd48e2SSiva Durga Prasad Paladugu 		break;
181cedd48e2SSiva Durga Prasad Paladugu #endif
1822e192b24SSimon Glass 
1832e192b24SSimon Glass 	default:
1842e192b24SSimon Glass 		printf("Unknown operation\n");
1852e192b24SSimon Glass 		return CMD_RET_USAGE;
1862e192b24SSimon Glass 	}
1872e192b24SSimon Glass 	return rc;
1882e192b24SSimon Glass }
1892e192b24SSimon Glass 
19049503f9aSMichal Simek #if defined(CONFIG_CMD_FPGA_LOADFS)
19149503f9aSMichal Simek static int do_fpga_loadfs(cmd_tbl_t *cmdtp, int flag, int argc,
19249503f9aSMichal Simek 			  char *const argv[])
19349503f9aSMichal Simek {
19449503f9aSMichal Simek 	size_t data_size = 0;
19549503f9aSMichal Simek 	long fpga_data, dev;
19649503f9aSMichal Simek 	int ret;
19749503f9aSMichal Simek 	fpga_fs_info fpga_fsinfo;
19849503f9aSMichal Simek 
19949503f9aSMichal Simek 	ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
20049503f9aSMichal Simek 				   cmdtp, argc, argv);
20149503f9aSMichal Simek 	if (ret)
20249503f9aSMichal Simek 		return ret;
20349503f9aSMichal Simek 
20449503f9aSMichal Simek 	fpga_fsinfo.fstype = FS_TYPE_ANY;
20549503f9aSMichal Simek 	fpga_fsinfo.blocksize = (unsigned int)simple_strtoul(argv[3], NULL, 16);
20649503f9aSMichal Simek 	fpga_fsinfo.interface = argv[4];
20749503f9aSMichal Simek 	fpga_fsinfo.dev_part = argv[5];
20849503f9aSMichal Simek 	fpga_fsinfo.filename = argv[6];
20949503f9aSMichal Simek 
21049503f9aSMichal Simek 	return fpga_fsload(dev, (void *)fpga_data, data_size, &fpga_fsinfo);
21149503f9aSMichal Simek }
21249503f9aSMichal Simek #endif
21349503f9aSMichal Simek 
214f4c7a4aeSMichal Simek static int do_fpga_info(cmd_tbl_t *cmdtp, int flag, int argc,
215f4c7a4aeSMichal Simek 			char * const argv[])
216f4c7a4aeSMichal Simek {
217f4c7a4aeSMichal Simek 	long dev = do_fpga_get_device(argv[0]);
218f4c7a4aeSMichal Simek 
219f4c7a4aeSMichal Simek 	return fpga_info(dev);
220f4c7a4aeSMichal Simek }
221f4c7a4aeSMichal Simek 
22285754795SMichal Simek static int do_fpga_dump(cmd_tbl_t *cmdtp, int flag, int argc,
22385754795SMichal Simek 			char * const argv[])
22485754795SMichal Simek {
22585754795SMichal Simek 	size_t data_size = 0;
22685754795SMichal Simek 	long fpga_data, dev;
22785754795SMichal Simek 	int ret;
22885754795SMichal Simek 
22985754795SMichal Simek 	ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
23085754795SMichal Simek 				   cmdtp, argc, argv);
23185754795SMichal Simek 	if (ret)
23285754795SMichal Simek 		return ret;
23385754795SMichal Simek 
23485754795SMichal Simek 	return fpga_dump(dev, (void *)fpga_data, data_size);
23585754795SMichal Simek }
23685754795SMichal Simek 
23785754795SMichal Simek static int do_fpga_load(cmd_tbl_t *cmdtp, int flag, int argc,
23885754795SMichal Simek 			char * const argv[])
23985754795SMichal Simek {
24085754795SMichal Simek 	size_t data_size = 0;
24185754795SMichal Simek 	long fpga_data, dev;
24285754795SMichal Simek 	int ret;
24385754795SMichal Simek 
24485754795SMichal Simek 	ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
24585754795SMichal Simek 				   cmdtp, argc, argv);
24685754795SMichal Simek 	if (ret)
24785754795SMichal Simek 		return ret;
24885754795SMichal Simek 
24985754795SMichal Simek 	return fpga_load(dev, (void *)fpga_data, data_size, BIT_FULL);
25085754795SMichal Simek }
25185754795SMichal Simek 
25285754795SMichal Simek static int do_fpga_loadb(cmd_tbl_t *cmdtp, int flag, int argc,
25385754795SMichal Simek 			 char * const argv[])
25485754795SMichal Simek {
25585754795SMichal Simek 	size_t data_size = 0;
25685754795SMichal Simek 	long fpga_data, dev;
25785754795SMichal Simek 	int ret;
25885754795SMichal Simek 
25985754795SMichal Simek 	ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
26085754795SMichal Simek 				   cmdtp, argc, argv);
26185754795SMichal Simek 	if (ret)
26285754795SMichal Simek 		return ret;
26385754795SMichal Simek 
26485754795SMichal Simek 	return fpga_loadbitstream(dev, (void *)fpga_data, data_size, BIT_FULL);
26585754795SMichal Simek }
26685754795SMichal Simek 
26785754795SMichal Simek #if defined(CONFIG_CMD_FPGA_LOADP)
26885754795SMichal Simek static int do_fpga_loadp(cmd_tbl_t *cmdtp, int flag, int argc,
26985754795SMichal Simek 			 char * const argv[])
27085754795SMichal Simek {
27185754795SMichal Simek 	size_t data_size = 0;
27285754795SMichal Simek 	long fpga_data, dev;
27385754795SMichal Simek 	int ret;
27485754795SMichal Simek 
27585754795SMichal Simek 	ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
27685754795SMichal Simek 				   cmdtp, argc, argv);
27785754795SMichal Simek 	if (ret)
27885754795SMichal Simek 		return ret;
27985754795SMichal Simek 
28085754795SMichal Simek 	return fpga_load(dev, (void *)fpga_data, data_size, BIT_PARTIAL);
28185754795SMichal Simek }
28285754795SMichal Simek #endif
28385754795SMichal Simek 
28485754795SMichal Simek #if defined(CONFIG_CMD_FPGA_LOADBP)
28585754795SMichal Simek static int do_fpga_loadbp(cmd_tbl_t *cmdtp, int flag, int argc,
28685754795SMichal Simek 			  char * const argv[])
28785754795SMichal Simek {
28885754795SMichal Simek 	size_t data_size = 0;
28985754795SMichal Simek 	long fpga_data, dev;
29085754795SMichal Simek 	int ret;
29185754795SMichal Simek 
29285754795SMichal Simek 	ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
29385754795SMichal Simek 				   cmdtp, argc, argv);
29485754795SMichal Simek 	if (ret)
29585754795SMichal Simek 		return ret;
29685754795SMichal Simek 
29785754795SMichal Simek 	return fpga_loadbitstream(dev, (void *)fpga_data, data_size,
29885754795SMichal Simek 				  BIT_PARTIAL);
29985754795SMichal Simek }
30085754795SMichal Simek #endif
30185754795SMichal Simek 
3022892fe80SMichal Simek #if defined(CONFIG_CMD_FPGA_LOADMK)
3032892fe80SMichal Simek static int do_fpga_loadmk(cmd_tbl_t *cmdtp, int flag, int argc,
3042892fe80SMichal Simek 			  char * const argv[])
3052892fe80SMichal Simek {
3062892fe80SMichal Simek 	size_t data_size = 0;
3072892fe80SMichal Simek 	void *fpga_data = NULL;
3082892fe80SMichal Simek #if defined(CONFIG_FIT)
3092892fe80SMichal Simek 	const char *fit_uname = NULL;
3102892fe80SMichal Simek 	ulong fit_addr;
3112892fe80SMichal Simek #endif
3122892fe80SMichal Simek 	ulong dev = do_fpga_get_device(argv[0]);
3132892fe80SMichal Simek 	char *datastr = env_get("fpgadata");
3142892fe80SMichal Simek 
3158c75f794SMichal Simek 	debug("fpga: argc %x, dev %lx, datastr %s\n", argc, dev, datastr);
3168c75f794SMichal Simek 
3178c75f794SMichal Simek 	if (dev == FPGA_INVALID_DEVICE) {
3188c75f794SMichal Simek 		debug("fpga: Invalid fpga device\n");
3198c75f794SMichal Simek 		return CMD_RET_USAGE;
3208c75f794SMichal Simek 	}
3218c75f794SMichal Simek 
3228c75f794SMichal Simek 	if (argc == 0 && !datastr) {
3238c75f794SMichal Simek 		debug("fpga: No datastr passed\n");
3248c75f794SMichal Simek 		return CMD_RET_USAGE;
3258c75f794SMichal Simek 	}
3262892fe80SMichal Simek 
3272892fe80SMichal Simek 	if (argc == 2) {
3288c75f794SMichal Simek 		datastr = argv[1];
3298c75f794SMichal Simek 		debug("fpga: Full command with two args\n");
3308c75f794SMichal Simek 	} else if (argc == 1 && !datastr) {
3318c75f794SMichal Simek 		debug("fpga: Dev is setup - fpgadata passed\n");
3328c75f794SMichal Simek 		datastr = argv[0];
3338c75f794SMichal Simek 	}
3348c75f794SMichal Simek 
3352892fe80SMichal Simek #if defined(CONFIG_FIT)
3368c75f794SMichal Simek 	if (fit_parse_subimage(datastr, (ulong)fpga_data,
3372892fe80SMichal Simek 			       &fit_addr, &fit_uname)) {
3382892fe80SMichal Simek 		fpga_data = (void *)fit_addr;
3392892fe80SMichal Simek 		debug("*  fpga: subimage '%s' from FIT image ",
3402892fe80SMichal Simek 		      fit_uname);
3412892fe80SMichal Simek 		debug("at 0x%08lx\n", fit_addr);
3422892fe80SMichal Simek 	} else
3432892fe80SMichal Simek #endif
3442892fe80SMichal Simek 	{
3458c75f794SMichal Simek 		fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
3462892fe80SMichal Simek 		debug("*  fpga: cmdline image address = 0x%08lx\n",
3472892fe80SMichal Simek 		      (ulong)fpga_data);
3482892fe80SMichal Simek 	}
3492892fe80SMichal Simek 	debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data);
3502892fe80SMichal Simek 	if (!fpga_data) {
3512892fe80SMichal Simek 		puts("Zero fpga_data address\n");
3522892fe80SMichal Simek 		return CMD_RET_USAGE;
3532892fe80SMichal Simek 	}
3542892fe80SMichal Simek 
3552892fe80SMichal Simek 	switch (genimg_get_format(fpga_data)) {
3562892fe80SMichal Simek #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
3572892fe80SMichal Simek 	case IMAGE_FORMAT_LEGACY:
3582892fe80SMichal Simek 	{
3592892fe80SMichal Simek 		image_header_t *hdr = (image_header_t *)fpga_data;
3602892fe80SMichal Simek 		ulong data;
3612892fe80SMichal Simek 		u8 comp;
3622892fe80SMichal Simek 
3632892fe80SMichal Simek 		comp = image_get_comp(hdr);
3642892fe80SMichal Simek 		if (comp == IH_COMP_GZIP) {
3652892fe80SMichal Simek #if defined(CONFIG_GZIP)
3662892fe80SMichal Simek 			ulong image_buf = image_get_data(hdr);
3672892fe80SMichal Simek 			ulong image_size = ~0UL;
3682892fe80SMichal Simek 
3692892fe80SMichal Simek 			data = image_get_load(hdr);
3702892fe80SMichal Simek 
3712892fe80SMichal Simek 			if (gunzip((void *)data, ~0UL, (void *)image_buf,
3722892fe80SMichal Simek 				   &image_size) != 0) {
3732892fe80SMichal Simek 				puts("GUNZIP: error\n");
374*a2d1033bSMichal Simek 				return CMD_RET_FAILURE;
3752892fe80SMichal Simek 			}
3762892fe80SMichal Simek 			data_size = image_size;
3772892fe80SMichal Simek #else
3782892fe80SMichal Simek 			puts("Gunzip image is not supported\n");
3792892fe80SMichal Simek 			return 1;
3802892fe80SMichal Simek #endif
3812892fe80SMichal Simek 		} else {
3822892fe80SMichal Simek 			data = (ulong)image_get_data(hdr);
3832892fe80SMichal Simek 			data_size = image_get_data_size(hdr);
3842892fe80SMichal Simek 		}
3852892fe80SMichal Simek 		return fpga_load(dev, (void *)data, data_size,
3862892fe80SMichal Simek 				  BIT_FULL);
3872892fe80SMichal Simek 	}
3882892fe80SMichal Simek #endif
3892892fe80SMichal Simek #if defined(CONFIG_FIT)
3902892fe80SMichal Simek 	case IMAGE_FORMAT_FIT:
3912892fe80SMichal Simek 	{
3922892fe80SMichal Simek 		const void *fit_hdr = (const void *)fpga_data;
3932892fe80SMichal Simek 		int noffset;
3942892fe80SMichal Simek 		const void *fit_data;
3952892fe80SMichal Simek 
3962892fe80SMichal Simek 		if (!fit_uname) {
3972892fe80SMichal Simek 			puts("No FIT subimage unit name\n");
398*a2d1033bSMichal Simek 			return CMD_RET_FAILURE;
3992892fe80SMichal Simek 		}
4002892fe80SMichal Simek 
4012892fe80SMichal Simek 		if (!fit_check_format(fit_hdr)) {
4022892fe80SMichal Simek 			puts("Bad FIT image format\n");
403*a2d1033bSMichal Simek 			return CMD_RET_FAILURE;
4042892fe80SMichal Simek 		}
4052892fe80SMichal Simek 
4062892fe80SMichal Simek 		/* get fpga component image node offset */
4072892fe80SMichal Simek 		noffset = fit_image_get_node(fit_hdr, fit_uname);
4082892fe80SMichal Simek 		if (noffset < 0) {
4092892fe80SMichal Simek 			printf("Can't find '%s' FIT subimage\n", fit_uname);
410*a2d1033bSMichal Simek 			return CMD_RET_FAILURE;
4112892fe80SMichal Simek 		}
4122892fe80SMichal Simek 
4132892fe80SMichal Simek 		/* verify integrity */
4142892fe80SMichal Simek 		if (!fit_image_verify(fit_hdr, noffset)) {
4152892fe80SMichal Simek 			puts("Bad Data Hash\n");
416*a2d1033bSMichal Simek 			return CMD_RET_FAILURE;
4172892fe80SMichal Simek 		}
4182892fe80SMichal Simek 
4192892fe80SMichal Simek 		/* get fpga subimage data address and length */
4202892fe80SMichal Simek 		if (fit_image_get_data(fit_hdr, noffset, &fit_data,
4212892fe80SMichal Simek 				       &data_size)) {
4222892fe80SMichal Simek 			puts("Fpga subimage data not found\n");
423*a2d1033bSMichal Simek 			return CMD_RET_FAILURE;
4242892fe80SMichal Simek 		}
4252892fe80SMichal Simek 
4262892fe80SMichal Simek 		return fpga_load(dev, fit_data, data_size, BIT_FULL);
4272892fe80SMichal Simek 	}
4282892fe80SMichal Simek #endif
4292892fe80SMichal Simek 	default:
4302892fe80SMichal Simek 		puts("** Unknown image type\n");
431*a2d1033bSMichal Simek 		return CMD_RET_FAILURE;
4322892fe80SMichal Simek 	}
4332892fe80SMichal Simek }
4342892fe80SMichal Simek #endif
4352892fe80SMichal Simek 
4369657d97cSMichal Simek static cmd_tbl_t fpga_commands[] = {
437f4c7a4aeSMichal Simek 	U_BOOT_CMD_MKENT(info, 1, 1, do_fpga_info, "", ""),
43885754795SMichal Simek 	U_BOOT_CMD_MKENT(dump, 3, 1, do_fpga_dump, "", ""),
43985754795SMichal Simek 	U_BOOT_CMD_MKENT(load, 3, 1, do_fpga_load, "", ""),
44085754795SMichal Simek 	U_BOOT_CMD_MKENT(loadb, 3, 1, do_fpga_loadb, "", ""),
44185754795SMichal Simek #if defined(CONFIG_CMD_FPGA_LOADP)
44285754795SMichal Simek 	U_BOOT_CMD_MKENT(loadp, 3, 1, do_fpga_loadp, "", ""),
44385754795SMichal Simek #endif
44485754795SMichal Simek #if defined(CONFIG_CMD_FPGA_LOADBP)
44585754795SMichal Simek 	U_BOOT_CMD_MKENT(loadbp, 3, 1, do_fpga_loadbp, "", ""),
44685754795SMichal Simek #endif
44749503f9aSMichal Simek #if defined(CONFIG_CMD_FPGA_LOADFS)
44849503f9aSMichal Simek 	U_BOOT_CMD_MKENT(loadfs, 7, 1, do_fpga_loadfs, "", ""),
44949503f9aSMichal Simek #endif
4502892fe80SMichal Simek #if defined(CONFIG_CMD_FPGA_LOADMK)
4512892fe80SMichal Simek 	U_BOOT_CMD_MKENT(loadmk, 2, 1, do_fpga_loadmk, "", ""),
4522892fe80SMichal Simek #endif
4539657d97cSMichal Simek };
4549657d97cSMichal Simek 
4559657d97cSMichal Simek static int do_fpga_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
4569657d97cSMichal Simek 			   char *const argv[])
4579657d97cSMichal Simek {
4589657d97cSMichal Simek 	cmd_tbl_t *fpga_cmd;
4599657d97cSMichal Simek 	int ret;
4609657d97cSMichal Simek 
4619657d97cSMichal Simek 	if (argc < 2)
4629657d97cSMichal Simek 		return CMD_RET_USAGE;
4639657d97cSMichal Simek 
4649657d97cSMichal Simek 	fpga_cmd = find_cmd_tbl(argv[1], fpga_commands,
4659657d97cSMichal Simek 				ARRAY_SIZE(fpga_commands));
4669657d97cSMichal Simek 
4679657d97cSMichal Simek 	/* This should be removed when all functions are converted */
4689657d97cSMichal Simek 	if (!fpga_cmd)
4699657d97cSMichal Simek 		return do_fpga(cmdtp, flag, argc, argv);
4709657d97cSMichal Simek 
4719657d97cSMichal Simek 	/* FIXME This can't be reached till all functions are converted */
4729657d97cSMichal Simek 	if (!fpga_cmd) {
4739657d97cSMichal Simek 		debug("fpga: non existing command\n");
4749657d97cSMichal Simek 		return CMD_RET_USAGE;
4759657d97cSMichal Simek 	}
4769657d97cSMichal Simek 
4779657d97cSMichal Simek 	argc -= 2;
4789657d97cSMichal Simek 	argv += 2;
4799657d97cSMichal Simek 
4809657d97cSMichal Simek 	if (argc > fpga_cmd->maxargs) {
4819657d97cSMichal Simek 		debug("fpga: more parameters passed\n");
4829657d97cSMichal Simek 		return CMD_RET_USAGE;
4839657d97cSMichal Simek 	}
4849657d97cSMichal Simek 
4859657d97cSMichal Simek 	ret = fpga_cmd->cmd(fpga_cmd, flag, argc, argv);
4869657d97cSMichal Simek 
4879657d97cSMichal Simek 	return cmd_process_error(fpga_cmd, ret);
4889657d97cSMichal Simek }
4899657d97cSMichal Simek 
490cedd48e2SSiva Durga Prasad Paladugu #if defined(CONFIG_CMD_FPGA_LOADFS) || defined(CONFIG_CMD_FPGA_LOAD_SECURE)
4919657d97cSMichal Simek U_BOOT_CMD(fpga, 9, 1, do_fpga_wrapper,
4922e192b24SSimon Glass #else
4939657d97cSMichal Simek U_BOOT_CMD(fpga, 6, 1, do_fpga_wrapper,
4942e192b24SSimon Glass #endif
4952e192b24SSimon Glass 	   "loadable FPGA image support",
4962e192b24SSimon Glass 	   "[operation type] [device number] [image address] [image size]\n"
4972e192b24SSimon Glass 	   "fpga operations:\n"
4982e192b24SSimon Glass 	   "  dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
4992e192b24SSimon Glass 	   "  info\t[dev]\t\t\tlist known device information\n"
5002e192b24SSimon Glass 	   "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
5012e192b24SSimon Glass #if defined(CONFIG_CMD_FPGA_LOADP)
5022e192b24SSimon Glass 	   "  loadp\t[dev] [address] [size]\t"
5032e192b24SSimon Glass 	   "Load device from memory buffer with partial bitstream\n"
5042e192b24SSimon Glass #endif
5052e192b24SSimon Glass 	   "  loadb\t[dev] [address] [size]\t"
5062e192b24SSimon Glass 	   "Load device from bitstream buffer (Xilinx only)\n"
5072e192b24SSimon Glass #if defined(CONFIG_CMD_FPGA_LOADBP)
5082e192b24SSimon Glass 	   "  loadbp\t[dev] [address] [size]\t"
5092e192b24SSimon Glass 	   "Load device from bitstream buffer with partial bitstream"
5102e192b24SSimon Glass 	   "(Xilinx only)\n"
5112e192b24SSimon Glass #endif
5122e192b24SSimon Glass #if defined(CONFIG_CMD_FPGA_LOADFS)
5132e192b24SSimon Glass 	   "Load device from filesystem (FAT by default) (Xilinx only)\n"
5142e192b24SSimon Glass 	   "  loadfs [dev] [address] [image size] [blocksize] <interface>\n"
5152e192b24SSimon Glass 	   "        [<dev[:part]>] <filename>\n"
5162e192b24SSimon Glass #endif
5172e192b24SSimon Glass #if defined(CONFIG_CMD_FPGA_LOADMK)
5182e192b24SSimon Glass 	   "  loadmk [dev] [address]\tLoad device generated with mkimage"
5192e192b24SSimon Glass #if defined(CONFIG_FIT)
5202e192b24SSimon Glass 	   "\n"
5212e192b24SSimon Glass 	   "\tFor loadmk operating on FIT format uImage address must include\n"
5222e192b24SSimon Glass 	   "\tsubimage unit name in the form of addr:<subimg_uname>"
5232e192b24SSimon Glass #endif
5242e192b24SSimon Glass #endif
525cedd48e2SSiva Durga Prasad Paladugu #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
526cedd48e2SSiva Durga Prasad Paladugu 	   "Load encrypted bitstream (Xilinx only)\n"
527cedd48e2SSiva Durga Prasad Paladugu 	   "  loads [dev] [address] [size] [auth-OCM-0/DDR-1/noauth-2]\n"
528cedd48e2SSiva Durga Prasad Paladugu 	   "        [enc-devkey(0)/userkey(1)/nenc(2) [Userkey address]\n"
529cedd48e2SSiva Durga Prasad Paladugu 	   "Loads the secure bistreams(authenticated/encrypted/both\n"
530cedd48e2SSiva Durga Prasad Paladugu 	   "authenticated and encrypted) of [size] from [address].\n"
531cedd48e2SSiva Durga Prasad Paladugu 	   "The auth-OCM/DDR flag specifies to perform authentication\n"
532cedd48e2SSiva Durga Prasad Paladugu 	   "in OCM or in DDR. 0 for OCM, 1 for DDR, 2 for no authentication.\n"
533cedd48e2SSiva Durga Prasad Paladugu 	   "The enc flag specifies which key to be used for decryption\n"
534cedd48e2SSiva Durga Prasad Paladugu 	   "0-device key, 1-user key, 2-no encryption.\n"
535cedd48e2SSiva Durga Prasad Paladugu 	   "The optional Userkey address specifies from which address key\n"
536cedd48e2SSiva Durga Prasad Paladugu 	   "has to be used for decryption if user key is selected.\n"
537cedd48e2SSiva Durga Prasad Paladugu 	   "NOTE: the sceure bitstream has to be created using xilinx\n"
538cedd48e2SSiva Durga Prasad Paladugu 	   "bootgen tool only.\n"
539cedd48e2SSiva Durga Prasad Paladugu #endif
5402e192b24SSimon Glass );
541