zy1000: keep up with command.h cleanup
[openocd.git] / src / ecosboard.c
1 /***************************************************************************
2 * Copyright (C) 2007-2009 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 <helper/types.h>
25 #include <jtag/jtag.h>
26 #include <helper/ioutil.h>
27 #include <helper/configuration.h>
28
29 #include <server/server.h>
30 #include <server/telnet_server.h>
31 #include <server/gdb_server.h>
32 #include <openocd.h>
33
34 #include <helper/time_support.h>
35 #include <sys/time.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <errno.h>
41
42 #include <cyg/io/flash.h>
43 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
44 #include <network.h>
45
46 #include <fcntl.h>
47 #include <sys/stat.h>
48 #include <cyg/fileio/fileio.h>
49 #include <dirent.h>
50 #include <cyg/athttpd/http.h>
51 #include <cyg/athttpd/socket.h>
52 #include <cyg/athttpd/handler.h>
53 #include <cyg/athttpd/cgi.h>
54 #include <cyg/athttpd/forms.h>
55 #include <cyg/discover/discover.h>
56 #include <cyg/hal/hal_diag.h>
57 #include <cyg/kernel/kapi.h>
58 #include <cyg/io/serialio.h>
59 #include <cyg/io/io.h>
60 #include <netinet/tcp.h>
61 #include "rom.h"
62 #include <sys/ioctl.h>
63 #include <sys/socket.h>
64 #include <netinet/in.h>
65 #include <net/if.h>
66 #include <arpa/inet.h>
67 #include <sys/types.h>
68 #include <sys/socket.h>
69 #include <netdb.h>
70 #include <netinet/in.h>
71 #include <unistd.h>
72 #include <arpa/inet.h>
73 #include <stdio.h>
74 #include <ifaddrs.h>
75 #include <string.h>
76
77 #include <unistd.h>
78 #include <stdio.h>
79
80 #include <openocd.h>
81
82 #ifdef CYGPKG_HAL_NIOS2
83 #define ZY1000_SER_DEV "/dev/uart_0"
84 #else
85 #define ZY1000_SER_DEV "/dev/ser0"
86
87 #endif
88
89
90 #define MAX_IFS 64
91 #if defined(CYGPKG_NET_FREEBSD_STACK)
92 #include <tftp_support.h>
93 /* posix compatibility broken*/
94 struct tftpd_fileops fileops =
95 {
96 (int (*)(const char *, int))open,
97 close,
98 (int (*)(int, const void *, int))write,
99 (int (*)(int, void *, int))read
100 };
101
102 #endif
103
104
105 void diag_write(char *buf, int len)
106 {
107 int j;
108 for (j = 0; j < len; j++)
109 {
110 diag_printf("%c", buf[j]);
111 }
112 }
113
114 static bool serialLog = true;
115 static bool writeLog = true;
116
117 char hwaddr[512];
118
119
120 extern struct flash_driver *flash_drivers[];
121 extern struct target_type *target_types[];
122
123 #ifdef CYGPKG_PROFILE_GPROF
124 #include <cyg/profile/profile.h>
125
126 extern char _stext, _etext; // Defined by the linker
127
128 static char *start_of_code=&_stext;
129 static char *end_of_code=&_etext;
130
131 void start_profile(void)
132 {
133 // This starts up the system-wide profiling, gathering
134 // profile information on all of the code, with a 16 byte
135 // "bucket" size, at a rate of 100us/profile hit.
136 // Note: a bucket size of 16 will give pretty good function
137 // resolution. Much smaller and the buffer becomes
138 // much too large for very little gain.
139 // Note: a timer period of 100us is also a reasonable
140 // compromise. Any smaller and the overhead of
141 // handling the timter (profile) interrupt could
142 // swamp the system. A fast processor might get
143 // by with a smaller value, but a slow one could
144 // even be swamped by this value. If the value is
145 // too large, the usefulness of the profile is reduced.
146
147 // no more interrupts than 1/10ms.
148 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
149 // profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
150 profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
151 }
152 #endif
153
154 static FILE *log;
155
156 static char reboot_stack[2048];
157
158 static void zylinjtag_reboot(cyg_addrword_t data)
159 {
160 serialLog = true;
161 diag_printf("Rebooting in 500 ticks..\n");
162 cyg_thread_delay(500);
163 diag_printf("Unmounting /config..\n");
164 umount("/config");
165 diag_printf("Rebooting..\n");
166 HAL_PLATFORM_RESET();
167 }
168 static cyg_thread zylinjtag_thread_object;
169 static cyg_handle_t zylinjtag_thread_handle;
170
171 void reboot(void)
172 {
173 cyg_thread_create(1, zylinjtag_reboot, (cyg_addrword_t) 0, "reboot Thread",
174 (void *) reboot_stack, sizeof(reboot_stack),
175 &zylinjtag_thread_handle, &zylinjtag_thread_object);
176 cyg_thread_resume(zylinjtag_thread_handle);
177 }
178
179 static char zylinjtag_reboot_port_stack[2048];
180 static cyg_thread zylinjtag_reboot_port_thread_object;
181 static cyg_handle_t zylinjtag_reboot_port_thread_handle;
182
183 static void zylinjtag_reboot_port_task(cyg_addrword_t data)
184 {
185 int so_reuseaddr_option = 1;
186
187 int fd;
188 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
189 {
190 LOG_ERROR("error creating socket: %s", strerror(errno));
191 exit(-1);
192 }
193
194 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
195 sizeof(int));
196
197 struct sockaddr_in sin;
198 unsigned int address_size;
199 address_size = sizeof(sin);
200 memset(&sin, 0, sizeof(sin));
201 sin.sin_family = AF_INET;
202 sin.sin_addr.s_addr = INADDR_ANY;
203 sin.sin_port = htons(1234);
204
205 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
206 {
207 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
208 exit(-1);
209 }
210
211 if (listen(fd, 1) == -1)
212 {
213 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
214 exit(-1);
215 }
216 // socket_nonblock(fd);
217
218
219 accept(fd, (struct sockaddr *) &sin, &address_size);
220
221 diag_printf("Got reboot signal on port 1234");
222
223 reboot();
224
225 }
226
227 void reboot_port(void)
228 {
229 cyg_thread_create(1, zylinjtag_reboot_port_task, (cyg_addrword_t) 0, "wait for reboot signal on port 1234",
230 (void *) zylinjtag_reboot_port_stack, sizeof(zylinjtag_reboot_port_stack),
231 &zylinjtag_reboot_port_thread_handle, &zylinjtag_reboot_port_thread_object);
232 cyg_thread_resume(zylinjtag_reboot_port_thread_handle);
233 }
234
235 int configuration_output_handler(struct command_context *context,
236 const char* line)
237 {
238 diag_printf("%s", line);
239
240 return ERROR_OK;
241 }
242
243 int zy1000_configuration_output_handler_log(struct command_context *context,
244 const char* line)
245 {
246 LOG_USER_N("%s", line);
247
248 return ERROR_OK;
249 }
250
251 #ifdef CYGPKG_PROFILE_GPROF
252 //extern int64_t totaltime;
253
254 static int zylinjtag_Jim_Command_profile(Jim_Interp *interp, int argc,
255 Jim_Obj * const *argv)
256 {
257 if ((argc == 2) && (strcmp(Jim_GetString(argv[1], NULL), "stats")==0))
258 {
259 // profile_off();
260 //LOG_USER("Stats %dms sleeping in select()", (int)totaltime);
261 } else
262 {
263 LOG_USER("Profiling started");
264 start_profile();
265 //totaltime = 0;
266 }
267 return ERROR_OK;
268 }
269
270 #endif
271
272 externC void phi_init_all_network_interfaces(void);
273
274 struct command_context *cmd_ctx;
275
276 static bool webRunning = false;
277
278 void keep_webserver(void)
279 {
280 // Target initialisation is only attempted at startup, so we sleep forever and
281 // let the http server bail us out(i.e. get config files set up).
282 diag_printf("OpenOCD has invoked exit().\n"
283 "Use web server to correct any configuration settings and reboot.\n");
284 if (!webRunning)
285 reboot();
286
287 // exit() will terminate the current thread and we we'll then sleep eternally or
288 // we'll have a reboot scheduled.
289 }
290
291 extern void printDccChar(char c);
292
293 static char logBuffer[128 * 1024];
294 static const int logSize = sizeof(logBuffer);
295 int writePtr = 0;
296 int logCount = 0;
297
298 void _zylinjtag_diag_write_char(char c, void **param)
299 {
300 if (writeLog)
301 {
302 logBuffer[writePtr] = c;
303 writePtr = (writePtr + 1) % logSize;
304 logCount++;
305 }
306 if (serialLog)
307 {
308 if (c == '\n')
309 {
310 HAL_DIAG_WRITE_CHAR('\r');
311 }
312 HAL_DIAG_WRITE_CHAR(c);
313 }
314
315 #ifdef CYGPKG_HAL_ZYLIN_PHI
316 printDccChar(c);
317 #endif
318 }
319
320 void copyfile(char *name2, char *name1);
321
322 void copydir(char *name, char *destdir);
323
324 #if 0
325 MTAB_ENTRY(romfs_mte1,
326 "/rom",
327 "romfs",
328 "",
329 (CYG_ADDRWORD) &filedata[0]);
330 #endif
331
332 void openocd_sleep_prelude(void)
333 {
334 cyg_mutex_unlock(&httpstate.jim_lock);
335 }
336
337 void openocd_sleep_postlude(void)
338 {
339 cyg_mutex_lock(&httpstate.jim_lock);
340 }
341
342 void format(void)
343 {
344 #ifdef CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1
345 diag_printf("Formatting JFFS2...\n");
346
347 cyg_io_handle_t handle;
348
349 Cyg_ErrNo err;
350 err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
351 if (err != ENOERR)
352 {
353 diag_printf("Flash Error cyg_io_lookup: %d\n", err);
354 reboot();
355 }
356
357 cyg_uint32 len;
358 cyg_io_flash_getconfig_devsize_t ds;
359 len = sizeof(ds);
360 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
361 if (err != ENOERR)
362 {
363 diag_printf("Flash error cyg_io_get_config %d\n", err);
364 reboot();
365 }
366
367 cyg_io_flash_getconfig_erase_t e;
368 len = sizeof(e);
369
370 e.offset = 0;
371 e.len = ds.dev_size;
372
373 diag_printf("Formatting 0x%08x bytes\n", (int)ds.dev_size);
374 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len);
375 if (err != ENOERR)
376 {
377 diag_printf("Flash erase error %d offset 0x%08x\n", err, e.err_address);
378 reboot();
379 }
380
381 diag_printf("Flash formatted successfully\n");
382 #endif
383
384 reboot();
385 }
386
387 static int zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp, int argc,
388 Jim_Obj * const *argv)
389 {
390 if (argc != 1)
391 {
392 return JIM_ERR;
393 }
394
395 format();
396 for (;;)
397 ;
398 }
399
400 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
401 Jim_Obj * const *argv)
402 {
403 cyg_handle_t thread = 0;
404 cyg_uint16 id = 0;
405 Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
406
407 /* Loop over the threads, and generate a table row for
408 * each.
409 */
410 while (cyg_thread_get_next(&thread, &id))
411 {
412 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
413
414 cyg_thread_info info;
415 char *state_string;
416
417 cyg_thread_get_info(thread, id, &info);
418
419 if (info.name == NULL)
420 info.name = "<no name>";
421
422 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
423 info.name, strlen(info.name)));
424
425 /* Translate the state into a string.
426 */
427 if (info.state == 0)
428 state_string = "RUN";
429 else if (info.state & 0x04)
430 state_string = "SUSP";
431 else
432 switch (info.state & 0x1b)
433 {
434 case 0x01:
435 state_string = "SLEEP";
436 break;
437 case 0x02:
438 state_string = "CNTSLEEP";
439 break;
440 case 0x08:
441 state_string = "CREATE";
442 break;
443 case 0x10:
444 state_string = "EXIT";
445 break;
446 default:
447 state_string = "????";
448 break;
449 }
450
451 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
452 state_string, strlen(state_string)));
453
454 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, id));
455 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
456 info.set_pri));
457 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
458 info.cur_pri));
459
460 Jim_ListAppendElement(interp, threads, threadObj);
461 }
462 Jim_SetResult(interp, threads);
463
464 return JIM_OK;
465 }
466
467 static int zylinjtag_Jim_Command_log(Jim_Interp *interp, int argc,
468 Jim_Obj * const *argv)
469 {
470 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
471
472 if (logCount >= logSize)
473 {
474 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer + logCount
475 % logSize, logSize - logCount % logSize);
476 }
477 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
478
479 Jim_SetResult(interp, tclOutput);
480 return JIM_OK;
481 }
482
483 static int zylinjtag_Jim_Command_reboot(Jim_Interp *interp, int argc,
484 Jim_Obj * const *argv)
485 {
486 reboot();
487 return JIM_OK;
488 }
489
490 static void zylinjtag_startNetwork(void)
491 {
492 // Bring TCP/IP up immediately before we're ready to accept commands.
493 //
494 // That is as soon as a PING responds, we're accepting telnet sessions.
495 #if defined(CYGPKG_NET_FREEBSD_STACK)
496 phi_init_all_network_interfaces();
497 #else
498 lwip_init();
499 #endif
500 if (!eth0_up)
501 {
502 diag_printf("Network not up and running\n");
503 exit(-1);
504 }
505
506 /* very first thing we want is a reboot capability */
507 reboot_port();
508
509 #if defined(CYGPKG_NET_FREEBSD_STACK)
510 /*start TFTP*/
511 tftpd_start(69, &fileops);
512 #endif
513
514 cyg_httpd_init_tcl_interpreter();
515
516 Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
517 NULL, NULL);
518 Jim_CreateCommand(httpstate.jim_interp, "zy1000_reboot",
519 zylinjtag_Jim_Command_reboot, NULL, NULL);
520 Jim_CreateCommand(httpstate.jim_interp, "threads",
521 zylinjtag_Jim_Command_threads, NULL, NULL);
522 Jim_CreateCommand(httpstate.jim_interp, "format_jffs2",
523 zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
524
525 cyg_httpd_start();
526
527 webRunning = true;
528
529 diag_printf("Web server running\n");
530
531 int s;
532 struct ifreq ifr;
533 s = socket(AF_INET, SOCK_DGRAM, 0);
534 if (s >= 0)
535 {
536 strcpy(ifr.ifr_name, "eth0");
537 int res;
538 res = ioctl(s, SIOCGIFHWADDR, &ifr);
539 close(s);
540
541 if (res < 0)
542 {
543 diag_printf("Can't obtain MAC address\n");
544 reboot();
545 }
546 }
547
548 sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
549 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
550 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
551 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
552 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
553 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
554 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
555
556 discover_message
557 = alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
558
559 discover_launch();
560 }
561
562 static void print_exception_handler(cyg_addrword_t data, cyg_code_t exception,
563 cyg_addrword_t info)
564 {
565 writeLog = false;
566 serialLog = true;
567 char *infoStr = "unknown";
568 switch (exception)
569 {
570 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
571 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
572 infoStr = "undefined instruction";
573 break;
574 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
575 infoStr = "software interrupt";
576 break;
577 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
578 infoStr = "abort prefetch";
579 break;
580 case CYGNUM_HAL_VECTOR_ABORT_DATA:
581 infoStr = "abort data";
582 break;
583 #endif
584 default:
585 break;
586 }
587
588 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
589
590 diag_printf("Dumping log\n---\n");
591 if (logCount >= logSize)
592 {
593 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
594 }
595 diag_write(logBuffer, writePtr);
596
597 diag_printf("---\nLogdump complete.\n");
598 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
599 diag_printf("\n---\nRebooting\n");
600 HAL_PLATFORM_RESET();
601
602 }
603
604 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
605 static void setHandler(cyg_code_t exception)
606 {
607 cyg_exception_handler_t *old_handler;
608 cyg_addrword_t old_data;
609
610 cyg_exception_set_handler(exception, print_exception_handler, 0,
611 &old_handler, &old_data);
612 }
613 #endif
614
615 static cyg_thread zylinjtag_uart_thread_object;
616 static cyg_handle_t zylinjtag_uart_thread_handle;
617 static char uart_stack[4096];
618
619 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
620 static char backwardBuffer[1024];
621
622 void setNoDelay(int session, int flag)
623 {
624 #if 1
625 // This decreases latency dramatically for e.g. GDB load which
626 // does not have a sliding window protocol
627 //
628 // Can cause *lots* of TCP/IP packets to be sent and it would have
629 // to be enabled/disabled on the fly to avoid the CPU being
630 // overloaded...
631 setsockopt(session, /* socket affected */
632 IPPROTO_TCP, /* set option at TCP level */
633 TCP_NODELAY, /* name of option */
634 (char *) &flag, /* the cast is historical
635 cruft */
636 sizeof(int)); /* length of option value */
637 #endif
638 }
639
640 #define TEST_TCPIP() 0
641
642 #if TEST_TCPIP
643 struct
644 {
645 int req;
646 int actual;
647 int req2;
648 int actual2;
649 } tcpipSent[512 * 1024];
650 int cur;
651 #endif
652
653 static void zylinjtag_uart(cyg_addrword_t data)
654 {
655 int so_reuseaddr_option = 1;
656
657 int fd;
658 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
659 {
660 LOG_ERROR("error creating socket: %s", strerror(errno));
661 exit(-1);
662 }
663
664 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
665 sizeof(int));
666
667 struct sockaddr_in sin;
668 unsigned int address_size;
669 address_size = sizeof(sin);
670 memset(&sin, 0, sizeof(sin));
671 sin.sin_family = AF_INET;
672 sin.sin_addr.s_addr = INADDR_ANY;
673 sin.sin_port = htons(5555);
674
675 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
676 {
677 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
678 exit(-1);
679 }
680
681 if (listen(fd, 1) == -1)
682 {
683 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
684 exit(-1);
685 }
686 // socket_nonblock(fd);
687
688
689 for (;;)
690 {
691 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
692 if (session < 0)
693 {
694 continue;
695 }
696
697 setNoDelay(session, 1);
698 int oldopts = fcntl(session, F_GETFL, 0);
699 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
700
701 int serHandle = open(ZY1000_SER_DEV, O_RDWR | O_NONBLOCK);
702 if (serHandle < 0)
703 {
704 close(session);
705 continue;
706 }
707
708 #ifdef CYGPKG_PROFILE_GPROF
709 start_profile();
710 #endif
711 size_t actual = 0;
712 size_t actual2 = 0;
713 size_t pos, pos2;
714 pos = 0;
715 pos2 = 0;
716 #if TEST_TCPIP
717 cur = 0;
718 #endif
719 for (;;)
720 {
721 fd_set write_fds;
722 fd_set read_fds;
723 FD_ZERO(&write_fds);
724 FD_ZERO(&read_fds);
725 int fd_max = -1;
726 FD_SET(session, &read_fds);
727 fd_max = session;
728 FD_SET(serHandle, &read_fds);
729 if (serHandle > fd_max)
730 {
731 fd_max = serHandle;
732 }
733 /* Wait... */
734
735 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
736 if ((actual == 0) && (actual2 == 0))
737 {
738 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
739 if (retval <= 0)
740 {
741 break;
742 }
743 }
744
745 if (actual2 <= 0)
746 {
747 memset(backwardBuffer, 's', sizeof(backwardBuffer));
748 int t;
749 t = read(serHandle, backwardBuffer,
750 sizeof(backwardBuffer));
751 actual2 = t;
752 if (t < 0)
753 {
754 if (errno != EAGAIN)
755 {
756 goto closeSession;
757 }
758 actual2 = 0;
759 }
760 pos2 = 0;
761 }
762
763 size_t y = 0;
764 if (actual2 > 0)
765 {
766 int written = write(session, backwardBuffer + pos2, actual2);
767 if (written <= 0)
768 goto closeSession;
769 actual2 -= written;
770 pos2 += written;
771 y = written;
772 }
773
774 if (FD_ISSET(session, &read_fds)
775 && (sizeof(forwardBuffer) > actual))
776 {
777 // NB! Here it is important that we empty the TCP/IP read buffer
778 // to make transmission tick right
779 memmove(forwardBuffer, forwardBuffer + pos, actual);
780 pos = 0;
781 int t;
782 // this will block if there is no data at all
783 t = read_socket(session, forwardBuffer + actual,
784 sizeof(forwardBuffer) - actual);
785 if (t <= 0)
786 {
787 goto closeSession;
788 }
789 actual += t;
790 }
791
792 int y2 = 0;
793 if (actual > 0)
794 {
795 /* Do not put things into the serial buffer if it has something to send
796 * as that can cause a single byte to be sent at the time.
797 *
798 *
799 */
800 int written = write(serHandle, forwardBuffer + pos, actual);
801 if (written < 0)
802 {
803 if (errno != EAGAIN)
804 {
805 goto closeSession;
806 }
807 // The serial buffer is full
808 written = 0;
809 }
810 else
811 {
812 actual -= written;
813 pos += written;
814 }
815 y2 = written;
816 }
817 #if TEST_TCPIP
818 if (cur < 1024)
819 {
820 tcpipSent[cur].req = x;
821 tcpipSent[cur].actual = y;
822 tcpipSent[cur].req2 = x2;
823 tcpipSent[cur].actual2 = y2;
824 cur++;
825 }
826 #endif
827 }
828 closeSession: close(session);
829 close(serHandle);
830
831 #if TEST_TCPIP
832 int i;
833 for (i = 0; i < 1024; i++)
834 {
835 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual,
836 tcpipSent[i].req2, tcpipSent[i].actual2);
837
838 }
839 #endif
840 }
841 close(fd);
842
843 }
844
845 void startUart(void)
846 {
847 cyg_thread_create(1, zylinjtag_uart, (cyg_addrword_t) 0, "uart thread",
848 (void *) uart_stack, sizeof(uart_stack),
849 &zylinjtag_uart_thread_handle, &zylinjtag_uart_thread_object);
850 cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
851 cyg_thread_resume(zylinjtag_uart_thread_handle);
852 }
853
854 static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
855 Jim_Obj * const *argv)
856 {
857 static int current_baud = 38400;
858 if (argc == 1)
859 {
860 command_print(cmd_ctx, "%d", current_baud);
861 return JIM_OK;
862 }
863 else if (argc != 2)
864 {
865 return JIM_ERR;
866 }
867
868 long new_baudrate;
869 if (Jim_GetLong(interp, argv[1], &new_baudrate) != JIM_OK)
870 return JIM_ERR;
871
872 current_baud = new_baudrate;
873
874 int baud;
875 switch (current_baud)
876 {
877 case 9600:
878 baud = CYGNUM_SERIAL_BAUD_9600;
879 break;
880 case 19200:
881 baud = CYGNUM_SERIAL_BAUD_19200;
882 break;
883 case 38400:
884 baud = CYGNUM_SERIAL_BAUD_38400;
885 break;
886 case 57600:
887 baud = CYGNUM_SERIAL_BAUD_57600;
888 break;
889 case 115200:
890 baud = CYGNUM_SERIAL_BAUD_115200;
891 break;
892 case 230400:
893 baud = CYGNUM_SERIAL_BAUD_230400;
894 break;
895 default:
896 command_print(cmd_ctx, "unsupported baudrate");
897 return ERROR_INVALID_ARGUMENTS;
898 }
899
900 cyg_serial_info_t buf;
901 cyg_uint32 len = 1;
902 //get existing serial configuration
903 len = sizeof(cyg_serial_info_t);
904 int err;
905 cyg_io_handle_t serial_handle;
906
907 err = cyg_io_lookup(ZY1000_SER_DEV, &serial_handle);
908 if (err != ENOERR)
909 {
910 LOG_ERROR("Could not open serial port\n");
911 return JIM_ERR;
912 }
913
914 err = cyg_io_get_config(serial_handle,
915 CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
916 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf,
917 &len);
918 if (err != ENOERR)
919 {
920 LOG_ERROR("Failed to get serial port settings %d", err);
921 return JIM_ERR;
922 }
923 buf.baud = baud;
924
925 err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf,
926 &len);
927 if (err != ENOERR)
928 {
929 LOG_ERROR("Failed to set serial port settings %d", err);
930 return JIM_ERR;
931 }
932
933 return JIM_OK;
934 }
935
936 bool logAllToSerial = false;
937
938
939 int boolParam(char *var);
940
941
942 static const char *zylin_config_dir="/config/settings";
943
944 static int add_default_dirs(void)
945 {
946 add_script_search_dir(zylin_config_dir);
947 add_script_search_dir("/rom/lib/openocd");
948 add_script_search_dir("/rom");
949 return ERROR_OK;
950 }
951
952 int main(int argc, char *argv[])
953 {
954 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
955 * need to allocate towards the end of the heap. */
956
957 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
958 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
959 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
960 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
961 #endif
962
963 int err;
964
965 atexit(keep_webserver);
966
967 diag_init_putc(_zylinjtag_diag_write_char);
968 // We want this in the log.
969 diag_printf("Zylin ZY1000.\n");
970
971 err = mount("", "/ram", "ramfs");
972 if (err < 0)
973 {
974 diag_printf("unable to mount ramfs\n");
975 }
976 chdir("/ram");
977
978 char address[16];
979 sprintf(address, "%p", &filedata[0]);
980 err = mount(address, "/rom", "romfs");
981 if (err < 0)
982 {
983 diag_printf("unable to mount /rom\n");
984 }
985
986 err = mount("", "/log", "logfs");
987 if (err < 0)
988 {
989 diag_printf("unable to mount logfs\n");
990 }
991
992 err = mount("", "/tftp", "tftpfs");
993 if (err < 0)
994 {
995 diag_printf("unable to mount logfs\n");
996 }
997
998 log = fopen("/log/log", "w");
999 if (log == NULL)
1000 {
1001 diag_printf("Could not open log file /ram/log\n");
1002 exit(-1);
1003 }
1004
1005
1006 copydir("/rom", "/ram/cgi");
1007
1008 err = mount("/dev/flash1", "/config", "jffs2");
1009 if (err < 0)
1010 {
1011 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1012 err = mount("", "/config", "ramfs");
1013 if (err < 0)
1014 {
1015 diag_printf("unable to mount /config as ramdisk.\n");
1016 reboot();
1017 }
1018 }
1019 else
1020 {
1021 /* are we using a ram disk instead of a flash disk? This is used
1022 * for ZY1000 live demo...
1023 *
1024 * copy over flash disk to ram block device
1025 */
1026 if (boolParam("ramdisk"))
1027 {
1028 diag_printf("Unmounting /config from flash and using ram instead\n");
1029 err = umount("/config");
1030 if (err < 0)
1031 {
1032 diag_printf("unable to unmount jffs\n");
1033 reboot();
1034 }
1035
1036 err = mount("/dev/flash1", "/config2", "jffs2");
1037 if (err < 0)
1038 {
1039 diag_printf("unable to mount jffs\n");
1040 reboot();
1041 }
1042
1043 err = mount("", "/config", "ramfs");
1044 if (err < 0)
1045 {
1046 diag_printf("unable to mount ram block device\n");
1047 reboot();
1048 }
1049
1050 // copydir("/config2", "/config");
1051 copyfile("/config2/ip", "/config/ip");
1052 copydir("/config2/settings", "/config/settings");
1053
1054 umount("/config2");
1055 }
1056 }
1057
1058 mkdir(zylin_config_dir, 0777);
1059 char *dirname = alloc_printf("%s/target", zylin_config_dir);
1060 mkdir(dirname, 0777);
1061 free(dirname);
1062 dirname = alloc_printf("%s/board", zylin_config_dir);
1063 mkdir(dirname, 0777);
1064 free(dirname);
1065 dirname = alloc_printf("%s/event", zylin_config_dir);
1066 mkdir(dirname, 0777);
1067 free(dirname);
1068
1069 logAllToSerial = boolParam("logserial");
1070
1071 // We need the network & web server in case there is something wrong with
1072 // the config files that invoke exit()
1073 zylinjtag_startNetwork();
1074
1075 /* we're going to access the jim interpreter from here on... */
1076 openocd_sleep_postlude();
1077 startUart();
1078
1079 add_default_dirs();
1080
1081 /* initialize commandline interface */
1082 struct command_context * cmd_ctx;
1083 struct command_context *setup_command_handler(Jim_Interp *interp);
1084 cmd_ctx = setup_command_handler(httpstate.jim_interp);
1085 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1086 command_context_mode(cmd_ctx, COMMAND_CONFIG);
1087
1088 if (ioutil_init(cmd_ctx) != ERROR_OK)
1089 return EXIT_FAILURE;
1090
1091 #ifdef CYGPKG_PROFILE_GPROF
1092 Jim_CreateCommand(httpstate.jim_interp, "zy1000_profile", zylinjtag_Jim_Command_profile,
1093 NULL, NULL);
1094 #endif
1095
1096 Jim_CreateCommand(httpstate.jim_interp, "uart", zylinjtag_Jim_Command_uart, NULL, NULL);
1097
1098
1099 log_init();
1100
1101 set_log_output(cmd_ctx, log);
1102
1103 LOG_DEBUG("log init complete");
1104
1105 // diag_printf("Executing config files\n");
1106
1107 if (logAllToSerial)
1108 {
1109 diag_printf(
1110 "%s/logserial = 1 => sending log output to serial port using \"debug_level 3\" as default.\n", zylin_config_dir);
1111 command_run_line(cmd_ctx, "debug_level 3");
1112 }
1113
1114 command_run_linef(cmd_ctx, "script /rom/openocd.cfg");
1115
1116 int ret;
1117 ret = server_init(cmd_ctx);
1118 if (ERROR_OK != ret)
1119 return EXIT_FAILURE;
1120
1121 /* we MUST always run the init command as it will launch telnet sessions */
1122 command_run_line(cmd_ctx, "init");
1123
1124 // FIX!!! Yuk!
1125 // diag_printf() is really invoked from many more places than we trust it
1126 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1127 //
1128 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1129 // fingers that it doesn't cause any crashes.
1130 diag_printf("Init complete, GDB & telnet servers launched.\n");
1131 command_set_output_handler(cmd_ctx,
1132 zy1000_configuration_output_handler_log, NULL);
1133 if (!logAllToSerial)
1134 {
1135 serialLog = false;
1136 }
1137
1138 /* handle network connections */
1139 server_loop(cmd_ctx);
1140 openocd_sleep_prelude();
1141
1142 /* shut server down */
1143 server_quit();
1144
1145 /* free commandline interface */
1146 command_done(cmd_ctx);
1147 umount("/config");
1148
1149 exit(0);
1150 for (;;)
1151 ;
1152 }
1153
1154 cyg_int32 cyg_httpd_exec_cgi_tcl(char *file_name);
1155 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1156 {
1157 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1158 return 0;
1159 }
1160
1161 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1162
1163 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1164 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1165
1166 #include <pkgconf/system.h>
1167 #include <pkgconf/hal.h>
1168 #include <pkgconf/kernel.h>
1169 #include <pkgconf/io_fileio.h>
1170 #include <pkgconf/fs_rom.h>
1171
1172 #include <cyg/kernel/ktypes.h> // base kernel types
1173 #include <cyg/infra/cyg_trac.h> // tracing macros
1174 #include <cyg/infra/cyg_ass.h> // assertion macros
1175 #include <cyg/fileio/fileio.h>
1176 #include <cyg/kernel/kapi.h>
1177 #include <cyg/infra/diag.h>
1178
1179 //==========================================================================
1180 // Eventually we want to eXecute In Place from the ROM in a protected
1181 // environment, so we'll need executables to be aligned to a boundary
1182 // suitable for MMU protection. A suitable boundary would be the 4k
1183 // boundary in all the CPU architectures I am currently aware of.
1184
1185 // Forward definitions
1186
1187 // Filesystem operations
1188 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1189 static int tftpfs_umount(cyg_mtab_entry *mte);
1190 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1191 int mode, cyg_file *fte);
1192 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1193 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1194
1195 // File operations
1196 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1197 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
1198 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
1199
1200 //==========================================================================
1201 // Filesystem table entries
1202
1203 // -------------------------------------------------------------------------
1204 // Fstab entry.
1205 // This defines the entry in the filesystem table.
1206 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1207 // we should never block in any filesystem operations.
1208 #if 1
1209 FSTAB_ENTRY(tftpfs_fste, "tftpfs", 0,
1210 CYG_SYNCMODE_NONE,
1211 tftpfs_mount,
1212 tftpfs_umount,
1213 tftpfs_open,
1214 (cyg_fsop_unlink *)cyg_fileio_erofs,
1215 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1216 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1217 (cyg_fsop_rename *)cyg_fileio_erofs,
1218 (cyg_fsop_link *)cyg_fileio_erofs,
1219 (cyg_fsop_opendir *)cyg_fileio_erofs,
1220 (cyg_fsop_chdir *)cyg_fileio_erofs,
1221 (cyg_fsop_stat *)cyg_fileio_erofs,
1222 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1223 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1224 #endif
1225
1226 // -------------------------------------------------------------------------
1227 // mtab entry.
1228 // This defines a single ROMFS loaded into ROM at the configured address
1229 //
1230 // MTAB_ENTRY(rom_mte, // structure name
1231 // "/rom", // mount point
1232 // "romfs", // FIlesystem type
1233 // "", // hardware device
1234 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
1235 //);
1236
1237
1238 // -------------------------------------------------------------------------
1239 // File operations.
1240 // This set of file operations are used for normal open files.
1241
1242 static cyg_fileops tftpfs_fileops =
1243 { tftpfs_fo_read, tftpfs_fo_write, tftpfs_fo_lseek,
1244 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1245 tftpfs_fo_fsync, tftpfs_fo_close,
1246 (cyg_fileop_fstat *) cyg_fileio_erofs,
1247 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1248 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1249
1250 // -------------------------------------------------------------------------
1251 // tftpfs_mount()
1252 // Process a mount request. This mainly finds root for the
1253 // filesystem.
1254
1255 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1256 {
1257 return ENOERR;
1258 }
1259
1260 static int tftpfs_umount(cyg_mtab_entry *mte)
1261 {
1262 return ENOERR;
1263 }
1264
1265 struct Tftp
1266 {
1267 int write;
1268 int readFile;
1269 cyg_uint8 *mem;
1270 int actual;
1271 char *server;
1272 char *file;
1273 };
1274
1275 static void freeTftp(struct Tftp *t)
1276 {
1277 if (t == NULL)
1278 return;
1279 if (t->mem)
1280 free(t->mem);
1281 if (t->server)
1282 free(t->server);
1283 if (t->file)
1284 free(t->file);
1285 free(t);
1286 }
1287
1288 static const int tftpMaxSize = 8192 * 1024;
1289 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1290 int mode, cyg_file *file)
1291 {
1292 struct Tftp *tftp;
1293 tftp = malloc(sizeof(struct Tftp));
1294 if (tftp == NULL)
1295 return EMFILE;
1296 memset(tftp, 0, sizeof(struct Tftp));
1297
1298 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1299 file->f_type = CYG_FILE_TYPE_FILE;
1300 file->f_ops = &tftpfs_fileops;
1301 file->f_offset = 0;
1302 file->f_data = 0;
1303 file->f_xops = 0;
1304
1305 tftp->mem = malloc(tftpMaxSize);
1306 if (tftp->mem == NULL)
1307 {
1308 freeTftp(tftp);
1309 return EMFILE;
1310 }
1311
1312 char *server = strchr(name, '/');
1313 if (server == NULL)
1314 {
1315 freeTftp(tftp);
1316 return EMFILE;
1317 }
1318
1319 tftp->server = malloc(server - name + 1);
1320 if (tftp->server == NULL)
1321 {
1322 freeTftp(tftp);
1323 return EMFILE;
1324 }
1325 strncpy(tftp->server, name, server - name);
1326 tftp->server[server - name] = 0;
1327
1328 tftp->file = strdup(server + 1);
1329 if (tftp->file == NULL)
1330 {
1331 freeTftp(tftp);
1332 return EMFILE;
1333 }
1334
1335 file->f_data = (CYG_ADDRWORD) tftp;
1336
1337 return ENOERR;
1338 }
1339
1340 static int fetchTftp(struct Tftp *tftp)
1341 {
1342 if (!tftp->readFile)
1343 {
1344 int err;
1345 tftp->actual = tftp_client_get(tftp->file, tftp->server, 0, tftp->mem,
1346 tftpMaxSize, TFTP_OCTET, &err);
1347
1348 if (tftp->actual < 0)
1349 {
1350 return EMFILE;
1351 }
1352 tftp->readFile = 1;
1353 }
1354 return ENOERR;
1355 }
1356
1357 // -------------------------------------------------------------------------
1358 // tftpfs_fo_write()
1359 // Read data from file.
1360
1361 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1362 {
1363 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1364
1365 if (fetchTftp(tftp) != ENOERR)
1366 return EMFILE;
1367
1368 int i;
1369 off_t pos = fp->f_offset;
1370 int resid = 0;
1371 for (i = 0; i < uio->uio_iovcnt; i++)
1372 {
1373 cyg_iovec *iov = &uio->uio_iov[i];
1374 char *buf = (char *) iov->iov_base;
1375 off_t len = iov->iov_len;
1376
1377 if (len + pos > tftp->actual)
1378 {
1379 len = tftp->actual - pos;
1380 }
1381 resid += iov->iov_len - len;
1382
1383 memcpy(buf, tftp->mem + pos, len);
1384 pos += len;
1385
1386 }
1387 uio->uio_resid = resid;
1388 fp->f_offset = pos;
1389
1390 return ENOERR;
1391 }
1392
1393 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1394 {
1395 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1396
1397 int i;
1398 off_t pos = fp->f_offset;
1399 int resid = 0;
1400 for (i = 0; i < uio->uio_iovcnt; i++)
1401 {
1402 cyg_iovec *iov = &uio->uio_iov[i];
1403 char *buf = (char *) iov->iov_base;
1404 off_t len = iov->iov_len;
1405
1406 if (len + pos > tftpMaxSize)
1407 {
1408 len = tftpMaxSize - pos;
1409 }
1410 resid += iov->iov_len - len;
1411
1412 memcpy(tftp->mem + pos, buf, len);
1413 pos += len;
1414
1415 }
1416 uio->uio_resid = resid;
1417 fp->f_offset = pos;
1418
1419 tftp->write = 1;
1420
1421 return ENOERR;
1422 }
1423
1424 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1425 {
1426 int error = ENOERR;
1427 return error;
1428 }
1429
1430 // -------------------------------------------------------------------------
1431 // romfs_fo_close()
1432 // Close a file. We just clear out the data pointer.
1433
1434 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
1435 {
1436 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1437 int error = ENOERR;
1438
1439 if (tftp->write)
1440 {
1441 tftp_client_put(tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,
1442 TFTP_OCTET, &error);
1443 }
1444
1445 freeTftp(tftp);
1446 fp->f_data = 0;
1447 return error;
1448 }
1449
1450 // -------------------------------------------------------------------------
1451 // romfs_fo_lseek()
1452 // Seek to a new file position.
1453
1454 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
1455 {
1456 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1457 off_t pos = *apos;
1458
1459 if (fetchTftp(tftp) != ENOERR)
1460 return EMFILE;
1461
1462 switch (whence)
1463 {
1464 case SEEK_SET:
1465 // Pos is already where we want to be.
1466 break;
1467
1468 case SEEK_CUR:
1469 // Add pos to current offset.
1470 pos += fp->f_offset;
1471 break;
1472
1473 case SEEK_END:
1474 // Add pos to file size.
1475 pos += tftp->actual;
1476 break;
1477
1478 default:
1479 return EINVAL;
1480 }
1481
1482 // Check that pos is still within current file size, or at the
1483 // very end.
1484 if (pos < 0 || pos > tftp->actual)
1485 return EINVAL;
1486
1487 // All OK, set fp offset and return new position.
1488 *apos = fp->f_offset = pos;
1489
1490 return ENOERR;
1491 }
1492
1493 void usleep(int us)
1494 {
1495 if (us > 10000)
1496 cyg_thread_delay(us / 10000 + 1);
1497 else
1498 HAL_DELAY_US(us);
1499 }
1500
1501 // Chunked version.
1502 cyg_int32 show_log_entry(CYG_HTTPD_STATE *phttpstate)
1503 {
1504 cyg_httpd_start_chunked("text");
1505 if (logCount >= logSize)
1506 {
1507 cyg_httpd_write_chunked(logBuffer + logCount % logSize, logSize
1508 - logCount % logSize);
1509 }
1510 cyg_httpd_write_chunked(logBuffer, writePtr);
1511 cyg_httpd_end_chunked();
1512 return -1;
1513 }
1514
1515 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
1516
1517 // Filesystem operations
1518 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1519 static int logfs_umount(cyg_mtab_entry *mte);
1520 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1521 int mode, cyg_file *fte);
1522 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1523
1524 // File operations
1525 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1526 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
1527
1528 #include <cyg/io/devtab.h>
1529
1530 //==========================================================================
1531 // Filesystem table entries
1532
1533 // -------------------------------------------------------------------------
1534 // Fstab entry.
1535 // This defines the entry in the filesystem table.
1536 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1537 // we should never block in any filesystem operations.
1538 FSTAB_ENTRY(logfs_fste, "logfs", 0,
1539 CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
1540 logfs_mount,
1541 logfs_umount,
1542 logfs_open,
1543 (cyg_fsop_unlink *)cyg_fileio_erofs,
1544 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1545 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1546 (cyg_fsop_rename *)cyg_fileio_erofs,
1547 (cyg_fsop_link *)cyg_fileio_erofs,
1548 (cyg_fsop_opendir *)cyg_fileio_erofs,
1549 (cyg_fsop_chdir *)cyg_fileio_erofs,
1550 (cyg_fsop_stat *)cyg_fileio_erofs,
1551 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1552 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1553
1554 // -------------------------------------------------------------------------
1555 // File operations.
1556 // This set of file operations are used for normal open files.
1557
1558 static cyg_fileops logfs_fileops =
1559 { (cyg_fileop_read *) cyg_fileio_erofs, (cyg_fileop_write *) logfs_fo_write,
1560 (cyg_fileop_lseek *) cyg_fileio_erofs,
1561 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1562 logfs_fo_fsync, logfs_fo_close, (cyg_fileop_fstat *) cyg_fileio_erofs,
1563 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1564 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1565
1566 // -------------------------------------------------------------------------
1567 // logfs_mount()
1568 // Process a mount request. This mainly finds root for the
1569 // filesystem.
1570
1571 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1572 {
1573 return ENOERR;
1574 }
1575
1576 static int logfs_umount(cyg_mtab_entry *mte)
1577 {
1578 return ENOERR;
1579 }
1580
1581 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1582 int mode, cyg_file *file)
1583 {
1584 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1585 file->f_type = CYG_FILE_TYPE_FILE;
1586 file->f_ops = &logfs_fileops;
1587 file->f_offset = 0;
1588 file->f_data = 0;
1589 file->f_xops = 0;
1590 return ENOERR;
1591 }
1592
1593 // -------------------------------------------------------------------------
1594 // logfs_fo_write()
1595 // Write data to file.
1596
1597 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1598 {
1599 int i;
1600 for (i = 0; i < uio->uio_iovcnt; i++)
1601 {
1602 cyg_iovec *iov = &uio->uio_iov[i];
1603 char *buf = (char *) iov->iov_base;
1604 off_t len = iov->iov_len;
1605
1606 diag_write(buf, len);
1607 }
1608 uio->uio_resid = 0;
1609
1610 return ENOERR;
1611 }
1612 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1613 {
1614 return ENOERR;
1615 }
1616
1617 // -------------------------------------------------------------------------
1618 // romfs_fo_close()
1619 // Close a file. We just clear out the data pointer.
1620
1621 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
1622 {
1623 return ENOERR;
1624 }
1625
1626 int loadFile(const char *fileName, void **data, int *len);
1627
1628 /* boolean parameter stored on config */
1629 int boolParam(char *var)
1630 {
1631 bool result = false;
1632 char *name = alloc_printf("%s/%s", zylin_config_dir, var);
1633 if (name == NULL)
1634 return result;
1635
1636 void *data;
1637 int len;
1638 if (loadFile(name, &data, &len) == ERROR_OK)
1639 {
1640 if (len > 1)
1641 len = 1;
1642 result = strncmp((char *) data, "1", len) == 0;
1643 free(data);
1644 }
1645 free(name);
1646 return result;
1647 }
1648

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)