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

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)