switch to jtag_add_dr_scan_check() - USB performance fix
[openocd.git] / src / helper / ioutil.c
1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 /* this file contains various functionality useful to standalone systems */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "log.h"
27 #include "time_support.h"
28
29 #ifdef HAVE_ARPA_INET_H
30 #include <arpa/inet.h>
31 #endif
32 #ifdef HAVE_DIRENT_H
33 #include <dirent.h>
34 #endif
35 #ifdef HAVE_NETDB_H
36 #include <netdb.h>
37 #endif
38 #ifdef HAVE_NET_IF_H
39 #include <net/if.h>
40 #endif
41 //#ifdef HAVE_NETINET_TCP_H
42 //#include <netinet/tcp.h>
43 //#endif
44 #ifdef HAVE_SYS_IOCTL_H
45 #include <sys/ioctl.h>
46 #endif
47 #ifdef HAVE_SYS_STAT_H
48 #include <sys/stat.h>
49 #endif
50 #ifdef HAVE_IFADDRS_H
51 #include <ifaddrs.h>
52 #endif
53 #ifdef HAVE_MALLOC_H
54 #if !BUILD_ECOSBOARD
55 #include <malloc.h>
56 #endif
57 #endif
58 //#ifdef HAVE_STRINGS_H
59 //#include <strings.h>
60 //#endif
61
62
63 int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
64 char **args, int argc)
65 {
66 if (argc != 1)
67 {
68 command_print(cmd_ctx, "rm <filename>");
69 return ERROR_INVALID_ARGUMENTS;
70 }
71
72 if (unlink(args[0]) != 0)
73 {
74 command_print(cmd_ctx, "failed: %d", errno);
75 }
76
77 return ERROR_OK;
78 }
79
80
81 /* loads a file and returns a pointer to it in memory. The file contains
82 * a 0 byte(sentinel) after len bytes - the length of the file. */
83 int loadFile(const char *fileName, void **data, size_t *len)
84 {
85 // ensure returned length is always sane
86 *len = 0;
87
88 FILE * pFile;
89 pFile = fopen(fileName,"rb");
90 if (pFile==NULL)
91 {
92 LOG_ERROR("Can't open %s\n", fileName);
93 return ERROR_FAIL;
94 }
95 if (fseek(pFile, 0, SEEK_END)!=0)
96 {
97 LOG_ERROR("Can't open %s\n", fileName);
98 fclose(pFile);
99 return ERROR_FAIL;
100 }
101 long fsize = ftell(pFile);
102 if (fsize == -1)
103 {
104 LOG_ERROR("Can't open %s\n", fileName);
105 fclose(pFile);
106 return ERROR_FAIL;
107 }
108 *len = fsize;
109
110 if (fseek(pFile, 0, SEEK_SET)!=0)
111 {
112 LOG_ERROR("Can't open %s\n", fileName);
113 fclose(pFile);
114 return ERROR_FAIL;
115 }
116 *data = malloc(*len + 1);
117 if (*data==NULL)
118 {
119 LOG_ERROR("Can't open %s\n", fileName);
120 fclose(pFile);
121 return ERROR_FAIL;
122 }
123
124 if (fread(*data, 1, *len, pFile)!=*len)
125 {
126 fclose(pFile);
127 free(*data);
128 LOG_ERROR("Can't open %s\n", fileName);
129 return ERROR_FAIL;
130 }
131 fclose(pFile);
132
133 // 0-byte after buffer (not included in *len) serves as a sentinel
134 char *buf = (char *)*data;
135 buf[*len] = 0;
136
137 return ERROR_OK;
138 }
139
140
141
142 int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
143 char **args, int argc)
144 {
145 if (argc != 1)
146 {
147 command_print(cmd_ctx, "cat <filename>");
148 return ERROR_INVALID_ARGUMENTS;
149 }
150
151 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
152 void *data;
153 size_t len;
154
155 int retval = loadFile(args[0], &data, &len);
156 if (retval == ERROR_OK)
157 {
158 command_print(cmd_ctx, "%s", data);
159 free(data);
160 }
161 else
162 {
163 command_print(cmd_ctx, "%s not found %d", args[0], retval);
164 }
165
166 return ERROR_OK;
167 }
168 int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
169 char **args, int argc)
170 {
171 if (argc != 1)
172 {
173 command_print(cmd_ctx, "trunc <filename>");
174 return ERROR_INVALID_ARGUMENTS;
175 }
176
177 FILE *config_file = NULL;
178 config_file = fopen(args[0], "w");
179 if (config_file != NULL)
180 fclose(config_file);
181
182 return ERROR_OK;
183 }
184
185
186 int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
187 {
188 static int prev = 0;
189 struct mallinfo info;
190
191 if (argc != 0)
192 {
193 command_print(cmd_ctx, "meminfo");
194 return ERROR_INVALID_ARGUMENTS;
195 }
196
197 info = mallinfo();
198
199 if (prev > 0)
200 {
201 command_print(cmd_ctx, "Diff: %d", prev - info.fordblks);
202 }
203 prev = info.fordblks;
204
205 command_print(cmd_ctx, "Available ram: %d", info.fordblks );
206
207 return ERROR_OK;
208 }
209
210
211 int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
212 char **args, int argc)
213 {
214 if (argc < 1)
215 {
216 command_print(cmd_ctx,
217 "append <filename> [<string1>, [<string2>, ...]]");
218 return ERROR_INVALID_ARGUMENTS;
219 }
220
221 FILE *config_file = NULL;
222 config_file = fopen(args[0], "a");
223 if (config_file != NULL)
224 {
225 int i;
226 fseek(config_file, 0, SEEK_END);
227
228 for (i = 1; i < argc; i++)
229 {
230 fwrite(args[i], strlen(args[i]), 1, config_file);
231 if (i != argc - 1)
232 {
233 fwrite(" ", 1, 1, config_file);
234 }
235 }
236 fwrite("\n", 1, 1, config_file);
237 fclose(config_file);
238 }
239
240 return ERROR_OK;
241 }
242
243
244
245 int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
246 {
247 if (argc != 2)
248 {
249 return ERROR_INVALID_ARGUMENTS;
250 }
251
252 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
253 void *data;
254 size_t len;
255
256 int retval = loadFile(args[0], &data, &len);
257 if (retval != ERROR_OK)
258 return retval;
259
260 FILE *f = fopen(args[1], "wb");
261 if (f == NULL)
262 retval = ERROR_INVALID_ARGUMENTS;
263
264 size_t pos = 0;
265 for (;;)
266 {
267 size_t chunk = len - pos;
268 static const size_t maxChunk = 512 * 1024; // ~1/sec
269 if (chunk > maxChunk)
270 {
271 chunk = maxChunk;
272 }
273
274 if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
275 retval = ERROR_INVALID_ARGUMENTS;
276
277 if (retval != ERROR_OK)
278 {
279 break;
280 }
281
282 command_print(cmd_ctx, "%d", len - pos);
283
284 pos += chunk;
285
286 if (pos == len)
287 break;
288 }
289
290 if (retval == ERROR_OK)
291 {
292 command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
293 } else
294 {
295 command_print(cmd_ctx, "Failed: %d", retval);
296 }
297
298 if (data != NULL)
299 free(data);
300 if (f != NULL)
301 fclose(f);
302
303 if (retval != ERROR_OK)
304 unlink(args[1]);
305
306 return retval;
307 }
308
309
310
311
312 #define SHOW_RESULT(a, b) LOG_ERROR(#a " failed %d\n", (int)b)
313
314 #define IOSIZE 512
315 void copyfile(char *name2, char *name1)
316 {
317
318 int err;
319 char buf[IOSIZE];
320 int fd1, fd2;
321 ssize_t done, wrote;
322
323 fd1 = open(name1, O_WRONLY | O_CREAT);
324 if (fd1 < 0)
325 SHOW_RESULT( open, fd1 );
326
327 fd2 = open(name2, O_RDONLY);
328 if (fd2 < 0)
329 SHOW_RESULT( open, fd2 );
330
331 for (;;)
332 {
333 done = read(fd2, buf, IOSIZE );
334 if (done < 0)
335 {
336 SHOW_RESULT( read, done );
337 break;
338 }
339
340 if( done == 0 ) break;
341
342 wrote = write(fd1, buf, done);
343 if( wrote != done ) SHOW_RESULT( write, wrote );
344
345 if( wrote != done ) break;
346 }
347
348 err = close(fd1);
349 if( err < 0 ) SHOW_RESULT( close, err );
350
351 err = close(fd2);
352 if( err < 0 ) SHOW_RESULT( close, err );
353
354 }
355
356 /* utility fn to copy a directory */
357 void copydir(char *name, char *destdir)
358 {
359 int err;
360 DIR *dirp;
361
362 dirp = opendir(destdir);
363 if (dirp==NULL)
364 {
365 mkdir(destdir, 0777);
366 } else
367 {
368 err = closedir(dirp);
369 }
370
371 dirp = opendir(name);
372 if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
373
374 for (;;)
375 {
376 struct dirent *entry = readdir(dirp);
377
378 if (entry == NULL)
379 break;
380
381 if (strcmp(entry->d_name, ".") == 0)
382 continue;
383 if (strcmp(entry->d_name, "..") == 0)
384 continue;
385
386 int isDir = 0;
387 struct stat buf;
388 char fullPath[PATH_MAX];
389 strncpy(fullPath, name, PATH_MAX);
390 strcat(fullPath, "/");
391 strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
392
393 if (stat(fullPath, &buf) == -1)
394 {
395 LOG_ERROR("unable to read status from %s", fullPath);
396 break;
397 }
398 isDir = S_ISDIR(buf.st_mode) != 0;
399
400 if (isDir)
401 continue;
402
403 // diag_printf("<INFO>: entry %14s",entry->d_name);
404 char fullname[PATH_MAX];
405 char fullname2[PATH_MAX];
406
407 strcpy(fullname, name);
408 strcat(fullname, "/");
409 strcat(fullname, entry->d_name);
410
411 strcpy(fullname2, destdir);
412 strcat(fullname2, "/");
413 strcat(fullname2, entry->d_name);
414 // diag_printf("from %s to %s\n", fullname, fullname2);
415 copyfile(fullname, fullname2);
416
417 // diag_printf("\n");
418 }
419
420 err = closedir(dirp);
421 if( err < 0 ) SHOW_RESULT( stat, err );
422 }
423
424
425
426
427 static int
428 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
429 int argc,
430 Jim_Obj * const *argv)
431 {
432 int del;
433 if (argc != 2)
434 {
435 Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
436 return JIM_ERR;
437 }
438
439 del = 0;
440 if (unlink(Jim_GetString(argv[1], NULL)) == 0)
441 del = 1;
442 if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
443 del = 1;
444
445 return del ? JIM_OK : JIM_ERR;
446 }
447
448
449 static int
450 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
451 int argc,
452 Jim_Obj * const *argv)
453 {
454 if (argc != 2)
455 {
456 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
457 return JIM_ERR;
458 }
459
460 char *name = (char*) Jim_GetString(argv[1], NULL);
461
462 DIR *dirp = NULL;
463 dirp = opendir(name);
464 if (dirp == NULL)
465 {
466 return JIM_ERR;
467 }
468 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
469
470 for (;;)
471 {
472 struct dirent *entry = NULL;
473 entry = readdir(dirp);
474 if (entry == NULL)
475 break;
476
477 if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
478 continue;
479
480 Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
481 }
482 closedir(dirp);
483
484 Jim_SetResult(interp, objPtr);
485
486 return JIM_OK;
487 }
488
489 int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
490 {
491 if (argc != 1)
492 {
493 return ERROR_COMMAND_SYNTAX_ERROR;
494 }
495 unsigned long addr = strtoul(args[0], NULL, 0);
496 volatile unsigned *address = (volatile unsigned *)addr;
497 unsigned value = *address;
498 command_print(cmd_ctx, "0x%x : 0x%x", address, value);
499 return ERROR_OK;
500 }
501
502 int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
503 {
504 if (argc != 2)
505 {
506 return ERROR_INVALID_ARGUMENTS;
507 }
508 unsigned long addr = strtoul(args[0], NULL, 0);
509 volatile int *address = (volatile int *)addr;
510 int value=strtoul(args[1], NULL, 0);
511 *address=value;
512 return ERROR_OK;
513 }
514
515 static int
516 zylinjtag_Jim_Command_peek(Jim_Interp *interp,
517 int argc,
518 Jim_Obj * const *argv)
519 {
520 if (argc != 2)
521 {
522 Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
523 return JIM_ERR;
524 }
525
526 long address;
527 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
528 return JIM_ERR;
529
530 int value = *((volatile int *) address);
531
532 Jim_SetResult(interp, Jim_NewIntObj(interp, value));
533
534 return JIM_OK;
535 }
536
537 static int
538 zylinjtag_Jim_Command_poke(Jim_Interp *interp,
539 int argc,
540 Jim_Obj * const *argv)
541 {
542 if (argc != 3)
543 {
544 Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
545 return JIM_ERR;
546 }
547
548 long address;
549 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
550 return JIM_ERR;
551 long value;
552 if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
553 return JIM_ERR;
554
555 *((volatile int *) address) = value;
556
557 return JIM_OK;
558 }
559
560
561 /* not so pretty code to fish out ip number*/
562 static int zylinjtag_Jim_Command_ip(Jim_Interp *interp, int argc,
563 Jim_Obj * const *argv)
564 {
565 #if !defined(__CYGWIN__)
566 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
567
568 struct ifaddrs *ifa = NULL, *ifp = NULL;
569
570 if (getifaddrs(&ifp) < 0)
571 {
572 return JIM_ERR;
573 }
574
575 for (ifa = ifp; ifa; ifa = ifa->ifa_next)
576 {
577 char ip[200];
578 socklen_t salen;
579
580 if (ifa->ifa_addr->sa_family == AF_INET)
581 salen = sizeof(struct sockaddr_in);
582 else if (ifa->ifa_addr->sa_family == AF_INET6)
583 salen = sizeof(struct sockaddr_in6);
584 else
585 continue;
586
587 if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
588 NI_NUMERICHOST) < 0)
589 {
590 continue;
591 }
592
593 Jim_AppendString(interp, tclOutput, ip, strlen(ip));
594 break;
595
596 }
597
598 freeifaddrs(ifp);
599 #else
600 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "fixme!!!", 0);
601 LOG_ERROR("NOT IMPLEMENTED!!!");
602 #endif
603 Jim_SetResult(interp, tclOutput);
604
605 return JIM_OK;
606 }
607
608 /* not so pretty code to fish out eth0 mac address */
609 static int zylinjtag_Jim_Command_mac(Jim_Interp *interp, int argc,
610 Jim_Obj * const *argv)
611 {
612
613
614 struct ifreq *ifr, *ifend;
615 struct ifreq ifreq;
616 struct ifconf ifc;
617 struct ifreq ifs[5];
618 int SockFD;
619
620 SockFD = socket(AF_INET, SOCK_DGRAM, 0);
621 if (SockFD < 0)
622 {
623 return JIM_ERR;
624 }
625
626 ifc.ifc_len = sizeof(ifs);
627 ifc.ifc_req = ifs;
628 if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0)
629 {
630 close(SockFD);
631 return JIM_ERR;
632 }
633
634 ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
635 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
636 {
637 //if (ifr->ifr_addr.sa_family == AF_INET)
638 {
639 if (strcmp("eth0", ifr->ifr_name)!=0)
640 continue;
641 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
642 if (ioctl(SockFD, SIOCGIFHWADDR, &ifreq) < 0)
643 {
644 close(SockFD);
645 return JIM_ERR;
646 }
647
648 close(SockFD);
649
650
651 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
652
653 char buffer[256];
654 sprintf(buffer, "%02x-%02x-%02x-%02x-%02x-%02x",
655 ifreq.ifr_hwaddr.sa_data[0]&0xff,
656 ifreq.ifr_hwaddr.sa_data[1]&0xff,
657 ifreq.ifr_hwaddr.sa_data[2]&0xff,
658 ifreq.ifr_hwaddr.sa_data[3]&0xff,
659 ifreq.ifr_hwaddr.sa_data[4]&0xff,
660 ifreq.ifr_hwaddr.sa_data[5]&0xff);
661
662 Jim_AppendString(interp, tclOutput, buffer, strlen(buffer));
663
664 Jim_SetResult(interp, tclOutput);
665
666 return JIM_OK;
667 }
668 }
669 close(SockFD);
670
671 return JIM_ERR;
672
673 }
674
675
676
677 int ioutil_init(struct command_context_s *cmd_ctx)
678 {
679 register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
680 "remove file");
681
682 register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
683 "display file content");
684
685 register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
686 "truncate a file to 0 size");
687
688 register_command(cmd_ctx, NULL, "cp", handle_cp_command,
689 COMMAND_ANY, "copy a file <from> <to>");
690
691 register_command(cmd_ctx, NULL, "append_file", handle_append_command,
692 COMMAND_ANY, "append a variable number of strings to a file");
693
694 register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
695 COMMAND_ANY, "display available ram memory");
696
697 Jim_CreateCommand(interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
698
699 Jim_CreateCommand(interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
700 Jim_CreateCommand(interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
701 Jim_CreateCommand(interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
702
703 Jim_CreateCommand(interp, "mac", zylinjtag_Jim_Command_mac,
704 NULL, NULL);
705
706 Jim_CreateCommand(interp, "ip", zylinjtag_Jim_Command_ip,
707 NULL, NULL);
708
709 return ERROR_OK;
710 }
711
712

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)