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

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)