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

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)