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