dummy driver now works under eCos
[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 void *err_addr;
300 len = sizeof(e);
301
302 e.offset = 0;
303 e.len = ds.dev_size;
304 e.err_address = &err_addr;
305
306 diag_printf("Formatting 0x%08x bytes\n", (int)ds.dev_size);
307 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len);
308 if (err != ENOERR)
309 {
310 diag_printf("Flash erase error %d offset 0x%p\n", err, err_addr);
311 reboot();
312 }
313
314 diag_printf("Flash formatted successfully\n");
315
316 reboot();
317 }
318
319 static int zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp, int argc,
320 Jim_Obj * const *argv)
321 {
322 if (argc != 1)
323 {
324 return JIM_ERR;
325 }
326
327 format();
328 for (;;)
329 ;
330 }
331
332 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
333 Jim_Obj * const *argv)
334 {
335 cyg_handle_t thread = 0;
336 cyg_uint16 id = 0;
337 Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
338
339 /* Loop over the threads, and generate a table row for
340 * each.
341 */
342 while (cyg_thread_get_next(&thread, &id))
343 {
344 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
345
346 cyg_thread_info info;
347 char *state_string;
348
349 cyg_thread_get_info(thread, id, &info);
350
351 if (info.name == NULL)
352 info.name = "<no name>";
353
354 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
355 info.name, strlen(info.name)));
356
357 /* Translate the state into a string.
358 */
359 if (info.state == 0)
360 state_string = "RUN";
361 else if (info.state & 0x04)
362 state_string = "SUSP";
363 else
364 switch (info.state & 0x1b)
365 {
366 case 0x01:
367 state_string = "SLEEP";
368 break;
369 case 0x02:
370 state_string = "CNTSLEEP";
371 break;
372 case 0x08:
373 state_string = "CREATE";
374 break;
375 case 0x10:
376 state_string = "EXIT";
377 break;
378 default:
379 state_string = "????";
380 break;
381 }
382
383 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
384 state_string, strlen(state_string)));
385
386 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, id));
387 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
388 info.set_pri));
389 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
390 info.cur_pri));
391
392 Jim_ListAppendElement(interp, threads, threadObj);
393 }
394 Jim_SetResult(interp, threads);
395
396 return JIM_OK;
397 }
398
399 static int zylinjtag_Jim_Command_log(Jim_Interp *interp, int argc,
400 Jim_Obj * const *argv)
401 {
402 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
403
404 if (logCount >= logSize)
405 {
406 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer + logCount
407 % logSize, logSize - logCount % logSize);
408 }
409 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
410
411 Jim_SetResult(interp, tclOutput);
412 return JIM_OK;
413 }
414
415 static int zylinjtag_Jim_Command_reboot(Jim_Interp *interp, int argc,
416 Jim_Obj * const *argv)
417 {
418 reboot();
419 return JIM_OK;
420 }
421
422
423 static void zylinjtag_startNetwork(void)
424 {
425 // Bring TCP/IP up immediately before we're ready to accept commands.
426 //
427 // That is as soon as a PING responds, we're accepting telnet sessions.
428 #if defined(CYGPKG_NET_FREEBSD_STACK)
429 phi_init_all_network_interfaces();
430 #else
431 lwip_init();
432 #endif
433 if (!eth0_up)
434 {
435 diag_printf("Network not up and running\n");
436 exit(-1);
437 }
438 #if defined(CYGPKG_NET_FREEBSD_STACK)
439 /*start TFTP*/
440 tftpd_start(69, &fileops);
441 #endif
442
443 cyg_httpd_init_tcl_interpreter();
444
445 interp = httpstate.jim_interp;
446
447 Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
448 NULL, NULL);
449 Jim_CreateCommand(httpstate.jim_interp, "reboot",
450 zylinjtag_Jim_Command_reboot, NULL, NULL);
451 Jim_CreateCommand(httpstate.jim_interp, "threads",
452 zylinjtag_Jim_Command_threads, NULL, NULL);
453 Jim_CreateCommand(httpstate.jim_interp, "format_jffs2",
454 zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
455
456 cyg_httpd_start();
457
458 webRunning = true;
459
460 diag_printf("Web server running\n");
461
462 int s;
463 struct ifreq ifr;
464 s = socket(AF_INET, SOCK_DGRAM, 0);
465 if (s >= 0)
466 {
467 strcpy(ifr.ifr_name, "eth0");
468 int res;
469 res = ioctl(s, SIOCGIFHWADDR, &ifr);
470 close(s);
471
472 if (res < 0)
473 {
474 diag_printf("Can't obtain MAC address\n");
475 reboot();
476 }
477 }
478
479 sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
480 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
481 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
482 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
483 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
484 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
485 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
486
487 discover_message
488 = alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
489
490 discover_launch();
491 }
492
493 static void print_exception_handler(cyg_addrword_t data, cyg_code_t exception,
494 cyg_addrword_t info)
495 {
496 writeLog = false;
497 serialLog = true;
498 char *infoStr = "unknown";
499 switch (exception)
500 {
501 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
502 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
503 infoStr = "undefined instruction";
504 break;
505 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
506 infoStr = "software interrupt";
507 break;
508 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
509 infoStr = "abort prefetch";
510 break;
511 case CYGNUM_HAL_VECTOR_ABORT_DATA:
512 infoStr = "abort data";
513 break;
514 #endif
515 default:
516 break;
517 }
518
519 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
520
521 diag_printf("Dumping log\n---\n");
522 if (logCount >= logSize)
523 {
524 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
525 }
526 diag_write(logBuffer, writePtr);
527
528 diag_printf("---\nLogdump complete.\n");
529 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
530 diag_printf("\n---\nRebooting\n");
531 HAL_PLATFORM_RESET();
532
533 }
534
535 static void setHandler(cyg_code_t exception)
536 {
537 cyg_exception_handler_t *old_handler;
538 cyg_addrword_t old_data;
539
540 cyg_exception_set_handler(exception, print_exception_handler, 0,
541 &old_handler, &old_data);
542 }
543
544 static cyg_thread zylinjtag_uart_thread_object;
545 static cyg_handle_t zylinjtag_uart_thread_handle;
546 static char uart_stack[4096];
547
548 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
549 static char backwardBuffer[1024];
550
551 void setNoDelay(int session, int flag)
552 {
553 #if 1
554 // This decreases latency dramatically for e.g. GDB load which
555 // does not have a sliding window protocol
556 //
557 // Can cause *lots* of TCP/IP packets to be sent and it would have
558 // to be enabled/disabled on the fly to avoid the CPU being
559 // overloaded...
560 setsockopt(session, /* socket affected */
561 IPPROTO_TCP, /* set option at TCP level */
562 TCP_NODELAY, /* name of option */
563 (char *) &flag, /* the cast is historical
564 cruft */
565 sizeof(int)); /* length of option value */
566 #endif
567 }
568
569 struct
570 {
571 int req;
572 int actual;
573 int req2;
574 int actual2;
575 } tcpipSent[512 * 1024];
576 int cur;
577
578 static void zylinjtag_uart(cyg_addrword_t data)
579 {
580 int so_reuseaddr_option = 1;
581
582 int fd;
583 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
584 {
585 LOG_ERROR("error creating socket: %s", strerror(errno));
586 exit(-1);
587 }
588
589 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
590 sizeof(int));
591
592 struct sockaddr_in sin;
593 unsigned int address_size;
594 address_size = sizeof(sin);
595 memset(&sin, 0, sizeof(sin));
596 sin.sin_family = AF_INET;
597 sin.sin_addr.s_addr = INADDR_ANY;
598 sin.sin_port = htons(5555);
599
600 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
601 {
602 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
603 exit(-1);
604 }
605
606 if (listen(fd, 1) == -1)
607 {
608 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
609 exit(-1);
610 }
611 // socket_nonblock(fd);
612
613
614 for (;;)
615 {
616 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
617 if (session < 0)
618 {
619 continue;
620 }
621
622 setNoDelay(session, 1);
623 int oldopts = fcntl(session, F_GETFL, 0);
624 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
625
626 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
627 if (serHandle < 0)
628 {
629 close(session);
630 continue;
631 }
632
633 #ifdef CYGPKG_PROFILE_GPROF
634 start_profile();
635 #endif
636 int actual = 0;
637 int actual2 = 0;
638 int pos, pos2;
639 pos = 0;
640 pos2 = 0;
641 cur = 0;
642 for (;;)
643 {
644 fd_set write_fds;
645 fd_set read_fds;
646 FD_ZERO(&write_fds);
647 FD_ZERO(&read_fds);
648 int fd_max = -1;
649 FD_SET(session, &read_fds);
650 fd_max = session;
651 FD_SET(serHandle, &read_fds);
652 if (serHandle > fd_max)
653 {
654 fd_max = serHandle;
655 }
656 /* Wait... */
657
658 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
659 if ((actual == 0) && (actual2 == 0))
660 {
661 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
662 if (retval <= 0)
663 {
664 break;
665 }
666 }
667
668 if (actual2 <= 0)
669 {
670 memset(backwardBuffer, 's', sizeof(backwardBuffer));
671 actual2 = read(serHandle, backwardBuffer,
672 sizeof(backwardBuffer));
673 if (actual2 < 0)
674 {
675 if (errno != EAGAIN)
676 {
677 goto closeSession;
678 }
679 actual2 = 0;
680 }
681 pos2 = 0;
682 }
683
684 int x = actual2;
685 int 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)