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

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)