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

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)