1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
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. *
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. *
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 ***************************************************************************/
27 #include "configuration.h"
36 #include "telnet_server.h"
37 #include "gdb_server.h"
39 #include <time_support.h>
41 #include <sys/types.h>
49 #include <cyg/io/flash.h>
50 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
55 #include <cyg/fileio/fileio.h>
57 #include <cyg/athttpd/http.h>
58 #include <cyg/athttpd/socket.h>
59 #include <cyg/athttpd/handler.h>
60 #include <cyg/athttpd/cgi.h>
61 #include <cyg/athttpd/forms.h>
62 #include <cyg/discover/discover.h>
63 #include <cyg/hal/hal_diag.h>
64 #include <cyg/kernel/kapi.h>
65 #include <cyg/io/serialio.h>
66 #include <cyg/io/io.h>
67 #include <netinet/tcp.h>
69 #include <sys/ioctl.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
73 #include <arpa/inet.h>
74 #include <sys/types.h>
75 #include <sys/socket.h>
77 #include <netinet/in.h>
79 #include <arpa/inet.h>
88 #if defined(CYGPKG_NET_FREEBSD_STACK)
89 #include <tftp_support.h>
90 /* posix compatibility broken*/
91 struct tftpd_fileops fileops
=
93 (int (*)(const char *, int))open
,
95 (int (*)(int, const void *, int))write
,
96 ( int (*)(int, void *, int))read
101 #define ZYLIN_VERSION "1.48"
102 #define ZYLIN_DATE __DATE__
103 #define ZYLIN_TIME __TIME__
104 /* hmmm.... we can't pick up the right # during build if we've checked this out
105 * in Eclipse... arrggghh...*/
106 #define ZYLIN_OPENOCD "$Revision$"
107 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
108 #define ZYLIN_CONFIG_DIR "/config/settings"
110 void diag_write(char *buf
, int len
)
113 for (j
= 0; j
< len
; j
++)
115 diag_printf("%c", buf
[j
]);
119 static bool serialLog
= true;
120 static bool writeLog
= true;
125 /* Give TELNET a way to find out what version this is */
126 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
127 char **args
, int argc
)
131 return ERROR_COMMAND_SYNTAX_ERROR
;
135 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
136 } else if (strcmp("openocd", args
[0])==0)
139 revision
=atol(ZYLIN_OPENOCD
+strlen("XRevision: "));
140 command_print(cmd_ctx
, "%d", revision
);
141 } else if (strcmp("zy1000", args
[0])==0)
143 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
144 } else if (strcmp("date", args
[0])==0)
146 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
149 return ERROR_COMMAND_SYNTAX_ERROR
;
158 extern flash_driver_t
*flash_drivers
[];
159 extern target_type_t
*target_types
[];
161 #ifdef CYGPKG_PROFILE_GPROF
162 #include <cyg/profile/profile.h>
164 extern char _stext
, _etext
; // Defined by the linker
166 static char *start_of_code
=&_stext
;
167 static char *end_of_code
=&_etext
;
169 void start_profile(void)
171 // This starts up the system-wide profiling, gathering
172 // profile information on all of the code, with a 16 byte
173 // "bucket" size, at a rate of 100us/profile hit.
174 // Note: a bucket size of 16 will give pretty good function
175 // resolution. Much smaller and the buffer becomes
176 // much too large for very little gain.
177 // Note: a timer period of 100us is also a reasonable
178 // compromise. Any smaller and the overhead of
179 // handling the timter (profile) interrupt could
180 // swamp the system. A fast processor might get
181 // by with a smaller value, but a slow one could
182 // even be swamped by this value. If the value is
183 // too large, the usefulness of the profile is reduced.
185 // no more interrupts than 1/10ms.
186 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
187 // profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
188 profile_on(start_of_code
, end_of_code
, 16, 10000); // Nios DRAM
192 // launch GDB server if a config file exists
193 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
195 bool foundFile
= false;
196 FILE *config_file
= NULL
;
197 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
198 config_file
= fopen(config_file_name
, "r");
203 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
204 if (retval
== ERROR_OK
)
210 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
215 command_print(cmd_ctx
, "No %s found", config_file_name
);
224 static char reboot_stack
[2048];
228 zylinjtag_reboot(cyg_addrword_t data
)
231 diag_printf("Rebooting in 100 ticks..\n");
232 cyg_thread_delay(100);
233 diag_printf("Unmounting /config..\n");
235 diag_printf("Rebooting..\n");
236 HAL_PLATFORM_RESET();
238 static cyg_thread zylinjtag_thread_object
;
239 static cyg_handle_t zylinjtag_thread_handle
;
247 (void *)reboot_stack
,
248 sizeof(reboot_stack
),
249 &zylinjtag_thread_handle
,
250 &zylinjtag_thread_object
);
251 cyg_thread_resume(zylinjtag_thread_handle
);
254 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
256 diag_printf("%s", line
);
261 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
263 LOG_USER_N("%s", line
);
268 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
269 char **args
, int argc
)
273 command_print(cmd_ctx
, "rm <filename>");
274 return ERROR_INVALID_ARGUMENTS
;
277 if (unlink(args
[0]) != 0)
279 command_print(cmd_ctx
, "failed: %d", errno
);
285 int loadFile(const char *fileName
, void **data
, int *len
);
287 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
288 char **args
, int argc
)
292 command_print(cmd_ctx
, "cat <filename>");
293 return ERROR_INVALID_ARGUMENTS
;
296 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
300 int retval
= loadFile(args
[0], &data
, &len
);
301 if (retval
== ERROR_OK
)
303 command_print(cmd_ctx
, "%s", data
);
308 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
313 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
314 char **args
, int argc
)
318 command_print(cmd_ctx
, "trunc <filename>");
319 return ERROR_INVALID_ARGUMENTS
;
322 FILE *config_file
= NULL
;
323 config_file
= fopen(args
[0], "w");
324 if (config_file
!= NULL
)
331 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
334 struct mallinfo info
;
338 command_print(cmd_ctx
, "meminfo");
339 return ERROR_INVALID_ARGUMENTS
;
346 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
348 prev
= info
.fordblks
;
350 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
355 static bool savePower
;
357 static void setPower(bool power
)
362 HAL_WRITE_UINT32(ZY1000_JTAG_BASE
+0x14, 0x8);
365 HAL_WRITE_UINT32(ZY1000_JTAG_BASE
+0x10, 0x8);
369 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
373 return ERROR_INVALID_ARGUMENTS
;
378 if (strcmp(args
[0], "on") == 0)
382 else if (strcmp(args
[0], "off") == 0)
387 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
388 return ERROR_INVALID_ARGUMENTS
;
392 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
397 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
398 char **args
, int argc
)
402 command_print(cmd_ctx
,
403 "append <filename> [<string1>, [<string2>, ...]]");
404 return ERROR_INVALID_ARGUMENTS
;
407 FILE *config_file
= NULL
;
408 config_file
= fopen(args
[0], "a");
409 if (config_file
!= NULL
)
412 fseek(config_file
, 0, SEEK_END
);
414 for (i
= 1; i
< argc
; i
++)
416 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
419 fwrite(" ", 1, 1, config_file
);
422 fwrite("\n", 1, 1, config_file
);
429 extern int telnet_socket
;
431 int readMore(int fd
, void *data
, int length
)
433 /* used in select() */
436 /* monitor sockets for acitvity */
439 /* listen for new connections */
440 FD_SET(fd
, &read_fds
);
442 // Maximum 5 seconds.
447 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
450 diag_printf("Timed out waiting for binary payload\n");
456 return read_socket(fd
, data
, length
);
459 int readAll(int fd
, void *data
, int length
)
464 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
465 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
475 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
480 return ERROR_INVALID_ARGUMENTS
;
482 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
483 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
487 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
491 return ERROR_INVALID_ARGUMENTS
;
493 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
497 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
501 return ERROR_INVALID_ARGUMENTS
;
504 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
508 int retval
= loadFile(args
[0], &data
, &len
);
509 if (retval
!= ERROR_OK
)
512 FILE *f
= fopen(args
[1], "wb");
514 retval
= ERROR_INVALID_ARGUMENTS
;
519 int chunk
= len
- pos
;
520 static const int maxChunk
= 512 * 1024; // ~1/sec
521 if (chunk
> maxChunk
)
526 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
527 retval
= ERROR_INVALID_ARGUMENTS
;
529 if (retval
!= ERROR_OK
)
534 command_print(cmd_ctx
, "%d", len
- pos
);
542 if (retval
== ERROR_OK
)
544 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
547 command_print(cmd_ctx
, "Failed: %d", retval
);
555 if (retval
!= ERROR_OK
)
561 #ifdef CYGPKG_PROFILE_GPROF
562 extern void start_profile();
564 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
566 command_print(cmd_ctx
, "Profiling started");
573 externC
void phi_init_all_network_interfaces();
575 command_context_t
*cmd_ctx
;
577 static bool webRunning
= false;
579 void keep_webserver()
581 // Target initialisation is only attempted at startup, so we sleep forever and
582 // let the http server bail us out(i.e. get config files set up).
583 diag_printf("OpenOCD has invoked exit().\n"
584 "Use web server to correct any configuration settings and reboot.\n");
588 // exit() will terminate the current thread and we we'll then sleep eternally or
589 // we'll have a reboot scheduled.
592 extern void printDccChar(char c
);
594 static char logBuffer
[128 * 1024];
595 static const int logSize
= sizeof(logBuffer
);
599 void _zylinjtag_diag_write_char(char c
, void **param
)
603 logBuffer
[writePtr
] = c
;
604 writePtr
= (writePtr
+ 1) % logSize
;
611 HAL_DIAG_WRITE_CHAR('\r');
613 HAL_DIAG_WRITE_CHAR(c
);
616 #ifdef CYGPKG_HAL_ZYLIN_PHI
621 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
624 static void copyfile(char *name2
, char *name1
)
632 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
634 SHOW_RESULT( open
, fd1
);
636 fd2
= open(name2
, O_RDONLY
);
638 SHOW_RESULT( open
, fd2
);
642 done
= read(fd2
, buf
, IOSIZE
);
645 SHOW_RESULT( read
, done
);
649 if( done
== 0 ) break;
651 wrote
= write(fd1
, buf
, done
);
652 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
654 if( wrote
!= done
) break;
658 if( err
< 0 ) SHOW_RESULT( close
, err
);
661 if( err
< 0 ) SHOW_RESULT( close
, err
);
664 static void copydir(char *name
, char *destdir
)
669 dirp
= opendir(destdir
);
672 mkdir(destdir
, 0777);
675 err
= closedir(dirp
);
678 dirp
= opendir(name
);
679 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
683 struct dirent
*entry
= readdir(dirp
);
688 if (strcmp(entry
->d_name
, ".") == 0)
690 if (strcmp(entry
->d_name
, "..") == 0)
695 char fullPath
[PATH_MAX
];
696 strncpy(fullPath
, name
, PATH_MAX
);
697 strcat(fullPath
, "/");
698 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
700 if (stat(fullPath
, &buf
) == -1)
702 diag_printf("unable to read status from %s", fullPath
);
705 isDir
= S_ISDIR(buf
.st_mode
) != 0;
710 // diag_printf("<INFO>: entry %14s",entry->d_name);
711 char fullname
[PATH_MAX
];
712 char fullname2
[PATH_MAX
];
714 strcpy(fullname
, name
);
715 strcat(fullname
, "/");
716 strcat(fullname
, entry
->d_name
);
718 strcpy(fullname2
, destdir
);
719 strcat(fullname2
, "/");
720 strcat(fullname2
, entry
->d_name
);
721 // diag_printf("from %s to %s\n", fullname, fullname2);
722 copyfile(fullname
, fullname2
);
724 // diag_printf("\n");
727 err
= closedir(dirp
);
728 if( err
< 0 ) SHOW_RESULT( stat
, err
);
732 MTAB_ENTRY( romfs_mte1
,
736 (CYG_ADDRWORD
) &filedata
[0] );
739 void openocd_sleep_prelude()
741 cyg_mutex_unlock(&httpstate
.jim_lock
);
744 void openocd_sleep_postlude()
746 cyg_mutex_lock(&httpstate
.jim_lock
);
752 diag_printf("Formatting JFFS2...\n");
754 cyg_io_handle_t handle
;
757 err
= cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1
, &handle
);
760 diag_printf("Flash Error cyg_io_lookup: %d\n", err
);
766 cyg_io_flash_getconfig_devsize_t ds
;
768 err
= cyg_io_get_config(handle
,
769 CYG_IO_GET_CONFIG_FLASH_DEVSIZE
, &ds
, &len
);
772 diag_printf("Flash error cyg_io_get_config %d\n", err
);
776 cyg_io_flash_getconfig_erase_t e
;
782 e
.err_address
= &err_addr
;
784 diag_printf("Formatting 0x%08x bytes\n", ds
.dev_size
);
785 err
= cyg_io_get_config(handle
, CYG_IO_GET_CONFIG_FLASH_ERASE
,
789 diag_printf("Flash erase error %d offset 0x%p\n", err
, err_addr
);
793 diag_printf("Flash formatted successfully\n");
801 zylinjtag_Jim_Command_format_jffs2(Jim_Interp
*interp
,
803 Jim_Obj
* const *argv
)
816 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
818 Jim_Obj
* const *argv
)
823 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
828 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
830 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
833 return del
? JIM_OK
: JIM_ERR
;
836 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
837 Jim_Obj
* const *argv
)
839 cyg_handle_t thread
= 0;
841 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
843 /* Loop over the threads, and generate a table row for
846 while (cyg_thread_get_next(&thread
, &id
))
848 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
850 cyg_thread_info info
;
853 cyg_thread_get_info(thread
, id
, &info
);
855 if (info
.name
== NULL
)
856 info
.name
= "<no name>";
858 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
859 info
.name
, strlen(info
.name
)));
861 /* Translate the state into a string.
864 state_string
= "RUN";
865 else if (info
.state
& 0x04)
866 state_string
= "SUSP";
868 switch (info
.state
& 0x1b)
871 state_string
= "SLEEP";
874 state_string
= "CNTSLEEP";
877 state_string
= "CREATE";
880 state_string
= "EXIT";
883 state_string
= "????";
887 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
888 state_string
, strlen(state_string
)));
890 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
891 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
892 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
894 Jim_ListAppendElement(interp
, threads
, threadObj
);
896 Jim_SetResult( interp
, threads
);
903 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
905 Jim_Obj
* const *argv
)
909 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
913 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
916 dirp
= opendir(name
);
921 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
925 struct dirent
*entry
= NULL
;
926 entry
= readdir(dirp
);
930 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
933 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
937 Jim_SetResult(interp
, objPtr
);
944 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
946 Jim_Obj
* const *argv
)
950 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
956 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
958 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
961 if (length
< 0 && length
> (4096 * 1024))
963 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
967 void *mem
= malloc(length
);
971 target_t
*target
= get_current_target(cmd_ctx
);
976 if ((address
% 4 == 0) && (count
% 4 == 0))
982 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
988 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
989 Jim_SetResult(interp
, objPtr
);
997 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
999 Jim_Obj
* const *argv
)
1003 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1008 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1011 int value
= *((volatile int *) address
);
1013 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1019 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1021 Jim_Obj
* const *argv
)
1025 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1030 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1033 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1036 *((volatile int *) address
) = value
;
1044 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1046 Jim_Obj
* const *argv
)
1050 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1060 if (retval
== JIM_OK
)
1062 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1073 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1075 Jim_Obj
* const *argv
)
1077 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1079 if (logCount
>= logSize
)
1081 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1083 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1085 Jim_SetResult(interp
, tclOutput
);
1090 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1092 Jim_Obj
* const *argv
)
1099 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1101 Jim_Obj
* const *argv
)
1104 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1106 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1108 Jim_SetResult(interp
, tclOutput
);
1114 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1116 Jim_Obj
* const *argv
)
1118 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1120 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1122 if (getifaddrs(&ifp
) < 0)
1127 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1132 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1133 salen
= sizeof(struct sockaddr_in
);
1134 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1135 salen
= sizeof(struct sockaddr_in6
);
1139 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1140 NI_NUMERICHOST
) < 0)
1145 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1152 Jim_SetResult(interp
, tclOutput
);
1157 extern Jim_Interp
*interp
;
1160 static void zylinjtag_startNetwork()
1162 // Bring TCP/IP up immediately before we're ready to accept commands.
1164 // That is as soon as a PING responds, we're accepting telnet sessions.
1165 #if defined(CYGPKG_NET_FREEBSD_STACK)
1166 phi_init_all_network_interfaces();
1172 diag_printf("Network not up and running\n");
1175 #if defined(CYGPKG_NET_FREEBSD_STACK)
1177 tftpd_start(69, &fileops
);
1180 cyg_httpd_init_tcl_interpreter();
1182 interp
= httpstate
.jim_interp
;
1184 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1185 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1186 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1187 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1188 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1189 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1190 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1191 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1192 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1193 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1194 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1195 Jim_CreateCommand(httpstate
.jim_interp
, "format_jffs2", zylinjtag_Jim_Command_format_jffs2
, NULL
, NULL
);
1201 diag_printf("Web server running\n");
1205 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1208 strcpy(ifr
.ifr_name
, "eth0");
1210 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1215 diag_printf("Can't obtain MAC address\n");
1220 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1221 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1222 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1223 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1224 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1225 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1226 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1229 discover_message
=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr
);
1239 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1243 char *infoStr
= "unknown";
1246 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1247 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1248 infoStr
= "undefined instruction";
1250 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1251 infoStr
= "software interrupt";
1253 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1254 infoStr
= "abort prefetch";
1256 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1257 infoStr
= "abort data";
1264 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1266 diag_printf("Dumping log\n---\n");
1267 if (logCount
>= logSize
)
1269 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1271 diag_write(logBuffer
, writePtr
);
1273 diag_printf("---\nLogdump complete.\n");
1274 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1275 diag_printf("\n---\nRebooting\n");
1276 HAL_PLATFORM_RESET();
1280 static void setHandler(cyg_code_t exception
)
1282 cyg_exception_handler_t
*old_handler
;
1283 cyg_addrword_t old_data
;
1285 cyg_exception_set_handler(exception
,
1286 print_exception_handler
,
1292 static cyg_thread zylinjtag_uart_thread_object
;
1293 static cyg_handle_t zylinjtag_uart_thread_handle
;
1294 static char uart_stack
[4096];
1296 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1297 static char backwardBuffer
[1024];
1300 void setNoDelay(int session
, int flag
)
1303 // This decreases latency dramatically for e.g. GDB load which
1304 // does not have a sliding window protocol
1306 // Can cause *lots* of TCP/IP packets to be sent and it would have
1307 // to be enabled/disabled on the fly to avoid the CPU being
1309 setsockopt(session
, /* socket affected */
1310 IPPROTO_TCP
, /* set option at TCP level */
1311 TCP_NODELAY
, /* name of option */
1312 (char *) &flag
, /* the cast is historical
1314 sizeof(int)); /* length of option value */
1324 } tcpipSent
[512 * 1024];
1328 zylinjtag_uart(cyg_addrword_t data
)
1330 int so_reuseaddr_option
= 1;
1333 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1335 LOG_ERROR("error creating socket: %s", strerror(errno
));
1339 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1341 struct sockaddr_in sin
;
1342 unsigned int address_size
;
1343 address_size
= sizeof(sin
);
1344 memset(&sin
, 0, sizeof(sin
));
1345 sin
.sin_family
= AF_INET
;
1346 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1347 sin
.sin_port
= htons(5555);
1349 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1351 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1355 if (listen(fd
, 1) == -1)
1357 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1360 // socket_nonblock(fd);
1365 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1371 setNoDelay(session
, 1);
1372 int oldopts
= fcntl(session
, F_GETFL
, 0);
1373 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1375 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1382 #ifdef CYGPKG_PROFILE_GPROF
1395 FD_ZERO(&write_fds
);
1398 FD_SET(session
, &read_fds
);
1400 FD_SET(serHandle
, &read_fds
);
1401 if (serHandle
> fd_max
)
1407 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1408 if ((actual
== 0) && (actual2
== 0))
1410 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1419 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1420 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1423 if (errno
!= EAGAIN
)
1436 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1444 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1446 // NB! Here it is important that we empty the TCP/IP read buffer
1447 // to make transmission tick right
1448 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1451 // this will block if there is no data at all
1452 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1464 /* Do not put things into the serial buffer if it has something to send
1465 * as that can cause a single byte to be sent at the time.
1469 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1472 if (errno
!= EAGAIN
)
1476 // The serial buffer is full
1487 tcpipSent
[cur
].req
= x
;
1488 tcpipSent
[cur
].actual
= y
;
1489 tcpipSent
[cur
].req2
= x2
;
1490 tcpipSent
[cur
].actual2
= y2
;
1500 for (i
= 0; i
< 1024; i
++)
1502 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1510 void startUart(void)
1512 cyg_thread_create(1,
1518 &zylinjtag_uart_thread_handle
,
1519 &zylinjtag_uart_thread_object
);
1520 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1521 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1526 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1528 static int current_baud
= 38400;
1531 command_print(cmd_ctx
, "%d", current_baud
);
1533 } else if (argc
!= 1)
1535 return ERROR_INVALID_ARGUMENTS
;
1538 current_baud
= atol(args
[0]);
1541 switch (current_baud
)
1544 baud
= CYGNUM_SERIAL_BAUD_9600
;
1547 baud
= CYGNUM_SERIAL_BAUD_19200
;
1550 baud
= CYGNUM_SERIAL_BAUD_38400
;
1553 baud
= CYGNUM_SERIAL_BAUD_57600
;
1556 baud
= CYGNUM_SERIAL_BAUD_115200
;
1559 baud
= CYGNUM_SERIAL_BAUD_230400
;
1562 command_print(cmd_ctx
, "unsupported baudrate");
1563 return ERROR_INVALID_ARGUMENTS
;
1566 cyg_serial_info_t buf
;
1568 //get existing serial configuration
1569 len
= sizeof(cyg_serial_info_t
);
1571 cyg_io_handle_t serial_handle
;
1573 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1576 LOG_ERROR("/dev/ser0 not found\n");
1581 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1582 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1585 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1590 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1593 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1600 bool logAllToSerial
= false;
1602 /* boolean parameter stored on config */
1603 bool boolParam(char *var
)
1605 bool result
= false;
1606 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1612 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1616 result
= strncmp((char *) data
, "1", len
) == 0;
1623 command_context_t
*setup_command_handler();
1625 int add_default_dirs(void)
1627 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1628 add_script_search_dir("/rom/lib/openocd");
1629 add_script_search_dir("/rom");
1633 static cyg_uint8
*ramblockdevice
;
1634 static const int ramblockdevice_size
=4096*1024;
1635 int main(int argc
, char *argv
[])
1637 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1638 * need to allocate towards the end of the heap. */
1640 ramblockdevice
=(cyg_uint8
*)malloc(ramblockdevice_size
);
1641 memset(ramblockdevice
, 0xff, ramblockdevice_size
);
1645 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1646 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1647 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1648 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1653 setPower(true); // on by default
1655 atexit(keep_webserver
);
1657 err
= mount("", "/ram", "ramfs");
1660 diag_printf("unable to mount ramfs\n");
1665 sprintf(address
, "%p", &filedata
[0]);
1666 err
= mount(address
, "/rom", "romfs");
1669 diag_printf("unable to mount /rom\n");
1672 err
= mount("", "/log", "logfs");
1675 diag_printf("unable to mount logfs\n");
1678 err
= mount("", "/tftp", "tftpfs");
1681 diag_printf("unable to mount logfs\n");
1684 log
= fopen("/log/log", "w");
1687 diag_printf("Could not open log file /ram/log\n");
1691 diag_init_putc(_zylinjtag_diag_write_char
);
1693 // We want this in the log.
1694 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1695 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1697 copydir("/rom", "/ram/cgi");
1699 err
= mount("/dev/flash1", "/config", "jffs2");
1702 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1703 err
= mount("", "/config", "ramfs");
1706 diag_printf("unable to mount /config as ramdisk.\n");
1711 /* are we using a ram disk instead of a flash disk? This is used
1712 * for ZY1000 live demo...
1714 * copy over flash disk to ram block device
1716 if (boolParam("ramdisk"))
1718 diag_printf("Unmounting /config from flash and using ram instead\n");
1719 err
=umount("/config");
1722 diag_printf("unable to unmount jffs\n");
1726 err
= mount("/dev/flash1", "/config2", "jffs2");
1729 diag_printf("unable to mount jffs\n");
1733 err
= mount("", "/config", "ramfs");
1736 diag_printf("unable to mount ram block device\n");
1740 // copydir("/config2", "/config");
1741 copyfile("/config2/ip", "/config/ip");
1742 copydir("/config2/settings", "/config/settings");
1747 /* we're not going to use a ram block disk */
1748 free(ramblockdevice
);
1753 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1754 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1755 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1757 logAllToSerial
= boolParam("logserial");
1759 // We need the network & web server in case there is something wrong with
1760 // the config files that invoke exit()
1761 zylinjtag_startNetwork();
1763 /* we're going to access the jim interpreter from here on... */
1764 openocd_sleep_postlude();
1769 /* initialize commandline interface */
1770 command_context_t
*cmd_ctx
;
1771 cmd_ctx
= setup_command_handler();
1772 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1773 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1776 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1777 COMMAND_EXEC
, "show zy1000 version numbers");
1779 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1782 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1783 "display file content");
1785 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1786 "truncate a file to 0 size");
1788 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1789 COMMAND_ANY
, "append a variable number of strings to a file");
1791 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1792 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1794 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1795 COMMAND_ANY
, "display available ram memory");
1797 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1798 COMMAND_ANY
, "copy a file <from> <to>");
1800 #ifdef CYGPKG_PROFILE_GPROF
1801 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1804 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1805 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1809 errVal
= log_init(cmd_ctx
);
1810 if (errVal
!= ERROR_OK
)
1812 diag_printf("log_init() failed %d\n", errVal
);
1816 set_log_output(cmd_ctx
, log
);
1818 LOG_DEBUG("log init complete");
1820 // diag_printf("Executing config files\n");
1824 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1825 command_run_line(cmd_ctx
, "debug_level 3");
1828 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1831 // diag_printf() is really invoked from many more places than we trust it
1832 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1834 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1835 // fingers that it doesn't cause any crashes.
1836 diag_printf("Init complete, GDB & telnet servers launched.\n");
1837 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1838 if (!logAllToSerial
)
1843 /* handle network connections */
1844 server_loop(cmd_ctx
);
1845 openocd_sleep_prelude();
1847 /* shut server down */
1850 /* free commandline interface */
1851 command_done(cmd_ctx
);
1861 cyg_httpd_exec_cgi_tcl(char *file_name
);
1862 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1864 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1868 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1870 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1871 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1873 #include <pkgconf/system.h>
1874 #include <pkgconf/hal.h>
1875 #include <pkgconf/kernel.h>
1876 #include <pkgconf/io_fileio.h>
1877 #include <pkgconf/fs_rom.h>
1879 #include <cyg/kernel/ktypes.h> // base kernel types
1880 #include <cyg/infra/cyg_trac.h> // tracing macros
1881 #include <cyg/infra/cyg_ass.h> // assertion macros
1883 #include <sys/types.h>
1885 #include <sys/stat.h>
1894 #include <cyg/fileio/fileio.h>
1896 #include <cyg/kernel/kapi.h>
1897 #include <cyg/infra/diag.h>
1899 //==========================================================================
1900 // Eventually we want to eXecute In Place from the ROM in a protected
1901 // environment, so we'll need executables to be aligned to a boundary
1902 // suitable for MMU protection. A suitable boundary would be the 4k
1903 // boundary in all the CPU architectures I am currently aware of.
1905 // Forward definitions
1907 // Filesystem operations
1908 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
1909 static int tftpfs_umount(cyg_mtab_entry
*mte
);
1910 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
1911 int mode
, cyg_file
*fte
);
1912 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
1913 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
1916 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
1917 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
1918 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
1920 //==========================================================================
1921 // Filesystem table entries
1923 // -------------------------------------------------------------------------
1925 // This defines the entry in the filesystem table.
1926 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1927 // we should never block in any filesystem operations.
1929 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
1934 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
1935 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
1936 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
1937 (cyg_fsop_rename
*)cyg_fileio_erofs
,
1938 (cyg_fsop_link
*)cyg_fileio_erofs
,
1939 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
1940 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
1941 (cyg_fsop_stat
*)cyg_fileio_erofs
,
1942 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
1943 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
1946 // -------------------------------------------------------------------------
1948 // This defines a single ROMFS loaded into ROM at the configured address
1950 // MTAB_ENTRY( rom_mte, // structure name
1951 // "/rom", // mount point
1952 // "romfs", // FIlesystem type
1953 // "", // hardware device
1954 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
1958 // -------------------------------------------------------------------------
1960 // This set of file operations are used for normal open files.
1962 static cyg_fileops tftpfs_fileops
=
1967 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
1971 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
1972 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
1973 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
1976 // -------------------------------------------------------------------------
1978 // Process a mount request. This mainly finds root for the
1981 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
1986 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2001 static void freeTftp(struct Tftp
*t
)
2014 static const int tftpMaxSize
= 8192 * 1024;
2015 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2016 int mode
, cyg_file
*file
)
2019 tftp
= malloc(sizeof(struct Tftp
));
2022 memset(tftp
, 0, sizeof(struct Tftp
));
2024 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2025 file
->f_type
= CYG_FILE_TYPE_FILE
;
2026 file
->f_ops
= &tftpfs_fileops
;
2031 tftp
->mem
= malloc(tftpMaxSize
);
2032 if (tftp
->mem
== NULL
)
2038 char *server
= strchr(name
, '/');
2045 tftp
->server
= malloc(server
- name
+ 1);
2046 if (tftp
->server
== NULL
)
2051 strncpy(tftp
->server
, name
, server
- name
);
2052 tftp
->server
[server
- name
] = 0;
2054 tftp
->file
= strdup(server
+ 1);
2055 if (tftp
->file
== NULL
)
2061 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2066 static int fetchTftp(struct Tftp
*tftp
)
2068 if (!tftp
->readFile
)
2071 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2073 if (tftp
->actual
< 0)
2082 // -------------------------------------------------------------------------
2083 // tftpfs_fo_write()
2084 // Read data from file.
2087 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2089 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2091 if (fetchTftp(tftp
) != ENOERR
)
2095 off_t pos
= fp
->f_offset
;
2097 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2099 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2100 char *buf
= (char *) iov
->iov_base
;
2101 off_t len
= iov
->iov_len
;
2103 if (len
+ pos
> tftp
->actual
)
2105 len
= tftp
->actual
- pos
;
2107 resid
+= iov
->iov_len
- len
;
2109 memcpy(buf
, tftp
->mem
+ pos
, len
);
2113 uio
->uio_resid
= resid
;
2121 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2123 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2126 off_t pos
= fp
->f_offset
;
2128 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2130 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2131 char *buf
= (char *) iov
->iov_base
;
2132 off_t len
= iov
->iov_len
;
2134 if (len
+ pos
> tftpMaxSize
)
2136 len
= tftpMaxSize
- pos
;
2138 resid
+= iov
->iov_len
- len
;
2140 memcpy(tftp
->mem
+ pos
, buf
, len
);
2144 uio
->uio_resid
= resid
;
2153 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2159 // -------------------------------------------------------------------------
2161 // Close a file. We just clear out the data pointer.
2163 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2165 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2170 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2178 // -------------------------------------------------------------------------
2180 // Seek to a new file position.
2182 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2184 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2187 if (fetchTftp(tftp
) != ENOERR
)
2193 // Pos is already where we want to be.
2197 // Add pos to current offset.
2198 pos
+= fp
->f_offset
;
2202 // Add pos to file size.
2203 pos
+= tftp
->actual
;
2210 // Check that pos is still within current file size, or at the
2212 if (pos
< 0 || pos
> tftp
->actual
)
2215 // All OK, set fp offset and return new position.
2216 *apos
= fp
->f_offset
= pos
;
2224 cyg_thread_delay(us
/ 10000 + 1);
2231 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2233 cyg_httpd_start_chunked("text");
2234 if (logCount
>= logSize
)
2236 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2238 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2239 cyg_httpd_end_chunked();
2243 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2245 // Filesystem operations
2246 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2247 static int logfs_umount(cyg_mtab_entry
*mte
);
2248 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2249 int mode
, cyg_file
*fte
);
2251 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2254 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2255 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2257 #include <cyg/io/devtab.h>
2259 //==========================================================================
2260 // Filesystem table entries
2262 // -------------------------------------------------------------------------
2264 // This defines the entry in the filesystem table.
2265 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2266 // we should never block in any filesystem operations.
2267 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2268 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2272 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2273 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2274 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2275 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2276 (cyg_fsop_link
*)cyg_fileio_erofs
,
2277 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2278 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2279 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2280 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2281 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2283 // -------------------------------------------------------------------------
2285 // This set of file operations are used for normal open files.
2287 static cyg_fileops logfs_fileops
=
2289 (cyg_fileop_read
*)cyg_fileio_erofs
,
2290 (cyg_fileop_write
*)logfs_fo_write
,
2291 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2292 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2296 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2297 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2298 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2301 // -------------------------------------------------------------------------
2303 // Process a mount request. This mainly finds root for the
2306 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2311 static int logfs_umount(cyg_mtab_entry
*mte
)
2316 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2317 int mode
, cyg_file
*file
)
2319 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2320 file
->f_type
= CYG_FILE_TYPE_FILE
;
2321 file
->f_ops
= &logfs_fileops
;
2328 // -------------------------------------------------------------------------
2330 // Write data to file.
2333 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2336 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2338 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2339 char *buf
= (char *) iov
->iov_base
;
2340 off_t len
= iov
->iov_len
;
2342 diag_write(buf
, len
);
2349 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2354 // -------------------------------------------------------------------------
2356 // Close a file. We just clear out the data pointer.
2358 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
)
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)