Fix compilation of target_request.h when it is included first.
[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 <strings.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <errno.h>
48
49 #include <cyg/io/flash.h>
50 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
51 #include <network.h>
52
53 #include <fcntl.h>
54 #include <sys/stat.h>
55 #include <cyg/fileio/fileio.h>
56 #include <dirent.h>
57 #include <cyg/athttpd/http.h>
58 #include <cyg/athttpd/socket.h>
59 #include <cyg/athttpd/handler.h>
60 #include <cyg/athttpd/cgi.h>
61 #include <cyg/athttpd/forms.h>
62 #include <cyg/discover/discover.h>
63 #include <cyg/hal/hal_diag.h>
64 #include <cyg/kernel/kapi.h>
65 #include <cyg/io/serialio.h>
66 #include <cyg/io/io.h>
67 #include <netinet/tcp.h>
68 #include "rom.h"
69 #include <sys/ioctl.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #include <net/if.h>
73 #include <arpa/inet.h>
74 #include <sys/types.h>
75 #include <sys/socket.h>
76 #include <netdb.h>
77 #include <netinet/in.h>
78 #include <unistd.h>
79 #include <arpa/inet.h>
80 #include <stdio.h>
81 #include <ifaddrs.h>
82 #include <string.h>
83
84 #include <unistd.h>
85 #include <stdio.h>
86 #define MAX_IFS 64
87 #if defined(CYGPKG_NET_FREEBSD_STACK)
88 #include <tftp_support.h>
89 /* posix compatibility broken*/
90 struct tftpd_fileops fileops =
91 {
92 (int (*)(const char *, int))open,
93 close,
94 (int (*)(int, const void *, int))write,
95 ( int (*)(int, void *, int))read
96 };
97
98 #endif
99
100
101 void diag_write(char *buf, int len)
102 {
103 int j;
104 for (j = 0; j < len; j++)
105 {
106 diag_printf("%c", buf[j]);
107 }
108 }
109
110 static bool serialLog = true;
111 static bool writeLog = true;
112
113 char hwaddr[512];
114
115
116 extern flash_driver_t *flash_drivers[];
117 extern target_type_t *target_types[];
118
119 #ifdef CYGPKG_PROFILE_GPROF
120 #include <cyg/profile/profile.h>
121
122 extern char _stext, _etext; // Defined by the linker
123
124 static char *start_of_code=&_stext;
125 static char *end_of_code=&_etext;
126
127 void start_profile(void)
128 {
129 // This starts up the system-wide profiling, gathering
130 // profile information on all of the code, with a 16 byte
131 // "bucket" size, at a rate of 100us/profile hit.
132 // Note: a bucket size of 16 will give pretty good function
133 // resolution. Much smaller and the buffer becomes
134 // much too large for very little gain.
135 // Note: a timer period of 100us is also a reasonable
136 // compromise. Any smaller and the overhead of
137 // handling the timter (profile) interrupt could
138 // swamp the system. A fast processor might get
139 // by with a smaller value, but a slow one could
140 // even be swamped by this value. If the value is
141 // too large, the usefulness of the profile is reduced.
142
143 // no more interrupts than 1/10ms.
144 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
145 // profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
146 profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
147 }
148 #endif
149
150 extern int eth0_up;
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 extern void start_profile(void);
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", 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 extern Jim_Interp *interp;
424
425 static void zylinjtag_startNetwork(void)
426 {
427 // Bring TCP/IP up immediately before we're ready to accept commands.
428 //
429 // That is as soon as a PING responds, we're accepting telnet sessions.
430 #if defined(CYGPKG_NET_FREEBSD_STACK)
431 phi_init_all_network_interfaces();
432 #else
433 lwip_init();
434 #endif
435 if (!eth0_up)
436 {
437 diag_printf("Network not up and running\n");
438 exit(-1);
439 }
440 #if defined(CYGPKG_NET_FREEBSD_STACK)
441 /*start TFTP*/
442 tftpd_start(69, &fileops);
443 #endif
444
445 cyg_httpd_init_tcl_interpreter();
446
447 interp = httpstate.jim_interp;
448
449 Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
450 NULL, NULL);
451 Jim_CreateCommand(httpstate.jim_interp, "reboot",
452 zylinjtag_Jim_Command_reboot, NULL, NULL);
453 Jim_CreateCommand(httpstate.jim_interp, "threads",
454 zylinjtag_Jim_Command_threads, NULL, NULL);
455 Jim_CreateCommand(httpstate.jim_interp, "format_jffs2",
456 zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
457
458 cyg_httpd_start();
459
460 webRunning = true;
461
462 diag_printf("Web server running\n");
463
464 int s;
465 struct ifreq ifr;
466 s = socket(AF_INET, SOCK_DGRAM, 0);
467 if (s >= 0)
468 {
469 strcpy(ifr.ifr_name, "eth0");
470 int res;
471 res = ioctl(s, SIOCGIFHWADDR, &ifr);
472 close(s);
473
474 if (res < 0)
475 {
476 diag_printf("Can't obtain MAC address\n");
477 reboot();
478 }
479 }
480
481 sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
482 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
483 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
484 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
485 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
486 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
487 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
488
489 discover_message
490 = alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
491
492 discover_launch();
493 }
494
495 static void print_exception_handler(cyg_addrword_t data, cyg_code_t exception,
496 cyg_addrword_t info)
497 {
498 writeLog = false;
499 serialLog = true;
500 char *infoStr = "unknown";
501 switch (exception)
502 {
503 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
504 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
505 infoStr = "undefined instruction";
506 break;
507 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
508 infoStr = "software interrupt";
509 break;
510 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
511 infoStr = "abort prefetch";
512 break;
513 case CYGNUM_HAL_VECTOR_ABORT_DATA:
514 infoStr = "abort data";
515 break;
516 #endif
517 default:
518 break;
519 }
520
521 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
522
523 diag_printf("Dumping log\n---\n");
524 if (logCount >= logSize)
525 {
526 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
527 }
528 diag_write(logBuffer, writePtr);
529
530 diag_printf("---\nLogdump complete.\n");
531 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
532 diag_printf("\n---\nRebooting\n");
533 HAL_PLATFORM_RESET();
534
535 }
536
537 static void setHandler(cyg_code_t exception)
538 {
539 cyg_exception_handler_t *old_handler;
540 cyg_addrword_t old_data;
541
542 cyg_exception_set_handler(exception, print_exception_handler, 0,
543 &old_handler, &old_data);
544 }
545
546 static cyg_thread zylinjtag_uart_thread_object;
547 static cyg_handle_t zylinjtag_uart_thread_handle;
548 static char uart_stack[4096];
549
550 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
551 static char backwardBuffer[1024];
552
553 void setNoDelay(int session, int flag)
554 {
555 #if 1
556 // This decreases latency dramatically for e.g. GDB load which
557 // does not have a sliding window protocol
558 //
559 // Can cause *lots* of TCP/IP packets to be sent and it would have
560 // to be enabled/disabled on the fly to avoid the CPU being
561 // overloaded...
562 setsockopt(session, /* socket affected */
563 IPPROTO_TCP, /* set option at TCP level */
564 TCP_NODELAY, /* name of option */
565 (char *) &flag, /* the cast is historical
566 cruft */
567 sizeof(int)); /* length of option value */
568 #endif
569 }
570
571 struct
572 {
573 int req;
574 int actual;
575 int req2;
576 int actual2;
577 } tcpipSent[512 * 1024];
578 int cur;
579
580 static void zylinjtag_uart(cyg_addrword_t data)
581 {
582 int so_reuseaddr_option = 1;
583
584 int fd;
585 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
586 {
587 LOG_ERROR("error creating socket: %s", strerror(errno));
588 exit(-1);
589 }
590
591 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
592 sizeof(int));
593
594 struct sockaddr_in sin;
595 unsigned int address_size;
596 address_size = sizeof(sin);
597 memset(&sin, 0, sizeof(sin));
598 sin.sin_family = AF_INET;
599 sin.sin_addr.s_addr = INADDR_ANY;
600 sin.sin_port = htons(5555);
601
602 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
603 {
604 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
605 exit(-1);
606 }
607
608 if (listen(fd, 1) == -1)
609 {
610 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
611 exit(-1);
612 }
613 // socket_nonblock(fd);
614
615
616 for (;;)
617 {
618 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
619 if (session < 0)
620 {
621 continue;
622 }
623
624 setNoDelay(session, 1);
625 int oldopts = fcntl(session, F_GETFL, 0);
626 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
627
628 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
629 if (serHandle < 0)
630 {
631 close(session);
632 continue;
633 }
634
635 #ifdef CYGPKG_PROFILE_GPROF
636 start_profile();
637 #endif
638 int actual = 0;
639 int actual2 = 0;
640 int pos, pos2;
641 pos = 0;
642 pos2 = 0;
643 cur = 0;
644 for (;;)
645 {
646 fd_set write_fds;
647 fd_set read_fds;
648 FD_ZERO(&write_fds);
649 FD_ZERO(&read_fds);
650 int fd_max = -1;
651 FD_SET(session, &read_fds);
652 fd_max = session;
653 FD_SET(serHandle, &read_fds);
654 if (serHandle > fd_max)
655 {
656 fd_max = serHandle;
657 }
658 /* Wait... */
659
660 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
661 if ((actual == 0) && (actual2 == 0))
662 {
663 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
664 if (retval <= 0)
665 {
666 break;
667 }
668 }
669
670 if (actual2 <= 0)
671 {
672 memset(backwardBuffer, 's', sizeof(backwardBuffer));
673 actual2 = read(serHandle, backwardBuffer,
674 sizeof(backwardBuffer));
675 if (actual2 < 0)
676 {
677 if (errno != EAGAIN)
678 {
679 goto closeSession;
680 }
681 actual2 = 0;
682 }
683 pos2 = 0;
684 }
685
686 int x = actual2;
687 int y = 0;
688 if (actual2 > 0)
689 {
690 int written = write(session, backwardBuffer + pos2, actual2);
691 if (written <= 0)
692 goto closeSession;
693 actual2 -= written;
694 pos2 += written;
695 y = written;
696 }
697
698 if (FD_ISSET(session, &read_fds)
699 && (sizeof(forwardBuffer) > actual))
700 {
701 // NB! Here it is important that we empty the TCP/IP read buffer
702 // to make transmission tick right
703 memmove(forwardBuffer, forwardBuffer + pos, actual);
704 pos = 0;
705 int t;
706 // this will block if there is no data at all
707 t = read_socket(session, forwardBuffer + actual,
708 sizeof(forwardBuffer) - actual);
709 if (t <= 0)
710 {
711 goto closeSession;
712 }
713 actual += t;
714 }
715
716 int x2 = actual;
717 int y2 = 0;
718 if (actual > 0)
719 {
720 /* Do not put things into the serial buffer if it has something to send
721 * as that can cause a single byte to be sent at the time.
722 *
723 *
724 */
725 int written = write(serHandle, forwardBuffer + pos, actual);
726 if (written < 0)
727 {
728 if (errno != EAGAIN)
729 {
730 goto closeSession;
731 }
732 // The serial buffer is full
733 written = 0;
734 }
735 else
736 {
737 actual -= written;
738 pos += written;
739 }
740 y2 = written;
741 }
742 if (cur < 1024)
743 {
744 tcpipSent[cur].req = x;
745 tcpipSent[cur].actual = y;
746 tcpipSent[cur].req2 = x2;
747 tcpipSent[cur].actual2 = y2;
748 cur++;
749 }
750
751 }
752 closeSession: close(session);
753 close(serHandle);
754
755 int i;
756 for (i = 0; i < 1024; i++)
757 {
758 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual,
759 tcpipSent[i].req2, tcpipSent[i].actual2);
760
761 }
762 }
763 close(fd);
764
765 }
766
767 void startUart(void)
768 {
769 cyg_thread_create(1, zylinjtag_uart, (cyg_addrword_t) 0, "uart thread",
770 (void *) uart_stack, sizeof(uart_stack),
771 &zylinjtag_uart_thread_handle, &zylinjtag_uart_thread_object);
772 cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
773 cyg_thread_resume(zylinjtag_uart_thread_handle);
774 }
775
776 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd,
777 char **args, int argc)
778 {
779 static int current_baud = 38400;
780 if (argc == 0)
781 {
782 command_print(cmd_ctx, "%d", current_baud);
783 return ERROR_OK;
784 }
785 else if (argc != 1)
786 {
787 return ERROR_INVALID_ARGUMENTS;
788 }
789
790 current_baud = atol(args[0]);
791
792 int baud;
793 switch (current_baud)
794 {
795 case 9600:
796 baud = CYGNUM_SERIAL_BAUD_9600;
797 break;
798 case 19200:
799 baud = CYGNUM_SERIAL_BAUD_19200;
800 break;
801 case 38400:
802 baud = CYGNUM_SERIAL_BAUD_38400;
803 break;
804 case 57600:
805 baud = CYGNUM_SERIAL_BAUD_57600;
806 break;
807 case 115200:
808 baud = CYGNUM_SERIAL_BAUD_115200;
809 break;
810 case 230400:
811 baud = CYGNUM_SERIAL_BAUD_230400;
812 break;
813 default:
814 command_print(cmd_ctx, "unsupported baudrate");
815 return ERROR_INVALID_ARGUMENTS;
816 }
817
818 cyg_serial_info_t buf;
819 cyg_uint32 len = 1;
820 //get existing serial configuration
821 len = sizeof(cyg_serial_info_t);
822 int err;
823 cyg_io_handle_t serial_handle;
824
825 err = cyg_io_lookup("/dev/ser0", &serial_handle);
826 if (err != ENOERR)
827 {
828 LOG_ERROR("/dev/ser0 not found\n");
829 return ERROR_FAIL;
830 }
831
832 err = cyg_io_get_config(serial_handle,
833 CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
834 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf,
835 &len);
836 if (err != ENOERR)
837 {
838 command_print(cmd_ctx, "Failed to get serial port settings %d", err);
839 return ERROR_OK;
840 }
841 buf.baud = baud;
842
843 err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf,
844 &len);
845 if (err != ENOERR)
846 {
847 command_print(cmd_ctx, "Failed to set serial port settings %d", err);
848 return ERROR_OK;
849 }
850
851 return ERROR_OK;
852 }
853
854 bool logAllToSerial = false;
855
856
857 int boolParam(char *var);
858
859
860 command_context_t *setup_command_handler(void);
861
862 extern const char *zylin_config_dir;
863
864 int add_default_dirs(void)
865 {
866 add_script_search_dir(zylin_config_dir);
867 add_script_search_dir("/rom/lib/openocd");
868 add_script_search_dir("/rom");
869 return ERROR_OK;
870 }
871
872 int ioutil_init(struct command_context_s *cmd_ctx);
873
874 int main(int argc, char *argv[])
875 {
876 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
877 * need to allocate towards the end of the heap. */
878
879 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
880 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
881 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
882 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
883 #endif
884
885 int err;
886
887 atexit(keep_webserver);
888
889 diag_init_putc(_zylinjtag_diag_write_char);
890 // We want this in the log.
891 diag_printf("Zylin ZY1000.\n");
892
893 err = mount("", "/ram", "ramfs");
894 if (err < 0)
895 {
896 diag_printf("unable to mount ramfs\n");
897 }
898 chdir("/ram");
899
900 char address[16];
901 sprintf(address, "%p", &filedata[0]);
902 err = mount(address, "/rom", "romfs");
903 if (err < 0)
904 {
905 diag_printf("unable to mount /rom\n");
906 }
907
908 err = mount("", "/log", "logfs");
909 if (err < 0)
910 {
911 diag_printf("unable to mount logfs\n");
912 }
913
914 err = mount("", "/tftp", "tftpfs");
915 if (err < 0)
916 {
917 diag_printf("unable to mount logfs\n");
918 }
919
920 log = fopen("/log/log", "w");
921 if (log == NULL)
922 {
923 diag_printf("Could not open log file /ram/log\n");
924 exit(-1);
925 }
926
927
928 copydir("/rom", "/ram/cgi");
929
930 err = mount("/dev/flash1", "/config", "jffs2");
931 if (err < 0)
932 {
933 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
934 err = mount("", "/config", "ramfs");
935 if (err < 0)
936 {
937 diag_printf("unable to mount /config as ramdisk.\n");
938 reboot();
939 }
940 }
941 else
942 {
943 /* are we using a ram disk instead of a flash disk? This is used
944 * for ZY1000 live demo...
945 *
946 * copy over flash disk to ram block device
947 */
948 if (boolParam("ramdisk"))
949 {
950 diag_printf("Unmounting /config from flash and using ram instead\n");
951 err = umount("/config");
952 if (err < 0)
953 {
954 diag_printf("unable to unmount jffs\n");
955 reboot();
956 }
957
958 err = mount("/dev/flash1", "/config2", "jffs2");
959 if (err < 0)
960 {
961 diag_printf("unable to mount jffs\n");
962 reboot();
963 }
964
965 err = mount("", "/config", "ramfs");
966 if (err < 0)
967 {
968 diag_printf("unable to mount ram block device\n");
969 reboot();
970 }
971
972 // copydir("/config2", "/config");
973 copyfile("/config2/ip", "/config/ip");
974 copydir("/config2/settings", "/config/settings");
975
976 umount("/config2");
977 }
978 }
979
980 mkdir(zylin_config_dir, 0777);
981 char *dirname=alloc_printf("%s/target", zylin_config_dir);
982 mkdir(dirname, 0777);
983 free(dirname);
984 dirname=alloc_printf("%s/board", zylin_config_dir);
985 mkdir(dirname, 0777);
986 free(dirname);
987 dirname=alloc_printf("%s/event", zylin_config_dir);
988 mkdir(dirname, 0777);
989 free(dirname);
990
991 logAllToSerial = boolParam("logserial");
992
993 // We need the network & web server in case there is something wrong with
994 // the config files that invoke exit()
995 zylinjtag_startNetwork();
996
997 /* we're going to access the jim interpreter from here on... */
998 openocd_sleep_postlude();
999 startUart();
1000
1001 add_default_dirs();
1002
1003 /* initialize commandline interface */
1004 command_context_t * cmd_ctx;
1005 cmd_ctx = setup_command_handler();
1006 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1007 command_context_mode(cmd_ctx, COMMAND_CONFIG);
1008
1009 #if BUILD_IOUTIL
1010 if (ioutil_init(cmd_ctx) != ERROR_OK)
1011 {
1012 return EXIT_FAILURE;
1013 }
1014 #endif
1015
1016
1017 #ifdef CYGPKG_PROFILE_GPROF
1018 register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1019 COMMAND_ANY, NULL);
1020 #endif
1021
1022 register_command(cmd_ctx, NULL, "uart", handle_uart_command, COMMAND_ANY,
1023 "uart <baud> - forward uart on port 5555");
1024
1025 int errVal;
1026 errVal = log_init(cmd_ctx);
1027 if (errVal != ERROR_OK)
1028 {
1029 diag_printf("log_init() failed %d\n", errVal);
1030 exit(-1);
1031 }
1032
1033 set_log_output(cmd_ctx, log);
1034
1035 LOG_DEBUG("log init complete");
1036
1037 // diag_printf("Executing config files\n");
1038
1039 if (logAllToSerial)
1040 {
1041 diag_printf(
1042 "%s/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n", zylin_config_dir);
1043 command_run_line(cmd_ctx, "debug_level 3");
1044 }
1045
1046 command_run_linef(cmd_ctx, "script /rom/openocd.cfg");
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 <unistd.h>
1100 #include <sys/types.h>
1101 #include <fcntl.h>
1102 #include <sys/stat.h>
1103 #include <errno.h>
1104 #include <dirent.h>
1105
1106 #include <stdarg.h>
1107 #include <stdio.h>
1108 #include <stdlib.h>
1109 #include <string.h>
1110
1111 #include <cyg/fileio/fileio.h>
1112
1113 #include <cyg/kernel/kapi.h>
1114 #include <cyg/infra/diag.h>
1115
1116 //==========================================================================
1117 // Eventually we want to eXecute In Place from the ROM in a protected
1118 // environment, so we'll need executables to be aligned to a boundary
1119 // suitable for MMU protection. A suitable boundary would be the 4k
1120 // boundary in all the CPU architectures I am currently aware of.
1121
1122 // Forward definitions
1123
1124 // Filesystem operations
1125 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1126 static int tftpfs_umount(cyg_mtab_entry *mte);
1127 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1128 int mode, cyg_file *fte);
1129 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1130 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1131
1132 // File operations
1133 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1134 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
1135 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
1136
1137 //==========================================================================
1138 // Filesystem table entries
1139
1140 // -------------------------------------------------------------------------
1141 // Fstab entry.
1142 // This defines the entry in the filesystem table.
1143 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1144 // we should never block in any filesystem operations.
1145 #if 1
1146 FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,
1147 CYG_SYNCMODE_NONE,
1148 tftpfs_mount,
1149 tftpfs_umount,
1150 tftpfs_open,
1151 (cyg_fsop_unlink *)cyg_fileio_erofs,
1152 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1153 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1154 (cyg_fsop_rename *)cyg_fileio_erofs,
1155 (cyg_fsop_link *)cyg_fileio_erofs,
1156 (cyg_fsop_opendir *)cyg_fileio_erofs,
1157 (cyg_fsop_chdir *)cyg_fileio_erofs,
1158 (cyg_fsop_stat *)cyg_fileio_erofs,
1159 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1160 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1161 #endif
1162
1163 // -------------------------------------------------------------------------
1164 // mtab entry.
1165 // This defines a single ROMFS loaded into ROM at the configured address
1166 //
1167 // MTAB_ENTRY( rom_mte, // structure name
1168 // "/rom", // mount point
1169 // "romfs", // FIlesystem type
1170 // "", // hardware device
1171 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
1172 // );
1173
1174
1175 // -------------------------------------------------------------------------
1176 // File operations.
1177 // This set of file operations are used for normal open files.
1178
1179 static cyg_fileops tftpfs_fileops =
1180 { tftpfs_fo_read, tftpfs_fo_write, tftpfs_fo_lseek,
1181 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1182 tftpfs_fo_fsync, tftpfs_fo_close,
1183 (cyg_fileop_fstat *) cyg_fileio_erofs,
1184 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1185 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1186
1187 // -------------------------------------------------------------------------
1188 // tftpfs_mount()
1189 // Process a mount request. This mainly finds root for the
1190 // filesystem.
1191
1192 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1193 {
1194 return ENOERR;
1195 }
1196
1197 static int tftpfs_umount(cyg_mtab_entry *mte)
1198 {
1199 return ENOERR;
1200 }
1201
1202 struct Tftp
1203 {
1204 int write;
1205 int readFile;
1206 cyg_uint8 *mem;
1207 int actual;
1208 char *server;
1209 char *file;
1210 };
1211
1212 static void freeTftp(struct Tftp *t)
1213 {
1214 if (t == NULL)
1215 return;
1216 if (t->mem)
1217 free(t->mem);
1218 if (t->server)
1219 free(t->server);
1220 if (t->file)
1221 free(t->file);
1222 free(t);
1223 }
1224
1225 static const int tftpMaxSize = 8192 * 1024;
1226 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1227 int mode, cyg_file *file)
1228 {
1229 struct Tftp *tftp;
1230 tftp = malloc(sizeof(struct Tftp));
1231 if (tftp == NULL)
1232 return EMFILE;
1233 memset(tftp, 0, sizeof(struct Tftp));
1234
1235 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1236 file->f_type = CYG_FILE_TYPE_FILE;
1237 file->f_ops = &tftpfs_fileops;
1238 file->f_offset = 0;
1239 file->f_data = 0;
1240 file->f_xops = 0;
1241
1242 tftp->mem = malloc(tftpMaxSize);
1243 if (tftp->mem == NULL)
1244 {
1245 freeTftp(tftp);
1246 return EMFILE;
1247 }
1248
1249 char *server = strchr(name, '/');
1250 if (server == NULL)
1251 {
1252 freeTftp(tftp);
1253 return EMFILE;
1254 }
1255
1256 tftp->server = malloc(server - name + 1);
1257 if (tftp->server == NULL)
1258 {
1259 freeTftp(tftp);
1260 return EMFILE;
1261 }
1262 strncpy(tftp->server, name, server - name);
1263 tftp->server[server - name] = 0;
1264
1265 tftp->file = strdup(server + 1);
1266 if (tftp->file == NULL)
1267 {
1268 freeTftp(tftp);
1269 return EMFILE;
1270 }
1271
1272 file->f_data = (CYG_ADDRWORD) tftp;
1273
1274 return ENOERR;
1275 }
1276
1277 static int fetchTftp(struct Tftp *tftp)
1278 {
1279 if (!tftp->readFile)
1280 {
1281 int err;
1282 tftp->actual = tftp_client_get(tftp->file, tftp->server, 0, tftp->mem,
1283 tftpMaxSize, TFTP_OCTET, &err);
1284
1285 if (tftp->actual < 0)
1286 {
1287 return EMFILE;
1288 }
1289 tftp->readFile = 1;
1290 }
1291 return ENOERR;
1292 }
1293
1294 // -------------------------------------------------------------------------
1295 // tftpfs_fo_write()
1296 // Read data from file.
1297
1298 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1299 {
1300 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1301
1302 if (fetchTftp(tftp) != ENOERR)
1303 return EMFILE;
1304
1305 int i;
1306 off_t pos = fp->f_offset;
1307 int resid = 0;
1308 for (i = 0; i < uio->uio_iovcnt; i++)
1309 {
1310 cyg_iovec *iov = &uio->uio_iov[i];
1311 char *buf = (char *) iov->iov_base;
1312 off_t len = iov->iov_len;
1313
1314 if (len + pos > tftp->actual)
1315 {
1316 len = tftp->actual - pos;
1317 }
1318 resid += iov->iov_len - len;
1319
1320 memcpy(buf, tftp->mem + pos, len);
1321 pos += len;
1322
1323 }
1324 uio->uio_resid = resid;
1325 fp->f_offset = pos;
1326
1327 return ENOERR;
1328 }
1329
1330 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1331 {
1332 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1333
1334 int i;
1335 off_t pos = fp->f_offset;
1336 int resid = 0;
1337 for (i = 0; i < uio->uio_iovcnt; i++)
1338 {
1339 cyg_iovec *iov = &uio->uio_iov[i];
1340 char *buf = (char *) iov->iov_base;
1341 off_t len = iov->iov_len;
1342
1343 if (len + pos > tftpMaxSize)
1344 {
1345 len = tftpMaxSize - pos;
1346 }
1347 resid += iov->iov_len - len;
1348
1349 memcpy(tftp->mem + pos, buf, len);
1350 pos += len;
1351
1352 }
1353 uio->uio_resid = resid;
1354 fp->f_offset = pos;
1355
1356 tftp->write = 1;
1357
1358 return ENOERR;
1359 }
1360
1361 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1362 {
1363 int error = ENOERR;
1364 return error;
1365 }
1366
1367 // -------------------------------------------------------------------------
1368 // romfs_fo_close()
1369 // Close a file. We just clear out the data pointer.
1370
1371 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
1372 {
1373 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1374 int error = ENOERR;
1375
1376 if (tftp->write)
1377 {
1378 tftp_client_put(tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,
1379 TFTP_OCTET, &error);
1380 }
1381
1382 freeTftp(tftp);
1383 fp->f_data = 0;
1384 return error;
1385 }
1386
1387 // -------------------------------------------------------------------------
1388 // romfs_fo_lseek()
1389 // Seek to a new file position.
1390
1391 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
1392 {
1393 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1394 off_t pos = *apos;
1395
1396 if (fetchTftp(tftp) != ENOERR)
1397 return EMFILE;
1398
1399 switch (whence)
1400 {
1401 case SEEK_SET:
1402 // Pos is already where we want to be.
1403 break;
1404
1405 case SEEK_CUR:
1406 // Add pos to current offset.
1407 pos += fp->f_offset;
1408 break;
1409
1410 case SEEK_END:
1411 // Add pos to file size.
1412 pos += tftp->actual;
1413 break;
1414
1415 default:
1416 return EINVAL;
1417 }
1418
1419 // Check that pos is still within current file size, or at the
1420 // very end.
1421 if (pos < 0 || pos > tftp->actual)
1422 return EINVAL;
1423
1424 // All OK, set fp offset and return new position.
1425 *apos = fp->f_offset = pos;
1426
1427 return ENOERR;
1428 }
1429
1430 void usleep(int us)
1431 {
1432 if (us > 10000)
1433 cyg_thread_delay(us / 10000 + 1);
1434 else
1435 HAL_DELAY_US(us);
1436 }
1437
1438 // Chunked version.
1439 cyg_int32 show_log_entry(CYG_HTTPD_STATE *phttpstate)
1440 {
1441 cyg_httpd_start_chunked("text");
1442 if (logCount >= logSize)
1443 {
1444 cyg_httpd_write_chunked(logBuffer + logCount % logSize, logSize
1445 - logCount % logSize);
1446 }
1447 cyg_httpd_write_chunked(logBuffer, writePtr);
1448 cyg_httpd_end_chunked();
1449 return -1;
1450 }
1451
1452 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
1453
1454 // Filesystem operations
1455 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1456 static int logfs_umount(cyg_mtab_entry *mte);
1457 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1458 int mode, cyg_file *fte);
1459 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1460
1461 // File operations
1462 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1463 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
1464
1465 #include <cyg/io/devtab.h>
1466
1467 //==========================================================================
1468 // Filesystem table entries
1469
1470 // -------------------------------------------------------------------------
1471 // Fstab entry.
1472 // This defines the entry in the filesystem table.
1473 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1474 // we should never block in any filesystem operations.
1475 FSTAB_ENTRY( logfs_fste, "logfs", 0,
1476 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
1477 logfs_mount,
1478 logfs_umount,
1479 logfs_open,
1480 (cyg_fsop_unlink *)cyg_fileio_erofs,
1481 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1482 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1483 (cyg_fsop_rename *)cyg_fileio_erofs,
1484 (cyg_fsop_link *)cyg_fileio_erofs,
1485 (cyg_fsop_opendir *)cyg_fileio_erofs,
1486 (cyg_fsop_chdir *)cyg_fileio_erofs,
1487 (cyg_fsop_stat *)cyg_fileio_erofs,
1488 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1489 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1490
1491 // -------------------------------------------------------------------------
1492 // File operations.
1493 // This set of file operations are used for normal open files.
1494
1495 static cyg_fileops logfs_fileops =
1496 { (cyg_fileop_read *) cyg_fileio_erofs, (cyg_fileop_write *) logfs_fo_write,
1497 (cyg_fileop_lseek *) cyg_fileio_erofs,
1498 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1499 logfs_fo_fsync, logfs_fo_close, (cyg_fileop_fstat *) cyg_fileio_erofs,
1500 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1501 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1502
1503 // -------------------------------------------------------------------------
1504 // logfs_mount()
1505 // Process a mount request. This mainly finds root for the
1506 // filesystem.
1507
1508 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1509 {
1510 return ENOERR;
1511 }
1512
1513 static int logfs_umount(cyg_mtab_entry *mte)
1514 {
1515 return ENOERR;
1516 }
1517
1518 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1519 int mode, cyg_file *file)
1520 {
1521 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1522 file->f_type = CYG_FILE_TYPE_FILE;
1523 file->f_ops = &logfs_fileops;
1524 file->f_offset = 0;
1525 file->f_data = 0;
1526 file->f_xops = 0;
1527 return ENOERR;
1528 }
1529
1530 // -------------------------------------------------------------------------
1531 // logfs_fo_write()
1532 // Write data to file.
1533
1534 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1535 {
1536 int i;
1537 for (i = 0; i < uio->uio_iovcnt; i++)
1538 {
1539 cyg_iovec *iov = &uio->uio_iov[i];
1540 char *buf = (char *) iov->iov_base;
1541 off_t len = iov->iov_len;
1542
1543 diag_write(buf, len);
1544 }
1545 uio->uio_resid = 0;
1546
1547 return ENOERR;
1548 }
1549 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1550 {
1551 return ENOERR;
1552 }
1553
1554 // -------------------------------------------------------------------------
1555 // romfs_fo_close()
1556 // Close a file. We just clear out the data pointer.
1557
1558 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
1559 {
1560 return ENOERR;
1561 }
1562

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)