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

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)