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

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)