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

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)