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

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)