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

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)