change #include "gdb_server.h" to <server/gdb_server.h>
[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 #include "xsvf.h"
29 #include "svf.h"
30 #include <flash/nand.h>
31 #include "pld.h"
32
33 #include "server.h"
34 #include "telnet_server.h"
35 #include <server/gdb_server.h>
36 #include "openocd.h"
37
38 #include <time_support.h>
39 #include <sys/time.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <errno.h>
45
46 #include <cyg/io/flash.h>
47 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
48 #include <network.h>
49
50 #include <fcntl.h>
51 #include <sys/stat.h>
52 #include <cyg/fileio/fileio.h>
53 #include <dirent.h>
54 #include <cyg/athttpd/http.h>
55 #include <cyg/athttpd/socket.h>
56 #include <cyg/athttpd/handler.h>
57 #include <cyg/athttpd/cgi.h>
58 #include <cyg/athttpd/forms.h>
59 #include <cyg/discover/discover.h>
60 #include <cyg/hal/hal_diag.h>
61 #include <cyg/kernel/kapi.h>
62 #include <cyg/io/serialio.h>
63 #include <cyg/io/io.h>
64 #include <netinet/tcp.h>
65 #include "rom.h"
66 #include <sys/ioctl.h>
67 #include <sys/socket.h>
68 #include <netinet/in.h>
69 #include <net/if.h>
70 #include <arpa/inet.h>
71 #include <sys/types.h>
72 #include <sys/socket.h>
73 #include <netdb.h>
74 #include <netinet/in.h>
75 #include <unistd.h>
76 #include <arpa/inet.h>
77 #include <stdio.h>
78 #include <ifaddrs.h>
79 #include <string.h>
80
81 #include <unistd.h>
82 #include <stdio.h>
83
84 #include <openocd.h>
85
86 #ifdef CYGPKG_HAL_NIOS2
87 #define ZY1000_SER_DEV "/dev/uart_0"
88 #else
89 #define ZY1000_SER_DEV "/dev/ser0"
90
91 #endif
92
93
94 #define MAX_IFS 64
95 #if defined(CYGPKG_NET_FREEBSD_STACK)
96 #include <tftp_support.h>
97 /* posix compatibility broken*/
98 struct tftpd_fileops fileops =
99 {
100 (int (*)(const char *, int))open,
101 close,
102 (int (*)(int, const void *, int))write,
103 (int (*)(int, void *, int))read
104 };
105
106 #endif
107
108
109 void diag_write(char *buf, int len)
110 {
111 int j;
112 for (j = 0; j < len; j++)
113 {
114 diag_printf("%c", buf[j]);
115 }
116 }
117
118 static bool serialLog = true;
119 static bool writeLog = true;
120
121 char hwaddr[512];
122
123
124 extern struct flash_driver *flash_drivers[];
125 extern struct target_type *target_types[];
126
127 #ifdef CYGPKG_PROFILE_GPROF
128 #include <cyg/profile/profile.h>
129
130 extern char _stext, _etext; // Defined by the linker
131
132 static char *start_of_code=&_stext;
133 static char *end_of_code=&_etext;
134
135 void start_profile(void)
136 {
137 // This starts up the system-wide profiling, gathering
138 // profile information on all of the code, with a 16 byte
139 // "bucket" size, at a rate of 100us/profile hit.
140 // Note: a bucket size of 16 will give pretty good function
141 // resolution. Much smaller and the buffer becomes
142 // much too large for very little gain.
143 // Note: a timer period of 100us is also a reasonable
144 // compromise. Any smaller and the overhead of
145 // handling the timter (profile) interrupt could
146 // swamp the system. A fast processor might get
147 // by with a smaller value, but a slow one could
148 // even be swamped by this value. If the value is
149 // too large, the usefulness of the profile is reduced.
150
151 // no more interrupts than 1/10ms.
152 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
153 // profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
154 profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
155 }
156 #endif
157
158 static FILE *log;
159
160 static char reboot_stack[2048];
161
162 static void zylinjtag_reboot(cyg_addrword_t data)
163 {
164 serialLog = true;
165 diag_printf("Rebooting in 500 ticks..\n");
166 cyg_thread_delay(500);
167 diag_printf("Unmounting /config..\n");
168 umount("/config");
169 diag_printf("Rebooting..\n");
170 HAL_PLATFORM_RESET();
171 }
172 static cyg_thread zylinjtag_thread_object;
173 static cyg_handle_t zylinjtag_thread_handle;
174
175 void reboot(void)
176 {
177 cyg_thread_create(1, zylinjtag_reboot, (cyg_addrword_t) 0, "reboot Thread",
178 (void *) reboot_stack, sizeof(reboot_stack),
179 &zylinjtag_thread_handle, &zylinjtag_thread_object);
180 cyg_thread_resume(zylinjtag_thread_handle);
181 }
182
183 static char zylinjtag_reboot_port_stack[2048];
184 static cyg_thread zylinjtag_reboot_port_thread_object;
185 static cyg_handle_t zylinjtag_reboot_port_thread_handle;
186
187 static void zylinjtag_reboot_port_task(cyg_addrword_t data)
188 {
189 int so_reuseaddr_option = 1;
190
191 int fd;
192 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
193 {
194 LOG_ERROR("error creating socket: %s", strerror(errno));
195 exit(-1);
196 }
197
198 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
199 sizeof(int));
200
201 struct sockaddr_in sin;
202 unsigned int address_size;
203 address_size = sizeof(sin);
204 memset(&sin, 0, sizeof(sin));
205 sin.sin_family = AF_INET;
206 sin.sin_addr.s_addr = INADDR_ANY;
207 sin.sin_port = htons(1234);
208
209 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
210 {
211 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
212 exit(-1);
213 }
214
215 if (listen(fd, 1) == -1)
216 {
217 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
218 exit(-1);
219 }
220 // socket_nonblock(fd);
221
222
223 accept(fd, (struct sockaddr *) &sin, &address_size);
224
225 diag_printf("Got reboot signal on port 1234");
226
227 reboot();
228
229 }
230
231 void reboot_port(void)
232 {
233 cyg_thread_create(1, zylinjtag_reboot_port_task, (cyg_addrword_t) 0, "wait for reboot signal on port 1234",
234 (void *) zylinjtag_reboot_port_stack, sizeof(zylinjtag_reboot_port_stack),
235 &zylinjtag_reboot_port_thread_handle, &zylinjtag_reboot_port_thread_object);
236 cyg_thread_resume(zylinjtag_reboot_port_thread_handle);
237 }
238
239 int configuration_output_handler(struct command_context *context,
240 const char* line)
241 {
242 diag_printf("%s", line);
243
244 return ERROR_OK;
245 }
246
247 int zy1000_configuration_output_handler_log(struct command_context *context,
248 const char* line)
249 {
250 LOG_USER_N("%s", line);
251
252 return ERROR_OK;
253 }
254
255 #ifdef CYGPKG_PROFILE_GPROF
256
257 int eCosBoard_handle_eCosBoard_profile_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc)
258 {
259 command_print(cmd_ctx, "Profiling started");
260 start_profile();
261 return ERROR_OK;
262 }
263
264 #endif
265
266 externC void phi_init_all_network_interfaces(void);
267
268 struct command_context *cmd_ctx;
269
270 static bool webRunning = false;
271
272 void keep_webserver(void)
273 {
274 // Target initialisation is only attempted at startup, so we sleep forever and
275 // let the http server bail us out(i.e. get config files set up).
276 diag_printf("OpenOCD has invoked exit().\n"
277 "Use web server to correct any configuration settings and reboot.\n");
278 if (!webRunning)
279 reboot();
280
281 // exit() will terminate the current thread and we we'll then sleep eternally or
282 // we'll have a reboot scheduled.
283 }
284
285 extern void printDccChar(char c);
286
287 static char logBuffer[128 * 1024];
288 static const int logSize = sizeof(logBuffer);
289 int writePtr = 0;
290 int logCount = 0;
291
292 void _zylinjtag_diag_write_char(char c, void **param)
293 {
294 if (writeLog)
295 {
296 logBuffer[writePtr] = c;
297 writePtr = (writePtr + 1) % logSize;
298 logCount++;
299 }
300 if (serialLog)
301 {
302 if (c == '\n')
303 {
304 HAL_DIAG_WRITE_CHAR('\r');
305 }
306 HAL_DIAG_WRITE_CHAR(c);
307 }
308
309 #ifdef CYGPKG_HAL_ZYLIN_PHI
310 printDccChar(c);
311 #endif
312 }
313
314 void copyfile(char *name2, char *name1);
315
316 void copydir(char *name, char *destdir);
317
318 #if 0
319 MTAB_ENTRY(romfs_mte1,
320 "/rom",
321 "romfs",
322 "",
323 (CYG_ADDRWORD) &filedata[0]);
324 #endif
325
326 void openocd_sleep_prelude(void)
327 {
328 cyg_mutex_unlock(&httpstate.jim_lock);
329 }
330
331 void openocd_sleep_postlude(void)
332 {
333 cyg_mutex_lock(&httpstate.jim_lock);
334 }
335
336 void format(void)
337 {
338 #ifdef CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1
339 diag_printf("Formatting JFFS2...\n");
340
341 cyg_io_handle_t handle;
342
343 Cyg_ErrNo err;
344 err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
345 if (err != ENOERR)
346 {
347 diag_printf("Flash Error cyg_io_lookup: %d\n", err);
348 reboot();
349 }
350
351 cyg_uint32 len;
352 cyg_io_flash_getconfig_devsize_t ds;
353 len = sizeof(ds);
354 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
355 if (err != ENOERR)
356 {
357 diag_printf("Flash error cyg_io_get_config %d\n", err);
358 reboot();
359 }
360
361 cyg_io_flash_getconfig_erase_t e;
362 len = sizeof(e);
363
364 e.offset = 0;
365 e.len = ds.dev_size;
366
367 diag_printf("Formatting 0x%08x bytes\n", (int)ds.dev_size);
368 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len);
369 if (err != ENOERR)
370 {
371 diag_printf("Flash erase error %d offset 0x%08x\n", err, e.err_address);
372 reboot();
373 }
374
375 diag_printf("Flash formatted successfully\n");
376 #endif
377
378 reboot();
379 }
380
381 static int zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp, int argc,
382 Jim_Obj * const *argv)
383 {
384 if (argc != 1)
385 {
386 return JIM_ERR;
387 }
388
389 format();
390 for (;;)
391 ;
392 }
393
394 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
395 Jim_Obj * const *argv)
396 {
397 cyg_handle_t thread = 0;
398 cyg_uint16 id = 0;
399 Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
400
401 /* Loop over the threads, and generate a table row for
402 * each.
403 */
404 while (cyg_thread_get_next(&thread, &id))
405 {
406 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
407
408 cyg_thread_info info;
409 char *state_string;
410
411 cyg_thread_get_info(thread, id, &info);
412
413 if (info.name == NULL)
414 info.name = "<no name>";
415
416 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
417 info.name, strlen(info.name)));
418
419 /* Translate the state into a string.
420 */
421 if (info.state == 0)
422 state_string = "RUN";
423 else if (info.state & 0x04)
424 state_string = "SUSP";
425 else
426 switch (info.state & 0x1b)
427 {
428 case 0x01:
429 state_string = "SLEEP";
430 break;
431 case 0x02:
432 state_string = "CNTSLEEP";
433 break;
434 case 0x08:
435 state_string = "CREATE";
436 break;
437 case 0x10:
438 state_string = "EXIT";
439 break;
440 default:
441 state_string = "????";
442 break;
443 }
444
445 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
446 state_string, strlen(state_string)));
447
448 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, id));
449 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
450 info.set_pri));
451 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
452 info.cur_pri));
453
454 Jim_ListAppendElement(interp, threads, threadObj);
455 }
456 Jim_SetResult(interp, threads);
457
458 return JIM_OK;
459 }
460
461 static int zylinjtag_Jim_Command_log(Jim_Interp *interp, int argc,
462 Jim_Obj * const *argv)
463 {
464 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
465
466 if (logCount >= logSize)
467 {
468 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer + logCount
469 % logSize, logSize - logCount % logSize);
470 }
471 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
472
473 Jim_SetResult(interp, tclOutput);
474 return JIM_OK;
475 }
476
477 static int zylinjtag_Jim_Command_reboot(Jim_Interp *interp, int argc,
478 Jim_Obj * const *argv)
479 {
480 reboot();
481 return JIM_OK;
482 }
483
484 static void zylinjtag_startNetwork(void)
485 {
486 // Bring TCP/IP up immediately before we're ready to accept commands.
487 //
488 // That is as soon as a PING responds, we're accepting telnet sessions.
489 #if defined(CYGPKG_NET_FREEBSD_STACK)
490 phi_init_all_network_interfaces();
491 #else
492 lwip_init();
493 #endif
494 if (!eth0_up)
495 {
496 diag_printf("Network not up and running\n");
497 exit(-1);
498 }
499
500 /* very first thing we want is a reboot capability */
501 reboot_port();
502
503 #if defined(CYGPKG_NET_FREEBSD_STACK)
504 /*start TFTP*/
505 tftpd_start(69, &fileops);
506 #endif
507
508 cyg_httpd_init_tcl_interpreter();
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 static const char *zylin_config_dir="/config/settings";
937
938 static int add_default_dirs(void)
939 {
940 add_script_search_dir(zylin_config_dir);
941 add_script_search_dir("/rom/lib/openocd");
942 add_script_search_dir("/rom");
943 return ERROR_OK;
944 }
945
946 int main(int argc, char *argv[])
947 {
948 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
949 * need to allocate towards the end of the heap. */
950
951 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
952 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
953 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
954 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
955 #endif
956
957 int err;
958
959 atexit(keep_webserver);
960
961 diag_init_putc(_zylinjtag_diag_write_char);
962 // We want this in the log.
963 diag_printf("Zylin ZY1000.\n");
964
965 err = mount("", "/ram", "ramfs");
966 if (err < 0)
967 {
968 diag_printf("unable to mount ramfs\n");
969 }
970 chdir("/ram");
971
972 char address[16];
973 sprintf(address, "%p", &filedata[0]);
974 err = mount(address, "/rom", "romfs");
975 if (err < 0)
976 {
977 diag_printf("unable to mount /rom\n");
978 }
979
980 err = mount("", "/log", "logfs");
981 if (err < 0)
982 {
983 diag_printf("unable to mount logfs\n");
984 }
985
986 err = mount("", "/tftp", "tftpfs");
987 if (err < 0)
988 {
989 diag_printf("unable to mount logfs\n");
990 }
991
992 log = fopen("/log/log", "w");
993 if (log == NULL)
994 {
995 diag_printf("Could not open log file /ram/log\n");
996 exit(-1);
997 }
998
999
1000 copydir("/rom", "/ram/cgi");
1001
1002 err = mount("/dev/flash1", "/config", "jffs2");
1003 if (err < 0)
1004 {
1005 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1006 err = mount("", "/config", "ramfs");
1007 if (err < 0)
1008 {
1009 diag_printf("unable to mount /config as ramdisk.\n");
1010 reboot();
1011 }
1012 }
1013 else
1014 {
1015 /* are we using a ram disk instead of a flash disk? This is used
1016 * for ZY1000 live demo...
1017 *
1018 * copy over flash disk to ram block device
1019 */
1020 if (boolParam("ramdisk"))
1021 {
1022 diag_printf("Unmounting /config from flash and using ram instead\n");
1023 err = umount("/config");
1024 if (err < 0)
1025 {
1026 diag_printf("unable to unmount jffs\n");
1027 reboot();
1028 }
1029
1030 err = mount("/dev/flash1", "/config2", "jffs2");
1031 if (err < 0)
1032 {
1033 diag_printf("unable to mount jffs\n");
1034 reboot();
1035 }
1036
1037 err = mount("", "/config", "ramfs");
1038 if (err < 0)
1039 {
1040 diag_printf("unable to mount ram block device\n");
1041 reboot();
1042 }
1043
1044 // copydir("/config2", "/config");
1045 copyfile("/config2/ip", "/config/ip");
1046 copydir("/config2/settings", "/config/settings");
1047
1048 umount("/config2");
1049 }
1050 }
1051
1052 mkdir(zylin_config_dir, 0777);
1053 char *dirname = alloc_printf("%s/target", zylin_config_dir);
1054 mkdir(dirname, 0777);
1055 free(dirname);
1056 dirname = alloc_printf("%s/board", zylin_config_dir);
1057 mkdir(dirname, 0777);
1058 free(dirname);
1059 dirname = alloc_printf("%s/event", zylin_config_dir);
1060 mkdir(dirname, 0777);
1061 free(dirname);
1062
1063 logAllToSerial = boolParam("logserial");
1064
1065 // We need the network & web server in case there is something wrong with
1066 // the config files that invoke exit()
1067 zylinjtag_startNetwork();
1068
1069 /* we're going to access the jim interpreter from here on... */
1070 openocd_sleep_postlude();
1071 startUart();
1072
1073 add_default_dirs();
1074
1075 /* initialize commandline interface */
1076 struct command_context * cmd_ctx;
1077 struct command_context *setup_command_handler(Jim_Interp *interp);
1078 cmd_ctx = setup_command_handler(httpstate.jim_interp);
1079 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1080 command_context_mode(cmd_ctx, COMMAND_CONFIG);
1081
1082 if (ioutil_init(cmd_ctx) != ERROR_OK)
1083 return EXIT_FAILURE;
1084
1085 #ifdef CYGPKG_PROFILE_GPROF
1086 COMMAND_REGISTER(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1087 COMMAND_ANY, NULL);
1088 #endif
1089
1090 Jim_CreateCommand(httpstate.jim_interp, "uart", zylinjtag_Jim_Command_uart, NULL, NULL);
1091
1092
1093 log_init();
1094
1095 set_log_output(cmd_ctx, log);
1096
1097 LOG_DEBUG("log init complete");
1098
1099 // diag_printf("Executing config files\n");
1100
1101 if (logAllToSerial)
1102 {
1103 diag_printf(
1104 "%s/logserial = 1 => sending log output to serial port using \"debug_level 3\" as default.\n", zylin_config_dir);
1105 command_run_line(cmd_ctx, "debug_level 3");
1106 }
1107
1108 command_run_linef(cmd_ctx, "script /rom/openocd.cfg");
1109
1110 int ret;
1111 ret = server_init(cmd_ctx);
1112 if (ERROR_OK != ret)
1113 return EXIT_FAILURE;
1114
1115 /* we MUST always run the init command as it will launch telnet sessions */
1116 command_run_line(cmd_ctx, "init");
1117
1118 // FIX!!! Yuk!
1119 // diag_printf() is really invoked from many more places than we trust it
1120 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1121 //
1122 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1123 // fingers that it doesn't cause any crashes.
1124 diag_printf("Init complete, GDB & telnet servers launched.\n");
1125 command_set_output_handler(cmd_ctx,
1126 zy1000_configuration_output_handler_log, NULL);
1127 if (!logAllToSerial)
1128 {
1129 serialLog = false;
1130 }
1131
1132 /* handle network connections */
1133 server_loop(cmd_ctx);
1134 openocd_sleep_prelude();
1135
1136 /* shut server down */
1137 server_quit();
1138
1139 /* free commandline interface */
1140 command_done(cmd_ctx);
1141 umount("/config");
1142
1143 exit(0);
1144 for (;;)
1145 ;
1146 }
1147
1148 cyg_int32 cyg_httpd_exec_cgi_tcl(char *file_name);
1149 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1150 {
1151 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1152 return 0;
1153 }
1154
1155 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1156
1157 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1158 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1159
1160 #include <pkgconf/system.h>
1161 #include <pkgconf/hal.h>
1162 #include <pkgconf/kernel.h>
1163 #include <pkgconf/io_fileio.h>
1164 #include <pkgconf/fs_rom.h>
1165
1166 #include <cyg/kernel/ktypes.h> // base kernel types
1167 #include <cyg/infra/cyg_trac.h> // tracing macros
1168 #include <cyg/infra/cyg_ass.h> // assertion macros
1169 #include <cyg/fileio/fileio.h>
1170 #include <cyg/kernel/kapi.h>
1171 #include <cyg/infra/diag.h>
1172
1173 //==========================================================================
1174 // Eventually we want to eXecute In Place from the ROM in a protected
1175 // environment, so we'll need executables to be aligned to a boundary
1176 // suitable for MMU protection. A suitable boundary would be the 4k
1177 // boundary in all the CPU architectures I am currently aware of.
1178
1179 // Forward definitions
1180
1181 // Filesystem operations
1182 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1183 static int tftpfs_umount(cyg_mtab_entry *mte);
1184 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1185 int mode, cyg_file *fte);
1186 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1187 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1188
1189 // File operations
1190 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1191 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
1192 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
1193
1194 //==========================================================================
1195 // Filesystem table entries
1196
1197 // -------------------------------------------------------------------------
1198 // Fstab entry.
1199 // This defines the entry in the filesystem table.
1200 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1201 // we should never block in any filesystem operations.
1202 #if 1
1203 FSTAB_ENTRY(tftpfs_fste, "tftpfs", 0,
1204 CYG_SYNCMODE_NONE,
1205 tftpfs_mount,
1206 tftpfs_umount,
1207 tftpfs_open,
1208 (cyg_fsop_unlink *)cyg_fileio_erofs,
1209 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1210 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1211 (cyg_fsop_rename *)cyg_fileio_erofs,
1212 (cyg_fsop_link *)cyg_fileio_erofs,
1213 (cyg_fsop_opendir *)cyg_fileio_erofs,
1214 (cyg_fsop_chdir *)cyg_fileio_erofs,
1215 (cyg_fsop_stat *)cyg_fileio_erofs,
1216 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1217 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1218 #endif
1219
1220 // -------------------------------------------------------------------------
1221 // mtab entry.
1222 // This defines a single ROMFS loaded into ROM at the configured address
1223 //
1224 // MTAB_ENTRY(rom_mte, // structure name
1225 // "/rom", // mount point
1226 // "romfs", // FIlesystem type
1227 // "", // hardware device
1228 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
1229 //);
1230
1231
1232 // -------------------------------------------------------------------------
1233 // File operations.
1234 // This set of file operations are used for normal open files.
1235
1236 static cyg_fileops tftpfs_fileops =
1237 { tftpfs_fo_read, tftpfs_fo_write, tftpfs_fo_lseek,
1238 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1239 tftpfs_fo_fsync, tftpfs_fo_close,
1240 (cyg_fileop_fstat *) cyg_fileio_erofs,
1241 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1242 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1243
1244 // -------------------------------------------------------------------------
1245 // tftpfs_mount()
1246 // Process a mount request. This mainly finds root for the
1247 // filesystem.
1248
1249 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1250 {
1251 return ENOERR;
1252 }
1253
1254 static int tftpfs_umount(cyg_mtab_entry *mte)
1255 {
1256 return ENOERR;
1257 }
1258
1259 struct Tftp
1260 {
1261 int write;
1262 int readFile;
1263 cyg_uint8 *mem;
1264 int actual;
1265 char *server;
1266 char *file;
1267 };
1268
1269 static void freeTftp(struct Tftp *t)
1270 {
1271 if (t == NULL)
1272 return;
1273 if (t->mem)
1274 free(t->mem);
1275 if (t->server)
1276 free(t->server);
1277 if (t->file)
1278 free(t->file);
1279 free(t);
1280 }
1281
1282 static const int tftpMaxSize = 8192 * 1024;
1283 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1284 int mode, cyg_file *file)
1285 {
1286 struct Tftp *tftp;
1287 tftp = malloc(sizeof(struct Tftp));
1288 if (tftp == NULL)
1289 return EMFILE;
1290 memset(tftp, 0, sizeof(struct Tftp));
1291
1292 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1293 file->f_type = CYG_FILE_TYPE_FILE;
1294 file->f_ops = &tftpfs_fileops;
1295 file->f_offset = 0;
1296 file->f_data = 0;
1297 file->f_xops = 0;
1298
1299 tftp->mem = malloc(tftpMaxSize);
1300 if (tftp->mem == NULL)
1301 {
1302 freeTftp(tftp);
1303 return EMFILE;
1304 }
1305
1306 char *server = strchr(name, '/');
1307 if (server == NULL)
1308 {
1309 freeTftp(tftp);
1310 return EMFILE;
1311 }
1312
1313 tftp->server = malloc(server - name + 1);
1314 if (tftp->server == NULL)
1315 {
1316 freeTftp(tftp);
1317 return EMFILE;
1318 }
1319 strncpy(tftp->server, name, server - name);
1320 tftp->server[server - name] = 0;
1321
1322 tftp->file = strdup(server + 1);
1323 if (tftp->file == NULL)
1324 {
1325 freeTftp(tftp);
1326 return EMFILE;
1327 }
1328
1329 file->f_data = (CYG_ADDRWORD) tftp;
1330
1331 return ENOERR;
1332 }
1333
1334 static int fetchTftp(struct Tftp *tftp)
1335 {
1336 if (!tftp->readFile)
1337 {
1338 int err;
1339 tftp->actual = tftp_client_get(tftp->file, tftp->server, 0, tftp->mem,
1340 tftpMaxSize, TFTP_OCTET, &err);
1341
1342 if (tftp->actual < 0)
1343 {
1344 return EMFILE;
1345 }
1346 tftp->readFile = 1;
1347 }
1348 return ENOERR;
1349 }
1350
1351 // -------------------------------------------------------------------------
1352 // tftpfs_fo_write()
1353 // Read data from file.
1354
1355 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1356 {
1357 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1358
1359 if (fetchTftp(tftp) != ENOERR)
1360 return EMFILE;
1361
1362 int i;
1363 off_t pos = fp->f_offset;
1364 int resid = 0;
1365 for (i = 0; i < uio->uio_iovcnt; i++)
1366 {
1367 cyg_iovec *iov = &uio->uio_iov[i];
1368 char *buf = (char *) iov->iov_base;
1369 off_t len = iov->iov_len;
1370
1371 if (len + pos > tftp->actual)
1372 {
1373 len = tftp->actual - pos;
1374 }
1375 resid += iov->iov_len - len;
1376
1377 memcpy(buf, tftp->mem + pos, len);
1378 pos += len;
1379
1380 }
1381 uio->uio_resid = resid;
1382 fp->f_offset = pos;
1383
1384 return ENOERR;
1385 }
1386
1387 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1388 {
1389 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1390
1391 int i;
1392 off_t pos = fp->f_offset;
1393 int resid = 0;
1394 for (i = 0; i < uio->uio_iovcnt; i++)
1395 {
1396 cyg_iovec *iov = &uio->uio_iov[i];
1397 char *buf = (char *) iov->iov_base;
1398 off_t len = iov->iov_len;
1399
1400 if (len + pos > tftpMaxSize)
1401 {
1402 len = tftpMaxSize - pos;
1403 }
1404 resid += iov->iov_len - len;
1405
1406 memcpy(tftp->mem + pos, buf, len);
1407 pos += len;
1408
1409 }
1410 uio->uio_resid = resid;
1411 fp->f_offset = pos;
1412
1413 tftp->write = 1;
1414
1415 return ENOERR;
1416 }
1417
1418 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1419 {
1420 int error = ENOERR;
1421 return error;
1422 }
1423
1424 // -------------------------------------------------------------------------
1425 // romfs_fo_close()
1426 // Close a file. We just clear out the data pointer.
1427
1428 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
1429 {
1430 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1431 int error = ENOERR;
1432
1433 if (tftp->write)
1434 {
1435 tftp_client_put(tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,
1436 TFTP_OCTET, &error);
1437 }
1438
1439 freeTftp(tftp);
1440 fp->f_data = 0;
1441 return error;
1442 }
1443
1444 // -------------------------------------------------------------------------
1445 // romfs_fo_lseek()
1446 // Seek to a new file position.
1447
1448 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
1449 {
1450 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1451 off_t pos = *apos;
1452
1453 if (fetchTftp(tftp) != ENOERR)
1454 return EMFILE;
1455
1456 switch (whence)
1457 {
1458 case SEEK_SET:
1459 // Pos is already where we want to be.
1460 break;
1461
1462 case SEEK_CUR:
1463 // Add pos to current offset.
1464 pos += fp->f_offset;
1465 break;
1466
1467 case SEEK_END:
1468 // Add pos to file size.
1469 pos += tftp->actual;
1470 break;
1471
1472 default:
1473 return EINVAL;
1474 }
1475
1476 // Check that pos is still within current file size, or at the
1477 // very end.
1478 if (pos < 0 || pos > tftp->actual)
1479 return EINVAL;
1480
1481 // All OK, set fp offset and return new position.
1482 *apos = fp->f_offset = pos;
1483
1484 return ENOERR;
1485 }
1486
1487 void usleep(int us)
1488 {
1489 if (us > 10000)
1490 cyg_thread_delay(us / 10000 + 1);
1491 else
1492 HAL_DELAY_US(us);
1493 }
1494
1495 // Chunked version.
1496 cyg_int32 show_log_entry(CYG_HTTPD_STATE *phttpstate)
1497 {
1498 cyg_httpd_start_chunked("text");
1499 if (logCount >= logSize)
1500 {
1501 cyg_httpd_write_chunked(logBuffer + logCount % logSize, logSize
1502 - logCount % logSize);
1503 }
1504 cyg_httpd_write_chunked(logBuffer, writePtr);
1505 cyg_httpd_end_chunked();
1506 return -1;
1507 }
1508
1509 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
1510
1511 // Filesystem operations
1512 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1513 static int logfs_umount(cyg_mtab_entry *mte);
1514 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1515 int mode, cyg_file *fte);
1516 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1517
1518 // File operations
1519 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1520 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
1521
1522 #include <cyg/io/devtab.h>
1523
1524 //==========================================================================
1525 // Filesystem table entries
1526
1527 // -------------------------------------------------------------------------
1528 // Fstab entry.
1529 // This defines the entry in the filesystem table.
1530 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1531 // we should never block in any filesystem operations.
1532 FSTAB_ENTRY(logfs_fste, "logfs", 0,
1533 CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
1534 logfs_mount,
1535 logfs_umount,
1536 logfs_open,
1537 (cyg_fsop_unlink *)cyg_fileio_erofs,
1538 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1539 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1540 (cyg_fsop_rename *)cyg_fileio_erofs,
1541 (cyg_fsop_link *)cyg_fileio_erofs,
1542 (cyg_fsop_opendir *)cyg_fileio_erofs,
1543 (cyg_fsop_chdir *)cyg_fileio_erofs,
1544 (cyg_fsop_stat *)cyg_fileio_erofs,
1545 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1546 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1547
1548 // -------------------------------------------------------------------------
1549 // File operations.
1550 // This set of file operations are used for normal open files.
1551
1552 static cyg_fileops logfs_fileops =
1553 { (cyg_fileop_read *) cyg_fileio_erofs, (cyg_fileop_write *) logfs_fo_write,
1554 (cyg_fileop_lseek *) cyg_fileio_erofs,
1555 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1556 logfs_fo_fsync, logfs_fo_close, (cyg_fileop_fstat *) cyg_fileio_erofs,
1557 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1558 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1559
1560 // -------------------------------------------------------------------------
1561 // logfs_mount()
1562 // Process a mount request. This mainly finds root for the
1563 // filesystem.
1564
1565 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1566 {
1567 return ENOERR;
1568 }
1569
1570 static int logfs_umount(cyg_mtab_entry *mte)
1571 {
1572 return ENOERR;
1573 }
1574
1575 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1576 int mode, cyg_file *file)
1577 {
1578 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1579 file->f_type = CYG_FILE_TYPE_FILE;
1580 file->f_ops = &logfs_fileops;
1581 file->f_offset = 0;
1582 file->f_data = 0;
1583 file->f_xops = 0;
1584 return ENOERR;
1585 }
1586
1587 // -------------------------------------------------------------------------
1588 // logfs_fo_write()
1589 // Write data to file.
1590
1591 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1592 {
1593 int i;
1594 for (i = 0; i < uio->uio_iovcnt; i++)
1595 {
1596 cyg_iovec *iov = &uio->uio_iov[i];
1597 char *buf = (char *) iov->iov_base;
1598 off_t len = iov->iov_len;
1599
1600 diag_write(buf, len);
1601 }
1602 uio->uio_resid = 0;
1603
1604 return ENOERR;
1605 }
1606 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1607 {
1608 return ENOERR;
1609 }
1610
1611 // -------------------------------------------------------------------------
1612 // romfs_fo_close()
1613 // Close a file. We just clear out the data pointer.
1614
1615 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
1616 {
1617 return ENOERR;
1618 }
1619
1620 int loadFile(const char *fileName, void **data, int *len);
1621
1622 /* boolean parameter stored on config */
1623 int boolParam(char *var)
1624 {
1625 bool result = false;
1626 char *name = alloc_printf("%s/%s", zylin_config_dir, var);
1627 if (name == NULL)
1628 return result;
1629
1630 void *data;
1631 int len;
1632 if (loadFile(name, &data, &len) == ERROR_OK)
1633 {
1634 if (len > 1)
1635 len = 1;
1636 result = strncmp((char *) data, "1", len) == 0;
1637 free(data);
1638 }
1639 free(name);
1640 return result;
1641 }
1642

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)