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

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)