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

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)