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

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)