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