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

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)