6326b9873dad52dd726041e35107721e41aa1083
[openocd.git] / src / ecosboard.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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "log.h"
25 #include "types.h"
26 #include "jtag.h"
27 #include "configuration.h"
28 #include "xsvf.h"
29 #include "target.h"
30 #include "flash.h"
31 #include "nand.h"
32 #include "pld.h"
33
34 #include "command.h"
35 #include "server.h"
36 #include "telnet_server.h"
37 #include "gdb_server.h"
38
39 #include <time_support.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 #include <strings.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <errno.h>
48
49 #include <cyg/io/flash.h>
50 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
51 #include <network.h>
52
53 #include <fcntl.h>
54 #include <sys/stat.h>
55 #include <cyg/fileio/fileio.h>
56 #include <dirent.h>
57 #include <cyg/athttpd/http.h>
58 #include <cyg/athttpd/socket.h>
59 #include <cyg/athttpd/handler.h>
60 #include <cyg/athttpd/cgi.h>
61 #include <cyg/athttpd/forms.h>
62 #include <cyg/discover/discover.h>
63 #include <cyg/hal/hal_diag.h>
64 #include <cyg/kernel/kapi.h>
65 #include <cyg/io/serialio.h>
66 #include <cyg/io/io.h>
67 #include <netinet/tcp.h>
68 #include "rom.h"
69 #include <sys/ioctl.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #include <net/if.h>
73 #include <arpa/inet.h>
74 #include <sys/types.h>
75 #include <sys/socket.h>
76 #include <netdb.h>
77 #include <netinet/in.h>
78 #include <unistd.h>
79 #include <arpa/inet.h>
80 #include <stdio.h>
81 #include <ifaddrs.h>
82 #include <string.h>
83
84
85 #include <unistd.h>
86 #include <stdio.h>
87 #define MAX_IFS 64
88 #if defined(CYGPKG_NET_FREEBSD_STACK)
89 #include <tftp_support.h>
90 /* posix compatibility broken*/
91 struct tftpd_fileops fileops =
92 {
93 (int (*)(const char *, int))open,
94 close,
95 (int (*)(int, const void *, int))write,
96 ( int (*)(int, void *, int))read
97 };
98
99 #endif
100
101 #define ZYLIN_VERSION "1.48"
102 #define ZYLIN_DATE __DATE__
103 #define ZYLIN_TIME __TIME__
104 /* hmmm.... we can't pick up the right # during build if we've checked this out
105 * in Eclipse... arrggghh...*/
106 #define ZYLIN_OPENOCD "$Revision$"
107 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
108 #define ZYLIN_CONFIG_DIR "/config/settings"
109
110 void diag_write(char *buf, int len)
111 {
112 int j;
113 for (j = 0; j < len; j++)
114 {
115 diag_printf("%c", buf[j]);
116 }
117 }
118
119 static bool serialLog = true;
120 static bool writeLog = true;
121
122 char hwaddr[512];
123
124
125 /* Give TELNET a way to find out what version this is */
126 int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,
127 char **args, int argc)
128 {
129 if (argc > 1)
130 {
131 return ERROR_COMMAND_SYNTAX_ERROR;
132 }
133 if (argc == 0)
134 {
135 command_print(cmd_ctx, ZYLIN_OPENOCD_VERSION);
136 } else if (strcmp("openocd", args[0])==0)
137 {
138 int revision;
139 revision=atol(ZYLIN_OPENOCD+strlen("XRevision: "));
140 command_print(cmd_ctx, "%d", revision);
141 } else if (strcmp("zy1000", args[0])==0)
142 {
143 command_print(cmd_ctx, "%s", ZYLIN_VERSION);
144 } else if (strcmp("date", args[0])==0)
145 {
146 command_print(cmd_ctx, "%s", ZYLIN_DATE);
147 } else
148 {
149 return ERROR_COMMAND_SYNTAX_ERROR;
150 }
151
152 return ERROR_OK;
153 }
154
155
156
157
158 extern flash_driver_t *flash_drivers[];
159 extern target_type_t *target_types[];
160
161 #ifdef CYGPKG_PROFILE_GPROF
162 #include <cyg/profile/profile.h>
163
164 extern char _stext, _etext; // Defined by the linker
165
166 static char *start_of_code=&_stext;
167 static char *end_of_code=&_etext;
168
169 void start_profile(void)
170 {
171 // This starts up the system-wide profiling, gathering
172 // profile information on all of the code, with a 16 byte
173 // "bucket" size, at a rate of 100us/profile hit.
174 // Note: a bucket size of 16 will give pretty good function
175 // resolution. Much smaller and the buffer becomes
176 // much too large for very little gain.
177 // Note: a timer period of 100us is also a reasonable
178 // compromise. Any smaller and the overhead of
179 // handling the timter (profile) interrupt could
180 // swamp the system. A fast processor might get
181 // by with a smaller value, but a slow one could
182 // even be swamped by this value. If the value is
183 // too large, the usefulness of the profile is reduced.
184
185 // no more interrupts than 1/10ms.
186 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
187 // profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
188 profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
189 }
190 #endif
191
192 // launch GDB server if a config file exists
193 bool zylinjtag_parse_config_file(struct command_context_s *cmd_ctx, const char *config_file_name)
194 {
195 bool foundFile = false;
196 FILE *config_file = NULL;
197 command_print(cmd_ctx, "executing config file %s", config_file_name);
198 config_file = fopen(config_file_name, "r");
199 if (config_file)
200 {
201 fclose(config_file);
202 int retval;
203 retval = command_run_linef(cmd_ctx, "script %s", config_file_name);
204 if (retval == ERROR_OK)
205 {
206 foundFile = true;
207 }
208 else
209 {
210 command_print(cmd_ctx, "Failed executing %s %d", config_file_name, retval);
211 }
212 }
213 else
214 {
215 command_print(cmd_ctx, "No %s found", config_file_name);
216 }
217
218 return foundFile;
219 }
220
221 extern int eth0_up;
222 static FILE *log;
223
224 static char reboot_stack[2048];
225
226
227 static void
228 zylinjtag_reboot(cyg_addrword_t data)
229 {
230 serialLog = true;
231 diag_printf("Rebooting in 100 ticks..\n");
232 cyg_thread_delay(100);
233 diag_printf("Unmounting /config..\n");
234 umount("/config");
235 diag_printf("Rebooting..\n");
236 HAL_PLATFORM_RESET();
237 }
238 static cyg_thread zylinjtag_thread_object;
239 static cyg_handle_t zylinjtag_thread_handle;
240
241 void reboot(void)
242 {
243 cyg_thread_create(1,
244 zylinjtag_reboot,
245 (cyg_addrword_t)0,
246 "reboot Thread",
247 (void *)reboot_stack,
248 sizeof(reboot_stack),
249 &zylinjtag_thread_handle,
250 &zylinjtag_thread_object);
251 cyg_thread_resume(zylinjtag_thread_handle);
252 }
253
254 int configuration_output_handler(struct command_context_s *context, const char* line)
255 {
256 diag_printf("%s", line);
257
258 return ERROR_OK;
259 }
260
261 int zy1000_configuration_output_handler_log(struct command_context_s *context, const char* line)
262 {
263 LOG_USER_N("%s", line);
264
265 return ERROR_OK;
266 }
267
268 int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
269 char **args, int argc)
270 {
271 if (argc != 1)
272 {
273 command_print(cmd_ctx, "rm <filename>");
274 return ERROR_INVALID_ARGUMENTS;
275 }
276
277 if (unlink(args[0]) != 0)
278 {
279 command_print(cmd_ctx, "failed: %d", errno);
280 }
281
282 return ERROR_OK;
283 }
284
285 int loadFile(const char *fileName, void **data, int *len);
286
287 int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
288 char **args, int argc)
289 {
290 if (argc != 1)
291 {
292 command_print(cmd_ctx, "cat <filename>");
293 return ERROR_INVALID_ARGUMENTS;
294 }
295
296 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
297 void *data;
298 int len;
299
300 int retval = loadFile(args[0], &data, &len);
301 if (retval == ERROR_OK)
302 {
303 command_print(cmd_ctx, "%s", data);
304 free(data);
305 }
306 else
307 {
308 command_print(cmd_ctx, "%s not found %d", args[0], retval);
309 }
310
311 return ERROR_OK;
312 }
313 int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
314 char **args, int argc)
315 {
316 if (argc != 1)
317 {
318 command_print(cmd_ctx, "trunc <filename>");
319 return ERROR_INVALID_ARGUMENTS;
320 }
321
322 FILE *config_file = NULL;
323 config_file = fopen(args[0], "w");
324 if (config_file != NULL)
325 fclose(config_file);
326
327 return ERROR_OK;
328 }
329
330
331 int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
332 {
333 static int prev = 0;
334 struct mallinfo info;
335
336 if (argc != 0)
337 {
338 command_print(cmd_ctx, "meminfo");
339 return ERROR_INVALID_ARGUMENTS;
340 }
341
342 info = mallinfo();
343
344 if (prev > 0)
345 {
346 command_print(cmd_ctx, "Diff: %d", prev - info.fordblks);
347 }
348 prev = info.fordblks;
349
350 command_print(cmd_ctx, "Available ram: %d", info.fordblks );
351
352 return ERROR_OK;
353 }
354
355 static bool savePower;
356
357 static void setPower(bool power)
358 {
359 savePower = power;
360 if (power)
361 {
362 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x14, 0x8);
363 } else
364 {
365 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x10, 0x8);
366 }
367 }
368
369 int handle_power_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
370 {
371 if (argc > 1)
372 {
373 return ERROR_INVALID_ARGUMENTS;
374 }
375
376 if (argc == 1)
377 {
378 if (strcmp(args[0], "on") == 0)
379 {
380 setPower(1);
381 }
382 else if (strcmp(args[0], "off") == 0)
383 {
384 setPower(0);
385 } else
386 {
387 command_print(cmd_ctx, "arg is \"on\" or \"off\"");
388 return ERROR_INVALID_ARGUMENTS;
389 }
390 }
391
392 command_print(cmd_ctx, "Target power %s", savePower ? "on" : "off");
393
394 return ERROR_OK;
395 }
396
397 int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
398 char **args, int argc)
399 {
400 if (argc < 1)
401 {
402 command_print(cmd_ctx,
403 "append <filename> [<string1>, [<string2>, ...]]");
404 return ERROR_INVALID_ARGUMENTS;
405 }
406
407 FILE *config_file = NULL;
408 config_file = fopen(args[0], "a");
409 if (config_file != NULL)
410 {
411 int i;
412 fseek(config_file, 0, SEEK_END);
413
414 for (i = 1; i < argc; i++)
415 {
416 fwrite(args[i], strlen(args[i]), 1, config_file);
417 if (i != argc - 1)
418 {
419 fwrite(" ", 1, 1, config_file);
420 }
421 }
422 fwrite("\n", 1, 1, config_file);
423 fclose(config_file);
424 }
425
426 return ERROR_OK;
427 }
428
429 extern int telnet_socket;
430
431 int readMore(int fd, void *data, int length)
432 {
433 /* used in select() */
434 fd_set read_fds;
435
436 /* monitor sockets for acitvity */
437 int fd_max = 1;
438 FD_ZERO(&read_fds);
439 /* listen for new connections */
440 FD_SET(fd, &read_fds);
441
442 // Maximum 5 seconds.
443 struct timeval tv;
444 tv.tv_sec = 5;
445 tv.tv_usec = 0;
446
447 int retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
448 if (retval == 0)
449 {
450 diag_printf("Timed out waiting for binary payload\n");
451 return -1;
452 }
453 if (retval != 1)
454 return -1;
455
456 return read_socket(fd, data, length);
457 }
458
459 int readAll(int fd, void *data, int length)
460 {
461 int pos = 0;
462 for (;;)
463 {
464 int actual = readMore(fd, ((char *) data) + pos, length - pos);
465 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
466 if (actual <= 0)
467 return -1;
468 pos += actual;
469 if (pos == length)
470 break;
471 }
472 return length;
473 }
474
475 int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
476 {
477 cyg_uint32 value;
478 if (argc != 1)
479 {
480 return ERROR_INVALID_ARGUMENTS;
481 }
482 HAL_READ_UINT32(strtoul(args[0], NULL, 0), value);
483 command_print(cmd_ctx, "0x%x : 0x%x", strtoul(args[0], NULL, 0), value);
484 return ERROR_OK;
485 }
486
487 int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
488 {
489 if (argc != 2)
490 {
491 return ERROR_INVALID_ARGUMENTS;
492 }
493 HAL_WRITE_UINT32(strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0));
494 return ERROR_OK;
495 }
496
497 int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
498 {
499 if (argc != 2)
500 {
501 return ERROR_INVALID_ARGUMENTS;
502 }
503
504 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
505 void *data;
506 int len;
507
508 int retval = loadFile(args[0], &data, &len);
509 if (retval != ERROR_OK)
510 return retval;
511
512 FILE *f = fopen(args[1], "wb");
513 if (f == NULL)
514 retval = ERROR_INVALID_ARGUMENTS;
515
516 int pos = 0;
517 for (;;)
518 {
519 int chunk = len - pos;
520 static const int maxChunk = 512 * 1024; // ~1/sec
521 if (chunk > maxChunk)
522 {
523 chunk = maxChunk;
524 }
525
526 if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
527 retval = ERROR_INVALID_ARGUMENTS;
528
529 if (retval != ERROR_OK)
530 {
531 break;
532 }
533
534 command_print(cmd_ctx, "%d", len - pos);
535
536 pos += chunk;
537
538 if (pos == len)
539 break;
540 }
541
542 if (retval == ERROR_OK)
543 {
544 command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
545 } else
546 {
547 command_print(cmd_ctx, "Failed: %d", retval);
548 }
549
550 if (data != NULL)
551 free(data);
552 if (f != NULL)
553 fclose(f);
554
555 if (retval != ERROR_OK)
556 unlink(args[1]);
557
558 return retval;
559 }
560
561 #ifdef CYGPKG_PROFILE_GPROF
562 extern void start_profile();
563
564 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
565 {
566 command_print(cmd_ctx, "Profiling started");
567 start_profile();
568 return ERROR_OK;
569 }
570
571 #endif
572
573 externC void phi_init_all_network_interfaces();
574
575 command_context_t *cmd_ctx;
576
577 static bool webRunning = false;
578
579 void keep_webserver()
580 {
581 // Target initialisation is only attempted at startup, so we sleep forever and
582 // let the http server bail us out(i.e. get config files set up).
583 diag_printf("OpenOCD has invoked exit().\n"
584 "Use web server to correct any configuration settings and reboot.\n");
585 if (!webRunning)
586 reboot();
587
588 // exit() will terminate the current thread and we we'll then sleep eternally or
589 // we'll have a reboot scheduled.
590 }
591
592 extern void printDccChar(char c);
593
594 static char logBuffer[128 * 1024];
595 static const int logSize = sizeof(logBuffer);
596 int writePtr = 0;
597 int logCount = 0;
598
599 void _zylinjtag_diag_write_char(char c, void **param)
600 {
601 if (writeLog)
602 {
603 logBuffer[writePtr] = c;
604 writePtr = (writePtr + 1) % logSize;
605 logCount++;
606 }
607 if (serialLog)
608 {
609 if (c == '\n')
610 {
611 HAL_DIAG_WRITE_CHAR('\r');
612 }
613 HAL_DIAG_WRITE_CHAR(c);
614 }
615
616 #ifdef CYGPKG_HAL_ZYLIN_PHI
617 printDccChar(c);
618 #endif
619 }
620
621 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
622
623 #define IOSIZE 512
624 static void copyfile(char *name2, char *name1)
625 {
626
627 int err;
628 char buf[IOSIZE];
629 int fd1, fd2;
630 ssize_t done, wrote;
631
632 fd1 = open(name1, O_WRONLY | O_CREAT);
633 if (fd1 < 0)
634 SHOW_RESULT( open, fd1 );
635
636 fd2 = open(name2, O_RDONLY);
637 if (fd2 < 0)
638 SHOW_RESULT( open, fd2 );
639
640 for (;;)
641 {
642 done = read(fd2, buf, IOSIZE );
643 if (done < 0)
644 {
645 SHOW_RESULT( read, done );
646 break;
647 }
648
649 if( done == 0 ) break;
650
651 wrote = write(fd1, buf, done);
652 if( wrote != done ) SHOW_RESULT( write, wrote );
653
654 if( wrote != done ) break;
655 }
656
657 err = close(fd1);
658 if( err < 0 ) SHOW_RESULT( close, err );
659
660 err = close(fd2);
661 if( err < 0 ) SHOW_RESULT( close, err );
662
663 }
664 static void copydir(char *name, char *destdir)
665 {
666 int err;
667 DIR *dirp;
668
669 dirp = opendir(destdir);
670 if (dirp==NULL)
671 {
672 mkdir(destdir, 0777);
673 } else
674 {
675 err = closedir(dirp);
676 }
677
678 dirp = opendir(name);
679 if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
680
681 for (;;)
682 {
683 struct dirent *entry = readdir(dirp);
684
685 if (entry == NULL)
686 break;
687
688 if (strcmp(entry->d_name, ".") == 0)
689 continue;
690 if (strcmp(entry->d_name, "..") == 0)
691 continue;
692
693 bool isDir = false;
694 struct stat buf;
695 char fullPath[PATH_MAX];
696 strncpy(fullPath, name, PATH_MAX);
697 strcat(fullPath, "/");
698 strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
699
700 if (stat(fullPath, &buf) == -1)
701 {
702 diag_printf("unable to read status from %s", fullPath);
703 break;
704 }
705 isDir = S_ISDIR(buf.st_mode) != 0;
706
707 if (isDir)
708 continue;
709
710 // diag_printf("<INFO>: entry %14s",entry->d_name);
711 char fullname[PATH_MAX];
712 char fullname2[PATH_MAX];
713
714 strcpy(fullname, name);
715 strcat(fullname, "/");
716 strcat(fullname, entry->d_name);
717
718 strcpy(fullname2, destdir);
719 strcat(fullname2, "/");
720 strcat(fullname2, entry->d_name);
721 // diag_printf("from %s to %s\n", fullname, fullname2);
722 copyfile(fullname, fullname2);
723
724 // diag_printf("\n");
725 }
726
727 err = closedir(dirp);
728 if( err < 0 ) SHOW_RESULT( stat, err );
729 }
730
731 #if 0
732 MTAB_ENTRY( romfs_mte1,
733 "/rom",
734 "romfs",
735 "",
736 (CYG_ADDRWORD) &filedata[0] );
737 #endif
738
739 void openocd_sleep_prelude()
740 {
741 cyg_mutex_unlock(&httpstate.jim_lock);
742 }
743
744 void openocd_sleep_postlude()
745 {
746 cyg_mutex_lock(&httpstate.jim_lock);
747 }
748
749
750 void format(void)
751 {
752 diag_printf("Formatting JFFS2...\n");
753
754 cyg_io_handle_t handle;
755
756 Cyg_ErrNo err;
757 err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
758 if (err != ENOERR)
759 {
760 diag_printf("Flash Error cyg_io_lookup: %d\n", err);
761 reboot();
762 }
763
764
765 cyg_uint32 len;
766 cyg_io_flash_getconfig_devsize_t ds;
767 len = sizeof (ds);
768 err = cyg_io_get_config(handle,
769 CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
770 if (err != ENOERR)
771 {
772 diag_printf("Flash error cyg_io_get_config %d\n", err);
773 reboot();
774 }
775
776 cyg_io_flash_getconfig_erase_t e;
777 void *err_addr;
778 len = sizeof (e);
779
780 e.offset = 0;
781 e.len = ds.dev_size;
782 e.err_address = &err_addr;
783
784 diag_printf("Formatting 0x%08x bytes\n", ds.dev_size);
785 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE,
786 &e, &len);
787 if (err != ENOERR)
788 {
789 diag_printf("Flash erase error %d offset 0x%p\n", err, err_addr);
790 reboot();
791 }
792
793 diag_printf("Flash formatted successfully\n");
794
795 reboot();
796 }
797
798
799
800 static int
801 zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp,
802 int argc,
803 Jim_Obj * const *argv)
804 {
805 if (argc != 1)
806 {
807 return JIM_ERR;
808 }
809
810 format();
811 for(;;);
812 }
813
814
815 static int
816 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
817 int argc,
818 Jim_Obj * const *argv)
819 {
820 int del;
821 if (argc != 2)
822 {
823 Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
824 return JIM_ERR;
825 }
826
827 del = 0;
828 if (unlink(Jim_GetString(argv[1], NULL)) == 0)
829 del = 1;
830 if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
831 del = 1;
832
833 return del ? JIM_OK : JIM_ERR;
834 }
835
836 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
837 Jim_Obj * const *argv)
838 {
839 cyg_handle_t thread = 0;
840 cyg_uint16 id = 0;
841 Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
842
843 /* Loop over the threads, and generate a table row for
844 * each.
845 */
846 while (cyg_thread_get_next(&thread, &id))
847 {
848 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
849
850 cyg_thread_info info;
851 char *state_string;
852
853 cyg_thread_get_info(thread, id, &info);
854
855 if (info.name == NULL)
856 info.name = "<no name>";
857
858 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
859 info.name, strlen(info.name)));
860
861 /* Translate the state into a string.
862 */
863 if (info.state == 0)
864 state_string = "RUN";
865 else if (info.state & 0x04)
866 state_string = "SUSP";
867 else
868 switch (info.state & 0x1b)
869 {
870 case 0x01:
871 state_string = "SLEEP";
872 break;
873 case 0x02:
874 state_string = "CNTSLEEP";
875 break;
876 case 0x08:
877 state_string = "CREATE";
878 break;
879 case 0x10:
880 state_string = "EXIT";
881 break;
882 default:
883 state_string = "????";
884 break;
885 }
886
887 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
888 state_string, strlen(state_string)));
889
890 Jim_ListAppendElement (interp, threadObj, Jim_NewIntObj(interp, id));
891 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.set_pri));
892 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.cur_pri));
893
894 Jim_ListAppendElement(interp, threads, threadObj);
895 }
896 Jim_SetResult( interp, threads);
897
898 return JIM_OK;
899 }
900
901
902 static int
903 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
904 int argc,
905 Jim_Obj * const *argv)
906 {
907 if (argc != 2)
908 {
909 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
910 return JIM_ERR;
911 }
912
913 char *name = (char*) Jim_GetString(argv[1], NULL);
914
915 DIR *dirp = NULL;
916 dirp = opendir(name);
917 if (dirp == NULL)
918 {
919 return JIM_ERR;
920 }
921 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
922
923 for (;;)
924 {
925 struct dirent *entry = NULL;
926 entry = readdir(dirp);
927 if (entry == NULL)
928 break;
929
930 if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
931 continue;
932
933 Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
934 }
935 closedir(dirp);
936
937 Jim_SetResult(interp, objPtr);
938
939 return JIM_OK;
940 }
941
942
943 static int
944 zylinjtag_Jim_Command_getmem(Jim_Interp *interp,
945 int argc,
946 Jim_Obj * const *argv)
947 {
948 if (argc != 3)
949 {
950 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
951 return JIM_ERR;
952 }
953
954 long address;
955 long length;
956 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
957 return JIM_ERR;
958 if (Jim_GetLong(interp, argv[2], &length) != JIM_OK)
959 return JIM_ERR;
960
961 if (length < 0 && length > (4096 * 1024))
962 {
963 Jim_WrongNumArgs(interp, 1, argv, "getmem ?dir?");
964 return JIM_ERR;
965 }
966
967 void *mem = malloc(length);
968 if (mem == NULL)
969 return JIM_ERR;
970
971 target_t *target = get_current_target(cmd_ctx);
972
973 int retval;
974 int size = 1;
975 int count = length;
976 if ((address % 4 == 0) && (count % 4 == 0))
977 {
978 size = 4;
979 count /= 4;
980 }
981
982 if ((retval = target->type->read_memory(target, address, size, count, mem)) != ERROR_OK)
983 {
984 free(mem);
985 return JIM_ERR;
986 }
987
988 Jim_Obj *objPtr = Jim_NewStringObj(interp, mem, length);
989 Jim_SetResult(interp, objPtr);
990
991 free(mem);
992
993 return JIM_OK;
994 }
995
996 static int
997 zylinjtag_Jim_Command_peek(Jim_Interp *interp,
998 int argc,
999 Jim_Obj * const *argv)
1000 {
1001 if (argc != 2)
1002 {
1003 Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
1004 return JIM_ERR;
1005 }
1006
1007 long address;
1008 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1009 return JIM_ERR;
1010
1011 int value = *((volatile int *) address);
1012
1013 Jim_SetResult(interp, Jim_NewIntObj(interp, value));
1014
1015 return JIM_OK;
1016 }
1017
1018 static int
1019 zylinjtag_Jim_Command_poke(Jim_Interp *interp,
1020 int argc,
1021 Jim_Obj * const *argv)
1022 {
1023 if (argc != 3)
1024 {
1025 Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
1026 return JIM_ERR;
1027 }
1028
1029 long address;
1030 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1031 return JIM_ERR;
1032 long value;
1033 if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
1034 return JIM_ERR;
1035
1036 *((volatile int *) address) = value;
1037
1038 return JIM_OK;
1039 }
1040
1041
1042
1043 static int
1044 zylinjtag_Jim_Command_flash(Jim_Interp *interp,
1045 int argc,
1046 Jim_Obj * const *argv)
1047 {
1048 int retval;
1049 u32 base = 0;
1050 flash_bank_t *t = get_flash_bank_by_num_noprobe(0);
1051 if (t != NULL)
1052 {
1053 base = t->base;
1054 retval = JIM_OK;
1055 } else
1056 {
1057 retval = JIM_ERR;
1058 }
1059
1060 if (retval == JIM_OK)
1061 {
1062 Jim_SetResult(interp, Jim_NewIntObj(interp, base));
1063 }
1064
1065 return retval;
1066 }
1067
1068
1069
1070
1071
1072 static int
1073 zylinjtag_Jim_Command_log(Jim_Interp *interp,
1074 int argc,
1075 Jim_Obj * const *argv)
1076 {
1077 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1078
1079 if (logCount >= logSize)
1080 {
1081 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer+logCount%logSize, logSize-logCount%logSize);
1082 }
1083 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
1084
1085 Jim_SetResult(interp, tclOutput);
1086 return JIM_OK;
1087 }
1088
1089 static int
1090 zylinjtag_Jim_Command_reboot(Jim_Interp *interp,
1091 int argc,
1092 Jim_Obj * const *argv)
1093 {
1094 reboot();
1095 return JIM_OK;
1096 }
1097
1098 static int
1099 zylinjtag_Jim_Command_mac(Jim_Interp *interp,
1100 int argc,
1101 Jim_Obj * const *argv)
1102 {
1103
1104 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1105
1106 Jim_AppendString(httpstate.jim_interp, tclOutput, hwaddr, strlen(hwaddr));
1107
1108 Jim_SetResult(interp, tclOutput);
1109
1110 return JIM_OK;
1111 }
1112
1113 static int
1114 zylinjtag_Jim_Command_ip(Jim_Interp *interp,
1115 int argc,
1116 Jim_Obj * const *argv)
1117 {
1118 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1119
1120 struct ifaddrs *ifa = NULL, *ifp = NULL;
1121
1122 if (getifaddrs(&ifp) < 0)
1123 {
1124 return JIM_ERR;
1125 }
1126
1127 for (ifa = ifp; ifa; ifa = ifa->ifa_next)
1128 {
1129 char ip[200];
1130 socklen_t salen;
1131
1132 if (ifa->ifa_addr->sa_family == AF_INET)
1133 salen = sizeof(struct sockaddr_in);
1134 else if (ifa->ifa_addr->sa_family == AF_INET6)
1135 salen = sizeof(struct sockaddr_in6);
1136 else
1137 continue;
1138
1139 if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
1140 NI_NUMERICHOST) < 0)
1141 {
1142 continue;
1143 }
1144
1145 Jim_AppendString(httpstate.jim_interp, tclOutput, ip, strlen(ip));
1146 break;
1147
1148 }
1149
1150 freeifaddrs(ifp);
1151
1152 Jim_SetResult(interp, tclOutput);
1153
1154 return JIM_OK;
1155 }
1156
1157 extern Jim_Interp *interp;
1158
1159
1160 static void zylinjtag_startNetwork()
1161 {
1162 // Bring TCP/IP up immediately before we're ready to accept commands.
1163 //
1164 // That is as soon as a PING responds, we're accepting telnet sessions.
1165 #if defined(CYGPKG_NET_FREEBSD_STACK)
1166 phi_init_all_network_interfaces();
1167 #else
1168 lwip_init();
1169 #endif
1170 if (!eth0_up)
1171 {
1172 diag_printf("Network not up and running\n");
1173 exit(-1);
1174 }
1175 #if defined(CYGPKG_NET_FREEBSD_STACK)
1176 /*start TFTP*/
1177 tftpd_start(69, &fileops);
1178 #endif
1179
1180 cyg_httpd_init_tcl_interpreter();
1181
1182 interp = httpstate.jim_interp;
1183
1184 Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log, NULL, NULL);
1185 Jim_CreateCommand(httpstate.jim_interp, "reboot", zylinjtag_Jim_Command_reboot, NULL, NULL);
1186 Jim_CreateCommand(httpstate.jim_interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
1187 Jim_CreateCommand(httpstate.jim_interp, "zy1000_flash", zylinjtag_Jim_Command_flash, NULL, NULL);
1188 Jim_CreateCommand(httpstate.jim_interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
1189 Jim_CreateCommand(httpstate.jim_interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
1190 Jim_CreateCommand(httpstate.jim_interp, "threads", zylinjtag_Jim_Command_threads, NULL, NULL);
1191 Jim_CreateCommand(httpstate.jim_interp, "getmem", zylinjtag_Jim_Command_getmem, NULL, NULL);
1192 Jim_CreateCommand(httpstate.jim_interp, "mac", zylinjtag_Jim_Command_mac, NULL, NULL);
1193 Jim_CreateCommand(httpstate.jim_interp, "ip", zylinjtag_Jim_Command_ip, NULL, NULL);
1194 Jim_CreateCommand(httpstate.jim_interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
1195 Jim_CreateCommand(httpstate.jim_interp, "format_jffs2", zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
1196
1197 cyg_httpd_start();
1198
1199 webRunning = true;
1200
1201 diag_printf("Web server running\n");
1202
1203 int s;
1204 struct ifreq ifr;
1205 s = socket(AF_INET, SOCK_DGRAM, 0);
1206 if (s >= 0)
1207 {
1208 strcpy(ifr.ifr_name, "eth0");
1209 int res;
1210 res = ioctl(s, SIOCGIFHWADDR, &ifr);
1211 close(s);
1212
1213 if (res < 0)
1214 {
1215 diag_printf("Can't obtain MAC address\n");
1216 reboot();
1217 }
1218 }
1219
1220 sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
1221 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
1222 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
1223 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
1224 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
1225 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
1226 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
1227
1228
1229 discover_message=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
1230
1231 discover_launch();
1232 }
1233
1234
1235
1236
1237
1238 static void
1239 print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_t info)
1240 {
1241 writeLog = false;
1242 serialLog = true;
1243 char *infoStr = "unknown";
1244 switch (exception)
1245 {
1246 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1247 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
1248 infoStr = "undefined instruction";
1249 break;
1250 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
1251 infoStr = "software interrupt";
1252 break;
1253 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
1254 infoStr = "abort prefetch";
1255 break;
1256 case CYGNUM_HAL_VECTOR_ABORT_DATA:
1257 infoStr = "abort data";
1258 break;
1259 #endif
1260 default:
1261 break;
1262 }
1263
1264 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1265
1266 diag_printf("Dumping log\n---\n");
1267 if (logCount >= logSize)
1268 {
1269 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
1270 }
1271 diag_write(logBuffer, writePtr);
1272
1273 diag_printf("---\nLogdump complete.\n");
1274 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1275 diag_printf("\n---\nRebooting\n");
1276 HAL_PLATFORM_RESET();
1277
1278 }
1279
1280 static void setHandler(cyg_code_t exception)
1281 {
1282 cyg_exception_handler_t *old_handler;
1283 cyg_addrword_t old_data;
1284
1285 cyg_exception_set_handler(exception,
1286 print_exception_handler,
1287 0,
1288 &old_handler,
1289 &old_data);
1290 }
1291
1292 static cyg_thread zylinjtag_uart_thread_object;
1293 static cyg_handle_t zylinjtag_uart_thread_handle;
1294 static char uart_stack[4096];
1295
1296 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1297 static char backwardBuffer[1024];
1298
1299
1300 void setNoDelay(int session, int flag)
1301 {
1302 #if 1
1303 // This decreases latency dramatically for e.g. GDB load which
1304 // does not have a sliding window protocol
1305 //
1306 // Can cause *lots* of TCP/IP packets to be sent and it would have
1307 // to be enabled/disabled on the fly to avoid the CPU being
1308 // overloaded...
1309 setsockopt(session, /* socket affected */
1310 IPPROTO_TCP, /* set option at TCP level */
1311 TCP_NODELAY, /* name of option */
1312 (char *) &flag, /* the cast is historical
1313 cruft */
1314 sizeof(int)); /* length of option value */
1315 #endif
1316 }
1317
1318 struct
1319 {
1320 int req;
1321 int actual;
1322 int req2;
1323 int actual2;
1324 } tcpipSent[512 * 1024];
1325 int cur;
1326
1327 static void
1328 zylinjtag_uart(cyg_addrword_t data)
1329 {
1330 int so_reuseaddr_option = 1;
1331
1332 int fd;
1333 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1334 {
1335 LOG_ERROR("error creating socket: %s", strerror(errno));
1336 exit(-1);
1337 }
1338
1339 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
1340
1341 struct sockaddr_in sin;
1342 unsigned int address_size;
1343 address_size = sizeof(sin);
1344 memset(&sin, 0, sizeof(sin));
1345 sin.sin_family = AF_INET;
1346 sin.sin_addr.s_addr = INADDR_ANY;
1347 sin.sin_port = htons(5555);
1348
1349 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
1350 {
1351 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
1352 exit(-1);
1353 }
1354
1355 if (listen(fd, 1) == -1)
1356 {
1357 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
1358 exit(-1);
1359 }
1360 // socket_nonblock(fd);
1361
1362
1363 for (;;)
1364 {
1365 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
1366 if (session < 0)
1367 {
1368 continue;
1369 }
1370
1371 setNoDelay(session, 1);
1372 int oldopts = fcntl(session, F_GETFL, 0);
1373 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
1374
1375 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
1376 if (serHandle < 0)
1377 {
1378 close(session);
1379 continue;
1380 }
1381
1382 #ifdef CYGPKG_PROFILE_GPROF
1383 start_profile();
1384 #endif
1385 int actual = 0;
1386 int actual2 = 0;
1387 int pos, pos2;
1388 pos = 0;
1389 pos2 = 0;
1390 cur = 0;
1391 for (;;)
1392 {
1393 fd_set write_fds;
1394 fd_set read_fds;
1395 FD_ZERO(&write_fds);
1396 FD_ZERO(&read_fds);
1397 int fd_max = -1;
1398 FD_SET(session, &read_fds);
1399 fd_max = session;
1400 FD_SET(serHandle, &read_fds);
1401 if (serHandle > fd_max)
1402 {
1403 fd_max = serHandle;
1404 }
1405 /* Wait... */
1406
1407 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1408 if ((actual == 0) && (actual2 == 0))
1409 {
1410 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
1411 if (retval <= 0)
1412 {
1413 break;
1414 }
1415 }
1416
1417 if (actual2 <= 0)
1418 {
1419 memset(backwardBuffer, 's', sizeof(backwardBuffer));
1420 actual2=read(serHandle, backwardBuffer, sizeof(backwardBuffer));
1421 if (actual2 < 0)
1422 {
1423 if (errno != EAGAIN)
1424 {
1425 goto closeSession;
1426 }
1427 actual2 = 0;
1428 }
1429 pos2 = 0;
1430 }
1431
1432 int x = actual2;
1433 int y = 0;
1434 if (actual2 > 0)
1435 {
1436 int written = write(session, backwardBuffer + pos2, actual2);
1437 if (written <= 0)
1438 goto closeSession;
1439 actual2 -= written;
1440 pos2 += written;
1441 y = written;
1442 }
1443
1444 if (FD_ISSET(session, &read_fds)&&(sizeof(forwardBuffer)>actual))
1445 {
1446 // NB! Here it is important that we empty the TCP/IP read buffer
1447 // to make transmission tick right
1448 memmove(forwardBuffer, forwardBuffer + pos, actual);
1449 pos = 0;
1450 int t;
1451 // this will block if there is no data at all
1452 t=read_socket(session, forwardBuffer+actual, sizeof(forwardBuffer)-actual);
1453 if (t <= 0)
1454 {
1455 goto closeSession;
1456 }
1457 actual += t;
1458 }
1459
1460 int x2 = actual;
1461 int y2 = 0;
1462 if (actual > 0)
1463 {
1464 /* Do not put things into the serial buffer if it has something to send
1465 * as that can cause a single byte to be sent at the time.
1466 *
1467 *
1468 */
1469 int written = write(serHandle, forwardBuffer + pos, actual);
1470 if (written < 0)
1471 {
1472 if (errno != EAGAIN)
1473 {
1474 goto closeSession;
1475 }
1476 // The serial buffer is full
1477 written = 0;
1478 } else
1479 {
1480 actual -= written;
1481 pos += written;
1482 }
1483 y2 = written;
1484 }
1485 if (cur < 1024)
1486 {
1487 tcpipSent[cur].req = x;
1488 tcpipSent[cur].actual = y;
1489 tcpipSent[cur].req2 = x2;
1490 tcpipSent[cur].actual2 = y2;
1491 cur++;
1492 }
1493
1494 }
1495 closeSession:
1496 close(session);
1497 close(serHandle);
1498
1499 int i;
1500 for (i = 0; i < 1024; i++)
1501 {
1502 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual, tcpipSent[i].req2, tcpipSent[i].actual2);
1503
1504 }
1505 }
1506 close(fd);
1507
1508 }
1509
1510 void startUart(void)
1511 {
1512 cyg_thread_create(1,
1513 zylinjtag_uart,
1514 (cyg_addrword_t)0,
1515 "uart thread",
1516 (void *)uart_stack,
1517 sizeof(uart_stack),
1518 &zylinjtag_uart_thread_handle,
1519 &zylinjtag_uart_thread_object);
1520 cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
1521 cyg_thread_resume(zylinjtag_uart_thread_handle);
1522 }
1523
1524
1525
1526 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1527 {
1528 static int current_baud = 38400;
1529 if (argc == 0)
1530 {
1531 command_print(cmd_ctx, "%d", current_baud);
1532 return ERROR_OK;
1533 } else if (argc != 1)
1534 {
1535 return ERROR_INVALID_ARGUMENTS;
1536 }
1537
1538 current_baud = atol(args[0]);
1539
1540 int baud;
1541 switch (current_baud)
1542 {
1543 case 9600:
1544 baud = CYGNUM_SERIAL_BAUD_9600;
1545 break;
1546 case 19200:
1547 baud = CYGNUM_SERIAL_BAUD_19200;
1548 break;
1549 case 38400:
1550 baud = CYGNUM_SERIAL_BAUD_38400;
1551 break;
1552 case 57600:
1553 baud = CYGNUM_SERIAL_BAUD_57600;
1554 break;
1555 case 115200:
1556 baud = CYGNUM_SERIAL_BAUD_115200;
1557 break;
1558 case 230400:
1559 baud = CYGNUM_SERIAL_BAUD_230400;
1560 break;
1561 default:
1562 command_print(cmd_ctx, "unsupported baudrate");
1563 return ERROR_INVALID_ARGUMENTS;
1564 }
1565
1566 cyg_serial_info_t buf;
1567 cyg_uint32 len = 1;
1568 //get existing serial configuration
1569 len = sizeof(cyg_serial_info_t);
1570 int err;
1571 cyg_io_handle_t serial_handle;
1572
1573 err = cyg_io_lookup("/dev/ser0", &serial_handle);
1574 if (err != ENOERR)
1575 {
1576 LOG_ERROR("/dev/ser0 not found\n");
1577 return ERROR_FAIL;
1578 }
1579
1580
1581 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
1582 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf, &len);
1583 if (err != ENOERR)
1584 {
1585 command_print(cmd_ctx, "Failed to get serial port settings %d", err);
1586 return ERROR_OK;
1587 }
1588 buf.baud = baud;
1589
1590 err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf, &len);
1591 if (err != ENOERR)
1592 {
1593 command_print(cmd_ctx, "Failed to set serial port settings %d", err);
1594 return ERROR_OK;
1595 }
1596
1597 return ERROR_OK;
1598 }
1599
1600 bool logAllToSerial = false;
1601
1602 /* boolean parameter stored on config */
1603 bool boolParam(char *var)
1604 {
1605 bool result = false;
1606 char *name = alloc_printf(ZYLIN_CONFIG_DIR "/%s", var);
1607 if (name == NULL)
1608 return result;
1609
1610 void *data;
1611 int len;
1612 if (loadFile(name, &data, &len) == ERROR_OK)
1613 {
1614 if (len > 1)
1615 len = 1;
1616 result = strncmp((char *) data, "1", len) == 0;
1617 free(data);
1618 }
1619 free(name);
1620 return result;
1621 }
1622
1623 command_context_t *setup_command_handler();
1624
1625 int add_default_dirs(void)
1626 {
1627 add_script_search_dir(ZYLIN_CONFIG_DIR);
1628 add_script_search_dir("/rom/lib/openocd");
1629 add_script_search_dir("/rom");
1630 return ERROR_OK;
1631 }
1632
1633 static cyg_uint8 *ramblockdevice;
1634 static const int ramblockdevice_size=4096*1024;
1635 int main(int argc, char *argv[])
1636 {
1637 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1638 * need to allocate towards the end of the heap. */
1639
1640 ramblockdevice=(cyg_uint8 *)malloc(ramblockdevice_size);
1641 memset(ramblockdevice, 0xff, ramblockdevice_size);
1642
1643
1644
1645 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1646 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
1647 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
1648 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
1649 #endif
1650
1651 int err;
1652
1653 setPower(true); // on by default
1654
1655 atexit(keep_webserver);
1656
1657 err = mount("", "/ram", "ramfs");
1658 if (err < 0)
1659 {
1660 diag_printf("unable to mount ramfs\n");
1661 }
1662 chdir("/ram");
1663
1664 char address[16];
1665 sprintf(address, "%p", &filedata[0]);
1666 err = mount(address, "/rom", "romfs");
1667 if (err < 0)
1668 {
1669 diag_printf("unable to mount /rom\n");
1670 }
1671
1672 err = mount("", "/log", "logfs");
1673 if (err < 0)
1674 {
1675 diag_printf("unable to mount logfs\n");
1676 }
1677
1678 err = mount("", "/tftp", "tftpfs");
1679 if (err < 0)
1680 {
1681 diag_printf("unable to mount logfs\n");
1682 }
1683
1684 log = fopen("/log/log", "w");
1685 if (log == NULL)
1686 {
1687 diag_printf("Could not open log file /ram/log\n");
1688 exit(-1);
1689 }
1690
1691 diag_init_putc(_zylinjtag_diag_write_char);
1692
1693 // We want this in the log.
1694 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1695 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);
1696
1697 copydir("/rom", "/ram/cgi");
1698
1699 err = mount("/dev/flash1", "/config", "jffs2");
1700 if (err < 0)
1701 {
1702 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1703 err = mount("", "/config", "ramfs");
1704 if (err<0)
1705 {
1706 diag_printf("unable to mount /config as ramdisk.\n");
1707 reboot();
1708 }
1709 } else
1710 {
1711 /* are we using a ram disk instead of a flash disk? This is used
1712 * for ZY1000 live demo...
1713 *
1714 * copy over flash disk to ram block device
1715 */
1716 if (boolParam("ramdisk"))
1717 {
1718 diag_printf("Unmounting /config from flash and using ram instead\n");
1719 err=umount("/config");
1720 if (err < 0)
1721 {
1722 diag_printf("unable to unmount jffs\n");
1723 reboot();
1724 }
1725
1726 err = mount("/dev/flash1", "/config2", "jffs2");
1727 if (err < 0)
1728 {
1729 diag_printf("unable to mount jffs\n");
1730 reboot();
1731 }
1732
1733 err = mount("", "/config", "ramfs");
1734 if (err < 0)
1735 {
1736 diag_printf("unable to mount ram block device\n");
1737 reboot();
1738 }
1739
1740 // copydir("/config2", "/config");
1741 copyfile("/config2/ip", "/config/ip");
1742 copydir("/config2/settings", "/config/settings");
1743
1744 umount("/config2");
1745 } else
1746 {
1747 /* we're not going to use a ram block disk */
1748 free(ramblockdevice);
1749 }
1750 }
1751
1752
1753 mkdir(ZYLIN_CONFIG_DIR, 0777);
1754 mkdir(ZYLIN_CONFIG_DIR "/target", 0777);
1755 mkdir(ZYLIN_CONFIG_DIR "/event", 0777);
1756
1757 logAllToSerial = boolParam("logserial");
1758
1759 // We need the network & web server in case there is something wrong with
1760 // the config files that invoke exit()
1761 zylinjtag_startNetwork();
1762
1763 /* we're going to access the jim interpreter from here on... */
1764 openocd_sleep_postlude();
1765 startUart();
1766
1767 add_default_dirs();
1768
1769 /* initialize commandline interface */
1770 command_context_t *cmd_ctx;
1771 cmd_ctx = setup_command_handler();
1772 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1773 command_context_mode(cmd_ctx, COMMAND_CONFIG);
1774
1775
1776 register_command(cmd_ctx, NULL, "zy1000_version", handle_zy1000_version_command,
1777 COMMAND_EXEC, "show zy1000 version numbers");
1778
1779 register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
1780 "remove file");
1781
1782 register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
1783 "display file content");
1784
1785 register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
1786 "truncate a file to 0 size");
1787
1788 register_command(cmd_ctx, NULL, "append_file", handle_append_command,
1789 COMMAND_ANY, "append a variable number of strings to a file");
1790
1791 register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,
1792 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1793
1794 register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
1795 COMMAND_ANY, "display available ram memory");
1796
1797 register_command(cmd_ctx, NULL, "cp", handle_cp_command,
1798 COMMAND_ANY, "copy a file <from> <to>");
1799
1800 #ifdef CYGPKG_PROFILE_GPROF
1801 register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1802 COMMAND_ANY, NULL);
1803 #endif
1804 register_command(cmd_ctx, NULL, "uart", handle_uart_command,
1805 COMMAND_ANY, "uart <baud> - forward uart on port 5555");
1806
1807
1808 int errVal;
1809 errVal = log_init(cmd_ctx);
1810 if (errVal != ERROR_OK)
1811 {
1812 diag_printf("log_init() failed %d\n", errVal);
1813 exit(-1);
1814 }
1815
1816 set_log_output(cmd_ctx, log);
1817
1818 LOG_DEBUG("log init complete");
1819
1820 // diag_printf("Executing config files\n");
1821
1822 if (logAllToSerial)
1823 {
1824 diag_printf(ZYLIN_CONFIG_DIR "/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1825 command_run_line(cmd_ctx, "debug_level 3");
1826 }
1827
1828 zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");
1829
1830 // FIX!!! Yuk!
1831 // diag_printf() is really invoked from many more places than we trust it
1832 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1833 //
1834 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1835 // fingers that it doesn't cause any crashes.
1836 diag_printf("Init complete, GDB & telnet servers launched.\n");
1837 command_set_output_handler(cmd_ctx, zy1000_configuration_output_handler_log, NULL);
1838 if (!logAllToSerial)
1839 {
1840 serialLog = false;
1841 }
1842
1843 /* handle network connections */
1844 server_loop(cmd_ctx);
1845 openocd_sleep_prelude();
1846
1847 /* shut server down */
1848 server_quit();
1849
1850 /* free commandline interface */
1851 command_done(cmd_ctx);
1852 umount("/config");
1853
1854 exit(0);
1855 for (;;);
1856 }
1857
1858
1859
1860 cyg_int32
1861 cyg_httpd_exec_cgi_tcl(char *file_name);
1862 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1863 {
1864 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1865 return 0;
1866 }
1867
1868 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1869
1870 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1871 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1872
1873 #include <pkgconf/system.h>
1874 #include <pkgconf/hal.h>
1875 #include <pkgconf/kernel.h>
1876 #include <pkgconf/io_fileio.h>
1877 #include <pkgconf/fs_rom.h>
1878
1879 #include <cyg/kernel/ktypes.h> // base kernel types
1880 #include <cyg/infra/cyg_trac.h> // tracing macros
1881 #include <cyg/infra/cyg_ass.h> // assertion macros
1882 #include <unistd.h>
1883 #include <sys/types.h>
1884 #include <fcntl.h>
1885 #include <sys/stat.h>
1886 #include <errno.h>
1887 #include <dirent.h>
1888
1889 #include <stdarg.h>
1890 #include <stdio.h>
1891 #include <stdlib.h>
1892 #include <string.h>
1893
1894 #include <cyg/fileio/fileio.h>
1895
1896 #include <cyg/kernel/kapi.h>
1897 #include <cyg/infra/diag.h>
1898
1899 //==========================================================================
1900 // Eventually we want to eXecute In Place from the ROM in a protected
1901 // environment, so we'll need executables to be aligned to a boundary
1902 // suitable for MMU protection. A suitable boundary would be the 4k
1903 // boundary in all the CPU architectures I am currently aware of.
1904
1905 // Forward definitions
1906
1907 // Filesystem operations
1908 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1909 static int tftpfs_umount(cyg_mtab_entry *mte);
1910 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1911 int mode, cyg_file *fte);
1912 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1913 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1914
1915 // File operations
1916 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1917 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
1918 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
1919
1920 //==========================================================================
1921 // Filesystem table entries
1922
1923 // -------------------------------------------------------------------------
1924 // Fstab entry.
1925 // This defines the entry in the filesystem table.
1926 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1927 // we should never block in any filesystem operations.
1928 #if 1
1929 FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,
1930 CYG_SYNCMODE_NONE,
1931 tftpfs_mount,
1932 tftpfs_umount,
1933 tftpfs_open,
1934 (cyg_fsop_unlink *)cyg_fileio_erofs,
1935 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1936 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1937 (cyg_fsop_rename *)cyg_fileio_erofs,
1938 (cyg_fsop_link *)cyg_fileio_erofs,
1939 (cyg_fsop_opendir *)cyg_fileio_erofs,
1940 (cyg_fsop_chdir *)cyg_fileio_erofs,
1941 (cyg_fsop_stat *)cyg_fileio_erofs,
1942 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1943 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1944 #endif
1945
1946 // -------------------------------------------------------------------------
1947 // mtab entry.
1948 // This defines a single ROMFS loaded into ROM at the configured address
1949 //
1950 // MTAB_ENTRY( rom_mte, // structure name
1951 // "/rom", // mount point
1952 // "romfs", // FIlesystem type
1953 // "", // hardware device
1954 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
1955 // );
1956
1957
1958 // -------------------------------------------------------------------------
1959 // File operations.
1960 // This set of file operations are used for normal open files.
1961
1962 static cyg_fileops tftpfs_fileops =
1963 {
1964 tftpfs_fo_read,
1965 tftpfs_fo_write,
1966 tftpfs_fo_lseek,
1967 (cyg_fileop_ioctl *)cyg_fileio_erofs,
1968 cyg_fileio_seltrue,
1969 tftpfs_fo_fsync,
1970 tftpfs_fo_close,
1971 (cyg_fileop_fstat *) cyg_fileio_erofs,
1972 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1973 (cyg_fileop_setinfo *)cyg_fileio_erofs,
1974 };
1975
1976 // -------------------------------------------------------------------------
1977 // tftpfs_mount()
1978 // Process a mount request. This mainly finds root for the
1979 // filesystem.
1980
1981 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1982 {
1983 return ENOERR;
1984 }
1985
1986 static int tftpfs_umount(cyg_mtab_entry *mte)
1987 {
1988 return ENOERR;
1989 }
1990
1991 struct Tftp
1992 {
1993 int write;
1994 int readFile;
1995 cyg_uint8 *mem;
1996 int actual;
1997 char *server;
1998 char *file;
1999 };
2000
2001 static void freeTftp(struct Tftp *t)
2002 {
2003 if (t == NULL)
2004 return;
2005 if (t->mem)
2006 free(t->mem);
2007 if (t->server)
2008 free(t->server);
2009 if (t->file)
2010 free(t->file);
2011 free(t);
2012 }
2013
2014 static const int tftpMaxSize = 8192 * 1024;
2015 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2016 int mode, cyg_file *file)
2017 {
2018 struct Tftp *tftp;
2019 tftp = malloc(sizeof(struct Tftp));
2020 if (tftp == NULL)
2021 return EMFILE;
2022 memset(tftp, 0, sizeof(struct Tftp));
2023
2024 file->f_flag |= mode & CYG_FILE_MODE_MASK;
2025 file->f_type = CYG_FILE_TYPE_FILE;
2026 file->f_ops = &tftpfs_fileops;
2027 file->f_offset = 0;
2028 file->f_data = 0;
2029 file->f_xops = 0;
2030
2031 tftp->mem = malloc(tftpMaxSize);
2032 if (tftp->mem == NULL)
2033 {
2034 freeTftp(tftp);
2035 return EMFILE;
2036 }
2037
2038 char *server = strchr(name, '/');
2039 if (server == NULL)
2040 {
2041 freeTftp(tftp);
2042 return EMFILE;
2043 }
2044
2045 tftp->server = malloc(server - name + 1);
2046 if (tftp->server == NULL)
2047 {
2048 freeTftp(tftp);
2049 return EMFILE;
2050 }
2051 strncpy(tftp->server, name, server - name);
2052 tftp->server[server - name] = 0;
2053
2054 tftp->file = strdup(server + 1);
2055 if (tftp->file == NULL)
2056 {
2057 freeTftp(tftp);
2058 return EMFILE;
2059 }
2060
2061 file->f_data = (CYG_ADDRWORD) tftp;
2062
2063 return ENOERR;
2064 }
2065
2066 static int fetchTftp(struct Tftp *tftp)
2067 {
2068 if (!tftp->readFile)
2069 {
2070 int err;
2071 tftp->actual = tftp_client_get( tftp->file, tftp->server, 0, tftp->mem, tftpMaxSize, TFTP_OCTET, &err);
2072
2073 if (tftp->actual < 0)
2074 {
2075 return EMFILE;
2076 }
2077 tftp->readFile = 1;
2078 }
2079 return ENOERR;
2080 }
2081
2082 // -------------------------------------------------------------------------
2083 // tftpfs_fo_write()
2084 // Read data from file.
2085
2086 static int
2087 tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2088 {
2089 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2090
2091 if (fetchTftp(tftp) != ENOERR)
2092 return EMFILE;
2093
2094 int i;
2095 off_t pos = fp->f_offset;
2096 int resid = 0;
2097 for (i = 0; i < uio->uio_iovcnt; i++)
2098 {
2099 cyg_iovec *iov = &uio->uio_iov[i];
2100 char *buf = (char *) iov->iov_base;
2101 off_t len = iov->iov_len;
2102
2103 if (len + pos > tftp->actual)
2104 {
2105 len = tftp->actual - pos;
2106 }
2107 resid += iov->iov_len - len;
2108
2109 memcpy(buf, tftp->mem + pos, len);
2110 pos += len;
2111
2112 }
2113 uio->uio_resid = resid;
2114 fp->f_offset = pos;
2115
2116 return ENOERR;
2117 }
2118
2119
2120 static int
2121 tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2122 {
2123 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2124
2125 int i;
2126 off_t pos = fp->f_offset;
2127 int resid = 0;
2128 for (i = 0; i < uio->uio_iovcnt; i++)
2129 {
2130 cyg_iovec *iov = &uio->uio_iov[i];
2131 char *buf = (char *) iov->iov_base;
2132 off_t len = iov->iov_len;
2133
2134 if (len + pos > tftpMaxSize)
2135 {
2136 len = tftpMaxSize - pos;
2137 }
2138 resid += iov->iov_len - len;
2139
2140 memcpy(tftp->mem + pos, buf, len);
2141 pos += len;
2142
2143 }
2144 uio->uio_resid = resid;
2145 fp->f_offset = pos;
2146
2147 tftp->write = 1;
2148
2149 return ENOERR;
2150 }
2151
2152 static int
2153 tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2154 {
2155 int error = ENOERR;
2156 return error;
2157 }
2158
2159 // -------------------------------------------------------------------------
2160 // romfs_fo_close()
2161 // Close a file. We just clear out the data pointer.
2162
2163 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
2164 {
2165 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2166 int error = ENOERR;
2167
2168 if (tftp->write)
2169 {
2170 tftp_client_put( tftp->file, tftp->server, 0, tftp->mem, fp->f_offset, TFTP_OCTET, &error);
2171 }
2172
2173 freeTftp(tftp);
2174 fp->f_data = 0;
2175 return error;
2176 }
2177
2178 // -------------------------------------------------------------------------
2179 // romfs_fo_lseek()
2180 // Seek to a new file position.
2181
2182 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
2183 {
2184 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2185 off_t pos = *apos;
2186
2187 if (fetchTftp(tftp) != ENOERR)
2188 return EMFILE;
2189
2190 switch (whence)
2191 {
2192 case SEEK_SET:
2193 // Pos is already where we want to be.
2194 break;
2195
2196 case SEEK_CUR:
2197 // Add pos to current offset.
2198 pos += fp->f_offset;
2199 break;
2200
2201 case SEEK_END:
2202 // Add pos to file size.
2203 pos += tftp->actual;
2204 break;
2205
2206 default:
2207 return EINVAL;
2208 }
2209
2210 // Check that pos is still within current file size, or at the
2211 // very end.
2212 if (pos < 0 || pos > tftp->actual)
2213 return EINVAL;
2214
2215 // All OK, set fp offset and return new position.
2216 *apos = fp->f_offset = pos;
2217
2218 return ENOERR;
2219 }
2220
2221 void usleep(int us)
2222 {
2223 if (us > 10000)
2224 cyg_thread_delay(us / 10000 + 1);
2225 else
2226 HAL_DELAY_US(us);
2227 }
2228
2229 // Chunked version.
2230 cyg_int32
2231 show_log_entry(CYG_HTTPD_STATE *phttpstate)
2232 {
2233 cyg_httpd_start_chunked("text");
2234 if (logCount >= logSize)
2235 {
2236 cyg_httpd_write_chunked(logBuffer+logCount%logSize, logSize-logCount%logSize);
2237 }
2238 cyg_httpd_write_chunked(logBuffer, writePtr);
2239 cyg_httpd_end_chunked();
2240 return -1;
2241 }
2242
2243 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
2244
2245 // Filesystem operations
2246 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
2247 static int logfs_umount(cyg_mtab_entry *mte);
2248 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2249 int mode, cyg_file *fte);
2250 static int
2251 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2252
2253 // File operations
2254 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2255 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
2256
2257 #include <cyg/io/devtab.h>
2258
2259 //==========================================================================
2260 // Filesystem table entries
2261
2262 // -------------------------------------------------------------------------
2263 // Fstab entry.
2264 // This defines the entry in the filesystem table.
2265 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2266 // we should never block in any filesystem operations.
2267 FSTAB_ENTRY( logfs_fste, "logfs", 0,
2268 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
2269 logfs_mount,
2270 logfs_umount,
2271 logfs_open,
2272 (cyg_fsop_unlink *)cyg_fileio_erofs,
2273 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2274 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2275 (cyg_fsop_rename *)cyg_fileio_erofs,
2276 (cyg_fsop_link *)cyg_fileio_erofs,
2277 (cyg_fsop_opendir *)cyg_fileio_erofs,
2278 (cyg_fsop_chdir *)cyg_fileio_erofs,
2279 (cyg_fsop_stat *)cyg_fileio_erofs,
2280 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2281 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2282
2283 // -------------------------------------------------------------------------
2284 // File operations.
2285 // This set of file operations are used for normal open files.
2286
2287 static cyg_fileops logfs_fileops =
2288 {
2289 (cyg_fileop_read *)cyg_fileio_erofs,
2290 (cyg_fileop_write *)logfs_fo_write,
2291 (cyg_fileop_lseek *) cyg_fileio_erofs,
2292 (cyg_fileop_ioctl *)cyg_fileio_erofs,
2293 cyg_fileio_seltrue,
2294 logfs_fo_fsync,
2295 logfs_fo_close,
2296 (cyg_fileop_fstat *)cyg_fileio_erofs,
2297 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2298 (cyg_fileop_setinfo *)cyg_fileio_erofs,
2299 };
2300
2301 // -------------------------------------------------------------------------
2302 // logfs_mount()
2303 // Process a mount request. This mainly finds root for the
2304 // filesystem.
2305
2306 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2307 {
2308 return ENOERR;
2309 }
2310
2311 static int logfs_umount(cyg_mtab_entry *mte)
2312 {
2313 return ENOERR;
2314 }
2315
2316 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2317 int mode, cyg_file *file)
2318 {
2319 file->f_flag |= mode & CYG_FILE_MODE_MASK;
2320 file->f_type = CYG_FILE_TYPE_FILE;
2321 file->f_ops = &logfs_fileops;
2322 file->f_offset = 0;
2323 file->f_data = 0;
2324 file->f_xops = 0;
2325 return ENOERR;
2326 }
2327
2328 // -------------------------------------------------------------------------
2329 // logfs_fo_write()
2330 // Write data to file.
2331
2332 static int
2333 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2334 {
2335 int i;
2336 for (i = 0; i < uio->uio_iovcnt; i++)
2337 {
2338 cyg_iovec *iov = &uio->uio_iov[i];
2339 char *buf = (char *) iov->iov_base;
2340 off_t len = iov->iov_len;
2341
2342 diag_write(buf, len);
2343 }
2344 uio->uio_resid = 0;
2345
2346 return ENOERR;
2347 }
2348 static int
2349 logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2350 {
2351 return ENOERR;
2352 }
2353
2354 // -------------------------------------------------------------------------
2355 // romfs_fo_close()
2356 // Close a file. We just clear out the data pointer.
2357
2358 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
2359 {
2360 return ENOERR;
2361 }
2362

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)