disable ZY1000's UART forwarding test code.
[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 #define TEST_TCPIP() 0
629
630 #if TEST_TCPIP
631 struct
632 {
633 int req;
634 int actual;
635 int req2;
636 int actual2;
637 } tcpipSent[512 * 1024];
638 int cur;
639 #endif
640
641 static void zylinjtag_uart(cyg_addrword_t data)
642 {
643 int so_reuseaddr_option = 1;
644
645 int fd;
646 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
647 {
648 LOG_ERROR("error creating socket: %s", strerror(errno));
649 exit(-1);
650 }
651
652 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
653 sizeof(int));
654
655 struct sockaddr_in sin;
656 unsigned int address_size;
657 address_size = sizeof(sin);
658 memset(&sin, 0, sizeof(sin));
659 sin.sin_family = AF_INET;
660 sin.sin_addr.s_addr = INADDR_ANY;
661 sin.sin_port = htons(5555);
662
663 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
664 {
665 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
666 exit(-1);
667 }
668
669 if (listen(fd, 1) == -1)
670 {
671 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
672 exit(-1);
673 }
674 // socket_nonblock(fd);
675
676
677 for (;;)
678 {
679 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
680 if (session < 0)
681 {
682 continue;
683 }
684
685 setNoDelay(session, 1);
686 int oldopts = fcntl(session, F_GETFL, 0);
687 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
688
689 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
690 if (serHandle < 0)
691 {
692 close(session);
693 continue;
694 }
695
696 #ifdef CYGPKG_PROFILE_GPROF
697 start_profile();
698 #endif
699 size_t actual = 0;
700 size_t actual2 = 0;
701 size_t pos, pos2;
702 pos = 0;
703 pos2 = 0;
704 #if TEST_TCPIP
705 cur = 0;
706 #endif
707 for (;;)
708 {
709 fd_set write_fds;
710 fd_set read_fds;
711 FD_ZERO(&write_fds);
712 FD_ZERO(&read_fds);
713 int fd_max = -1;
714 FD_SET(session, &read_fds);
715 fd_max = session;
716 FD_SET(serHandle, &read_fds);
717 if (serHandle > fd_max)
718 {
719 fd_max = serHandle;
720 }
721 /* Wait... */
722
723 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
724 if ((actual == 0) && (actual2 == 0))
725 {
726 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
727 if (retval <= 0)
728 {
729 break;
730 }
731 }
732
733 if (actual2 <= 0)
734 {
735 memset(backwardBuffer, 's', sizeof(backwardBuffer));
736 int t;
737 t = read(serHandle, backwardBuffer,
738 sizeof(backwardBuffer));
739 actual2 = t;
740 if (t < 0)
741 {
742 if (errno != EAGAIN)
743 {
744 goto closeSession;
745 }
746 actual2 = 0;
747 }
748 pos2 = 0;
749 }
750
751 size_t x = actual2;
752 size_t y = 0;
753 if (actual2 > 0)
754 {
755 int written = write(session, backwardBuffer + pos2, actual2);
756 if (written <= 0)
757 goto closeSession;
758 actual2 -= written;
759 pos2 += written;
760 y = written;
761 }
762
763 if (FD_ISSET(session, &read_fds)
764 && (sizeof(forwardBuffer) > actual))
765 {
766 // NB! Here it is important that we empty the TCP/IP read buffer
767 // to make transmission tick right
768 memmove(forwardBuffer, forwardBuffer + pos, actual);
769 pos = 0;
770 int t;
771 // this will block if there is no data at all
772 t = read_socket(session, forwardBuffer + actual,
773 sizeof(forwardBuffer) - actual);
774 if (t <= 0)
775 {
776 goto closeSession;
777 }
778 actual += t;
779 }
780
781 int x2 = actual;
782 int y2 = 0;
783 if (actual > 0)
784 {
785 /* Do not put things into the serial buffer if it has something to send
786 * as that can cause a single byte to be sent at the time.
787 *
788 *
789 */
790 int written = write(serHandle, forwardBuffer + pos, actual);
791 if (written < 0)
792 {
793 if (errno != EAGAIN)
794 {
795 goto closeSession;
796 }
797 // The serial buffer is full
798 written = 0;
799 }
800 else
801 {
802 actual -= written;
803 pos += written;
804 }
805 y2 = written;
806 }
807 #if TEST_TCPIP
808 if (cur < 1024)
809 {
810 tcpipSent[cur].req = x;
811 tcpipSent[cur].actual = y;
812 tcpipSent[cur].req2 = x2;
813 tcpipSent[cur].actual2 = y2;
814 cur++;
815 }
816 #endif
817 }
818 closeSession: close(session);
819 close(serHandle);
820
821 #if TEST_TCPIP
822 int i;
823 for (i = 0; i < 1024; i++)
824 {
825 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual,
826 tcpipSent[i].req2, tcpipSent[i].actual2);
827
828 }
829 #endif
830 }
831 close(fd);
832
833 }
834
835 void startUart(void)
836 {
837 cyg_thread_create(1, zylinjtag_uart, (cyg_addrword_t) 0, "uart thread",
838 (void *) uart_stack, sizeof(uart_stack),
839 &zylinjtag_uart_thread_handle, &zylinjtag_uart_thread_object);
840 cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
841 cyg_thread_resume(zylinjtag_uart_thread_handle);
842 }
843
844 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd,
845 char **args, int argc)
846 {
847 static int current_baud = 38400;
848 if (argc == 0)
849 {
850 command_print(cmd_ctx, "%d", current_baud);
851 return ERROR_OK;
852 }
853 else if (argc != 1)
854 {
855 return ERROR_INVALID_ARGUMENTS;
856 }
857
858 current_baud = atol(args[0]);
859
860 int baud;
861 switch (current_baud)
862 {
863 case 9600:
864 baud = CYGNUM_SERIAL_BAUD_9600;
865 break;
866 case 19200:
867 baud = CYGNUM_SERIAL_BAUD_19200;
868 break;
869 case 38400:
870 baud = CYGNUM_SERIAL_BAUD_38400;
871 break;
872 case 57600:
873 baud = CYGNUM_SERIAL_BAUD_57600;
874 break;
875 case 115200:
876 baud = CYGNUM_SERIAL_BAUD_115200;
877 break;
878 case 230400:
879 baud = CYGNUM_SERIAL_BAUD_230400;
880 break;
881 default:
882 command_print(cmd_ctx, "unsupported baudrate");
883 return ERROR_INVALID_ARGUMENTS;
884 }
885
886 cyg_serial_info_t buf;
887 cyg_uint32 len = 1;
888 //get existing serial configuration
889 len = sizeof(cyg_serial_info_t);
890 int err;
891 cyg_io_handle_t serial_handle;
892
893 err = cyg_io_lookup("/dev/ser0", &serial_handle);
894 if (err != ENOERR)
895 {
896 LOG_ERROR("/dev/ser0 not found\n");
897 return ERROR_FAIL;
898 }
899
900 err = cyg_io_get_config(serial_handle,
901 CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
902 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf,
903 &len);
904 if (err != ENOERR)
905 {
906 command_print(cmd_ctx, "Failed to get serial port settings %d", err);
907 return ERROR_OK;
908 }
909 buf.baud = baud;
910
911 err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf,
912 &len);
913 if (err != ENOERR)
914 {
915 command_print(cmd_ctx, "Failed to set serial port settings %d", err);
916 return ERROR_OK;
917 }
918
919 return ERROR_OK;
920 }
921
922 bool logAllToSerial = false;
923
924
925 int boolParam(char *var);
926
927
928 command_context_t *setup_command_handler(void);
929
930 static const char *zylin_config_dir="/config/settings";
931
932 static int add_default_dirs(void)
933 {
934 add_script_search_dir(zylin_config_dir);
935 add_script_search_dir("/rom/lib/openocd");
936 add_script_search_dir("/rom");
937 return ERROR_OK;
938 }
939
940 int ioutil_init(struct command_context_s *cmd_ctx);
941
942 int main(int argc, char *argv[])
943 {
944 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
945 * need to allocate towards the end of the heap. */
946
947 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
948 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
949 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
950 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
951 #endif
952
953 int err;
954
955 atexit(keep_webserver);
956
957 diag_init_putc(_zylinjtag_diag_write_char);
958 // We want this in the log.
959 diag_printf("Zylin ZY1000.\n");
960
961 err = mount("", "/ram", "ramfs");
962 if (err < 0)
963 {
964 diag_printf("unable to mount ramfs\n");
965 }
966 chdir("/ram");
967
968 char address[16];
969 sprintf(address, "%p", &filedata[0]);
970 err = mount(address, "/rom", "romfs");
971 if (err < 0)
972 {
973 diag_printf("unable to mount /rom\n");
974 }
975
976 err = mount("", "/log", "logfs");
977 if (err < 0)
978 {
979 diag_printf("unable to mount logfs\n");
980 }
981
982 err = mount("", "/tftp", "tftpfs");
983 if (err < 0)
984 {
985 diag_printf("unable to mount logfs\n");
986 }
987
988 log = fopen("/log/log", "w");
989 if (log == NULL)
990 {
991 diag_printf("Could not open log file /ram/log\n");
992 exit(-1);
993 }
994
995
996 copydir("/rom", "/ram/cgi");
997
998 err = mount("/dev/flash1", "/config", "jffs2");
999 if (err < 0)
1000 {
1001 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1002 err = mount("", "/config", "ramfs");
1003 if (err < 0)
1004 {
1005 diag_printf("unable to mount /config as ramdisk.\n");
1006 reboot();
1007 }
1008 }
1009 else
1010 {
1011 /* are we using a ram disk instead of a flash disk? This is used
1012 * for ZY1000 live demo...
1013 *
1014 * copy over flash disk to ram block device
1015 */
1016 if (boolParam("ramdisk"))
1017 {
1018 diag_printf("Unmounting /config from flash and using ram instead\n");
1019 err = umount("/config");
1020 if (err < 0)
1021 {
1022 diag_printf("unable to unmount jffs\n");
1023 reboot();
1024 }
1025
1026 err = mount("/dev/flash1", "/config2", "jffs2");
1027 if (err < 0)
1028 {
1029 diag_printf("unable to mount jffs\n");
1030 reboot();
1031 }
1032
1033 err = mount("", "/config", "ramfs");
1034 if (err < 0)
1035 {
1036 diag_printf("unable to mount ram block device\n");
1037 reboot();
1038 }
1039
1040 // copydir("/config2", "/config");
1041 copyfile("/config2/ip", "/config/ip");
1042 copydir("/config2/settings", "/config/settings");
1043
1044 umount("/config2");
1045 }
1046 }
1047
1048 mkdir(zylin_config_dir, 0777);
1049 char *dirname = alloc_printf("%s/target", zylin_config_dir);
1050 mkdir(dirname, 0777);
1051 free(dirname);
1052 dirname = alloc_printf("%s/board", zylin_config_dir);
1053 mkdir(dirname, 0777);
1054 free(dirname);
1055 dirname = alloc_printf("%s/event", zylin_config_dir);
1056 mkdir(dirname, 0777);
1057 free(dirname);
1058
1059 logAllToSerial = boolParam("logserial");
1060
1061 // We need the network & web server in case there is something wrong with
1062 // the config files that invoke exit()
1063 zylinjtag_startNetwork();
1064
1065 /* we're going to access the jim interpreter from here on... */
1066 openocd_sleep_postlude();
1067 startUart();
1068
1069 add_default_dirs();
1070
1071 /* initialize commandline interface */
1072 command_context_t * cmd_ctx;
1073 cmd_ctx = setup_command_handler();
1074 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1075 command_context_mode(cmd_ctx, COMMAND_CONFIG);
1076
1077 #if BUILD_IOUTIL
1078 if (ioutil_init(cmd_ctx) != ERROR_OK)
1079 {
1080 return EXIT_FAILURE;
1081 }
1082 #endif
1083
1084
1085 #ifdef CYGPKG_PROFILE_GPROF
1086 register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1087 COMMAND_ANY, NULL);
1088 #endif
1089
1090 register_command(cmd_ctx, NULL, "uart", handle_uart_command, COMMAND_ANY,
1091 "uart <baud> - forward uart on port 5555");
1092
1093 int errVal;
1094 errVal = log_init(cmd_ctx);
1095 if (errVal != ERROR_OK)
1096 {
1097 diag_printf("log_init() failed %d\n", errVal);
1098 exit(-1);
1099 }
1100
1101 set_log_output(cmd_ctx, log);
1102
1103 LOG_DEBUG("log init complete");
1104
1105 // diag_printf("Executing config files\n");
1106
1107 if (logAllToSerial)
1108 {
1109 diag_printf(
1110 "%s/logserial = 1 => sending log output to serial port using \"debug_level 3\" as default.\n", zylin_config_dir);
1111 command_run_line(cmd_ctx, "debug_level 3");
1112 }
1113
1114 command_run_linef(cmd_ctx, "script /rom/openocd.cfg");
1115
1116 /* we MUST always run the init command as it will launch telnet sessions */
1117 command_run_line(cmd_ctx, "init");
1118
1119 // FIX!!! Yuk!
1120 // diag_printf() is really invoked from many more places than we trust it
1121 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1122 //
1123 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1124 // fingers that it doesn't cause any crashes.
1125 diag_printf("Init complete, GDB & telnet servers launched.\n");
1126 command_set_output_handler(cmd_ctx,
1127 zy1000_configuration_output_handler_log, NULL);
1128 if (!logAllToSerial)
1129 {
1130 serialLog = false;
1131 }
1132
1133 /* handle network connections */
1134 server_loop(cmd_ctx);
1135 openocd_sleep_prelude();
1136
1137 /* shut server down */
1138 server_quit();
1139
1140 /* free commandline interface */
1141 command_done(cmd_ctx);
1142 umount("/config");
1143
1144 exit(0);
1145 for (;;)
1146 ;
1147 }
1148
1149 cyg_int32 cyg_httpd_exec_cgi_tcl(char *file_name);
1150 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1151 {
1152 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1153 return 0;
1154 }
1155
1156 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1157
1158 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1159 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1160
1161 #include <pkgconf/system.h>
1162 #include <pkgconf/hal.h>
1163 #include <pkgconf/kernel.h>
1164 #include <pkgconf/io_fileio.h>
1165 #include <pkgconf/fs_rom.h>
1166
1167 #include <cyg/kernel/ktypes.h> // base kernel types
1168 #include <cyg/infra/cyg_trac.h> // tracing macros
1169 #include <cyg/infra/cyg_ass.h> // assertion macros
1170 #include <cyg/fileio/fileio.h>
1171 #include <cyg/kernel/kapi.h>
1172 #include <cyg/infra/diag.h>
1173
1174 //==========================================================================
1175 // Eventually we want to eXecute In Place from the ROM in a protected
1176 // environment, so we'll need executables to be aligned to a boundary
1177 // suitable for MMU protection. A suitable boundary would be the 4k
1178 // boundary in all the CPU architectures I am currently aware of.
1179
1180 // Forward definitions
1181
1182 // Filesystem operations
1183 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1184 static int tftpfs_umount(cyg_mtab_entry *mte);
1185 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1186 int mode, cyg_file *fte);
1187 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1188 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1189
1190 // File operations
1191 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1192 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
1193 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
1194
1195 //==========================================================================
1196 // Filesystem table entries
1197
1198 // -------------------------------------------------------------------------
1199 // Fstab entry.
1200 // This defines the entry in the filesystem table.
1201 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1202 // we should never block in any filesystem operations.
1203 #if 1
1204 FSTAB_ENTRY(tftpfs_fste, "tftpfs", 0,
1205 CYG_SYNCMODE_NONE,
1206 tftpfs_mount,
1207 tftpfs_umount,
1208 tftpfs_open,
1209 (cyg_fsop_unlink *)cyg_fileio_erofs,
1210 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1211 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1212 (cyg_fsop_rename *)cyg_fileio_erofs,
1213 (cyg_fsop_link *)cyg_fileio_erofs,
1214 (cyg_fsop_opendir *)cyg_fileio_erofs,
1215 (cyg_fsop_chdir *)cyg_fileio_erofs,
1216 (cyg_fsop_stat *)cyg_fileio_erofs,
1217 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1218 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1219 #endif
1220
1221 // -------------------------------------------------------------------------
1222 // mtab entry.
1223 // This defines a single ROMFS loaded into ROM at the configured address
1224 //
1225 // MTAB_ENTRY(rom_mte, // structure name
1226 // "/rom", // mount point
1227 // "romfs", // FIlesystem type
1228 // "", // hardware device
1229 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
1230 //);
1231
1232
1233 // -------------------------------------------------------------------------
1234 // File operations.
1235 // This set of file operations are used for normal open files.
1236
1237 static cyg_fileops tftpfs_fileops =
1238 { tftpfs_fo_read, tftpfs_fo_write, tftpfs_fo_lseek,
1239 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1240 tftpfs_fo_fsync, tftpfs_fo_close,
1241 (cyg_fileop_fstat *) cyg_fileio_erofs,
1242 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1243 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1244
1245 // -------------------------------------------------------------------------
1246 // tftpfs_mount()
1247 // Process a mount request. This mainly finds root for the
1248 // filesystem.
1249
1250 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1251 {
1252 return ENOERR;
1253 }
1254
1255 static int tftpfs_umount(cyg_mtab_entry *mte)
1256 {
1257 return ENOERR;
1258 }
1259
1260 struct Tftp
1261 {
1262 int write;
1263 int readFile;
1264 cyg_uint8 *mem;
1265 int actual;
1266 char *server;
1267 char *file;
1268 };
1269
1270 static void freeTftp(struct Tftp *t)
1271 {
1272 if (t == NULL)
1273 return;
1274 if (t->mem)
1275 free(t->mem);
1276 if (t->server)
1277 free(t->server);
1278 if (t->file)
1279 free(t->file);
1280 free(t);
1281 }
1282
1283 static const int tftpMaxSize = 8192 * 1024;
1284 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1285 int mode, cyg_file *file)
1286 {
1287 struct Tftp *tftp;
1288 tftp = malloc(sizeof(struct Tftp));
1289 if (tftp == NULL)
1290 return EMFILE;
1291 memset(tftp, 0, sizeof(struct Tftp));
1292
1293 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1294 file->f_type = CYG_FILE_TYPE_FILE;
1295 file->f_ops = &tftpfs_fileops;
1296 file->f_offset = 0;
1297 file->f_data = 0;
1298 file->f_xops = 0;
1299
1300 tftp->mem = malloc(tftpMaxSize);
1301 if (tftp->mem == NULL)
1302 {
1303 freeTftp(tftp);
1304 return EMFILE;
1305 }
1306
1307 char *server = strchr(name, '/');
1308 if (server == NULL)
1309 {
1310 freeTftp(tftp);
1311 return EMFILE;
1312 }
1313
1314 tftp->server = malloc(server - name + 1);
1315 if (tftp->server == NULL)
1316 {
1317 freeTftp(tftp);
1318 return EMFILE;
1319 }
1320 strncpy(tftp->server, name, server - name);
1321 tftp->server[server - name] = 0;
1322
1323 tftp->file = strdup(server + 1);
1324 if (tftp->file == NULL)
1325 {
1326 freeTftp(tftp);
1327 return EMFILE;
1328 }
1329
1330 file->f_data = (CYG_ADDRWORD) tftp;
1331
1332 return ENOERR;
1333 }
1334
1335 static int fetchTftp(struct Tftp *tftp)
1336 {
1337 if (!tftp->readFile)
1338 {
1339 int err;
1340 tftp->actual = tftp_client_get(tftp->file, tftp->server, 0, tftp->mem,
1341 tftpMaxSize, TFTP_OCTET, &err);
1342
1343 if (tftp->actual < 0)
1344 {
1345 return EMFILE;
1346 }
1347 tftp->readFile = 1;
1348 }
1349 return ENOERR;
1350 }
1351
1352 // -------------------------------------------------------------------------
1353 // tftpfs_fo_write()
1354 // Read data from file.
1355
1356 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1357 {
1358 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1359
1360 if (fetchTftp(tftp) != ENOERR)
1361 return EMFILE;
1362
1363 int i;
1364 off_t pos = fp->f_offset;
1365 int resid = 0;
1366 for (i = 0; i < uio->uio_iovcnt; i++)
1367 {
1368 cyg_iovec *iov = &uio->uio_iov[i];
1369 char *buf = (char *) iov->iov_base;
1370 off_t len = iov->iov_len;
1371
1372 if (len + pos > tftp->actual)
1373 {
1374 len = tftp->actual - pos;
1375 }
1376 resid += iov->iov_len - len;
1377
1378 memcpy(buf, tftp->mem + pos, len);
1379 pos += len;
1380
1381 }
1382 uio->uio_resid = resid;
1383 fp->f_offset = pos;
1384
1385 return ENOERR;
1386 }
1387
1388 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1389 {
1390 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1391
1392 int i;
1393 off_t pos = fp->f_offset;
1394 int resid = 0;
1395 for (i = 0; i < uio->uio_iovcnt; i++)
1396 {
1397 cyg_iovec *iov = &uio->uio_iov[i];
1398 char *buf = (char *) iov->iov_base;
1399 off_t len = iov->iov_len;
1400
1401 if (len + pos > tftpMaxSize)
1402 {
1403 len = tftpMaxSize - pos;
1404 }
1405 resid += iov->iov_len - len;
1406
1407 memcpy(tftp->mem + pos, buf, len);
1408 pos += len;
1409
1410 }
1411 uio->uio_resid = resid;
1412 fp->f_offset = pos;
1413
1414 tftp->write = 1;
1415
1416 return ENOERR;
1417 }
1418
1419 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1420 {
1421 int error = ENOERR;
1422 return error;
1423 }
1424
1425 // -------------------------------------------------------------------------
1426 // romfs_fo_close()
1427 // Close a file. We just clear out the data pointer.
1428
1429 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
1430 {
1431 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1432 int error = ENOERR;
1433
1434 if (tftp->write)
1435 {
1436 tftp_client_put(tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,
1437 TFTP_OCTET, &error);
1438 }
1439
1440 freeTftp(tftp);
1441 fp->f_data = 0;
1442 return error;
1443 }
1444
1445 // -------------------------------------------------------------------------
1446 // romfs_fo_lseek()
1447 // Seek to a new file position.
1448
1449 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
1450 {
1451 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1452 off_t pos = *apos;
1453
1454 if (fetchTftp(tftp) != ENOERR)
1455 return EMFILE;
1456
1457 switch (whence)
1458 {
1459 case SEEK_SET:
1460 // Pos is already where we want to be.
1461 break;
1462
1463 case SEEK_CUR:
1464 // Add pos to current offset.
1465 pos += fp->f_offset;
1466 break;
1467
1468 case SEEK_END:
1469 // Add pos to file size.
1470 pos += tftp->actual;
1471 break;
1472
1473 default:
1474 return EINVAL;
1475 }
1476
1477 // Check that pos is still within current file size, or at the
1478 // very end.
1479 if (pos < 0 || pos > tftp->actual)
1480 return EINVAL;
1481
1482 // All OK, set fp offset and return new position.
1483 *apos = fp->f_offset = pos;
1484
1485 return ENOERR;
1486 }
1487
1488 void usleep(int us)
1489 {
1490 if (us > 10000)
1491 cyg_thread_delay(us / 10000 + 1);
1492 else
1493 HAL_DELAY_US(us);
1494 }
1495
1496 // Chunked version.
1497 cyg_int32 show_log_entry(CYG_HTTPD_STATE *phttpstate)
1498 {
1499 cyg_httpd_start_chunked("text");
1500 if (logCount >= logSize)
1501 {
1502 cyg_httpd_write_chunked(logBuffer + logCount % logSize, logSize
1503 - logCount % logSize);
1504 }
1505 cyg_httpd_write_chunked(logBuffer, writePtr);
1506 cyg_httpd_end_chunked();
1507 return -1;
1508 }
1509
1510 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
1511
1512 // Filesystem operations
1513 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1514 static int logfs_umount(cyg_mtab_entry *mte);
1515 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1516 int mode, cyg_file *fte);
1517 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1518
1519 // File operations
1520 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1521 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
1522
1523 #include <cyg/io/devtab.h>
1524
1525 //==========================================================================
1526 // Filesystem table entries
1527
1528 // -------------------------------------------------------------------------
1529 // Fstab entry.
1530 // This defines the entry in the filesystem table.
1531 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1532 // we should never block in any filesystem operations.
1533 FSTAB_ENTRY(logfs_fste, "logfs", 0,
1534 CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
1535 logfs_mount,
1536 logfs_umount,
1537 logfs_open,
1538 (cyg_fsop_unlink *)cyg_fileio_erofs,
1539 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1540 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1541 (cyg_fsop_rename *)cyg_fileio_erofs,
1542 (cyg_fsop_link *)cyg_fileio_erofs,
1543 (cyg_fsop_opendir *)cyg_fileio_erofs,
1544 (cyg_fsop_chdir *)cyg_fileio_erofs,
1545 (cyg_fsop_stat *)cyg_fileio_erofs,
1546 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1547 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1548
1549 // -------------------------------------------------------------------------
1550 // File operations.
1551 // This set of file operations are used for normal open files.
1552
1553 static cyg_fileops logfs_fileops =
1554 { (cyg_fileop_read *) cyg_fileio_erofs, (cyg_fileop_write *) logfs_fo_write,
1555 (cyg_fileop_lseek *) cyg_fileio_erofs,
1556 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1557 logfs_fo_fsync, logfs_fo_close, (cyg_fileop_fstat *) cyg_fileio_erofs,
1558 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1559 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1560
1561 // -------------------------------------------------------------------------
1562 // logfs_mount()
1563 // Process a mount request. This mainly finds root for the
1564 // filesystem.
1565
1566 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1567 {
1568 return ENOERR;
1569 }
1570
1571 static int logfs_umount(cyg_mtab_entry *mte)
1572 {
1573 return ENOERR;
1574 }
1575
1576 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1577 int mode, cyg_file *file)
1578 {
1579 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1580 file->f_type = CYG_FILE_TYPE_FILE;
1581 file->f_ops = &logfs_fileops;
1582 file->f_offset = 0;
1583 file->f_data = 0;
1584 file->f_xops = 0;
1585 return ENOERR;
1586 }
1587
1588 // -------------------------------------------------------------------------
1589 // logfs_fo_write()
1590 // Write data to file.
1591
1592 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1593 {
1594 int i;
1595 for (i = 0; i < uio->uio_iovcnt; i++)
1596 {
1597 cyg_iovec *iov = &uio->uio_iov[i];
1598 char *buf = (char *) iov->iov_base;
1599 off_t len = iov->iov_len;
1600
1601 diag_write(buf, len);
1602 }
1603 uio->uio_resid = 0;
1604
1605 return ENOERR;
1606 }
1607 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1608 {
1609 return ENOERR;
1610 }
1611
1612 // -------------------------------------------------------------------------
1613 // romfs_fo_close()
1614 // Close a file. We just clear out the data pointer.
1615
1616 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
1617 {
1618 return ENOERR;
1619 }
1620
1621 int loadFile(const char *fileName, void **data, int *len);
1622
1623 /* boolean parameter stored on config */
1624 int boolParam(char *var)
1625 {
1626 bool result = false;
1627 char *name = alloc_printf("%s/%s", zylin_config_dir, var);
1628 if (name == NULL)
1629 return result;
1630
1631 void *data;
1632 int len;
1633 if (loadFile(name, &data, &len) == ERROR_OK)
1634 {
1635 if (len > 1)
1636 len = 1;
1637 result = strncmp((char *) data, "1", len) == 0;
1638 free(data);
1639 }
1640 free(name);
1641 return result;
1642 }
1643

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)