dcd497ce9e943516e825cd6e227a87900ab2638d
[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 #include <openocd.h>
84
85 #ifdef CYGPKG_HAL_NIOS2
86 #define ZY1000_SER_DEV "/dev/uart_0"
87 #else
88 #define ZY1000_SER_DEV "/dev/ser0"
89
90 #endif
91
92
93 #define MAX_IFS 64
94 #if defined(CYGPKG_NET_FREEBSD_STACK)
95 #include <tftp_support.h>
96 /* posix compatibility broken*/
97 struct tftpd_fileops fileops =
98 {
99 (int (*)(const char *, int))open,
100 close,
101 (int (*)(int, const void *, int))write,
102 (int (*)(int, void *, int))read
103 };
104
105 #endif
106
107
108 void diag_write(char *buf, int len)
109 {
110 int j;
111 for (j = 0; j < len; j++)
112 {
113 diag_printf("%c", buf[j]);
114 }
115 }
116
117 static bool serialLog = true;
118 static bool writeLog = true;
119
120 char hwaddr[512];
121
122
123 extern struct flash_driver *flash_drivers[];
124 extern struct target_type *target_types[];
125
126 #ifdef CYGPKG_PROFILE_GPROF
127 #include <cyg/profile/profile.h>
128
129 extern char _stext, _etext; // Defined by the linker
130
131 static char *start_of_code=&_stext;
132 static char *end_of_code=&_etext;
133
134 void start_profile(void)
135 {
136 // This starts up the system-wide profiling, gathering
137 // profile information on all of the code, with a 16 byte
138 // "bucket" size, at a rate of 100us/profile hit.
139 // Note: a bucket size of 16 will give pretty good function
140 // resolution. Much smaller and the buffer becomes
141 // much too large for very little gain.
142 // Note: a timer period of 100us is also a reasonable
143 // compromise. Any smaller and the overhead of
144 // handling the timter (profile) interrupt could
145 // swamp the system. A fast processor might get
146 // by with a smaller value, but a slow one could
147 // even be swamped by this value. If the value is
148 // too large, the usefulness of the profile is reduced.
149
150 // no more interrupts than 1/10ms.
151 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
152 // profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
153 profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
154 }
155 #endif
156
157 static FILE *log;
158
159 static char reboot_stack[2048];
160
161 static void zylinjtag_reboot(cyg_addrword_t data)
162 {
163 serialLog = true;
164 diag_printf("Rebooting in 500 ticks..\n");
165 cyg_thread_delay(500);
166 diag_printf("Unmounting /config..\n");
167 umount("/config");
168 diag_printf("Rebooting..\n");
169 HAL_PLATFORM_RESET();
170 }
171 static cyg_thread zylinjtag_thread_object;
172 static cyg_handle_t zylinjtag_thread_handle;
173
174 void reboot(void)
175 {
176 cyg_thread_create(1, zylinjtag_reboot, (cyg_addrword_t) 0, "reboot Thread",
177 (void *) reboot_stack, sizeof(reboot_stack),
178 &zylinjtag_thread_handle, &zylinjtag_thread_object);
179 cyg_thread_resume(zylinjtag_thread_handle);
180 }
181
182 static char zylinjtag_reboot_port_stack[2048];
183 static cyg_thread zylinjtag_reboot_port_thread_object;
184 static cyg_handle_t zylinjtag_reboot_port_thread_handle;
185
186 static void zylinjtag_reboot_port_task(cyg_addrword_t data)
187 {
188 int so_reuseaddr_option = 1;
189
190 int fd;
191 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
192 {
193 LOG_ERROR("error creating socket: %s", strerror(errno));
194 exit(-1);
195 }
196
197 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
198 sizeof(int));
199
200 struct sockaddr_in sin;
201 unsigned int address_size;
202 address_size = sizeof(sin);
203 memset(&sin, 0, sizeof(sin));
204 sin.sin_family = AF_INET;
205 sin.sin_addr.s_addr = INADDR_ANY;
206 sin.sin_port = htons(1234);
207
208 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
209 {
210 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
211 exit(-1);
212 }
213
214 if (listen(fd, 1) == -1)
215 {
216 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
217 exit(-1);
218 }
219 // socket_nonblock(fd);
220
221
222 accept(fd, (struct sockaddr *) &sin, &address_size);
223
224 diag_printf("Got reboot signal on port 1234");
225
226 reboot();
227
228 }
229
230 void reboot_port(void)
231 {
232 cyg_thread_create(1, zylinjtag_reboot_port_task, (cyg_addrword_t) 0, "wait for reboot signal on port 1234",
233 (void *) zylinjtag_reboot_port_stack, sizeof(zylinjtag_reboot_port_stack),
234 &zylinjtag_reboot_port_thread_handle, &zylinjtag_reboot_port_thread_object);
235 cyg_thread_resume(zylinjtag_reboot_port_thread_handle);
236 }
237
238 int configuration_output_handler(struct command_context *context,
239 const char* line)
240 {
241 diag_printf("%s", line);
242
243 return ERROR_OK;
244 }
245
246 int zy1000_configuration_output_handler_log(struct command_context *context,
247 const char* line)
248 {
249 LOG_USER_N("%s", line);
250
251 return ERROR_OK;
252 }
253
254 #ifdef CYGPKG_PROFILE_GPROF
255
256 int eCosBoard_handle_eCosBoard_profile_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc)
257 {
258 command_print(cmd_ctx, "Profiling started");
259 start_profile();
260 return ERROR_OK;
261 }
262
263 #endif
264
265 externC void phi_init_all_network_interfaces(void);
266
267 struct command_context *cmd_ctx;
268
269 static bool webRunning = false;
270
271 void keep_webserver(void)
272 {
273 // Target initialisation is only attempted at startup, so we sleep forever and
274 // let the http server bail us out(i.e. get config files set up).
275 diag_printf("OpenOCD has invoked exit().\n"
276 "Use web server to correct any configuration settings and reboot.\n");
277 if (!webRunning)
278 reboot();
279
280 // exit() will terminate the current thread and we we'll then sleep eternally or
281 // we'll have a reboot scheduled.
282 }
283
284 extern void printDccChar(char c);
285
286 static char logBuffer[128 * 1024];
287 static const int logSize = sizeof(logBuffer);
288 int writePtr = 0;
289 int logCount = 0;
290
291 void _zylinjtag_diag_write_char(char c, void **param)
292 {
293 if (writeLog)
294 {
295 logBuffer[writePtr] = c;
296 writePtr = (writePtr + 1) % logSize;
297 logCount++;
298 }
299 if (serialLog)
300 {
301 if (c == '\n')
302 {
303 HAL_DIAG_WRITE_CHAR('\r');
304 }
305 HAL_DIAG_WRITE_CHAR(c);
306 }
307
308 #ifdef CYGPKG_HAL_ZYLIN_PHI
309 printDccChar(c);
310 #endif
311 }
312
313 void copyfile(char *name2, char *name1);
314
315 void copydir(char *name, char *destdir);
316
317 #if 0
318 MTAB_ENTRY(romfs_mte1,
319 "/rom",
320 "romfs",
321 "",
322 (CYG_ADDRWORD) &filedata[0]);
323 #endif
324
325 void openocd_sleep_prelude(void)
326 {
327 cyg_mutex_unlock(&httpstate.jim_lock);
328 }
329
330 void openocd_sleep_postlude(void)
331 {
332 cyg_mutex_lock(&httpstate.jim_lock);
333 }
334
335 void format(void)
336 {
337 #ifdef CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1
338 diag_printf("Formatting JFFS2...\n");
339
340 cyg_io_handle_t handle;
341
342 Cyg_ErrNo err;
343 err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
344 if (err != ENOERR)
345 {
346 diag_printf("Flash Error cyg_io_lookup: %d\n", err);
347 reboot();
348 }
349
350 cyg_uint32 len;
351 cyg_io_flash_getconfig_devsize_t ds;
352 len = sizeof(ds);
353 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
354 if (err != ENOERR)
355 {
356 diag_printf("Flash error cyg_io_get_config %d\n", err);
357 reboot();
358 }
359
360 cyg_io_flash_getconfig_erase_t e;
361 len = sizeof(e);
362
363 e.offset = 0;
364 e.len = ds.dev_size;
365
366 diag_printf("Formatting 0x%08x bytes\n", (int)ds.dev_size);
367 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len);
368 if (err != ENOERR)
369 {
370 diag_printf("Flash erase error %d offset 0x%08x\n", err, e.err_address);
371 reboot();
372 }
373
374 diag_printf("Flash formatted successfully\n");
375 #endif
376
377 reboot();
378 }
379
380 static int zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp, int argc,
381 Jim_Obj * const *argv)
382 {
383 if (argc != 1)
384 {
385 return JIM_ERR;
386 }
387
388 format();
389 for (;;)
390 ;
391 }
392
393 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
394 Jim_Obj * const *argv)
395 {
396 cyg_handle_t thread = 0;
397 cyg_uint16 id = 0;
398 Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
399
400 /* Loop over the threads, and generate a table row for
401 * each.
402 */
403 while (cyg_thread_get_next(&thread, &id))
404 {
405 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
406
407 cyg_thread_info info;
408 char *state_string;
409
410 cyg_thread_get_info(thread, id, &info);
411
412 if (info.name == NULL)
413 info.name = "<no name>";
414
415 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
416 info.name, strlen(info.name)));
417
418 /* Translate the state into a string.
419 */
420 if (info.state == 0)
421 state_string = "RUN";
422 else if (info.state & 0x04)
423 state_string = "SUSP";
424 else
425 switch (info.state & 0x1b)
426 {
427 case 0x01:
428 state_string = "SLEEP";
429 break;
430 case 0x02:
431 state_string = "CNTSLEEP";
432 break;
433 case 0x08:
434 state_string = "CREATE";
435 break;
436 case 0x10:
437 state_string = "EXIT";
438 break;
439 default:
440 state_string = "????";
441 break;
442 }
443
444 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
445 state_string, strlen(state_string)));
446
447 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, id));
448 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
449 info.set_pri));
450 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
451 info.cur_pri));
452
453 Jim_ListAppendElement(interp, threads, threadObj);
454 }
455 Jim_SetResult(interp, threads);
456
457 return JIM_OK;
458 }
459
460 static int zylinjtag_Jim_Command_log(Jim_Interp *interp, int argc,
461 Jim_Obj * const *argv)
462 {
463 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
464
465 if (logCount >= logSize)
466 {
467 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer + logCount
468 % logSize, logSize - logCount % logSize);
469 }
470 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
471
472 Jim_SetResult(interp, tclOutput);
473 return JIM_OK;
474 }
475
476 static int zylinjtag_Jim_Command_reboot(Jim_Interp *interp, int argc,
477 Jim_Obj * const *argv)
478 {
479 reboot();
480 return JIM_OK;
481 }
482
483 static void zylinjtag_startNetwork(void)
484 {
485 // Bring TCP/IP up immediately before we're ready to accept commands.
486 //
487 // That is as soon as a PING responds, we're accepting telnet sessions.
488 #if defined(CYGPKG_NET_FREEBSD_STACK)
489 phi_init_all_network_interfaces();
490 #else
491 lwip_init();
492 #endif
493 if (!eth0_up)
494 {
495 diag_printf("Network not up and running\n");
496 exit(-1);
497 }
498
499 /* very first thing we want is a reboot capability */
500 reboot_port();
501
502 #if defined(CYGPKG_NET_FREEBSD_STACK)
503 /*start TFTP*/
504 tftpd_start(69, &fileops);
505 #endif
506
507 cyg_httpd_init_tcl_interpreter();
508
509 Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
510 NULL, NULL);
511 Jim_CreateCommand(httpstate.jim_interp, "zy1000_reboot",
512 zylinjtag_Jim_Command_reboot, NULL, NULL);
513 Jim_CreateCommand(httpstate.jim_interp, "threads",
514 zylinjtag_Jim_Command_threads, NULL, NULL);
515 Jim_CreateCommand(httpstate.jim_interp, "format_jffs2",
516 zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
517
518 cyg_httpd_start();
519
520 webRunning = true;
521
522 diag_printf("Web server running\n");
523
524 int s;
525 struct ifreq ifr;
526 s = socket(AF_INET, SOCK_DGRAM, 0);
527 if (s >= 0)
528 {
529 strcpy(ifr.ifr_name, "eth0");
530 int res;
531 res = ioctl(s, SIOCGIFHWADDR, &ifr);
532 close(s);
533
534 if (res < 0)
535 {
536 diag_printf("Can't obtain MAC address\n");
537 reboot();
538 }
539 }
540
541 sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
542 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
543 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
544 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
545 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
546 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
547 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
548
549 discover_message
550 = alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
551
552 discover_launch();
553 }
554
555 static void print_exception_handler(cyg_addrword_t data, cyg_code_t exception,
556 cyg_addrword_t info)
557 {
558 writeLog = false;
559 serialLog = true;
560 char *infoStr = "unknown";
561 switch (exception)
562 {
563 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
564 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
565 infoStr = "undefined instruction";
566 break;
567 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
568 infoStr = "software interrupt";
569 break;
570 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
571 infoStr = "abort prefetch";
572 break;
573 case CYGNUM_HAL_VECTOR_ABORT_DATA:
574 infoStr = "abort data";
575 break;
576 #endif
577 default:
578 break;
579 }
580
581 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
582
583 diag_printf("Dumping log\n---\n");
584 if (logCount >= logSize)
585 {
586 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
587 }
588 diag_write(logBuffer, writePtr);
589
590 diag_printf("---\nLogdump complete.\n");
591 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
592 diag_printf("\n---\nRebooting\n");
593 HAL_PLATFORM_RESET();
594
595 }
596
597 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
598 static void setHandler(cyg_code_t exception)
599 {
600 cyg_exception_handler_t *old_handler;
601 cyg_addrword_t old_data;
602
603 cyg_exception_set_handler(exception, print_exception_handler, 0,
604 &old_handler, &old_data);
605 }
606 #endif
607
608 static cyg_thread zylinjtag_uart_thread_object;
609 static cyg_handle_t zylinjtag_uart_thread_handle;
610 static char uart_stack[4096];
611
612 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
613 static char backwardBuffer[1024];
614
615 void setNoDelay(int session, int flag)
616 {
617 #if 1
618 // This decreases latency dramatically for e.g. GDB load which
619 // does not have a sliding window protocol
620 //
621 // Can cause *lots* of TCP/IP packets to be sent and it would have
622 // to be enabled/disabled on the fly to avoid the CPU being
623 // overloaded...
624 setsockopt(session, /* socket affected */
625 IPPROTO_TCP, /* set option at TCP level */
626 TCP_NODELAY, /* name of option */
627 (char *) &flag, /* the cast is historical
628 cruft */
629 sizeof(int)); /* length of option value */
630 #endif
631 }
632
633 #define TEST_TCPIP() 0
634
635 #if TEST_TCPIP
636 struct
637 {
638 int req;
639 int actual;
640 int req2;
641 int actual2;
642 } tcpipSent[512 * 1024];
643 int cur;
644 #endif
645
646 static void zylinjtag_uart(cyg_addrword_t data)
647 {
648 int so_reuseaddr_option = 1;
649
650 int fd;
651 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
652 {
653 LOG_ERROR("error creating socket: %s", strerror(errno));
654 exit(-1);
655 }
656
657 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
658 sizeof(int));
659
660 struct sockaddr_in sin;
661 unsigned int address_size;
662 address_size = sizeof(sin);
663 memset(&sin, 0, sizeof(sin));
664 sin.sin_family = AF_INET;
665 sin.sin_addr.s_addr = INADDR_ANY;
666 sin.sin_port = htons(5555);
667
668 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
669 {
670 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
671 exit(-1);
672 }
673
674 if (listen(fd, 1) == -1)
675 {
676 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
677 exit(-1);
678 }
679 // socket_nonblock(fd);
680
681
682 for (;;)
683 {
684 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
685 if (session < 0)
686 {
687 continue;
688 }
689
690 setNoDelay(session, 1);
691 int oldopts = fcntl(session, F_GETFL, 0);
692 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
693
694 int serHandle = open(ZY1000_SER_DEV, O_RDWR | O_NONBLOCK);
695 if (serHandle < 0)
696 {
697 close(session);
698 continue;
699 }
700
701 #ifdef CYGPKG_PROFILE_GPROF
702 start_profile();
703 #endif
704 size_t actual = 0;
705 size_t actual2 = 0;
706 size_t pos, pos2;
707 pos = 0;
708 pos2 = 0;
709 #if TEST_TCPIP
710 cur = 0;
711 #endif
712 for (;;)
713 {
714 fd_set write_fds;
715 fd_set read_fds;
716 FD_ZERO(&write_fds);
717 FD_ZERO(&read_fds);
718 int fd_max = -1;
719 FD_SET(session, &read_fds);
720 fd_max = session;
721 FD_SET(serHandle, &read_fds);
722 if (serHandle > fd_max)
723 {
724 fd_max = serHandle;
725 }
726 /* Wait... */
727
728 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
729 if ((actual == 0) && (actual2 == 0))
730 {
731 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
732 if (retval <= 0)
733 {
734 break;
735 }
736 }
737
738 if (actual2 <= 0)
739 {
740 memset(backwardBuffer, 's', sizeof(backwardBuffer));
741 int t;
742 t = read(serHandle, backwardBuffer,
743 sizeof(backwardBuffer));
744 actual2 = t;
745 if (t < 0)
746 {
747 if (errno != EAGAIN)
748 {
749 goto closeSession;
750 }
751 actual2 = 0;
752 }
753 pos2 = 0;
754 }
755
756 size_t y = 0;
757 if (actual2 > 0)
758 {
759 int written = write(session, backwardBuffer + pos2, actual2);
760 if (written <= 0)
761 goto closeSession;
762 actual2 -= written;
763 pos2 += written;
764 y = written;
765 }
766
767 if (FD_ISSET(session, &read_fds)
768 && (sizeof(forwardBuffer) > actual))
769 {
770 // NB! Here it is important that we empty the TCP/IP read buffer
771 // to make transmission tick right
772 memmove(forwardBuffer, forwardBuffer + pos, actual);
773 pos = 0;
774 int t;
775 // this will block if there is no data at all
776 t = read_socket(session, forwardBuffer + actual,
777 sizeof(forwardBuffer) - actual);
778 if (t <= 0)
779 {
780 goto closeSession;
781 }
782 actual += t;
783 }
784
785 int y2 = 0;
786 if (actual > 0)
787 {
788 /* Do not put things into the serial buffer if it has something to send
789 * as that can cause a single byte to be sent at the time.
790 *
791 *
792 */
793 int written = write(serHandle, forwardBuffer + pos, actual);
794 if (written < 0)
795 {
796 if (errno != EAGAIN)
797 {
798 goto closeSession;
799 }
800 // The serial buffer is full
801 written = 0;
802 }
803 else
804 {
805 actual -= written;
806 pos += written;
807 }
808 y2 = written;
809 }
810 #if TEST_TCPIP
811 if (cur < 1024)
812 {
813 tcpipSent[cur].req = x;
814 tcpipSent[cur].actual = y;
815 tcpipSent[cur].req2 = x2;
816 tcpipSent[cur].actual2 = y2;
817 cur++;
818 }
819 #endif
820 }
821 closeSession: close(session);
822 close(serHandle);
823
824 #if TEST_TCPIP
825 int i;
826 for (i = 0; i < 1024; i++)
827 {
828 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual,
829 tcpipSent[i].req2, tcpipSent[i].actual2);
830
831 }
832 #endif
833 }
834 close(fd);
835
836 }
837
838 void startUart(void)
839 {
840 cyg_thread_create(1, zylinjtag_uart, (cyg_addrword_t) 0, "uart thread",
841 (void *) uart_stack, sizeof(uart_stack),
842 &zylinjtag_uart_thread_handle, &zylinjtag_uart_thread_object);
843 cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
844 cyg_thread_resume(zylinjtag_uart_thread_handle);
845 }
846
847 static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
848 Jim_Obj * const *argv)
849 {
850 static int current_baud = 38400;
851 if (argc == 1)
852 {
853 command_print(cmd_ctx, "%d", current_baud);
854 return JIM_OK;
855 }
856 else if (argc != 2)
857 {
858 return JIM_ERR;
859 }
860
861 long new_baudrate;
862 if (Jim_GetLong(interp, argv[1], &new_baudrate) != JIM_OK)
863 return JIM_ERR;
864
865 current_baud = new_baudrate;
866
867 int baud;
868 switch (current_baud)
869 {
870 case 9600:
871 baud = CYGNUM_SERIAL_BAUD_9600;
872 break;
873 case 19200:
874 baud = CYGNUM_SERIAL_BAUD_19200;
875 break;
876 case 38400:
877 baud = CYGNUM_SERIAL_BAUD_38400;
878 break;
879 case 57600:
880 baud = CYGNUM_SERIAL_BAUD_57600;
881 break;
882 case 115200:
883 baud = CYGNUM_SERIAL_BAUD_115200;
884 break;
885 case 230400:
886 baud = CYGNUM_SERIAL_BAUD_230400;
887 break;
888 default:
889 command_print(cmd_ctx, "unsupported baudrate");
890 return ERROR_INVALID_ARGUMENTS;
891 }
892
893 cyg_serial_info_t buf;
894 cyg_uint32 len = 1;
895 //get existing serial configuration
896 len = sizeof(cyg_serial_info_t);
897 int err;
898 cyg_io_handle_t serial_handle;
899
900 err = cyg_io_lookup(ZY1000_SER_DEV, &serial_handle);
901 if (err != ENOERR)
902 {
903 LOG_ERROR("Could not open serial port\n");
904 return JIM_ERR;
905 }
906
907 err = cyg_io_get_config(serial_handle,
908 CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
909 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf,
910 &len);
911 if (err != ENOERR)
912 {
913 LOG_ERROR("Failed to get serial port settings %d", err);
914 return JIM_ERR;
915 }
916 buf.baud = baud;
917
918 err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf,
919 &len);
920 if (err != ENOERR)
921 {
922 LOG_ERROR("Failed to set serial port settings %d", err);
923 return JIM_ERR;
924 }
925
926 return JIM_OK;
927 }
928
929 bool logAllToSerial = false;
930
931
932 int boolParam(char *var);
933
934
935 static const char *zylin_config_dir="/config/settings";
936
937 static int add_default_dirs(void)
938 {
939 add_script_search_dir(zylin_config_dir);
940 add_script_search_dir("/rom/lib/openocd");
941 add_script_search_dir("/rom");
942 return ERROR_OK;
943 }
944
945 int ioutil_init(struct command_context *cmd_ctx);
946
947 int main(int argc, char *argv[])
948 {
949 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
950 * need to allocate towards the end of the heap. */
951
952 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
953 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
954 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
955 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
956 #endif
957
958 int err;
959
960 atexit(keep_webserver);
961
962 diag_init_putc(_zylinjtag_diag_write_char);
963 // We want this in the log.
964 diag_printf("Zylin ZY1000.\n");
965
966 err = mount("", "/ram", "ramfs");
967 if (err < 0)
968 {
969 diag_printf("unable to mount ramfs\n");
970 }
971 chdir("/ram");
972
973 char address[16];
974 sprintf(address, "%p", &filedata[0]);
975 err = mount(address, "/rom", "romfs");
976 if (err < 0)
977 {
978 diag_printf("unable to mount /rom\n");
979 }
980
981 err = mount("", "/log", "logfs");
982 if (err < 0)
983 {
984 diag_printf("unable to mount logfs\n");
985 }
986
987 err = mount("", "/tftp", "tftpfs");
988 if (err < 0)
989 {
990 diag_printf("unable to mount logfs\n");
991 }
992
993 log = fopen("/log/log", "w");
994 if (log == NULL)
995 {
996 diag_printf("Could not open log file /ram/log\n");
997 exit(-1);
998 }
999
1000
1001 copydir("/rom", "/ram/cgi");
1002
1003 err = mount("/dev/flash1", "/config", "jffs2");
1004 if (err < 0)
1005 {
1006 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1007 err = mount("", "/config", "ramfs");
1008 if (err < 0)
1009 {
1010 diag_printf("unable to mount /config as ramdisk.\n");
1011 reboot();
1012 }
1013 }
1014 else
1015 {
1016 /* are we using a ram disk instead of a flash disk? This is used
1017 * for ZY1000 live demo...
1018 *
1019 * copy over flash disk to ram block device
1020 */
1021 if (boolParam("ramdisk"))
1022 {
1023 diag_printf("Unmounting /config from flash and using ram instead\n");
1024 err = umount("/config");
1025 if (err < 0)
1026 {
1027 diag_printf("unable to unmount jffs\n");
1028 reboot();
1029 }
1030
1031 err = mount("/dev/flash1", "/config2", "jffs2");
1032 if (err < 0)
1033 {
1034 diag_printf("unable to mount jffs\n");
1035 reboot();
1036 }
1037
1038 err = mount("", "/config", "ramfs");
1039 if (err < 0)
1040 {
1041 diag_printf("unable to mount ram block device\n");
1042 reboot();
1043 }
1044
1045 // copydir("/config2", "/config");
1046 copyfile("/config2/ip", "/config/ip");
1047 copydir("/config2/settings", "/config/settings");
1048
1049 umount("/config2");
1050 }
1051 }
1052
1053 mkdir(zylin_config_dir, 0777);
1054 char *dirname = alloc_printf("%s/target", zylin_config_dir);
1055 mkdir(dirname, 0777);
1056 free(dirname);
1057 dirname = alloc_printf("%s/board", zylin_config_dir);
1058 mkdir(dirname, 0777);
1059 free(dirname);
1060 dirname = alloc_printf("%s/event", zylin_config_dir);
1061 mkdir(dirname, 0777);
1062 free(dirname);
1063
1064 logAllToSerial = boolParam("logserial");
1065
1066 // We need the network & web server in case there is something wrong with
1067 // the config files that invoke exit()
1068 zylinjtag_startNetwork();
1069
1070 /* we're going to access the jim interpreter from here on... */
1071 openocd_sleep_postlude();
1072 startUart();
1073
1074 add_default_dirs();
1075
1076 /* initialize commandline interface */
1077 struct command_context * cmd_ctx;
1078 struct command_context *setup_command_handler(Jim_Interp *interp);
1079 cmd_ctx = setup_command_handler(httpstate.jim_interp);
1080 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1081 command_context_mode(cmd_ctx, COMMAND_CONFIG);
1082
1083 #if BUILD_IOUTIL
1084 if (ioutil_init(cmd_ctx) != ERROR_OK)
1085 {
1086 return EXIT_FAILURE;
1087 }
1088 #endif
1089
1090
1091 #ifdef CYGPKG_PROFILE_GPROF
1092 COMMAND_REGISTER(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1093 COMMAND_ANY, 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)