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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)