xref: /openbmc/u-boot/cmd/fpga.c (revision 58008cba)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2000, 2001
4  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
5  */
6 
7 /*
8  *  FPGA support
9  */
10 #include <common.h>
11 #include <command.h>
12 #include <fpga.h>
13 #include <fs.h>
14 #include <malloc.h>
15 
16 /* Local functions */
17 static int fpga_get_op(char *opstr);
18 
19 /* Local defines */
20 enum {
21 	FPGA_NONE = -1,
22 	FPGA_INFO,
23 	FPGA_LOAD,
24 	FPGA_LOADB,
25 	FPGA_DUMP,
26 	FPGA_LOADMK,
27 	FPGA_LOADP,
28 	FPGA_LOADBP,
29 	FPGA_LOADFS,
30 	FPGA_LOADS,
31 };
32 
33 /* ------------------------------------------------------------------------- */
34 /* command form:
35  *   fpga <op> <device number> <data addr> <datasize>
36  * where op is 'load', 'dump', or 'info'
37  * If there is no device number field, the fpga environment variable is used.
38  * If there is no data addr field, the fpgadata environment variable is used.
39  * The info command requires no data address field.
40  */
41 int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
42 {
43 	int op, dev = FPGA_INVALID_DEVICE;
44 	size_t data_size = 0;
45 	void *fpga_data = NULL;
46 	char *devstr = env_get("fpga");
47 	char *datastr = env_get("fpgadata");
48 	int rc = FPGA_FAIL;
49 	int wrong_parms = 0;
50 #if defined(CONFIG_FIT)
51 	const char *fit_uname = NULL;
52 	ulong fit_addr;
53 #endif
54 #if defined(CONFIG_CMD_FPGA_LOADFS)
55 	fpga_fs_info fpga_fsinfo;
56 	fpga_fsinfo.fstype = FS_TYPE_ANY;
57 #endif
58 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
59 	struct fpga_secure_info fpga_sec_info;
60 
61 	memset(&fpga_sec_info, 0, sizeof(fpga_sec_info));
62 #endif
63 
64 	if (devstr)
65 		dev = (int) simple_strtoul(devstr, NULL, 16);
66 	if (datastr)
67 		fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
68 
69 	if (argc > 9 || argc < 2) {
70 		debug("%s: Too many or too few args (%d)\n", __func__, argc);
71 		return CMD_RET_USAGE;
72 	}
73 
74 	op = (int)fpga_get_op(argv[1]);
75 
76 	switch (op) {
77 #if defined(CONFIG_CMD_FPGA_LOADFS)
78 	case FPGA_LOADFS:
79 		if (argc < 9)
80 			return CMD_RET_USAGE;
81 		fpga_fsinfo.blocksize = (unsigned int)
82 					simple_strtoul(argv[5], NULL, 16);
83 		fpga_fsinfo.interface = argv[6];
84 		fpga_fsinfo.dev_part = argv[7];
85 		fpga_fsinfo.filename = argv[8];
86 		argc = 5;
87 		break;
88 #endif
89 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
90 	case FPGA_LOADS:
91 		if (argc < 7)
92 			return CMD_RET_USAGE;
93 		if (argc == 8)
94 			fpga_sec_info.userkey_addr = (u8 *)(uintptr_t)
95 						     simple_strtoull(argv[7],
96 								     NULL, 16);
97 		fpga_sec_info.encflag = (u8)simple_strtoul(argv[6], NULL, 16);
98 		fpga_sec_info.authflag = (u8)simple_strtoul(argv[5], NULL, 16);
99 		argc = 5;
100 		break;
101 #endif
102 	default:
103 		break;
104 	}
105 
106 	switch (argc) {
107 	case 5:		/* fpga <op> <dev> <data> <datasize> */
108 		data_size = simple_strtoul(argv[4], NULL, 16);
109 
110 	case 4:		/* fpga <op> <dev> <data> */
111 #if defined(CONFIG_FIT)
112 		if (fit_parse_subimage(argv[3], (ulong)fpga_data,
113 				       &fit_addr, &fit_uname)) {
114 			fpga_data = (void *)fit_addr;
115 			debug("*  fpga: subimage '%s' from FIT image ",
116 			      fit_uname);
117 			debug("at 0x%08lx\n", fit_addr);
118 		} else
119 #endif
120 		{
121 			fpga_data = (void *)simple_strtoul(argv[3], NULL, 16);
122 			debug("*  fpga: cmdline image address = 0x%08lx\n",
123 			      (ulong)fpga_data);
124 		}
125 		debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data);
126 
127 	case 3:		/* fpga <op> <dev | data addr> */
128 		dev = (int)simple_strtoul(argv[2], NULL, 16);
129 		debug("%s: device = %d\n", __func__, dev);
130 		/* FIXME - this is a really weak test */
131 		if ((argc == 3) && (dev > fpga_count())) {
132 			/* must be buffer ptr */
133 			debug("%s: Assuming buffer pointer in arg 3\n",
134 			      __func__);
135 
136 #if defined(CONFIG_FIT)
137 			if (fit_parse_subimage(argv[2], (ulong)fpga_data,
138 					       &fit_addr, &fit_uname)) {
139 				fpga_data = (void *)fit_addr;
140 				debug("*  fpga: subimage '%s' from FIT image ",
141 				      fit_uname);
142 				debug("at 0x%08lx\n", fit_addr);
143 			} else
144 #endif
145 			{
146 				fpga_data = (void *)(uintptr_t)dev;
147 				debug("*  fpga: cmdline image addr = 0x%08lx\n",
148 				      (ulong)fpga_data);
149 			}
150 
151 			debug("%s: fpga_data = 0x%lx\n",
152 			      __func__, (ulong)fpga_data);
153 			dev = FPGA_INVALID_DEVICE;	/* reset device num */
154 		}
155 	}
156 
157 	if (dev == FPGA_INVALID_DEVICE) {
158 		puts("FPGA device not specified\n");
159 		op = FPGA_NONE;
160 	}
161 
162 	switch (op) {
163 	case FPGA_NONE:
164 	case FPGA_INFO:
165 		break;
166 #if defined(CONFIG_CMD_FPGA_LOADFS)
167 	case FPGA_LOADFS:
168 		/* Blocksize can be zero */
169 		if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part ||
170 		    !fpga_fsinfo.filename)
171 			wrong_parms = 1;
172 		break;
173 #endif
174 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
175 	case FPGA_LOADS:
176 		if (fpga_sec_info.authflag >= FPGA_NO_ENC_OR_NO_AUTH &&
177 		    fpga_sec_info.encflag >= FPGA_NO_ENC_OR_NO_AUTH) {
178 			puts("ERR: use <fpga load> for NonSecure bitstream\n");
179 			wrong_parms = 1;
180 		}
181 
182 		if (fpga_sec_info.encflag == FPGA_ENC_USR_KEY &&
183 		    !fpga_sec_info.userkey_addr) {
184 			wrong_parms = 1;
185 			puts("ERR:User key not provided\n");
186 		}
187 		break;
188 #endif
189 	case FPGA_LOAD:
190 	case FPGA_LOADP:
191 	case FPGA_LOADB:
192 	case FPGA_LOADBP:
193 	case FPGA_DUMP:
194 		if (!fpga_data || !data_size)
195 			wrong_parms = 1;
196 		break;
197 #if defined(CONFIG_CMD_FPGA_LOADMK)
198 	case FPGA_LOADMK:
199 		if (!fpga_data)
200 			wrong_parms = 1;
201 		break;
202 #endif
203 	}
204 
205 	if (wrong_parms) {
206 		puts("Wrong parameters for FPGA request\n");
207 		op = FPGA_NONE;
208 	}
209 
210 	switch (op) {
211 	case FPGA_NONE:
212 		return CMD_RET_USAGE;
213 
214 	case FPGA_INFO:
215 		rc = fpga_info(dev);
216 		break;
217 
218 	case FPGA_LOAD:
219 		rc = fpga_load(dev, fpga_data, data_size, BIT_FULL);
220 		break;
221 
222 #if defined(CONFIG_CMD_FPGA_LOADP)
223 	case FPGA_LOADP:
224 		rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL);
225 		break;
226 #endif
227 
228 	case FPGA_LOADB:
229 		rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL);
230 		break;
231 
232 #if defined(CONFIG_CMD_FPGA_LOADBP)
233 	case FPGA_LOADBP:
234 		rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL);
235 		break;
236 #endif
237 
238 #if defined(CONFIG_CMD_FPGA_LOADFS)
239 	case FPGA_LOADFS:
240 		rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo);
241 		break;
242 #endif
243 
244 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
245 	case FPGA_LOADS:
246 		rc = fpga_loads(dev, fpga_data, data_size, &fpga_sec_info);
247 		break;
248 #endif
249 
250 #if defined(CONFIG_CMD_FPGA_LOADMK)
251 	case FPGA_LOADMK:
252 		switch (genimg_get_format(fpga_data)) {
253 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
254 		case IMAGE_FORMAT_LEGACY:
255 			{
256 				image_header_t *hdr =
257 						(image_header_t *)fpga_data;
258 				ulong data;
259 				uint8_t comp;
260 
261 				comp = image_get_comp(hdr);
262 				if (comp == IH_COMP_GZIP) {
263 #if defined(CONFIG_GZIP)
264 					ulong image_buf = image_get_data(hdr);
265 					data = image_get_load(hdr);
266 					ulong image_size = ~0UL;
267 
268 					if (gunzip((void *)data, ~0UL,
269 						   (void *)image_buf,
270 						   &image_size) != 0) {
271 						puts("GUNZIP: error\n");
272 						return 1;
273 					}
274 					data_size = image_size;
275 #else
276 					puts("Gunzip image is not supported\n");
277 					return 1;
278 #endif
279 				} else {
280 					data = (ulong)image_get_data(hdr);
281 					data_size = image_get_data_size(hdr);
282 				}
283 				rc = fpga_load(dev, (void *)data, data_size,
284 					       BIT_FULL);
285 			}
286 			break;
287 #endif
288 #if defined(CONFIG_FIT)
289 		case IMAGE_FORMAT_FIT:
290 			{
291 				const void *fit_hdr = (const void *)fpga_data;
292 				int noffset;
293 				const void *fit_data;
294 
295 				if (fit_uname == NULL) {
296 					puts("No FIT subimage unit name\n");
297 					return 1;
298 				}
299 
300 				if (!fit_check_format(fit_hdr)) {
301 					puts("Bad FIT image format\n");
302 					return 1;
303 				}
304 
305 				/* get fpga component image node offset */
306 				noffset = fit_image_get_node(fit_hdr,
307 							     fit_uname);
308 				if (noffset < 0) {
309 					printf("Can't find '%s' FIT subimage\n",
310 					       fit_uname);
311 					return 1;
312 				}
313 
314 				/* verify integrity */
315 				if (!fit_image_verify(fit_hdr, noffset)) {
316 					puts ("Bad Data Hash\n");
317 					return 1;
318 				}
319 
320 				/* get fpga subimage data address and length */
321 				if (fit_image_get_data(fit_hdr, noffset,
322 						       &fit_data, &data_size)) {
323 					puts("Fpga subimage data not found\n");
324 					return 1;
325 				}
326 
327 				rc = fpga_load(dev, fit_data, data_size,
328 					       BIT_FULL);
329 			}
330 			break;
331 #endif
332 		default:
333 			puts("** Unknown image type\n");
334 			rc = FPGA_FAIL;
335 			break;
336 		}
337 		break;
338 #endif
339 
340 	case FPGA_DUMP:
341 		rc = fpga_dump(dev, fpga_data, data_size);
342 		break;
343 
344 	default:
345 		printf("Unknown operation\n");
346 		return CMD_RET_USAGE;
347 	}
348 	return rc;
349 }
350 
351 /*
352  * Map op to supported operations.  We don't use a table since we
353  * would just have to relocate it from flash anyway.
354  */
355 static int fpga_get_op(char *opstr)
356 {
357 	int op = FPGA_NONE;
358 
359 	if (!strcmp("info", opstr))
360 		op = FPGA_INFO;
361 	else if (!strcmp("loadb", opstr))
362 		op = FPGA_LOADB;
363 	else if (!strcmp("load", opstr))
364 		op = FPGA_LOAD;
365 #if defined(CONFIG_CMD_FPGA_LOADP)
366 	else if (!strcmp("loadp", opstr))
367 		op = FPGA_LOADP;
368 #endif
369 #if defined(CONFIG_CMD_FPGA_LOADBP)
370 	else if (!strcmp("loadbp", opstr))
371 		op = FPGA_LOADBP;
372 #endif
373 #if defined(CONFIG_CMD_FPGA_LOADFS)
374 	else if (!strcmp("loadfs", opstr))
375 		op = FPGA_LOADFS;
376 #endif
377 #if defined(CONFIG_CMD_FPGA_LOADMK)
378 	else if (!strcmp("loadmk", opstr))
379 		op = FPGA_LOADMK;
380 #endif
381 	else if (!strcmp("dump", opstr))
382 		op = FPGA_DUMP;
383 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
384 	else if (!strcmp("loads", opstr))
385 		op = FPGA_LOADS;
386 #endif
387 
388 	if (op == FPGA_NONE)
389 		printf("Unknown fpga operation \"%s\"\n", opstr);
390 
391 	return op;
392 }
393 
394 #if defined(CONFIG_CMD_FPGA_LOADFS) || defined(CONFIG_CMD_FPGA_LOAD_SECURE)
395 U_BOOT_CMD(fpga, 9, 1, do_fpga,
396 #else
397 U_BOOT_CMD(fpga, 6, 1, do_fpga,
398 #endif
399 	   "loadable FPGA image support",
400 	   "[operation type] [device number] [image address] [image size]\n"
401 	   "fpga operations:\n"
402 	   "  dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
403 	   "  info\t[dev]\t\t\tlist known device information\n"
404 	   "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
405 #if defined(CONFIG_CMD_FPGA_LOADP)
406 	   "  loadp\t[dev] [address] [size]\t"
407 	   "Load device from memory buffer with partial bitstream\n"
408 #endif
409 	   "  loadb\t[dev] [address] [size]\t"
410 	   "Load device from bitstream buffer (Xilinx only)\n"
411 #if defined(CONFIG_CMD_FPGA_LOADBP)
412 	   "  loadbp\t[dev] [address] [size]\t"
413 	   "Load device from bitstream buffer with partial bitstream"
414 	   "(Xilinx only)\n"
415 #endif
416 #if defined(CONFIG_CMD_FPGA_LOADFS)
417 	   "Load device from filesystem (FAT by default) (Xilinx only)\n"
418 	   "  loadfs [dev] [address] [image size] [blocksize] <interface>\n"
419 	   "        [<dev[:part]>] <filename>\n"
420 #endif
421 #if defined(CONFIG_CMD_FPGA_LOADMK)
422 	   "  loadmk [dev] [address]\tLoad device generated with mkimage"
423 #if defined(CONFIG_FIT)
424 	   "\n"
425 	   "\tFor loadmk operating on FIT format uImage address must include\n"
426 	   "\tsubimage unit name in the form of addr:<subimg_uname>"
427 #endif
428 #endif
429 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
430 	   "Load encrypted bitstream (Xilinx only)\n"
431 	   "  loads [dev] [address] [size] [auth-OCM-0/DDR-1/noauth-2]\n"
432 	   "        [enc-devkey(0)/userkey(1)/nenc(2) [Userkey address]\n"
433 	   "Loads the secure bistreams(authenticated/encrypted/both\n"
434 	   "authenticated and encrypted) of [size] from [address].\n"
435 	   "The auth-OCM/DDR flag specifies to perform authentication\n"
436 	   "in OCM or in DDR. 0 for OCM, 1 for DDR, 2 for no authentication.\n"
437 	   "The enc flag specifies which key to be used for decryption\n"
438 	   "0-device key, 1-user key, 2-no encryption.\n"
439 	   "The optional Userkey address specifies from which address key\n"
440 	   "has to be used for decryption if user key is selected.\n"
441 	   "NOTE: the sceure bitstream has to be created using xilinx\n"
442 	   "bootgen tool only.\n"
443 #endif
444 );
445