]> git.sur5r.net Git - u-boot/blob - cmd/fpga.c
3f09d424135f87ca50f34b41b4b8dffa9b06dbb5
[u-boot] / 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 <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 };
31
32 /* ------------------------------------------------------------------------- */
33 /* command form:
34  *   fpga <op> <device number> <data addr> <datasize>
35  * where op is 'load', 'dump', or 'info'
36  * If there is no device number field, the fpga environment variable is used.
37  * If there is no data addr field, the fpgadata environment variable is used.
38  * The info command requires no data address field.
39  */
40 int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
41 {
42         int op, dev = FPGA_INVALID_DEVICE;
43         size_t data_size = 0;
44         void *fpga_data = NULL;
45         char *devstr = env_get("fpga");
46         char *datastr = env_get("fpgadata");
47         int rc = FPGA_FAIL;
48         int wrong_parms = 0;
49 #if defined(CONFIG_FIT)
50         const char *fit_uname = NULL;
51         ulong fit_addr;
52 #endif
53 #if defined(CONFIG_CMD_FPGA_LOADFS)
54         fpga_fs_info fpga_fsinfo;
55         fpga_fsinfo.fstype = FS_TYPE_ANY;
56 #endif
57
58         if (devstr)
59                 dev = (int) simple_strtoul(devstr, NULL, 16);
60         if (datastr)
61                 fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
62
63         if (argc > 9 || argc < 2) {
64                 debug("%s: Too many or too few args (%d)\n", __func__, argc);
65                 return CMD_RET_USAGE;
66         }
67
68         op = (int)fpga_get_op(argv[1]);
69
70         switch (op) {
71 #if defined(CONFIG_CMD_FPGA_LOADFS)
72         case FPGA_LOADFS:
73                 if (argc < 9)
74                         return CMD_RET_USAGE;
75                 fpga_fsinfo.blocksize = (unsigned int)
76                                         simple_strtoul(argv[5], NULL, 16);
77                 fpga_fsinfo.interface = argv[6];
78                 fpga_fsinfo.dev_part = argv[7];
79                 fpga_fsinfo.filename = argv[8];
80                 argc = 5;
81                 break;
82 #endif
83         default:
84                 break;
85         }
86
87         switch (argc) {
88         case 5:         /* fpga <op> <dev> <data> <datasize> */
89                 data_size = simple_strtoul(argv[4], NULL, 16);
90
91         case 4:         /* fpga <op> <dev> <data> */
92 #if defined(CONFIG_FIT)
93                 if (fit_parse_subimage(argv[3], (ulong)fpga_data,
94                                        &fit_addr, &fit_uname)) {
95                         fpga_data = (void *)fit_addr;
96                         debug("*  fpga: subimage '%s' from FIT image ",
97                               fit_uname);
98                         debug("at 0x%08lx\n", fit_addr);
99                 } else
100 #endif
101                 {
102                         fpga_data = (void *)simple_strtoul(argv[3], NULL, 16);
103                         debug("*  fpga: cmdline image address = 0x%08lx\n",
104                               (ulong)fpga_data);
105                 }
106                 debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data);
107
108         case 3:         /* fpga <op> <dev | data addr> */
109                 dev = (int)simple_strtoul(argv[2], NULL, 16);
110                 debug("%s: device = %d\n", __func__, dev);
111                 /* FIXME - this is a really weak test */
112                 if ((argc == 3) && (dev > fpga_count())) {
113                         /* must be buffer ptr */
114                         debug("%s: Assuming buffer pointer in arg 3\n",
115                               __func__);
116
117 #if defined(CONFIG_FIT)
118                         if (fit_parse_subimage(argv[2], (ulong)fpga_data,
119                                                &fit_addr, &fit_uname)) {
120                                 fpga_data = (void *)fit_addr;
121                                 debug("*  fpga: subimage '%s' from FIT image ",
122                                       fit_uname);
123                                 debug("at 0x%08lx\n", fit_addr);
124                         } else
125 #endif
126                         {
127                                 fpga_data = (void *)(uintptr_t)dev;
128                                 debug("*  fpga: cmdline image addr = 0x%08lx\n",
129                                       (ulong)fpga_data);
130                         }
131
132                         debug("%s: fpga_data = 0x%lx\n",
133                               __func__, (ulong)fpga_data);
134                         dev = FPGA_INVALID_DEVICE;      /* reset device num */
135                 }
136         }
137
138         if (dev == FPGA_INVALID_DEVICE) {
139                 puts("FPGA device not specified\n");
140                 op = FPGA_NONE;
141         }
142
143         switch (op) {
144         case FPGA_NONE:
145         case FPGA_INFO:
146                 break;
147 #if defined(CONFIG_CMD_FPGA_LOADFS)
148         case FPGA_LOADFS:
149                 /* Blocksize can be zero */
150                 if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part ||
151                     !fpga_fsinfo.filename)
152                         wrong_parms = 1;
153 #endif
154         case FPGA_LOAD:
155         case FPGA_LOADP:
156         case FPGA_LOADB:
157         case FPGA_LOADBP:
158         case FPGA_DUMP:
159                 if (!fpga_data || !data_size)
160                         wrong_parms = 1;
161                 break;
162 #if defined(CONFIG_CMD_FPGA_LOADMK)
163         case FPGA_LOADMK:
164                 if (!fpga_data)
165                         wrong_parms = 1;
166                 break;
167 #endif
168         }
169
170         if (wrong_parms) {
171                 puts("Wrong parameters for FPGA request\n");
172                 op = FPGA_NONE;
173         }
174
175         switch (op) {
176         case FPGA_NONE:
177                 return CMD_RET_USAGE;
178
179         case FPGA_INFO:
180                 rc = fpga_info(dev);
181                 break;
182
183         case FPGA_LOAD:
184                 rc = fpga_load(dev, fpga_data, data_size, BIT_FULL);
185                 break;
186
187 #if defined(CONFIG_CMD_FPGA_LOADP)
188         case FPGA_LOADP:
189                 rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL);
190                 break;
191 #endif
192
193         case FPGA_LOADB:
194                 rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL);
195                 break;
196
197 #if defined(CONFIG_CMD_FPGA_LOADBP)
198         case FPGA_LOADBP:
199                 rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL);
200                 break;
201 #endif
202
203 #if defined(CONFIG_CMD_FPGA_LOADFS)
204         case FPGA_LOADFS:
205                 rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo);
206                 break;
207 #endif
208
209 #if defined(CONFIG_CMD_FPGA_LOADMK)
210         case FPGA_LOADMK:
211                 switch (genimg_get_format(fpga_data)) {
212 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
213                 case IMAGE_FORMAT_LEGACY:
214                         {
215                                 image_header_t *hdr =
216                                                 (image_header_t *)fpga_data;
217                                 ulong data;
218                                 uint8_t comp;
219
220                                 comp = image_get_comp(hdr);
221                                 if (comp == IH_COMP_GZIP) {
222 #if defined(CONFIG_GZIP)
223                                         ulong image_buf = image_get_data(hdr);
224                                         data = image_get_load(hdr);
225                                         ulong image_size = ~0UL;
226
227                                         if (gunzip((void *)data, ~0UL,
228                                                    (void *)image_buf,
229                                                    &image_size) != 0) {
230                                                 puts("GUNZIP: error\n");
231                                                 return 1;
232                                         }
233                                         data_size = image_size;
234 #else
235                                         puts("Gunzip image is not supported\n");
236                                         return 1;
237 #endif
238                                 } else {
239                                         data = (ulong)image_get_data(hdr);
240                                         data_size = image_get_data_size(hdr);
241                                 }
242                                 rc = fpga_load(dev, (void *)data, data_size,
243                                                BIT_FULL);
244                         }
245                         break;
246 #endif
247 #if defined(CONFIG_FIT)
248                 case IMAGE_FORMAT_FIT:
249                         {
250                                 const void *fit_hdr = (const void *)fpga_data;
251                                 int noffset;
252                                 const void *fit_data;
253
254                                 if (fit_uname == NULL) {
255                                         puts("No FIT subimage unit name\n");
256                                         return 1;
257                                 }
258
259                                 if (!fit_check_format(fit_hdr)) {
260                                         puts("Bad FIT image format\n");
261                                         return 1;
262                                 }
263
264                                 /* get fpga component image node offset */
265                                 noffset = fit_image_get_node(fit_hdr,
266                                                              fit_uname);
267                                 if (noffset < 0) {
268                                         printf("Can't find '%s' FIT subimage\n",
269                                                fit_uname);
270                                         return 1;
271                                 }
272
273                                 /* verify integrity */
274                                 if (!fit_image_verify(fit_hdr, noffset)) {
275                                         puts ("Bad Data Hash\n");
276                                         return 1;
277                                 }
278
279                                 /* get fpga subimage data address and length */
280                                 if (fit_image_get_data(fit_hdr, noffset,
281                                                        &fit_data, &data_size)) {
282                                         puts("Fpga subimage data not found\n");
283                                         return 1;
284                                 }
285
286                                 rc = fpga_load(dev, fit_data, data_size,
287                                                BIT_FULL);
288                         }
289                         break;
290 #endif
291                 default:
292                         puts("** Unknown image type\n");
293                         rc = FPGA_FAIL;
294                         break;
295                 }
296                 break;
297 #endif
298
299         case FPGA_DUMP:
300                 rc = fpga_dump(dev, fpga_data, data_size);
301                 break;
302
303         default:
304                 printf("Unknown operation\n");
305                 return CMD_RET_USAGE;
306         }
307         return rc;
308 }
309
310 /*
311  * Map op to supported operations.  We don't use a table since we
312  * would just have to relocate it from flash anyway.
313  */
314 static int fpga_get_op(char *opstr)
315 {
316         int op = FPGA_NONE;
317
318         if (!strcmp("info", opstr))
319                 op = FPGA_INFO;
320         else if (!strcmp("loadb", opstr))
321                 op = FPGA_LOADB;
322         else if (!strcmp("load", opstr))
323                 op = FPGA_LOAD;
324 #if defined(CONFIG_CMD_FPGA_LOADP)
325         else if (!strcmp("loadp", opstr))
326                 op = FPGA_LOADP;
327 #endif
328 #if defined(CONFIG_CMD_FPGA_LOADBP)
329         else if (!strcmp("loadbp", opstr))
330                 op = FPGA_LOADBP;
331 #endif
332 #if defined(CONFIG_CMD_FPGA_LOADFS)
333         else if (!strcmp("loadfs", opstr))
334                 op = FPGA_LOADFS;
335 #endif
336 #if defined(CONFIG_CMD_FPGA_LOADMK)
337         else if (!strcmp("loadmk", opstr))
338                 op = FPGA_LOADMK;
339 #endif
340         else if (!strcmp("dump", opstr))
341                 op = FPGA_DUMP;
342
343         if (op == FPGA_NONE)
344                 printf("Unknown fpga operation \"%s\"\n", opstr);
345
346         return op;
347 }
348
349 #if defined(CONFIG_CMD_FPGA_LOADFS)
350 U_BOOT_CMD(fpga, 9, 1, do_fpga,
351 #else
352 U_BOOT_CMD(fpga, 6, 1, do_fpga,
353 #endif
354            "loadable FPGA image support",
355            "[operation type] [device number] [image address] [image size]\n"
356            "fpga operations:\n"
357            "  dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
358            "  info\t[dev]\t\t\tlist known device information\n"
359            "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
360 #if defined(CONFIG_CMD_FPGA_LOADP)
361            "  loadp\t[dev] [address] [size]\t"
362            "Load device from memory buffer with partial bitstream\n"
363 #endif
364            "  loadb\t[dev] [address] [size]\t"
365            "Load device from bitstream buffer (Xilinx only)\n"
366 #if defined(CONFIG_CMD_FPGA_LOADBP)
367            "  loadbp\t[dev] [address] [size]\t"
368            "Load device from bitstream buffer with partial bitstream"
369            "(Xilinx only)\n"
370 #endif
371 #if defined(CONFIG_CMD_FPGA_LOADFS)
372            "Load device from filesystem (FAT by default) (Xilinx only)\n"
373            "  loadfs [dev] [address] [image size] [blocksize] <interface>\n"
374            "        [<dev[:part]>] <filename>\n"
375 #endif
376 #if defined(CONFIG_CMD_FPGA_LOADMK)
377            "  loadmk [dev] [address]\tLoad device generated with mkimage"
378 #if defined(CONFIG_FIT)
379            "\n"
380            "\tFor loadmk operating on FIT format uImage address must include\n"
381            "\tsubimage unit name in the form of addr:<subimg_uname>"
382 #endif
383 #endif
384 );