zy1000 1.47
[openocd.git] / src / ecosboard.c
1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "log.h"
25 #include "types.h"
26 #include "jtag.h"
27 #include "configuration.h"
28 #include "xsvf.h"
29 #include "target.h"
30 #include "flash.h"
31 #include "nand.h"
32 #include "pld.h"
33
34 #include "command.h"
35 #include "server.h"
36 #include "telnet_server.h"
37 #include "gdb_server.h"
38
39 #include <time_support.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 #include <strings.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <errno.h>
48
49 #include <cyg/io/flash.h>
50 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
51 #include <network.h>
52
53 #include <fcntl.h>
54 #include <sys/stat.h>
55 #include <cyg/fileio/fileio.h>
56 #include <dirent.h>
57 #include <cyg/athttpd/http.h>
58 #include <cyg/athttpd/socket.h>
59 #include <cyg/athttpd/handler.h>
60 #include <cyg/athttpd/cgi.h>
61 #include <cyg/athttpd/forms.h>
62 #include <cyg/discover/discover.h>
63 #include <cyg/hal/hal_diag.h>
64 #include <cyg/kernel/kapi.h>
65 #include <cyg/io/serialio.h>
66 #include <cyg/io/io.h>
67 #include <netinet/tcp.h>
68 #include "rom.h"
69 #include <sys/ioctl.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #include <net/if.h>
73 #include <arpa/inet.h>
74 #include <sys/types.h>
75 #include <sys/socket.h>
76 #include <netdb.h>
77 #include <netinet/in.h>
78 #include <unistd.h>
79 #include <arpa/inet.h>
80 #include <stdio.h>
81 #include <ifaddrs.h>
82 #include <string.h>
83
84
85 #include <unistd.h>
86 #include <stdio.h>
87 #define MAX_IFS 64
88 #if defined(CYGPKG_NET_FREEBSD_STACK)
89 #include <tftp_support.h>
90 /* posix compatibility broken*/
91 struct tftpd_fileops fileops =
92 {
93 (int (*)(const char *, int))open,
94 close,
95 (int (*)(int, const void *, int))write,
96 ( int (*)(int, void *, int))read
97 };
98
99 #endif
100
101 #define ZYLIN_VERSION "1.47"
102 #define ZYLIN_DATE __DATE__
103 #define ZYLIN_TIME __TIME__
104 /* hmmm.... we can't pick up the right # during build if we've checked this out
105 * in Eclipse... arrggghh...*/
106 #define ZYLIN_OPENOCD "$Revision$"
107 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
108 #define ZYLIN_CONFIG_DIR "/config/settings"
109
110 void diag_write(char *buf, int len)
111 {
112 int j;
113 for (j = 0; j < len; j++)
114 {
115 diag_printf("%c", buf[j]);
116 }
117 }
118
119 static bool serialLog = true;
120 static bool writeLog = true;
121
122
123 struct FastLoad
124 {
125 u32 address;
126 u8 *data;
127 int length;
128
129 };
130
131 static int fastload_num;
132 static struct FastLoad *fastload;
133
134 static void free_fastload()
135 {
136 if (fastload!=NULL)
137 {
138 int i;
139 for (i=0; i<fastload_num; i++)
140 {
141 if (fastload[i].data)
142 free(fastload[i].data);
143 }
144 free(fastload);
145 fastload=NULL;
146 }
147 }
148
149
150 int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
151 {
152 u8 *buffer;
153 u32 buf_cnt;
154 u32 image_size;
155 u32 min_address=0;
156 u32 max_address=0xffffffff;
157 int i;
158 int retval;
159
160 image_t image;
161
162 duration_t duration;
163 char *duration_text;
164
165 if ((argc < 1)||(argc > 5))
166 {
167 return ERROR_COMMAND_SYNTAX_ERROR;
168 }
169
170 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
171 if (argc >= 2)
172 {
173 image.base_address_set = 1;
174 image.base_address = strtoul(args[1], NULL, 0);
175 }
176 else
177 {
178 image.base_address_set = 0;
179 }
180
181
182 image.start_address_set = 0;
183
184 if (argc>=4)
185 {
186 min_address=strtoul(args[3], NULL, 0);
187 }
188 if (argc>=5)
189 {
190 max_address=strtoul(args[4], NULL, 0)+min_address;
191 }
192
193 if (min_address>max_address)
194 {
195 return ERROR_COMMAND_SYNTAX_ERROR;
196 }
197
198 duration_start_measure(&duration);
199
200 if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
201 {
202 return ERROR_OK;
203 }
204
205 image_size = 0x0;
206 retval = ERROR_OK;
207 fastload_num=image.num_sections;
208 fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
209 if (fastload==NULL)
210 {
211 image_close(&image);
212 return ERROR_FAIL;
213 }
214 memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
215 for (i = 0; i < image.num_sections; i++)
216 {
217 buffer = malloc(image.sections[i].size);
218 if (buffer == NULL)
219 {
220 command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
221 break;
222 }
223
224 if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
225 {
226 free(buffer);
227 break;
228 }
229
230 u32 offset=0;
231 u32 length=buf_cnt;
232
233
234 /* DANGER!!! beware of unsigned comparision here!!! */
235
236 if ((image.sections[i].base_address+buf_cnt>=min_address)&&
237 (image.sections[i].base_address<max_address))
238 {
239 if (image.sections[i].base_address<min_address)
240 {
241 /* clip addresses below */
242 offset+=min_address-image.sections[i].base_address;
243 length-=offset;
244 }
245
246 if (image.sections[i].base_address+buf_cnt>max_address)
247 {
248 length-=(image.sections[i].base_address+buf_cnt)-max_address;
249 }
250
251 fastload[i].address=image.sections[i].base_address+offset;
252 fastload[i].data=malloc(length);
253 if (fastload[i].data==NULL)
254 {
255 free(buffer);
256 break;
257 }
258 memcpy(fastload[i].data, buffer+offset, length);
259 fastload[i].length=length;
260
261 image_size += length;
262 command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);
263 }
264
265 free(buffer);
266 }
267
268 duration_stop_measure(&duration, &duration_text);
269 if (retval==ERROR_OK)
270 {
271 command_print(cmd_ctx, "Loaded %u bytes in %s", image_size, duration_text);
272 command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
273 }
274 free(duration_text);
275
276 image_close(&image);
277
278 if (retval!=ERROR_OK)
279 {
280 free_fastload();
281 }
282
283 return retval;
284 }
285
286 int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
287 {
288 if (argc>0)
289 return ERROR_COMMAND_SYNTAX_ERROR;
290 if (fastload==NULL)
291 {
292 LOG_ERROR("No image in memory");
293 return ERROR_FAIL;
294 }
295 int i;
296 int ms=timeval_ms();
297 int size=0;
298 for (i=0; i<fastload_num;i++)
299 {
300 int retval;
301 target_t *target = get_current_target(cmd_ctx);
302 if ((retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data)) != ERROR_OK)
303 {
304 return retval;
305 }
306 size+=fastload[i].length;
307 }
308 int after=timeval_ms();
309 command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
310 return ERROR_OK;
311 }
312
313
314 /* Give TELNET a way to find out what version this is */
315 int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,
316 char **args, int argc)
317 {
318 if (argc > 1)
319 {
320 return ERROR_COMMAND_SYNTAX_ERROR;
321 }
322 if (argc == 0)
323 {
324 command_print(cmd_ctx, ZYLIN_OPENOCD_VERSION);
325 } else if (strcmp("openocd", args[0])==0)
326 {
327 int revision;
328 revision=atol(ZYLIN_OPENOCD+strlen("XRevision: "));
329 command_print(cmd_ctx, "%d", revision);
330 } else if (strcmp("zy1000", args[0])==0)
331 {
332 command_print(cmd_ctx, "%s", ZYLIN_VERSION);
333 } else if (strcmp("date", args[0])==0)
334 {
335 command_print(cmd_ctx, "%s", ZYLIN_DATE);
336 } else
337 {
338 return ERROR_COMMAND_SYNTAX_ERROR;
339 }
340
341 return ERROR_OK;
342 }
343
344 extern flash_driver_t *flash_drivers[];
345 extern target_type_t *target_types[];
346
347 #ifdef CYGPKG_PROFILE_GPROF
348 #include <cyg/profile/profile.h>
349
350 extern char _stext, _etext; // Defined by the linker
351
352 void start_profile(void)
353 {
354 // This starts up the system-wide profiling, gathering
355 // profile information on all of the code, with a 16 byte
356 // "bucket" size, at a rate of 100us/profile hit.
357 // Note: a bucket size of 16 will give pretty good function
358 // resolution. Much smaller and the buffer becomes
359 // much too large for very little gain.
360 // Note: a timer period of 100us is also a reasonable
361 // compromise. Any smaller and the overhead of
362 // handling the timter (profile) interrupt could
363 // swamp the system. A fast processor might get
364 // by with a smaller value, but a slow one could
365 // even be swamped by this value. If the value is
366 // too large, the usefulness of the profile is reduced.
367
368 // no more interrupts than 1/10ms.
369 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
370 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
371 profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
372 }
373 #endif
374
375 // launch GDB server if a config file exists
376 bool zylinjtag_parse_config_file(struct command_context_s *cmd_ctx, const char *config_file_name)
377 {
378 bool foundFile = false;
379 FILE *config_file = NULL;
380 command_print(cmd_ctx, "executing config file %s", config_file_name);
381 config_file = fopen(config_file_name, "r");
382 if (config_file)
383 {
384 fclose(config_file);
385 int retval;
386 retval = command_run_linef(cmd_ctx, "script %s", config_file_name);
387 if (retval == ERROR_OK)
388 {
389 foundFile = true;
390 }
391 else
392 {
393 command_print(cmd_ctx, "Failed executing %s %d", config_file_name, retval);
394 }
395 }
396 else
397 {
398 command_print(cmd_ctx, "No %s found", config_file_name);
399 }
400
401 return foundFile;
402 }
403
404 extern int eth0_up;
405 static FILE *log;
406
407 static char reboot_stack[2048];
408
409
410 static void
411 zylinjtag_reboot(cyg_addrword_t data)
412 {
413 serialLog = true;
414 diag_printf("Rebooting in 100 ticks..\n");
415 cyg_thread_delay(100);
416 diag_printf("Unmounting /config..\n");
417 umount("/config");
418 diag_printf("Rebooting..\n");
419 HAL_PLATFORM_RESET();
420 }
421 static cyg_thread zylinjtag_thread_object;
422 static cyg_handle_t zylinjtag_thread_handle;
423
424 void reboot(void)
425 {
426 cyg_thread_create(1,
427 zylinjtag_reboot,
428 (cyg_addrword_t)0,
429 "reboot Thread",
430 (void *)reboot_stack,
431 sizeof(reboot_stack),
432 &zylinjtag_thread_handle,
433 &zylinjtag_thread_object);
434 cyg_thread_resume(zylinjtag_thread_handle);
435 }
436
437 int configuration_output_handler(struct command_context_s *context, const char* line)
438 {
439 diag_printf("%s", line);
440
441 return ERROR_OK;
442 }
443
444 int zy1000_configuration_output_handler_log(struct command_context_s *context, const char* line)
445 {
446 LOG_USER_N("%s", line);
447
448 return ERROR_OK;
449 }
450
451 int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
452 char **args, int argc)
453 {
454 if (argc != 1)
455 {
456 command_print(cmd_ctx, "rm <filename>");
457 return ERROR_INVALID_ARGUMENTS;
458 }
459
460 if (unlink(args[0]) != 0)
461 {
462 command_print(cmd_ctx, "failed: %d", errno);
463 }
464
465 return ERROR_OK;
466 }
467
468 int loadFile(const char *fileName, void **data, int *len);
469
470 int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
471 char **args, int argc)
472 {
473 if (argc != 1)
474 {
475 command_print(cmd_ctx, "cat <filename>");
476 return ERROR_INVALID_ARGUMENTS;
477 }
478
479 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
480 void *data;
481 int len;
482
483 int retval = loadFile(args[0], &data, &len);
484 if (retval == ERROR_OK)
485 {
486 command_print(cmd_ctx, "%s", data);
487 free(data);
488 }
489 else
490 {
491 command_print(cmd_ctx, "%s not found %d", args[0], retval);
492 }
493
494 return ERROR_OK;
495 }
496 int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
497 char **args, int argc)
498 {
499 if (argc != 1)
500 {
501 command_print(cmd_ctx, "trunc <filename>");
502 return ERROR_INVALID_ARGUMENTS;
503 }
504
505 FILE *config_file = NULL;
506 config_file = fopen(args[0], "w");
507 if (config_file != NULL)
508 fclose(config_file);
509
510 return ERROR_OK;
511 }
512
513
514 int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
515 {
516 static int prev = 0;
517 struct mallinfo info;
518
519 if (argc != 0)
520 {
521 command_print(cmd_ctx, "meminfo");
522 return ERROR_INVALID_ARGUMENTS;
523 }
524
525 info = mallinfo();
526
527 if (prev > 0)
528 {
529 command_print(cmd_ctx, "Diff: %d", prev - info.fordblks);
530 }
531 prev = info.fordblks;
532
533 command_print(cmd_ctx, "Available ram: %d", info.fordblks );
534
535 return ERROR_OK;
536 }
537
538 static bool savePower;
539
540 static void setPower(bool power)
541 {
542 savePower = power;
543 if (power)
544 {
545 HAL_WRITE_UINT32(0x08000014, 0x8);
546 } else
547 {
548 HAL_WRITE_UINT32(0x08000010, 0x8);
549 }
550 }
551
552 int handle_power_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
553 {
554 if (argc > 1)
555 {
556 return ERROR_INVALID_ARGUMENTS;
557 }
558
559 if (argc == 1)
560 {
561 if (strcmp(args[0], "on") == 0)
562 {
563 setPower(1);
564 }
565 else if (strcmp(args[0], "off") == 0)
566 {
567 setPower(0);
568 } else
569 {
570 command_print(cmd_ctx, "arg is \"on\" or \"off\"");
571 return ERROR_INVALID_ARGUMENTS;
572 }
573 }
574
575 command_print(cmd_ctx, "Target power %s", savePower ? "on" : "off");
576
577 return ERROR_OK;
578 }
579
580 int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
581 char **args, int argc)
582 {
583 if (argc < 1)
584 {
585 command_print(cmd_ctx,
586 "append <filename> [<string1>, [<string2>, ...]]");
587 return ERROR_INVALID_ARGUMENTS;
588 }
589
590 FILE *config_file = NULL;
591 config_file = fopen(args[0], "a");
592 if (config_file != NULL)
593 {
594 int i;
595 fseek(config_file, 0, SEEK_END);
596
597 for (i = 1; i < argc; i++)
598 {
599 fwrite(args[i], strlen(args[i]), 1, config_file);
600 if (i != argc - 1)
601 {
602 fwrite(" ", 1, 1, config_file);
603 }
604 }
605 fwrite("\n", 1, 1, config_file);
606 fclose(config_file);
607 }
608
609 return ERROR_OK;
610 }
611
612 extern int telnet_socket;
613
614 int readMore(int fd, void *data, int length)
615 {
616 /* used in select() */
617 fd_set read_fds;
618
619 /* monitor sockets for acitvity */
620 int fd_max = 1;
621 FD_ZERO(&read_fds);
622 /* listen for new connections */
623 FD_SET(fd, &read_fds);
624
625 // Maximum 5 seconds.
626 struct timeval tv;
627 tv.tv_sec = 5;
628 tv.tv_usec = 0;
629
630 int retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
631 if (retval == 0)
632 {
633 diag_printf("Timed out waiting for binary payload\n");
634 return -1;
635 }
636 if (retval != 1)
637 return -1;
638
639 return read_socket(fd, data, length);
640 }
641
642 int readAll(int fd, void *data, int length)
643 {
644 int pos = 0;
645 for (;;)
646 {
647 int actual = readMore(fd, ((char *) data) + pos, length - pos);
648 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
649 if (actual <= 0)
650 return -1;
651 pos += actual;
652 if (pos == length)
653 break;
654 }
655 return length;
656 }
657
658 int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
659 {
660 cyg_uint32 value;
661 if (argc != 1)
662 {
663 return ERROR_INVALID_ARGUMENTS;
664 }
665 HAL_READ_UINT32(strtoul(args[0], NULL, 0), value);
666 command_print(cmd_ctx, "0x%x : 0x%x", strtoul(args[0], NULL, 0), value);
667 return ERROR_OK;
668 }
669
670 int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
671 {
672 if (argc != 2)
673 {
674 return ERROR_INVALID_ARGUMENTS;
675 }
676 HAL_WRITE_UINT32(strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0));
677 return ERROR_OK;
678 }
679
680 int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
681 {
682 if (argc != 2)
683 {
684 return ERROR_INVALID_ARGUMENTS;
685 }
686
687 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
688 void *data;
689 int len;
690
691 int retval = loadFile(args[0], &data, &len);
692 if (retval != ERROR_OK)
693 return retval;
694
695 FILE *f = fopen(args[1], "wb");
696 if (f == NULL)
697 retval = ERROR_INVALID_ARGUMENTS;
698
699 int pos = 0;
700 for (;;)
701 {
702 int chunk = len - pos;
703 static const int maxChunk = 512 * 1024; // ~1/sec
704 if (chunk > maxChunk)
705 {
706 chunk = maxChunk;
707 }
708
709 if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
710 retval = ERROR_INVALID_ARGUMENTS;
711
712 if (retval != ERROR_OK)
713 {
714 break;
715 }
716
717 command_print(cmd_ctx, "%d", len - pos);
718
719 pos += chunk;
720
721 if (pos == len)
722 break;
723 }
724
725 if (retval == ERROR_OK)
726 {
727 command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
728 } else
729 {
730 command_print(cmd_ctx, "Failed: %d", retval);
731 }
732
733 if (data != NULL)
734 free(data);
735 if (f != NULL)
736 fclose(f);
737
738 if (retval != ERROR_OK)
739 unlink(args[1]);
740
741 return retval;
742 }
743
744 #ifdef CYGPKG_PROFILE_GPROF
745 extern void start_profile();
746
747 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
748 {
749 command_print(cmd_ctx, "Profiling started");
750 start_profile();
751 return ERROR_OK;
752 }
753
754 #endif
755
756 externC void phi_init_all_network_interfaces();
757
758 command_context_t *cmd_ctx;
759
760 static bool webRunning = false;
761
762 void keep_webserver()
763 {
764 // Target initialisation is only attempted at startup, so we sleep forever and
765 // let the http server bail us out(i.e. get config files set up).
766 diag_printf("OpenOCD has invoked exit().\n"
767 "Use web server to correct any configuration settings and reboot.\n");
768 if (!webRunning)
769 reboot();
770
771 // exit() will terminate the current thread and we we'll then sleep eternally or
772 // we'll have a reboot scheduled.
773 }
774
775 extern void printDccChar(char c);
776
777 static char logBuffer[128 * 1024];
778 static const int logSize = sizeof(logBuffer);
779 int writePtr = 0;
780 int logCount = 0;
781
782 void _zylinjtag_diag_write_char(char c, void **param)
783 {
784 if (writeLog)
785 {
786 logBuffer[writePtr] = c;
787 writePtr = (writePtr + 1) % logSize;
788 logCount++;
789 }
790 if (serialLog)
791 {
792 if (c == '\n')
793 {
794 HAL_DIAG_WRITE_CHAR('\r');
795 }
796 HAL_DIAG_WRITE_CHAR(c);
797 }
798
799 printDccChar(c);
800 }
801
802 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
803
804 #define IOSIZE 512
805 static void copyfile(char *name2, char *name1)
806 {
807
808 int err;
809 char buf[IOSIZE];
810 int fd1, fd2;
811 ssize_t done, wrote;
812
813 fd1 = open(name1, O_WRONLY | O_CREAT);
814 if (fd1 < 0)
815 SHOW_RESULT( open, fd1 );
816
817 fd2 = open(name2, O_RDONLY);
818 if (fd2 < 0)
819 SHOW_RESULT( open, fd2 );
820
821 for (;;)
822 {
823 done = read(fd2, buf, IOSIZE );
824 if (done < 0)
825 {
826 SHOW_RESULT( read, done );
827 break;
828 }
829
830 if( done == 0 ) break;
831
832 wrote = write(fd1, buf, done);
833 if( wrote != done ) SHOW_RESULT( write, wrote );
834
835 if( wrote != done ) break;
836 }
837
838 err = close(fd1);
839 if( err < 0 ) SHOW_RESULT( close, err );
840
841 err = close(fd2);
842 if( err < 0 ) SHOW_RESULT( close, err );
843
844 }
845 static void copydir(char *name, char *destdir)
846 {
847 int err;
848 DIR *dirp;
849
850 dirp = opendir(destdir);
851 if (dirp==NULL)
852 {
853 mkdir(destdir, 0777);
854 } else
855 {
856 err = closedir(dirp);
857 }
858
859 dirp = opendir(name);
860 if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
861
862 for (;;)
863 {
864 struct dirent *entry = readdir(dirp);
865
866 if (entry == NULL)
867 break;
868
869 if (strcmp(entry->d_name, ".") == 0)
870 continue;
871 if (strcmp(entry->d_name, "..") == 0)
872 continue;
873
874 bool isDir = false;
875 struct stat buf;
876 char fullPath[PATH_MAX];
877 strncpy(fullPath, name, PATH_MAX);
878 strcat(fullPath, "/");
879 strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
880
881 if (stat(fullPath, &buf) == -1)
882 {
883 diag_printf("unable to read status from %s", fullPath);
884 break;
885 }
886 isDir = S_ISDIR(buf.st_mode) != 0;
887
888 if (isDir)
889 continue;
890
891 // diag_printf("<INFO>: entry %14s",entry->d_name);
892 char fullname[PATH_MAX];
893 char fullname2[PATH_MAX];
894
895 strcpy(fullname, name);
896 strcat(fullname, "/");
897 strcat(fullname, entry->d_name);
898
899 strcpy(fullname2, destdir);
900 strcat(fullname2, "/");
901 strcat(fullname2, entry->d_name);
902 // diag_printf("from %s to %s\n", fullname, fullname2);
903 copyfile(fullname, fullname2);
904
905 // diag_printf("\n");
906 }
907
908 err = closedir(dirp);
909 if( err < 0 ) SHOW_RESULT( stat, err );
910 }
911
912 #if 0
913 MTAB_ENTRY( romfs_mte1,
914 "/rom",
915 "romfs",
916 "",
917 (CYG_ADDRWORD) &filedata[0] );
918 #endif
919
920 void openocd_sleep_prelude()
921 {
922 cyg_mutex_unlock(&httpstate.jim_lock);
923 }
924
925 void openocd_sleep_postlude()
926 {
927 cyg_mutex_lock(&httpstate.jim_lock);
928 }
929
930 static int
931 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
932 int argc,
933 Jim_Obj * const *argv)
934 {
935 int del;
936 if (argc != 2)
937 {
938 Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
939 return JIM_ERR;
940 }
941
942 del = 0;
943 if (unlink(Jim_GetString(argv[1], NULL)) == 0)
944 del = 1;
945 if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
946 del = 1;
947
948 return del ? JIM_OK : JIM_ERR;
949 }
950
951 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
952 Jim_Obj * const *argv)
953 {
954 cyg_handle_t thread = 0;
955 cyg_uint16 id = 0;
956 Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
957
958 /* Loop over the threads, and generate a table row for
959 * each.
960 */
961 while (cyg_thread_get_next(&thread, &id))
962 {
963 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
964
965 cyg_thread_info info;
966 char *state_string;
967
968 cyg_thread_get_info(thread, id, &info);
969
970 if (info.name == NULL)
971 info.name = "<no name>";
972
973 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
974 info.name, strlen(info.name)));
975
976 /* Translate the state into a string.
977 */
978 if (info.state == 0)
979 state_string = "RUN";
980 else if (info.state & 0x04)
981 state_string = "SUSP";
982 else
983 switch (info.state & 0x1b)
984 {
985 case 0x01:
986 state_string = "SLEEP";
987 break;
988 case 0x02:
989 state_string = "CNTSLEEP";
990 break;
991 case 0x08:
992 state_string = "CREATE";
993 break;
994 case 0x10:
995 state_string = "EXIT";
996 break;
997 default:
998 state_string = "????";
999 break;
1000 }
1001
1002 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
1003 state_string, strlen(state_string)));
1004
1005 Jim_ListAppendElement (interp, threadObj, Jim_NewIntObj(interp, id));
1006 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.set_pri));
1007 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.cur_pri));
1008
1009 Jim_ListAppendElement(interp, threads, threadObj);
1010 }
1011 Jim_SetResult( interp, threads);
1012
1013 return JIM_OK;
1014 }
1015
1016
1017 static int
1018 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
1019 int argc,
1020 Jim_Obj * const *argv)
1021 {
1022 if (argc != 2)
1023 {
1024 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
1025 return JIM_ERR;
1026 }
1027
1028 char *name = (char*) Jim_GetString(argv[1], NULL);
1029
1030 DIR *dirp = NULL;
1031 dirp = opendir(name);
1032 if (dirp == NULL)
1033 {
1034 return JIM_ERR;
1035 }
1036 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
1037
1038 for (;;)
1039 {
1040 struct dirent *entry = NULL;
1041 entry = readdir(dirp);
1042 if (entry == NULL)
1043 break;
1044
1045 if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
1046 continue;
1047
1048 Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
1049 }
1050 closedir(dirp);
1051
1052 Jim_SetResult(interp, objPtr);
1053
1054 return JIM_OK;
1055 }
1056
1057
1058 static int
1059 zylinjtag_Jim_Command_getmem(Jim_Interp *interp,
1060 int argc,
1061 Jim_Obj * const *argv)
1062 {
1063 if (argc != 3)
1064 {
1065 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
1066 return JIM_ERR;
1067 }
1068
1069 long address;
1070 long length;
1071 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1072 return JIM_ERR;
1073 if (Jim_GetLong(interp, argv[2], &length) != JIM_OK)
1074 return JIM_ERR;
1075
1076 if (length < 0 && length > (4096 * 1024))
1077 {
1078 Jim_WrongNumArgs(interp, 1, argv, "getmem ?dir?");
1079 return JIM_ERR;
1080 }
1081
1082 void *mem = malloc(length);
1083 if (mem == NULL)
1084 return JIM_ERR;
1085
1086 target_t *target = get_current_target(cmd_ctx);
1087
1088 int retval;
1089 int size = 1;
1090 int count = length;
1091 if ((address % 4 == 0) && (count % 4 == 0))
1092 {
1093 size = 4;
1094 count /= 4;
1095 }
1096
1097 if ((retval = target->type->read_memory(target, address, size, count, mem)) != ERROR_OK)
1098 {
1099 free(mem);
1100 return JIM_ERR;
1101 }
1102
1103 Jim_Obj *objPtr = Jim_NewStringObj(interp, mem, length);
1104 Jim_SetResult(interp, objPtr);
1105
1106 free(mem);
1107
1108 return JIM_OK;
1109 }
1110
1111 static int
1112 zylinjtag_Jim_Command_peek(Jim_Interp *interp,
1113 int argc,
1114 Jim_Obj * const *argv)
1115 {
1116 if (argc != 2)
1117 {
1118 Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
1119 return JIM_ERR;
1120 }
1121
1122 long address;
1123 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1124 return JIM_ERR;
1125
1126 int value = *((volatile int *) address);
1127
1128 Jim_SetResult(interp, Jim_NewIntObj(interp, value));
1129
1130 return JIM_OK;
1131 }
1132
1133 static int
1134 zylinjtag_Jim_Command_poke(Jim_Interp *interp,
1135 int argc,
1136 Jim_Obj * const *argv)
1137 {
1138 if (argc != 3)
1139 {
1140 Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
1141 return JIM_ERR;
1142 }
1143
1144 long address;
1145 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1146 return JIM_ERR;
1147 long value;
1148 if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
1149 return JIM_ERR;
1150
1151 *((volatile int *) address) = value;
1152
1153 return JIM_OK;
1154 }
1155
1156
1157
1158 static int
1159 zylinjtag_Jim_Command_flash(Jim_Interp *interp,
1160 int argc,
1161 Jim_Obj * const *argv)
1162 {
1163 int retval;
1164 u32 base = 0;
1165 flash_bank_t *t = get_flash_bank_by_num_noprobe(0);
1166 if (t != NULL)
1167 {
1168 base = t->base;
1169 retval = JIM_OK;
1170 } else
1171 {
1172 retval = JIM_ERR;
1173 }
1174
1175 if (retval == JIM_OK)
1176 {
1177 Jim_SetResult(interp, Jim_NewIntObj(interp, base));
1178 }
1179
1180 return retval;
1181 }
1182
1183
1184
1185
1186
1187 static int
1188 zylinjtag_Jim_Command_log(Jim_Interp *interp,
1189 int argc,
1190 Jim_Obj * const *argv)
1191 {
1192 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1193
1194 if (logCount >= logSize)
1195 {
1196 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer+logCount%logSize, logSize-logCount%logSize);
1197 }
1198 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
1199
1200 Jim_SetResult(interp, tclOutput);
1201 return JIM_OK;
1202 }
1203
1204 static int
1205 zylinjtag_Jim_Command_reboot(Jim_Interp *interp,
1206 int argc,
1207 Jim_Obj * const *argv)
1208 {
1209 reboot();
1210 return JIM_OK;
1211 }
1212
1213 static int
1214 zylinjtag_Jim_Command_mac(Jim_Interp *interp,
1215 int argc,
1216 Jim_Obj * const *argv)
1217 {
1218 int s;
1219 struct ifreq ifr;
1220 s = socket(AF_INET, SOCK_DGRAM, 0);
1221 if (s >= 0)
1222 {
1223 strcpy(ifr.ifr_name, "eth0");
1224 int res;
1225 res = ioctl(s, SIOCGIFHWADDR, &ifr);
1226 close(s);
1227
1228 if (res < 0)
1229 {
1230 return JIM_OK;
1231 }
1232 }
1233
1234 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1235
1236 char hwaddr[512];
1237 sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
1238 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
1239 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
1240 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
1241 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
1242 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
1243 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
1244
1245 Jim_AppendString(httpstate.jim_interp, tclOutput, hwaddr, strlen(hwaddr));
1246
1247 Jim_SetResult(interp, tclOutput);
1248
1249 return JIM_OK;
1250 }
1251
1252 static int
1253 zylinjtag_Jim_Command_ip(Jim_Interp *interp,
1254 int argc,
1255 Jim_Obj * const *argv)
1256 {
1257 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1258
1259 struct ifaddrs *ifa = NULL, *ifp = NULL;
1260
1261 if (getifaddrs(&ifp) < 0)
1262 {
1263 return JIM_ERR;
1264 }
1265
1266 for (ifa = ifp; ifa; ifa = ifa->ifa_next)
1267 {
1268 char ip[200];
1269 socklen_t salen;
1270
1271 if (ifa->ifa_addr->sa_family == AF_INET)
1272 salen = sizeof(struct sockaddr_in);
1273 else if (ifa->ifa_addr->sa_family == AF_INET6)
1274 salen = sizeof(struct sockaddr_in6);
1275 else
1276 continue;
1277
1278 if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
1279 NI_NUMERICHOST) < 0)
1280 {
1281 continue;
1282 }
1283
1284 Jim_AppendString(httpstate.jim_interp, tclOutput, ip, strlen(ip));
1285 break;
1286
1287 }
1288
1289 freeifaddrs(ifp);
1290
1291 Jim_SetResult(interp, tclOutput);
1292
1293 return JIM_OK;
1294 }
1295
1296 extern Jim_Interp *interp;
1297
1298 static void zylinjtag_startNetwork()
1299 {
1300 // Bring TCP/IP up immediately before we're ready to accept commands.
1301 //
1302 // That is as soon as a PING responds, we're accepting telnet sessions.
1303 #if defined(CYGPKG_NET_FREEBSD_STACK)
1304 phi_init_all_network_interfaces();
1305 #else
1306 lwip_init();
1307 #endif
1308 if (!eth0_up)
1309 {
1310 diag_printf("Network not up and running\n");
1311 exit(-1);
1312 }
1313 #if defined(CYGPKG_NET_FREEBSD_STACK)
1314 /*start TFTP*/
1315 tftpd_start(69, &fileops);
1316 #endif
1317
1318 cyg_httpd_init_tcl_interpreter();
1319
1320 interp = httpstate.jim_interp;
1321
1322 Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log, NULL, NULL);
1323 Jim_CreateCommand(httpstate.jim_interp, "reboot", zylinjtag_Jim_Command_reboot, NULL, NULL);
1324 Jim_CreateCommand(httpstate.jim_interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
1325 Jim_CreateCommand(httpstate.jim_interp, "zy1000_flash", zylinjtag_Jim_Command_flash, NULL, NULL);
1326 Jim_CreateCommand(httpstate.jim_interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
1327 Jim_CreateCommand(httpstate.jim_interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
1328 Jim_CreateCommand(httpstate.jim_interp, "threads", zylinjtag_Jim_Command_threads, NULL, NULL);
1329 Jim_CreateCommand(httpstate.jim_interp, "getmem", zylinjtag_Jim_Command_getmem, NULL, NULL);
1330 Jim_CreateCommand(httpstate.jim_interp, "mac", zylinjtag_Jim_Command_mac, NULL, NULL);
1331 Jim_CreateCommand(httpstate.jim_interp, "ip", zylinjtag_Jim_Command_ip, NULL, NULL);
1332 Jim_CreateCommand(httpstate.jim_interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
1333
1334 cyg_httpd_start();
1335
1336 webRunning = true;
1337
1338 diag_printf("Web server running\n");
1339
1340 discover_launch();
1341 }
1342
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 static cyg_uint8 *ramblockdevice;
1725 static const int ramblockdevice_size=4096*1024;
1726 int main(int argc, char *argv[])
1727 {
1728 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1729 * need to allocate towards the end of the heap. */
1730
1731 ramblockdevice=(cyg_uint8 *)malloc(ramblockdevice_size);
1732 memset(ramblockdevice, 0xff, ramblockdevice_size);
1733
1734 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
1735 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
1736 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
1737
1738 int err;
1739 err = cyg_io_lookup("/dev/ser0", &serial_handle);
1740 if (err != ENOERR)
1741 {
1742 diag_printf("/dev/ser0 not found\n");
1743 reboot();
1744 }
1745
1746 setPower(true); // on by default
1747
1748 atexit(keep_webserver);
1749
1750 err = mount("", "/ram", "ramfs");
1751 if (err < 0)
1752 {
1753 diag_printf("unable to mount ramfs\n");
1754 }
1755 chdir("/ram");
1756
1757 char address[16];
1758 sprintf(address, "%p", &filedata[0]);
1759 err = mount(address, "/rom", "romfs");
1760 if (err < 0)
1761 {
1762 diag_printf("unable to mount /rom\n");
1763 }
1764
1765 err = mount("", "/log", "logfs");
1766 if (err < 0)
1767 {
1768 diag_printf("unable to mount logfs\n");
1769 }
1770
1771 err = mount("", "/tftp", "tftpfs");
1772 if (err < 0)
1773 {
1774 diag_printf("unable to mount logfs\n");
1775 }
1776
1777 log = fopen("/log/log", "w");
1778 if (log == NULL)
1779 {
1780 diag_printf("Could not open log file /ram/log\n");
1781 exit(-1);
1782 }
1783
1784 diag_init_putc(_zylinjtag_diag_write_char);
1785
1786 // We want this in the log.
1787 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1788 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);
1789
1790 copydir("/rom", "/ram/cgi");
1791
1792 err = mount("/dev/flash1", "/config", "jffs2");
1793 if (err < 0)
1794 {
1795 diag_printf("unable to mount jffs\n");
1796 reboot();
1797 }
1798
1799 /* are we using a ram disk instead of a flash disk? This is used
1800 * for ZY1000 live demo...
1801 *
1802 * copy over flash disk to ram block device
1803 */
1804 if (boolParam("ramdisk"))
1805 {
1806 diag_printf("Unmounting /config from flash and using ram instead\n");
1807 err=umount("/config");
1808 if (err < 0)
1809 {
1810 diag_printf("unable to unmount jffs\n");
1811 reboot();
1812 }
1813
1814 err = mount("/dev/flash1", "/config2", "jffs2");
1815 if (err < 0)
1816 {
1817 diag_printf("unable to mount jffs\n");
1818 reboot();
1819 }
1820
1821 err = mount("/dev/ram", "/config", "jffs2");
1822 if (err < 0)
1823 {
1824 diag_printf("unable to mount ram block device\n");
1825 reboot();
1826 }
1827
1828 // copydir("/config2", "/config");
1829 copyfile("/config2/ip", "/config/ip");
1830 copydir("/config2/settings", "/config/settings");
1831
1832 umount("/config2");
1833 } else
1834 {
1835 /* we're not going to use a ram block disk */
1836 free(ramblockdevice);
1837 }
1838
1839
1840 mkdir(ZYLIN_CONFIG_DIR, 0777);
1841 mkdir(ZYLIN_CONFIG_DIR "/target", 0777);
1842 mkdir(ZYLIN_CONFIG_DIR "/event", 0777);
1843
1844 logAllToSerial = boolParam("logserial");
1845
1846 // We need the network & web server in case there is something wrong with
1847 // the config files that invoke exit()
1848 zylinjtag_startNetwork();
1849
1850 /* we're going to access the jim interpreter from here on... */
1851 openocd_sleep_postlude();
1852 startUart();
1853
1854 add_default_dirs();
1855
1856 /* initialize commandline interface */
1857 command_context_t *cmd_ctx;
1858 cmd_ctx = setup_command_handler();
1859 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1860 command_context_mode(cmd_ctx, COMMAND_CONFIG);
1861
1862
1863 register_command(cmd_ctx, NULL, "zy1000_version", handle_zy1000_version_command,
1864 COMMAND_EXEC, "show zy1000 version numbers");
1865
1866 register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
1867 "remove file");
1868
1869 register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,
1870 "same args as load_image, image stored in memory");
1871
1872 register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY,
1873 "loads active fast load image to current target");
1874
1875 register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
1876 "display file content");
1877
1878 register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
1879 "truncate a file to 0 size");
1880
1881 register_command(cmd_ctx, NULL, "append_file", handle_append_command,
1882 COMMAND_ANY, "append a variable number of strings to a file");
1883
1884 register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,
1885 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1886
1887 register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
1888 COMMAND_ANY, "display available ram memory");
1889
1890 register_command(cmd_ctx, NULL, "cp", handle_cp_command,
1891 COMMAND_ANY, "copy a file <from> <to>");
1892
1893 #ifdef CYGPKG_PROFILE_GPROF
1894 register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1895 COMMAND_ANY, NULL);
1896 #endif
1897 register_command(cmd_ctx, NULL, "uart", handle_uart_command,
1898 COMMAND_ANY, "uart <baud> - forward uart on port 5555");
1899
1900
1901 int errVal;
1902 errVal = log_init(cmd_ctx);
1903 if (errVal != ERROR_OK)
1904 {
1905 diag_printf("log_init() failed %d\n", errVal);
1906 exit(-1);
1907 }
1908
1909 set_log_output(cmd_ctx, log);
1910
1911 LOG_DEBUG("log init complete");
1912
1913 // diag_printf("Executing config files\n");
1914
1915 if (logAllToSerial)
1916 {
1917 diag_printf(ZYLIN_CONFIG_DIR "/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1918 command_run_line(cmd_ctx, "debug_level 3");
1919 }
1920
1921 zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");
1922
1923 // FIX!!! Yuk!
1924 // diag_printf() is really invoked from many more places than we trust it
1925 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1926 //
1927 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1928 // fingers that it doesn't cause any crashes.
1929 diag_printf("Init complete, GDB & telnet servers launched.\n");
1930 command_set_output_handler(cmd_ctx, zy1000_configuration_output_handler_log, NULL);
1931 if (!logAllToSerial)
1932 {
1933 serialLog = false;
1934 }
1935
1936 /* handle network connections */
1937 server_loop(cmd_ctx);
1938 openocd_sleep_prelude();
1939
1940 /* shut server down */
1941 server_quit();
1942
1943 /* free commandline interface */
1944 command_done(cmd_ctx);
1945 umount("/config");
1946
1947 exit(0);
1948 for (;;);
1949 }
1950
1951
1952
1953 cyg_int32
1954 cyg_httpd_exec_cgi_tcl(char *file_name);
1955 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1956 {
1957 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1958 return 0;
1959 }
1960
1961 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1962
1963 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1964 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1965
1966 #include <pkgconf/system.h>
1967 #include <pkgconf/hal.h>
1968 #include <pkgconf/kernel.h>
1969 #include <pkgconf/io_fileio.h>
1970 #include <pkgconf/fs_rom.h>
1971
1972 #include <cyg/kernel/ktypes.h> // base kernel types
1973 #include <cyg/infra/cyg_trac.h> // tracing macros
1974 #include <cyg/infra/cyg_ass.h> // assertion macros
1975 #include <unistd.h>
1976 #include <sys/types.h>
1977 #include <fcntl.h>
1978 #include <sys/stat.h>
1979 #include <errno.h>
1980 #include <dirent.h>
1981
1982 #include <stdarg.h>
1983 #include <stdio.h>
1984 #include <stdlib.h>
1985 #include <string.h>
1986
1987 #include <cyg/fileio/fileio.h>
1988
1989 #include <cyg/kernel/kapi.h>
1990 #include <cyg/infra/diag.h>
1991
1992 //==========================================================================
1993 // Eventually we want to eXecute In Place from the ROM in a protected
1994 // environment, so we'll need executables to be aligned to a boundary
1995 // suitable for MMU protection. A suitable boundary would be the 4k
1996 // boundary in all the CPU architectures I am currently aware of.
1997
1998 // Forward definitions
1999
2000 // Filesystem operations
2001 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
2002 static int tftpfs_umount(cyg_mtab_entry *mte);
2003 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2004 int mode, cyg_file *fte);
2005 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2006 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2007
2008 // File operations
2009 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2010 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
2011 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
2012
2013 //==========================================================================
2014 // Filesystem table entries
2015
2016 // -------------------------------------------------------------------------
2017 // Fstab entry.
2018 // This defines the entry in the filesystem table.
2019 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2020 // we should never block in any filesystem operations.
2021 #if 1
2022 FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,
2023 CYG_SYNCMODE_NONE,
2024 tftpfs_mount,
2025 tftpfs_umount,
2026 tftpfs_open,
2027 (cyg_fsop_unlink *)cyg_fileio_erofs,
2028 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2029 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2030 (cyg_fsop_rename *)cyg_fileio_erofs,
2031 (cyg_fsop_link *)cyg_fileio_erofs,
2032 (cyg_fsop_opendir *)cyg_fileio_erofs,
2033 (cyg_fsop_chdir *)cyg_fileio_erofs,
2034 (cyg_fsop_stat *)cyg_fileio_erofs,
2035 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2036 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2037 #endif
2038
2039 // -------------------------------------------------------------------------
2040 // mtab entry.
2041 // This defines a single ROMFS loaded into ROM at the configured address
2042 //
2043 // MTAB_ENTRY( rom_mte, // structure name
2044 // "/rom", // mount point
2045 // "romfs", // FIlesystem type
2046 // "", // hardware device
2047 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2048 // );
2049
2050
2051 // -------------------------------------------------------------------------
2052 // File operations.
2053 // This set of file operations are used for normal open files.
2054
2055 static cyg_fileops tftpfs_fileops =
2056 {
2057 tftpfs_fo_read,
2058 tftpfs_fo_write,
2059 tftpfs_fo_lseek,
2060 (cyg_fileop_ioctl *)cyg_fileio_erofs,
2061 cyg_fileio_seltrue,
2062 tftpfs_fo_fsync,
2063 tftpfs_fo_close,
2064 (cyg_fileop_fstat *) cyg_fileio_erofs,
2065 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2066 (cyg_fileop_setinfo *)cyg_fileio_erofs,
2067 };
2068
2069 // -------------------------------------------------------------------------
2070 // tftpfs_mount()
2071 // Process a mount request. This mainly finds root for the
2072 // filesystem.
2073
2074 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2075 {
2076 return ENOERR;
2077 }
2078
2079 static int tftpfs_umount(cyg_mtab_entry *mte)
2080 {
2081 return ENOERR;
2082 }
2083
2084 struct Tftp
2085 {
2086 int write;
2087 int readFile;
2088 cyg_uint8 *mem;
2089 int actual;
2090 char *server;
2091 char *file;
2092 };
2093
2094 static void freeTftp(struct Tftp *t)
2095 {
2096 if (t == NULL)
2097 return;
2098 if (t->mem)
2099 free(t->mem);
2100 if (t->server)
2101 free(t->server);
2102 if (t->file)
2103 free(t->file);
2104 free(t);
2105 }
2106
2107 static const int tftpMaxSize = 8192 * 1024;
2108 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2109 int mode, cyg_file *file)
2110 {
2111 struct Tftp *tftp;
2112 tftp = malloc(sizeof(struct Tftp));
2113 if (tftp == NULL)
2114 return EMFILE;
2115 memset(tftp, 0, sizeof(struct Tftp));
2116
2117 file->f_flag |= mode & CYG_FILE_MODE_MASK;
2118 file->f_type = CYG_FILE_TYPE_FILE;
2119 file->f_ops = &tftpfs_fileops;
2120 file->f_offset = 0;
2121 file->f_data = 0;
2122 file->f_xops = 0;
2123
2124 tftp->mem = malloc(tftpMaxSize);
2125 if (tftp->mem == NULL)
2126 {
2127 freeTftp(tftp);
2128 return EMFILE;
2129 }
2130
2131 char *server = strchr(name, '/');
2132 if (server == NULL)
2133 {
2134 freeTftp(tftp);
2135 return EMFILE;
2136 }
2137
2138 tftp->server = malloc(server - name + 1);
2139 if (tftp->server == NULL)
2140 {
2141 freeTftp(tftp);
2142 return EMFILE;
2143 }
2144 strncpy(tftp->server, name, server - name);
2145 tftp->server[server - name] = 0;
2146
2147 tftp->file = strdup(server + 1);
2148 if (tftp->file == NULL)
2149 {
2150 freeTftp(tftp);
2151 return EMFILE;
2152 }
2153
2154 file->f_data = (CYG_ADDRWORD) tftp;
2155
2156 return ENOERR;
2157 }
2158
2159 static int fetchTftp(struct Tftp *tftp)
2160 {
2161 if (!tftp->readFile)
2162 {
2163 int err;
2164 tftp->actual = tftp_client_get( tftp->file, tftp->server, 0, tftp->mem, tftpMaxSize, TFTP_OCTET, &err);
2165
2166 if (tftp->actual < 0)
2167 {
2168 return EMFILE;
2169 }
2170 tftp->readFile = 1;
2171 }
2172 return ENOERR;
2173 }
2174
2175 // -------------------------------------------------------------------------
2176 // tftpfs_fo_write()
2177 // Read data from file.
2178
2179 static int
2180 tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2181 {
2182 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2183
2184 if (fetchTftp(tftp) != ENOERR)
2185 return EMFILE;
2186
2187 int i;
2188 off_t pos = fp->f_offset;
2189 int resid = 0;
2190 for (i = 0; i < uio->uio_iovcnt; i++)
2191 {
2192 cyg_iovec *iov = &uio->uio_iov[i];
2193 char *buf = (char *) iov->iov_base;
2194 off_t len = iov->iov_len;
2195
2196 if (len + pos > tftp->actual)
2197 {
2198 len = tftp->actual - pos;
2199 }
2200 resid += iov->iov_len - len;
2201
2202 memcpy(buf, tftp->mem + pos, len);
2203 pos += len;
2204
2205 }
2206 uio->uio_resid = resid;
2207 fp->f_offset = pos;
2208
2209 return ENOERR;
2210 }
2211
2212
2213 static int
2214 tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2215 {
2216 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2217
2218 int i;
2219 off_t pos = fp->f_offset;
2220 int resid = 0;
2221 for (i = 0; i < uio->uio_iovcnt; i++)
2222 {
2223 cyg_iovec *iov = &uio->uio_iov[i];
2224 char *buf = (char *) iov->iov_base;
2225 off_t len = iov->iov_len;
2226
2227 if (len + pos > tftpMaxSize)
2228 {
2229 len = tftpMaxSize - pos;
2230 }
2231 resid += iov->iov_len - len;
2232
2233 memcpy(tftp->mem + pos, buf, len);
2234 pos += len;
2235
2236 }
2237 uio->uio_resid = resid;
2238 fp->f_offset = pos;
2239
2240 tftp->write = 1;
2241
2242 return ENOERR;
2243 }
2244
2245 static int
2246 tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2247 {
2248 int error = ENOERR;
2249 return error;
2250 }
2251
2252 // -------------------------------------------------------------------------
2253 // romfs_fo_close()
2254 // Close a file. We just clear out the data pointer.
2255
2256 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
2257 {
2258 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2259 int error = ENOERR;
2260
2261 if (tftp->write)
2262 {
2263 tftp_client_put( tftp->file, tftp->server, 0, tftp->mem, fp->f_offset, TFTP_OCTET, &error);
2264 }
2265
2266 freeTftp(tftp);
2267 fp->f_data = 0;
2268 return error;
2269 }
2270
2271 // -------------------------------------------------------------------------
2272 // romfs_fo_lseek()
2273 // Seek to a new file position.
2274
2275 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
2276 {
2277 struct Tftp *tftp = (struct Tftp *) fp->f_data;
2278 off_t pos = *apos;
2279
2280 if (fetchTftp(tftp) != ENOERR)
2281 return EMFILE;
2282
2283 switch (whence)
2284 {
2285 case SEEK_SET:
2286 // Pos is already where we want to be.
2287 break;
2288
2289 case SEEK_CUR:
2290 // Add pos to current offset.
2291 pos += fp->f_offset;
2292 break;
2293
2294 case SEEK_END:
2295 // Add pos to file size.
2296 pos += tftp->actual;
2297 break;
2298
2299 default:
2300 return EINVAL;
2301 }
2302
2303 // Check that pos is still within current file size, or at the
2304 // very end.
2305 if (pos < 0 || pos > tftp->actual)
2306 return EINVAL;
2307
2308 // All OK, set fp offset and return new position.
2309 *apos = fp->f_offset = pos;
2310
2311 return ENOERR;
2312 }
2313
2314 void usleep(int us)
2315 {
2316 if (us > 10000)
2317 cyg_thread_delay(us / 10000 + 1);
2318 else
2319 HAL_DELAY_US(us);
2320 }
2321
2322 // Chunked version.
2323 cyg_int32
2324 show_log_entry(CYG_HTTPD_STATE *phttpstate)
2325 {
2326 cyg_httpd_start_chunked("text");
2327 if (logCount >= logSize)
2328 {
2329 cyg_httpd_write_chunked(logBuffer+logCount%logSize, logSize-logCount%logSize);
2330 }
2331 cyg_httpd_write_chunked(logBuffer, writePtr);
2332 cyg_httpd_end_chunked();
2333 return -1;
2334 }
2335
2336 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
2337
2338 // Filesystem operations
2339 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
2340 static int logfs_umount(cyg_mtab_entry *mte);
2341 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2342 int mode, cyg_file *fte);
2343 static int
2344 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2345
2346 // File operations
2347 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2348 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
2349
2350 #include <cyg/io/devtab.h>
2351
2352 //==========================================================================
2353 // Filesystem table entries
2354
2355 // -------------------------------------------------------------------------
2356 // Fstab entry.
2357 // This defines the entry in the filesystem table.
2358 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2359 // we should never block in any filesystem operations.
2360 FSTAB_ENTRY( logfs_fste, "logfs", 0,
2361 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
2362 logfs_mount,
2363 logfs_umount,
2364 logfs_open,
2365 (cyg_fsop_unlink *)cyg_fileio_erofs,
2366 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2367 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2368 (cyg_fsop_rename *)cyg_fileio_erofs,
2369 (cyg_fsop_link *)cyg_fileio_erofs,
2370 (cyg_fsop_opendir *)cyg_fileio_erofs,
2371 (cyg_fsop_chdir *)cyg_fileio_erofs,
2372 (cyg_fsop_stat *)cyg_fileio_erofs,
2373 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2374 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2375
2376 // -------------------------------------------------------------------------
2377 // File operations.
2378 // This set of file operations are used for normal open files.
2379
2380 static cyg_fileops logfs_fileops =
2381 {
2382 (cyg_fileop_read *)cyg_fileio_erofs,
2383 (cyg_fileop_write *)logfs_fo_write,
2384 (cyg_fileop_lseek *) cyg_fileio_erofs,
2385 (cyg_fileop_ioctl *)cyg_fileio_erofs,
2386 cyg_fileio_seltrue,
2387 logfs_fo_fsync,
2388 logfs_fo_close,
2389 (cyg_fileop_fstat *)cyg_fileio_erofs,
2390 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2391 (cyg_fileop_setinfo *)cyg_fileio_erofs,
2392 };
2393
2394 // -------------------------------------------------------------------------
2395 // logfs_mount()
2396 // Process a mount request. This mainly finds root for the
2397 // filesystem.
2398
2399 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2400 {
2401 return ENOERR;
2402 }
2403
2404 static int logfs_umount(cyg_mtab_entry *mte)
2405 {
2406 return ENOERR;
2407 }
2408
2409 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2410 int mode, cyg_file *file)
2411 {
2412 file->f_flag |= mode & CYG_FILE_MODE_MASK;
2413 file->f_type = CYG_FILE_TYPE_FILE;
2414 file->f_ops = &logfs_fileops;
2415 file->f_offset = 0;
2416 file->f_data = 0;
2417 file->f_xops = 0;
2418 return ENOERR;
2419 }
2420
2421 // -------------------------------------------------------------------------
2422 // logfs_fo_write()
2423 // Write data to file.
2424
2425 static int
2426 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2427 {
2428 int i;
2429 for (i = 0; i < uio->uio_iovcnt; i++)
2430 {
2431 cyg_iovec *iov = &uio->uio_iov[i];
2432 char *buf = (char *) iov->iov_base;
2433 off_t len = iov->iov_len;
2434
2435 diag_write(buf, len);
2436 }
2437 uio->uio_resid = 0;
2438
2439 return ENOERR;
2440 }
2441 static int
2442 logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2443 {
2444 return ENOERR;
2445 }
2446
2447 // -------------------------------------------------------------------------
2448 // romfs_fo_close()
2449 // Close a file. We just clear out the data pointer.
2450
2451 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
2452 {
2453 return ENOERR;
2454 }
2455
2456 static bool
2457 ramiodev_init( struct cyg_devtab_entry *tab )
2458 {
2459 return true;
2460 }
2461
2462 static Cyg_ErrNo
2463 ramiodev_bread( cyg_io_handle_t handle, void *buf, cyg_uint32 *len,
2464 cyg_uint32 pos)
2465 {
2466 if (*len+pos>ramblockdevice_size)
2467 {
2468 *len=ramblockdevice_size-pos;
2469 }
2470 memcpy(buf, ramblockdevice+pos, *len);
2471 return ENOERR;
2472 }
2473
2474 static Cyg_ErrNo
2475 ramiodev_bwrite( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len,
2476 cyg_uint32 pos )
2477 {
2478 if (((pos%4)!=0)||(((*len)%4)!=0))
2479 {
2480 diag_printf("Unaligned write %d %d!", pos, *len);
2481 }
2482
2483 memcpy(ramblockdevice+pos, buf, *len);
2484 return ENOERR;
2485 }
2486
2487 static Cyg_ErrNo
2488 ramiodev_get_config( cyg_io_handle_t handle,
2489 cyg_uint32 key,
2490 void* buf,
2491 cyg_uint32* len)
2492 {
2493 switch (key) {
2494 case CYG_IO_GET_CONFIG_FLASH_ERASE:
2495 {
2496 if ( *len != sizeof( cyg_io_flash_getconfig_erase_t ) )
2497 return -EINVAL;
2498 {
2499 cyg_io_flash_getconfig_erase_t *e = (cyg_io_flash_getconfig_erase_t *)buf;
2500 char *startpos = ramblockdevice + e->offset;
2501
2502 if (((e->offset%(64*1024))!=0)||((e->len%(64*1024))!=0))
2503 {
2504 diag_printf("Erease is not aligned %d %d\n", e->offset, e->len);
2505 }
2506
2507 memset(startpos, 0xff, e->len);
2508
2509 e->flasherr = 0;
2510 }
2511 return ENOERR;
2512 }
2513 case CYG_IO_GET_CONFIG_FLASH_DEVSIZE:
2514 {
2515 if ( *len != sizeof( cyg_io_flash_getconfig_devsize_t ) )
2516 return -EINVAL;
2517 {
2518 cyg_io_flash_getconfig_devsize_t *d =
2519 (cyg_io_flash_getconfig_devsize_t *)buf;
2520
2521 d->dev_size = ramblockdevice_size;
2522 }
2523 return ENOERR;
2524 }
2525
2526 case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE:
2527 {
2528 cyg_io_flash_getconfig_blocksize_t *b =
2529 (cyg_io_flash_getconfig_blocksize_t *)buf;
2530 if ( *len != sizeof( cyg_io_flash_getconfig_blocksize_t ) )
2531 return -EINVAL;
2532
2533 // offset unused for now
2534 b->block_size = 64*1024;
2535 return ENOERR;
2536 }
2537
2538 default:
2539 return -EINVAL;
2540 }
2541 }
2542
2543 static Cyg_ErrNo
2544 ramiodev_set_config( cyg_io_handle_t handle,
2545 cyg_uint32 key,
2546 const void* buf,
2547 cyg_uint32* len)
2548 {
2549
2550 switch (key) {
2551 default:
2552 return -EINVAL;
2553 }
2554 } // ramiodev_set_config()
2555
2556 // get_config/set_config should be added later to provide the other flash
2557 // operations possible, like erase etc.
2558
2559 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops,
2560 &ramiodev_bwrite,
2561 &ramiodev_bread,
2562 0, // no select
2563 &ramiodev_get_config,
2564 &ramiodev_set_config
2565 );
2566
2567
2568 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1,
2569 "/dev/ram",
2570 0,
2571 &cyg_io_ramdev1_ops,
2572 &ramiodev_init,
2573 0, // No lookup required
2574 NULL );

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)