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

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)