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

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)