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