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

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)