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

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)