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

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)