summaryrefslogtreecommitdiffstats
path: root/meta-xilinx-core/recipes-bsp/fpga-manager-script/files/fpgautil.c
diff options
context:
space:
mode:
authorVaralaxmi Bingi <varalaxmi.bingi@xilinx.com>2022-04-27 16:50:18 +0530
committerMark Hatle <mhatle@xilinx.com>2022-04-28 06:56:59 -0700
commite75c70e4db78afa8f5c5ec1790359ede5e8bf00e (patch)
tree3931638ed2a626865d3e353291425f42e81a7246 /meta-xilinx-core/recipes-bsp/fpga-manager-script/files/fpgautil.c
parent9097f6a96da97bad6a688d0bee40f03423b21d7b (diff)
downloadmeta-xilinx-e75c70e4db78afa8f5c5ec1790359ede5e8bf00e.tar.gz
fpga-manager-script: adding this recipe to meta-xilinx
This fpgautil recipe was part of meta-xilinx-tools. This is required in decoupling flow as well till dfx mgr gets stabled and meta-xilinx-tools layer will no be there in decoupling flow. So moving this recipe to meta-xilinx. Signed-off-by: Varalaxmi Bingi <varalaxmi.bingi@xilinx.com> Signed-off-by: Mark Hatle <mhatle@xilinx.com>
Diffstat (limited to 'meta-xilinx-core/recipes-bsp/fpga-manager-script/files/fpgautil.c')
-rw-r--r--meta-xilinx-core/recipes-bsp/fpga-manager-script/files/fpgautil.c464
1 files changed, 464 insertions, 0 deletions
diff --git a/meta-xilinx-core/recipes-bsp/fpga-manager-script/files/fpgautil.c b/meta-xilinx-core/recipes-bsp/fpga-manager-script/files/fpgautil.c
new file mode 100644
index 00000000..0b77569d
--- /dev/null
+++ b/meta-xilinx-core/recipes-bsp/fpga-manager-script/files/fpgautil.c
@@ -0,0 +1,464 @@
1/******************************************************************************
2 *
3 * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is furnished to do
10 * so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 ******************************************************************************/
24/*****************************************************************************/
25/**
26 * @file: fpgautil.c
27 * Simple command line tool to load fpga via overlay or through sysfs interface
28 * and read fpga configuration using Xilinx Zynq/ZynqMP fpga manager
29 * Author: Appana Durga Kedareswara Rao <appanad@xilinx.com>
30 * Author: Nava kishore Manne <navam@xilinx.com>
31 */
32#include <stdbool.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37#include <string.h>
38#include <signal.h>
39#include <getopt.h>
40#include <poll.h>
41#include <ctype.h>
42#include <libgen.h>
43#include <time.h>
44#include <errno.h>
45#include <sys/time.h>
46#include <sys/stat.h>
47
48#define OVERLAY 1
49#define FPGA_SYSFS 2
50#define READBACK 3
51#define ENCRYPTION_USERKEY_EN (0x20U)
52
53int fpga_getplatform()
54{
55 char fpstr[100];
56 FILE *fptr;
57 char *zynqmpstr = "Xilinx ZynqMP FPGA Manager";
58
59 if ((fptr = fopen("/sys/class/fpga_manager/fpga0/name", "r")) == NULL)
60 {
61 printf("Error! opening file");
62 // Program exits if file pointer returns NULL.
63 exit(1);
64 }
65
66 // reads text until newline
67 fscanf(fptr,"%[^\n]", fpstr);
68 fclose(fptr);
69
70 if (!strcmp(zynqmpstr, fpstr))
71 return 1;
72 else
73 return 0;
74
75}
76
77void print_usage(char *prg)
78{
79 int iszynqmp = fpga_getplatform();
80
81 fprintf(stderr, "\n%s: FPGA Utility for Loading/reading PL Configuration\n\n", prg);
82 fprintf(stderr, "Usage: %s -b <bin file path> -o <dtbo file path>\n\r", prg);
83 fprintf(stderr, "\n");
84 fprintf(stderr, "Options: -b <binfile> (Bin file path)\n");
85 fprintf(stderr, " -o <dtbofile> (DTBO file path)\n");
86 fprintf(stderr, " -f <flags> Optional: <Bitstream type flags>\n");
87 fprintf(stderr, " f := <Full | Partial > \n");
88 fprintf(stderr, " -n <Fpga region info> FPGA Regions represent FPGA's\n");
89 fprintf(stderr, " and partial reconfiguration\n");
90 fprintf(stderr, " regions of FPGA's in the\n");
91 fprintf(stderr, " Device Tree\n");
92 if (iszynqmp)
93 {
94 fprintf(stderr, " Default: <Full>\n");
95 fprintf(stderr, " -s <secure flags> Optional: <Secure flags>\n");
96 fprintf(stderr, " s := <AuthDDR | AuthOCM | EnUsrKey | EnDevKey | AuthEnUsrKeyDDR | AuthEnUsrKeyOCM | AuthEnDevKeyDDR | AuthEnDevKeyOCM>\n");
97 fprintf(stderr, " -k <AesKey> Optional: <AES User Key>\n");
98 fprintf(stderr, " -r <Readback> Optional: <file name>\n");
99 fprintf(stderr, " Default: By default Read back contents will be stored in readback.bin file\n");
100 fprintf(stderr, " -t Optional: <Readback Type>\n");
101 fprintf(stderr, " 0 - Configuration Register readback\n");
102 fprintf(stderr, " 1 - Configuration Data Frames readback\n");
103 fprintf(stderr, " Default: 0 (Configuration register readback)\n");
104 fprintf(stderr, " -R Optional: Remove overlay from a live tree\n");
105 }
106
107 fprintf(stderr, " \n");
108 fprintf(stderr, "Examples:\n");
109 fprintf(stderr, "(Load Full bitstream using Overlay)\n");
110 fprintf(stderr, "%s -b top.bit.bin -o can.dtbo -f Full -n Full \n", prg);
111 fprintf(stderr, "(Load Partial bitstream using Overlay)\n");
112 fprintf(stderr, "%s -b rm0.bit.bin -o rm0.dtbo -f Partial -n PR0\n", prg);
113 fprintf(stderr, "(Load Full bitstream using sysfs interface)\n");
114 fprintf(stderr, "%s -b top.bit.bin -f Full\n", prg);
115 fprintf(stderr, "(Load Partial bitstream using sysfs interface)\n");
116 fprintf(stderr, "%s -b rm0.bit.bin -f Partial\n", prg);
117 if (iszynqmp)
118 {
119 fprintf(stderr, "(Load Authenticated bitstream through the sysfs interface)\n");
120 fprintf(stderr, "%s -b top.bit.bin -f Full -s AuthDDR \n", prg);
121 fprintf(stderr, "(Load Parital Encrypted Userkey bitstream using Overlay)\n");
122 fprintf(stderr, "%s -b top.bit.bin -o pl.dtbo -f Partial -s EnUsrKey -k <32byte key value>\n", prg);
123 fprintf(stderr, "(Read PL Configuration Registers)\n");
124 fprintf(stderr, "%s -b top.bit.bin -r\n", prg);
125 }
126 fprintf(stderr, " \n");
127}
128
129int gettime(struct timeval t0, struct timeval t1)
130{
131 return ((t1.tv_sec - t0.tv_sec) * 1000.0f + (t1.tv_usec -t0.tv_usec) / 1000.0f);
132}
133
134int fpga_state()
135{
136 FILE *fptr;
137 char buf[10];
138 char *state_operating = "operating";
139 char *state_unknown = "unknown";
140
141 system("cat /sys/class/fpga_manager/fpga0/state >> state.txt");
142 fptr = fopen("state.txt", "r");
143 if (fptr) {
144 fgets(buf, 10, fptr);
145 fclose(fptr);
146 system("rm state.txt");
147 if ((strncmp(buf, state_operating, 9) == 0) || (strncmp(buf, state_unknown, 7) == 0))
148 return 0;
149 else
150 return 1;
151 }
152
153 return 1;
154}
155
156static int fpga_overlay_check(char *cmd, char *state)
157{
158 char buf[512];
159 FILE *fptr;
160 int len;
161
162 system(cmd);
163 len = strlen(state) + 1;
164 fptr = fopen("state.txt", "r");
165 if (fptr) {
166 fgets(buf, len, fptr);
167 fclose(fptr);
168 system("rm state.txt");
169 if (!strcmp(buf, state))
170 return 0;
171 else
172 return 1;
173 }
174
175 return 1;
176}
177
178struct fpgaflag {
179 char *flag;
180 unsigned int value;
181};
182
183static struct fpgaflag flagdump[] = {
184 {.flag = "Full", .value = 0x0},
185 {.flag = "Partial", .value = 0x1},
186 {.flag = "AuthDDR", .value = 0x40},
187 {.flag = "AuthOCM", .value = 0x80},
188 {.flag = "EnUsrKey", .value = 0x20},
189 {.flag = "EnDevKey", .value = 0x4},
190 {.flag = "AuthEnUsrKeyDDR", .value = 0x60},
191 {.flag = "AuthEnUsrKeyOCM", .value = 0xA0},
192 {.flag = "AuthEnDevKeyDDR", .value = 0x44},
193 {.flag = "AuthEnDevKeyOCM", .value = 0x84},
194 {}
195};
196
197static int cmd_flags(int argc, const char *name)
198{
199 int valid_flag = 0;
200 int flag = 0;
201 struct fpgaflag *p = flagdump;
202
203 while (p->flag) {
204 if (!strcmp(name, p->flag)) {
205 flag = p->value;
206 break;
207 }
208 p++;
209 }
210
211 return flag;
212}
213
214static int isvalid_flags(int argc, const char *name, bool is_secure)
215{
216 int valid_flag = 0;
217 int count = 0;
218 struct fpgaflag *p;
219
220 if (!is_secure)
221 p = flagdump;
222 else
223 p = &flagdump[2];
224
225 while (p->flag) {
226 if (!strcmp(name, p->flag))
227 return 0;
228 else if ((!is_secure) && (++count == 2))
229 return 1;
230 p++;
231 }
232
233 return 1;
234}
235
236int main(int argc, char **argv)
237{
238 int ret;
239 int iszynqmp = fpga_getplatform();
240 char *binfile = NULL, *overlay = NULL, *AesKey = NULL, *flag = NULL, *partial_overlay = NULL;
241 char *region = NULL, *Module[100] = {0};
242 int opt, flags = 0, flow = 0,rm_overlay = 0, readback_type = 0, sflags = 0;
243 char command[2048], folder[512], *token, *tmp, *tmp1, *tmp2 , *tmp3;
244 const char *filename = "readback", *name;
245 struct stat sb;
246 double time;
247 struct timeval t1, t0;
248
249 if (argc == 1) {
250 print_usage(basename(argv[0]));
251 return 1;
252 }
253
254 while ((opt = getopt(argc, argv, "o:b:n:f:s:p:k:rt::Rh?:")) != -1) {
255 switch (opt) {
256 case 'o':
257 overlay = optarg;
258 flow = OVERLAY;
259 break;
260 case 'b':
261 binfile = optarg;
262 if (!(flow == OVERLAY))
263 flow = FPGA_SYSFS;
264 break;
265 case 'n':
266 region = optarg;
267 break;
268 case 'f':
269 if (flow == OVERLAY) {
270 name = argv[6];
271 flags = cmd_flags(argc, name);
272 } else if (flow == FPGA_SYSFS) {
273 name = argv[4];
274 flags = cmd_flags(argc, name);
275 }
276
277 ret = isvalid_flags(argc, name, false);
278 if (ret) {
279 printf("Error: Invalid arugments :%s\n", strerror(1));
280 print_usage(basename(argv[0]));
281 return -EINVAL;
282 }
283
284 flags += sflags;
285 break;
286 case 's':
287 if (flow == OVERLAY) {
288 name = argv[8];
289 sflags = cmd_flags(argc, name);
290 } else if (flow == FPGA_SYSFS) {
291 name = argv[6];
292 sflags = cmd_flags(argc, name);
293 }
294
295 ret = isvalid_flags(argc, name, true);
296 if (ret) {
297 printf("Error: Invalid arugments :%s\n", strerror(1));
298 print_usage(basename(argv[0]));
299 return -EINVAL;
300 }
301
302 flags += sflags;
303 break;
304 case 'p':
305 partial_overlay = optarg;
306 break;
307 case 'k':
308 AesKey = optarg;
309 break;
310 case 't':
311 if (optarg == NULL && argv[4] != NULL)
312 readback_type = atoi(argv[4]);
313 break;
314 case 'r':
315 if (optarg == NULL && argv[2] != NULL)
316 filename = argv[2];
317 flow = READBACK;
318 break;
319 case 'R':
320 rm_overlay = 1;
321 break;
322 case '?':
323 case 'h':
324 default:
325 print_usage(basename(argv[0]));
326 return 1;
327 break;
328 }
329 }
330
331 if(region != NULL)
332 snprintf(folder, sizeof(folder), "/configfs/device-tree/overlays/%s", region);
333 else if (!(flags & 1))
334 snprintf(folder, sizeof(folder), "/configfs/device-tree/overlays/full");
335 else if (overlay != NULL) {
336 printf("Error: Provide valid Overlay region info\n\r");
337 return 1;
338 }
339 system("mkdir -p /lib/firmware");
340 if (rm_overlay) {
341 if (((stat(folder, &sb) == 0) && S_ISDIR(sb.st_mode))) {
342 snprintf(command, sizeof(command), "rmdir %s", folder);
343 system(command);
344 }
345 return 0;
346 }
347
348 if (flow == OVERLAY) {
349 if (((stat(folder, &sb) == 0) && S_ISDIR(sb.st_mode))) {
350 printf("Error: Overlay already exists in the live tree\n\r");
351 return 1;
352 }
353
354 if (((stat("/configfs/device-tree/", &sb) == 0) && S_ISDIR(sb.st_mode))) {
355 } else {
356 system("mkdir /configfs");
357 system("mount -t configfs configfs /configfs");
358 }
359
360 if (binfile != NULL) {
361 snprintf(command, sizeof(command), "cp %s /lib/firmware", binfile);
362 system(command);
363 }
364
365 snprintf(command, sizeof(command), "cp %s /lib/firmware", overlay);
366 system(command);
367 tmp = strdup(overlay);
368 while((token = strsep(&tmp, "/"))) {
369 tmp1 = token;
370 }
371
372 if (binfile != NULL) {
373 snprintf(command, sizeof(command), "echo %x > /sys/class/fpga_manager/fpga0/flags", flags);
374 system(command);
375 if (ENCRYPTION_USERKEY_EN & flags) {
376 snprintf(command, sizeof(command), "echo %s > /sys/class/fpga_manager/fpga0/key", AesKey);
377 system(command);
378 }
379 }
380
381 snprintf(command, sizeof(command), "mkdir %s", folder);
382 system(command);
383 snprintf(command, sizeof(command), "echo -n %s > %s/path", tmp1, folder);
384 gettimeofday(&t0, NULL);
385 system(command);
386 gettimeofday(&t1, NULL);
387 time = gettime(t0, t1);
388
389 snprintf(command, sizeof(command), "cat %s/path >> state.txt", folder);
390 ret = fpga_overlay_check(command, tmp1);
391 if (ret) {
392 printf("Failed to apply Overlay\n\r");
393 }
394
395 /* Delete Bin file and DTBO file*/
396 snprintf(command, sizeof(command), "rm /lib/firmware/%s", tmp1);
397 system(command);
398 if (binfile != NULL) {
399 tmp = strdup(binfile);
400 while((token = strsep(&tmp, "/"))) {
401 tmp1 = token;
402 }
403 snprintf(command, sizeof(command), "rm /lib/firmware/%s", tmp1);
404 system(command);
405 }
406
407 /* FPGA state check */
408 if (binfile != NULL) {
409 if (!fpga_state()) {
410 printf("Time taken to load BIN is %f Milli Seconds\n\r", time);
411 printf("BIN FILE loaded through FPGA manager successfully\n\r");
412 } else {
413 printf("BIN FILE loading through FPGA manager failed\n\r");
414 }
415 }
416 } else if (flow == FPGA_SYSFS) {
417 if (argc < 3) {
418 printf("%s: For more information run %s -h\n", strerror(22), basename(argv[0]));
419 return 1;
420 }
421 snprintf(command, sizeof(command), "cp %s /lib/firmware", binfile);
422 system(command);
423 snprintf(command, sizeof(command), "echo %x > /sys/class/fpga_manager/fpga0/flags", flags);
424 system(command);
425 if (ENCRYPTION_USERKEY_EN & flags) {
426 snprintf(command, sizeof(command), "echo %s > /sys/class/fpga_manager/fpga0/key", AesKey);
427 system(command);
428 }
429 tmp = strdup(binfile);
430 while((token = strsep(&tmp, "/"))) {
431 tmp1 = token;
432 }
433 snprintf(command, sizeof(command), "echo %s > /sys/class/fpga_manager/fpga0/firmware", tmp1);
434 gettimeofday(&t0, NULL);
435 system(command);
436 gettimeofday(&t1, NULL);
437 time = gettime(t0, t1);
438
439 /* Delete Bin file and DTBO file*/
440 snprintf(command, sizeof(command), "rm /lib/firmware/%s", tmp1);
441 system(command);
442
443 /* FPGA state check */
444 if (!fpga_state()) {
445 printf("Time taken to load BIN is %f Milli Seconds\n\r", time);
446 printf("BIN FILE loaded through FPGA manager successfully\n\r");
447 } else {
448 printf("BIN FILE loading through FPGA manager failed\n\r");
449 }
450 } else if (flow == READBACK) {
451 if (readback_type > 1) {
452 printf("Invalid arugments :%s\n", strerror(1));
453 printf("For more information run %s -h\n", basename(argv[0]));
454 return -EINVAL;
455 }
456 snprintf(command, sizeof(command), "echo %x > /sys/module/zynqmp_fpga/parameters/readback_type", readback_type);
457 system(command);
458 snprintf(command, sizeof(command), "cat /sys/kernel/debug/fpga/fpga0/image >> %s.bin", filename);
459 system(command);
460 printf("Readback contents are stored in the file %s.bin\n\r", filename);
461 }
462
463 return 0;
464}