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.46"
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;
131 static int fastload_num
;
132 static struct FastLoad
*fastload
;
134 static void free_fastload()
139 for (i
=0; i
<fastload_num
; i
++)
141 if (fastload
[i
].data
)
142 free(fastload
[i
].data
);
150 int handle_fast_load_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
156 u32 max_address
=0xffffffff;
165 if ((argc
< 1)||(argc
> 5))
167 return ERROR_COMMAND_SYNTAX_ERROR
;
170 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
173 image
.base_address_set
= 1;
174 image
.base_address
= strtoul(args
[1], NULL
, 0);
178 image
.base_address_set
= 0;
182 image
.start_address_set
= 0;
186 min_address
=strtoul(args
[3], NULL
, 0);
190 max_address
=strtoul(args
[4], NULL
, 0)+min_address
;
193 if (min_address
>max_address
)
195 return ERROR_COMMAND_SYNTAX_ERROR
;
198 duration_start_measure(&duration
);
200 if (image_open(&image
, args
[0], (argc
>= 3) ? args
[2] : NULL
) != ERROR_OK
)
207 fastload_num
=image
.num_sections
;
208 fastload
=(struct FastLoad
*)malloc(sizeof(struct FastLoad
)*image
.num_sections
);
214 memset(fastload
, 0, sizeof(struct FastLoad
)*image
.num_sections
);
215 for (i
= 0; i
< image
.num_sections
; i
++)
217 buffer
= malloc(image
.sections
[i
].size
);
220 command_print(cmd_ctx
, "error allocating buffer for section (%d bytes)", image
.sections
[i
].size
);
224 if ((retval
= image_read_section(&image
, i
, 0x0, image
.sections
[i
].size
, buffer
, &buf_cnt
)) != ERROR_OK
)
234 /* DANGER!!! beware of unsigned comparision here!!! */
236 if ((image
.sections
[i
].base_address
+buf_cnt
>=min_address
)&&
237 (image
.sections
[i
].base_address
<max_address
))
239 if (image
.sections
[i
].base_address
<min_address
)
241 /* clip addresses below */
242 offset
+=min_address
-image
.sections
[i
].base_address
;
246 if (image
.sections
[i
].base_address
+buf_cnt
>max_address
)
248 length
-=(image
.sections
[i
].base_address
+buf_cnt
)-max_address
;
251 fastload
[i
].address
=image
.sections
[i
].base_address
+offset
;
252 fastload
[i
].data
=malloc(length
);
253 if (fastload
[i
].data
==NULL
)
258 memcpy(fastload
[i
].data
, buffer
+offset
, length
);
259 fastload
[i
].length
=length
;
261 image_size
+= length
;
262 command_print(cmd_ctx
, "%u byte written at address 0x%8.8x", length
, image
.sections
[i
].base_address
+offset
);
268 duration_stop_measure(&duration
, &duration_text
);
269 if (retval
==ERROR_OK
)
271 command_print(cmd_ctx
, "Loaded %u bytes in %s", image_size
, duration_text
);
272 command_print(cmd_ctx
, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
278 if (retval
!=ERROR_OK
)
286 int handle_fast_load_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
289 return ERROR_COMMAND_SYNTAX_ERROR
;
292 LOG_ERROR("No image in memory");
298 for (i
=0; i
<fastload_num
;i
++)
301 target_t
*target
= get_current_target(cmd_ctx
);
302 if ((retval
= target_write_buffer(target
, fastload
[i
].address
, fastload
[i
].length
, fastload
[i
].data
)) != ERROR_OK
)
306 size
+=fastload
[i
].length
;
308 int after
=timeval_ms();
309 command_print(cmd_ctx
, "Loaded image %f kBytes/s", (float)(size
/1024.0)/((float)(after
-ms
)/1000.0));
314 /* Give TELNET a way to find out what version this is */
315 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
316 char **args
, int argc
)
320 return ERROR_COMMAND_SYNTAX_ERROR
;
324 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
325 } else if (strcmp("openocd", args
[0])==0)
328 revision
=atol(ZYLIN_OPENOCD
+strlen("XRevision: "));
329 command_print(cmd_ctx
, "%d", revision
);
330 } else if (strcmp("zy1000", args
[0])==0)
332 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
333 } else if (strcmp("date", args
[0])==0)
335 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
338 return ERROR_COMMAND_SYNTAX_ERROR
;
344 extern flash_driver_t
*flash_drivers
[];
345 extern target_type_t
*target_types
[];
347 #ifdef CYGPKG_PROFILE_GPROF
348 #include <cyg/profile/profile.h>
350 extern char _stext
, _etext
; // Defined by the linker
352 void start_profile(void)
354 // This starts up the system-wide profiling, gathering
355 // profile information on all of the code, with a 16 byte
356 // "bucket" size, at a rate of 100us/profile hit.
357 // Note: a bucket size of 16 will give pretty good function
358 // resolution. Much smaller and the buffer becomes
359 // much too large for very little gain.
360 // Note: a timer period of 100us is also a reasonable
361 // compromise. Any smaller and the overhead of
362 // handling the timter (profile) interrupt could
363 // swamp the system. A fast processor might get
364 // by with a smaller value, but a slow one could
365 // even be swamped by this value. If the value is
366 // too large, the usefulness of the profile is reduced.
368 // no more interrupts than 1/10ms.
369 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
370 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
371 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
375 // launch GDB server if a config file exists
376 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
378 bool foundFile
= false;
379 FILE *config_file
= NULL
;
380 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
381 config_file
= fopen(config_file_name
, "r");
386 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
387 if (retval
== ERROR_OK
)
393 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
398 command_print(cmd_ctx
, "No %s found", config_file_name
);
407 static char reboot_stack
[2048];
411 zylinjtag_reboot(cyg_addrword_t data
)
414 diag_printf("Rebooting in 100 ticks..\n");
415 cyg_thread_delay(100);
416 diag_printf("Unmounting /config..\n");
418 diag_printf("Rebooting..\n");
419 HAL_PLATFORM_RESET();
421 static cyg_thread zylinjtag_thread_object
;
422 static cyg_handle_t zylinjtag_thread_handle
;
430 (void *)reboot_stack
,
431 sizeof(reboot_stack
),
432 &zylinjtag_thread_handle
,
433 &zylinjtag_thread_object
);
434 cyg_thread_resume(zylinjtag_thread_handle
);
437 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
439 diag_printf("%s", line
);
444 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
446 LOG_USER_N("%s", line
);
451 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
452 char **args
, int argc
)
456 command_print(cmd_ctx
, "rm <filename>");
457 return ERROR_INVALID_ARGUMENTS
;
460 if (unlink(args
[0]) != 0)
462 command_print(cmd_ctx
, "failed: %d", errno
);
468 int loadFile(const char *fileName
, void **data
, int *len
);
470 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
471 char **args
, int argc
)
475 command_print(cmd_ctx
, "cat <filename>");
476 return ERROR_INVALID_ARGUMENTS
;
479 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
483 int retval
= loadFile(args
[0], &data
, &len
);
484 if (retval
== ERROR_OK
)
486 command_print(cmd_ctx
, "%s", data
);
491 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
496 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
497 char **args
, int argc
)
501 command_print(cmd_ctx
, "trunc <filename>");
502 return ERROR_INVALID_ARGUMENTS
;
505 FILE *config_file
= NULL
;
506 config_file
= fopen(args
[0], "w");
507 if (config_file
!= NULL
)
514 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
517 struct mallinfo info
;
521 command_print(cmd_ctx
, "meminfo");
522 return ERROR_INVALID_ARGUMENTS
;
529 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
531 prev
= info
.fordblks
;
533 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
538 static bool savePower
;
540 static void setPower(bool power
)
545 HAL_WRITE_UINT32(0x08000014, 0x8);
548 HAL_WRITE_UINT32(0x08000010, 0x8);
552 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
556 return ERROR_INVALID_ARGUMENTS
;
561 if (strcmp(args
[0], "on") == 0)
565 else if (strcmp(args
[0], "off") == 0)
570 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
571 return ERROR_INVALID_ARGUMENTS
;
575 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
580 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
581 char **args
, int argc
)
585 command_print(cmd_ctx
,
586 "append <filename> [<string1>, [<string2>, ...]]");
587 return ERROR_INVALID_ARGUMENTS
;
590 FILE *config_file
= NULL
;
591 config_file
= fopen(args
[0], "a");
592 if (config_file
!= NULL
)
595 fseek(config_file
, 0, SEEK_END
);
597 for (i
= 1; i
< argc
; i
++)
599 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
602 fwrite(" ", 1, 1, config_file
);
605 fwrite("\n", 1, 1, config_file
);
612 extern int telnet_socket
;
614 int readMore(int fd
, void *data
, int length
)
616 /* used in select() */
619 /* monitor sockets for acitvity */
622 /* listen for new connections */
623 FD_SET(fd
, &read_fds
);
625 // Maximum 5 seconds.
630 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
633 diag_printf("Timed out waiting for binary payload\n");
639 return read_socket(fd
, data
, length
);
642 int readAll(int fd
, void *data
, int length
)
647 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
648 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
658 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
663 return ERROR_INVALID_ARGUMENTS
;
665 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
666 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
670 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
674 return ERROR_INVALID_ARGUMENTS
;
676 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
680 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
684 return ERROR_INVALID_ARGUMENTS
;
687 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
691 int retval
= loadFile(args
[0], &data
, &len
);
692 if (retval
!= ERROR_OK
)
695 FILE *f
= fopen(args
[1], "wb");
697 retval
= ERROR_INVALID_ARGUMENTS
;
702 int chunk
= len
- pos
;
703 static const int maxChunk
= 512 * 1024; // ~1/sec
704 if (chunk
> maxChunk
)
709 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
710 retval
= ERROR_INVALID_ARGUMENTS
;
712 if (retval
!= ERROR_OK
)
717 command_print(cmd_ctx
, "%d", len
- pos
);
725 if (retval
== ERROR_OK
)
727 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
730 command_print(cmd_ctx
, "Failed: %d", retval
);
738 if (retval
!= ERROR_OK
)
744 #ifdef CYGPKG_PROFILE_GPROF
745 extern void start_profile();
747 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
749 command_print(cmd_ctx
, "Profiling started");
756 externC
void phi_init_all_network_interfaces();
758 command_context_t
*cmd_ctx
;
760 static bool webRunning
= false;
762 void keep_webserver()
764 // Target initialisation is only attempted at startup, so we sleep forever and
765 // let the http server bail us out(i.e. get config files set up).
766 diag_printf("OpenOCD has invoked exit().\n"
767 "Use web server to correct any configuration settings and reboot.\n");
771 // exit() will terminate the current thread and we we'll then sleep eternally or
772 // we'll have a reboot scheduled.
775 extern void printDccChar(char c
);
777 static char logBuffer
[128 * 1024];
778 static const int logSize
= sizeof(logBuffer
);
782 void _zylinjtag_diag_write_char(char c
, void **param
)
786 logBuffer
[writePtr
] = c
;
787 writePtr
= (writePtr
+ 1) % logSize
;
794 HAL_DIAG_WRITE_CHAR('\r');
796 HAL_DIAG_WRITE_CHAR(c
);
802 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
805 static void copyfile(char *name2
, char *name1
)
813 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
815 SHOW_RESULT( open
, fd1
);
817 fd2
= open(name2
, O_RDONLY
);
819 SHOW_RESULT( open
, fd2
);
823 done
= read(fd2
, buf
, IOSIZE
);
826 SHOW_RESULT( read
, done
);
830 if( done
== 0 ) break;
832 wrote
= write(fd1
, buf
, done
);
833 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
835 if( wrote
!= done
) break;
839 if( err
< 0 ) SHOW_RESULT( close
, err
);
842 if( err
< 0 ) SHOW_RESULT( close
, err
);
845 static void copydir(char *name
, char *destdir
)
850 dirp
= opendir(destdir
);
853 mkdir(destdir
, 0777);
856 err
= closedir(dirp
);
859 dirp
= opendir(name
);
860 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
864 struct dirent
*entry
= readdir(dirp
);
869 if (strcmp(entry
->d_name
, ".") == 0)
871 if (strcmp(entry
->d_name
, "..") == 0)
876 char fullPath
[PATH_MAX
];
877 strncpy(fullPath
, name
, PATH_MAX
);
878 strcat(fullPath
, "/");
879 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
881 if (stat(fullPath
, &buf
) == -1)
883 diag_printf("unable to read status from %s", fullPath
);
886 isDir
= S_ISDIR(buf
.st_mode
) != 0;
891 // diag_printf("<INFO>: entry %14s",entry->d_name);
892 char fullname
[PATH_MAX
];
893 char fullname2
[PATH_MAX
];
895 strcpy(fullname
, name
);
896 strcat(fullname
, "/");
897 strcat(fullname
, entry
->d_name
);
899 strcpy(fullname2
, destdir
);
900 strcat(fullname2
, "/");
901 strcat(fullname2
, entry
->d_name
);
902 // diag_printf("from %s to %s\n", fullname, fullname2);
903 copyfile(fullname
, fullname2
);
905 // diag_printf("\n");
908 err
= closedir(dirp
);
909 if( err
< 0 ) SHOW_RESULT( stat
, err
);
913 MTAB_ENTRY( romfs_mte1
,
917 (CYG_ADDRWORD
) &filedata
[0] );
920 void openocd_sleep_prelude()
922 cyg_mutex_unlock(&httpstate
.jim_lock
);
925 void openocd_sleep_postlude()
927 cyg_mutex_lock(&httpstate
.jim_lock
);
931 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
933 Jim_Obj
* const *argv
)
938 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
943 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
945 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
948 return del
? JIM_OK
: JIM_ERR
;
951 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
952 Jim_Obj
* const *argv
)
954 cyg_handle_t thread
= 0;
956 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
958 /* Loop over the threads, and generate a table row for
961 while (cyg_thread_get_next(&thread
, &id
))
963 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
965 cyg_thread_info info
;
968 cyg_thread_get_info(thread
, id
, &info
);
970 if (info
.name
== NULL
)
971 info
.name
= "<no name>";
973 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
974 info
.name
, strlen(info
.name
)));
976 /* Translate the state into a string.
979 state_string
= "RUN";
980 else if (info
.state
& 0x04)
981 state_string
= "SUSP";
983 switch (info
.state
& 0x1b)
986 state_string
= "SLEEP";
989 state_string
= "CNTSLEEP";
992 state_string
= "CREATE";
995 state_string
= "EXIT";
998 state_string
= "????";
1002 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
1003 state_string
, strlen(state_string
)));
1005 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
1006 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
1007 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
1009 Jim_ListAppendElement(interp
, threads
, threadObj
);
1011 Jim_SetResult( interp
, threads
);
1018 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
1020 Jim_Obj
* const *argv
)
1024 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1028 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
1031 dirp
= opendir(name
);
1036 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
1040 struct dirent
*entry
= NULL
;
1041 entry
= readdir(dirp
);
1045 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
1048 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
1052 Jim_SetResult(interp
, objPtr
);
1059 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
1061 Jim_Obj
* const *argv
)
1065 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1071 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1073 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
1076 if (length
< 0 && length
> (4096 * 1024))
1078 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1082 void *mem
= malloc(length
);
1086 target_t
*target
= get_current_target(cmd_ctx
);
1091 if ((address
% 4 == 0) && (count
% 4 == 0))
1097 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1103 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1104 Jim_SetResult(interp
, objPtr
);
1112 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1114 Jim_Obj
* const *argv
)
1118 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1123 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1126 int value
= *((volatile int *) address
);
1128 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1134 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1136 Jim_Obj
* const *argv
)
1140 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1145 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1148 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1151 *((volatile int *) address
) = value
;
1159 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1161 Jim_Obj
* const *argv
)
1165 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1175 if (retval
== JIM_OK
)
1177 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1188 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1190 Jim_Obj
* const *argv
)
1192 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1194 if (logCount
>= logSize
)
1196 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1198 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1200 Jim_SetResult(interp
, tclOutput
);
1205 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1207 Jim_Obj
* const *argv
)
1214 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1216 Jim_Obj
* const *argv
)
1220 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1223 strcpy(ifr
.ifr_name
, "eth0");
1225 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1234 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1237 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1238 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1239 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1240 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1241 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1242 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1243 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1245 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1247 Jim_SetResult(interp
, tclOutput
);
1253 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1255 Jim_Obj
* const *argv
)
1257 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1259 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1261 if (getifaddrs(&ifp
) < 0)
1266 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1271 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1272 salen
= sizeof(struct sockaddr_in
);
1273 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1274 salen
= sizeof(struct sockaddr_in6
);
1278 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1279 NI_NUMERICHOST
) < 0)
1284 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1291 Jim_SetResult(interp
, tclOutput
);
1296 extern Jim_Interp
*interp
;
1298 static void zylinjtag_startNetwork()
1300 // Bring TCP/IP up immediately before we're ready to accept commands.
1302 // That is as soon as a PING responds, we're accepting telnet sessions.
1303 #if defined(CYGPKG_NET_FREEBSD_STACK)
1304 phi_init_all_network_interfaces();
1310 diag_printf("Network not up and running\n");
1313 #if defined(CYGPKG_NET_FREEBSD_STACK)
1315 tftpd_start(69, &fileops
);
1318 cyg_httpd_init_tcl_interpreter();
1320 interp
= httpstate
.jim_interp
;
1322 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1323 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1324 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1325 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1326 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1327 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1328 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1329 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1330 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1331 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1332 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1338 diag_printf("Web server running\n");
1348 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1352 char *infoStr
= "unknown";
1355 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1356 infoStr
= "undefined instruction";
1358 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1359 infoStr
= "software interrupt";
1361 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1362 infoStr
= "abort prefetch";
1364 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1365 infoStr
= "abort data";
1371 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1373 diag_printf("Dumping log\n---\n");
1374 if (logCount
>= logSize
)
1376 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1378 diag_write(logBuffer
, writePtr
);
1380 diag_printf("---\nLogdump complete.\n");
1381 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1382 diag_printf("\n---\nRebooting\n");
1383 HAL_PLATFORM_RESET();
1387 static void setHandler(cyg_code_t exception
)
1389 cyg_exception_handler_t
*old_handler
;
1390 cyg_addrword_t old_data
;
1392 cyg_exception_set_handler(exception
,
1393 print_exception_handler
,
1399 static cyg_thread zylinjtag_uart_thread_object
;
1400 static cyg_handle_t zylinjtag_uart_thread_handle
;
1401 static char uart_stack
[4096];
1403 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1404 static char backwardBuffer
[1024];
1406 static cyg_io_handle_t serial_handle
;
1408 void setNoDelay(int session
, int flag
)
1411 // This decreases latency dramatically for e.g. GDB load which
1412 // does not have a sliding window protocol
1414 // Can cause *lots* of TCP/IP packets to be sent and it would have
1415 // to be enabled/disabled on the fly to avoid the CPU being
1417 setsockopt(session
, /* socket affected */
1418 IPPROTO_TCP
, /* set option at TCP level */
1419 TCP_NODELAY
, /* name of option */
1420 (char *) &flag
, /* the cast is historical
1422 sizeof(int)); /* length of option value */
1432 } tcpipSent
[512 * 1024];
1436 zylinjtag_uart(cyg_addrword_t data
)
1438 int so_reuseaddr_option
= 1;
1441 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1443 LOG_ERROR("error creating socket: %s", strerror(errno
));
1447 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1449 struct sockaddr_in sin
;
1450 unsigned int address_size
;
1451 address_size
= sizeof(sin
);
1452 memset(&sin
, 0, sizeof(sin
));
1453 sin
.sin_family
= AF_INET
;
1454 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1455 sin
.sin_port
= htons(5555);
1457 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1459 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1463 if (listen(fd
, 1) == -1)
1465 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1468 // socket_nonblock(fd);
1473 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1479 setNoDelay(session
, 1);
1480 int oldopts
= fcntl(session
, F_GETFL
, 0);
1481 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1483 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1501 FD_ZERO(&write_fds
);
1504 FD_SET(session
, &read_fds
);
1506 FD_SET(serHandle
, &read_fds
);
1507 if (serHandle
> fd_max
)
1513 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1514 if ((actual
== 0) && (actual2
== 0))
1516 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1525 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1526 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1529 if (errno
!= EAGAIN
)
1542 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1550 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1552 // NB! Here it is important that we empty the TCP/IP read buffer
1553 // to make transmission tick right
1554 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1557 // this will block if there is no data at all
1558 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1570 /* Do not put things into the serial buffer if it has something to send
1571 * as that can cause a single byte to be sent at the time.
1575 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1578 if (errno
!= EAGAIN
)
1582 // The serial buffer is full
1593 tcpipSent
[cur
].req
= x
;
1594 tcpipSent
[cur
].actual
= y
;
1595 tcpipSent
[cur
].req2
= x2
;
1596 tcpipSent
[cur
].actual2
= y2
;
1606 for (i
= 0; i
< 1024; i
++)
1608 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1616 void startUart(void)
1618 cyg_thread_create(1,
1624 &zylinjtag_uart_thread_handle
,
1625 &zylinjtag_uart_thread_object
);
1626 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1627 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1632 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1636 command_print(cmd_ctx
, "usage: uart <baudrate>");
1637 return ERROR_INVALID_ARGUMENTS
;
1640 int baud
= atol(args
[0]);
1645 baud
= CYGNUM_SERIAL_BAUD_9600
;
1648 baud
= CYGNUM_SERIAL_BAUD_19200
;
1651 baud
= CYGNUM_SERIAL_BAUD_38400
;
1654 baud
= CYGNUM_SERIAL_BAUD_57600
;
1657 baud
= CYGNUM_SERIAL_BAUD_115200
;
1660 baud
= CYGNUM_SERIAL_BAUD_230400
;
1663 command_print(cmd_ctx
, "unsupported baudrate");
1664 return ERROR_INVALID_ARGUMENTS
;
1667 cyg_serial_info_t buf
;
1669 //get existing serial configuration
1670 len
= sizeof(cyg_serial_info_t
);
1672 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1673 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1676 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1681 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1684 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1691 bool logAllToSerial
= false;
1693 /* boolean parameter stored on config */
1694 bool boolParam(char *var
)
1696 bool result
= false;
1697 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1703 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1707 result
= strncmp((char *) data
, "1", len
) == 0;
1714 command_context_t
*setup_command_handler();
1716 int add_default_dirs(void)
1718 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1719 add_script_search_dir("/rom/lib/openocd");
1720 add_script_search_dir("/rom");
1724 static cyg_uint8
*ramblockdevice
;
1725 static const int ramblockdevice_size
=4096*1024;
1726 int main(int argc
, char *argv
[])
1728 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1729 * need to allocate towards the end of the heap. */
1731 ramblockdevice
=(cyg_uint8
*)malloc(ramblockdevice_size
);
1732 memset(ramblockdevice
, 0xff, ramblockdevice_size
);
1734 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1735 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1736 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1739 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1742 diag_printf("/dev/ser0 not found\n");
1746 setPower(true); // on by default
1748 atexit(keep_webserver
);
1750 err
= mount("", "/ram", "ramfs");
1753 diag_printf("unable to mount ramfs\n");
1758 sprintf(address
, "%p", &filedata
[0]);
1759 err
= mount(address
, "/rom", "romfs");
1762 diag_printf("unable to mount /rom\n");
1765 err
= mount("", "/log", "logfs");
1768 diag_printf("unable to mount logfs\n");
1771 err
= mount("", "/tftp", "tftpfs");
1774 diag_printf("unable to mount logfs\n");
1777 log
= fopen("/log/log", "w");
1780 diag_printf("Could not open log file /ram/log\n");
1784 diag_init_putc(_zylinjtag_diag_write_char
);
1786 // We want this in the log.
1787 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1788 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1790 copydir("/rom", "/ram/cgi");
1792 err
= mount("/dev/flash1", "/config", "jffs2");
1795 diag_printf("unable to mount jffs\n");
1799 /* are we using a ram disk instead of a flash disk? This is used
1800 * for ZY1000 live demo...
1802 * copy over flash disk to ram block device
1804 if (boolParam("ramdisk"))
1806 diag_printf("Unmounting /config from flash and using ram instead\n");
1807 err
=umount("/config");
1810 diag_printf("unable to unmount jffs\n");
1814 err
= mount("/dev/flash1", "/config2", "jffs2");
1817 diag_printf("unable to mount jffs\n");
1821 err
= mount("/dev/ram", "/config", "jffs2");
1824 diag_printf("unable to mount ram block device\n");
1828 // copydir("/config2", "/config");
1829 copyfile("/config2/ip", "/config/ip");
1830 copydir("/config2/settings", "/config/settings");
1835 /* we're not going to use a ram block disk */
1836 free(ramblockdevice
);
1840 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1841 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1842 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1844 logAllToSerial
= boolParam("logserial");
1846 // We need the network & web server in case there is something wrong with
1847 // the config files that invoke exit()
1848 zylinjtag_startNetwork();
1850 /* we're going to access the jim interpreter from here on... */
1851 openocd_sleep_postlude();
1856 /* initialize commandline interface */
1857 command_context_t
*cmd_ctx
;
1858 cmd_ctx
= setup_command_handler();
1859 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1860 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1863 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1864 COMMAND_EXEC
, "show zy1000 version numbers");
1866 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1869 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1870 "same args as load_image, image stored in memory");
1872 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1873 "loads active fast load image to current target");
1875 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1876 "display file content");
1878 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1879 "truncate a file to 0 size");
1881 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1882 COMMAND_ANY
, "append a variable number of strings to a file");
1884 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1885 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1887 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1888 COMMAND_ANY
, "display available ram memory");
1890 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1891 COMMAND_ANY
, "copy a file <from> <to>");
1893 #ifdef CYGPKG_PROFILE_GPROF
1894 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1897 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1898 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1902 errVal
= log_init(cmd_ctx
);
1903 if (errVal
!= ERROR_OK
)
1905 diag_printf("log_init() failed %d\n", errVal
);
1909 set_log_output(cmd_ctx
, log
);
1911 LOG_DEBUG("log init complete");
1913 // diag_printf("Executing config files\n");
1917 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1918 command_run_line(cmd_ctx
, "debug_level 3");
1921 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1924 // diag_printf() is really invoked from many more places than we trust it
1925 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1927 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1928 // fingers that it doesn't cause any crashes.
1929 diag_printf("Init complete, GDB & telnet servers launched.\n");
1930 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1931 if (!logAllToSerial
)
1936 /* handle network connections */
1937 server_loop(cmd_ctx
);
1938 openocd_sleep_prelude();
1940 /* shut server down */
1943 /* free commandline interface */
1944 command_done(cmd_ctx
);
1954 cyg_httpd_exec_cgi_tcl(char *file_name
);
1955 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1957 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1961 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1963 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1964 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1966 #include <pkgconf/system.h>
1967 #include <pkgconf/hal.h>
1968 #include <pkgconf/kernel.h>
1969 #include <pkgconf/io_fileio.h>
1970 #include <pkgconf/fs_rom.h>
1972 #include <cyg/kernel/ktypes.h> // base kernel types
1973 #include <cyg/infra/cyg_trac.h> // tracing macros
1974 #include <cyg/infra/cyg_ass.h> // assertion macros
1976 #include <sys/types.h>
1978 #include <sys/stat.h>
1987 #include <cyg/fileio/fileio.h>
1989 #include <cyg/kernel/kapi.h>
1990 #include <cyg/infra/diag.h>
1992 //==========================================================================
1993 // Eventually we want to eXecute In Place from the ROM in a protected
1994 // environment, so we'll need executables to be aligned to a boundary
1995 // suitable for MMU protection. A suitable boundary would be the 4k
1996 // boundary in all the CPU architectures I am currently aware of.
1998 // Forward definitions
2000 // Filesystem operations
2001 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2002 static int tftpfs_umount(cyg_mtab_entry
*mte
);
2003 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2004 int mode
, cyg_file
*fte
);
2005 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2006 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2009 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2010 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
2011 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
2013 //==========================================================================
2014 // Filesystem table entries
2016 // -------------------------------------------------------------------------
2018 // This defines the entry in the filesystem table.
2019 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2020 // we should never block in any filesystem operations.
2022 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
2027 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2028 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2029 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2030 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2031 (cyg_fsop_link
*)cyg_fileio_erofs
,
2032 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2033 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2034 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2035 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2036 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2039 // -------------------------------------------------------------------------
2041 // This defines a single ROMFS loaded into ROM at the configured address
2043 // MTAB_ENTRY( rom_mte, // structure name
2044 // "/rom", // mount point
2045 // "romfs", // FIlesystem type
2046 // "", // hardware device
2047 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2051 // -------------------------------------------------------------------------
2053 // This set of file operations are used for normal open files.
2055 static cyg_fileops tftpfs_fileops
=
2060 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2064 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2065 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2066 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2069 // -------------------------------------------------------------------------
2071 // Process a mount request. This mainly finds root for the
2074 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2079 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2094 static void freeTftp(struct Tftp
*t
)
2107 static const int tftpMaxSize
= 8192 * 1024;
2108 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2109 int mode
, cyg_file
*file
)
2112 tftp
= malloc(sizeof(struct Tftp
));
2115 memset(tftp
, 0, sizeof(struct Tftp
));
2117 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2118 file
->f_type
= CYG_FILE_TYPE_FILE
;
2119 file
->f_ops
= &tftpfs_fileops
;
2124 tftp
->mem
= malloc(tftpMaxSize
);
2125 if (tftp
->mem
== NULL
)
2131 char *server
= strchr(name
, '/');
2138 tftp
->server
= malloc(server
- name
+ 1);
2139 if (tftp
->server
== NULL
)
2144 strncpy(tftp
->server
, name
, server
- name
);
2145 tftp
->server
[server
- name
] = 0;
2147 tftp
->file
= strdup(server
+ 1);
2148 if (tftp
->file
== NULL
)
2154 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2159 static int fetchTftp(struct Tftp
*tftp
)
2161 if (!tftp
->readFile
)
2164 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2166 if (tftp
->actual
< 0)
2175 // -------------------------------------------------------------------------
2176 // tftpfs_fo_write()
2177 // Read data from file.
2180 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2182 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2184 if (fetchTftp(tftp
) != ENOERR
)
2188 off_t pos
= fp
->f_offset
;
2190 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2192 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2193 char *buf
= (char *) iov
->iov_base
;
2194 off_t len
= iov
->iov_len
;
2196 if (len
+ pos
> tftp
->actual
)
2198 len
= tftp
->actual
- pos
;
2200 resid
+= iov
->iov_len
- len
;
2202 memcpy(buf
, tftp
->mem
+ pos
, len
);
2206 uio
->uio_resid
= resid
;
2214 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2216 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2219 off_t pos
= fp
->f_offset
;
2221 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2223 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2224 char *buf
= (char *) iov
->iov_base
;
2225 off_t len
= iov
->iov_len
;
2227 if (len
+ pos
> tftpMaxSize
)
2229 len
= tftpMaxSize
- pos
;
2231 resid
+= iov
->iov_len
- len
;
2233 memcpy(tftp
->mem
+ pos
, buf
, len
);
2237 uio
->uio_resid
= resid
;
2246 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2252 // -------------------------------------------------------------------------
2254 // Close a file. We just clear out the data pointer.
2256 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2258 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2263 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2271 // -------------------------------------------------------------------------
2273 // Seek to a new file position.
2275 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2277 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2280 if (fetchTftp(tftp
) != ENOERR
)
2286 // Pos is already where we want to be.
2290 // Add pos to current offset.
2291 pos
+= fp
->f_offset
;
2295 // Add pos to file size.
2296 pos
+= tftp
->actual
;
2303 // Check that pos is still within current file size, or at the
2305 if (pos
< 0 || pos
> tftp
->actual
)
2308 // All OK, set fp offset and return new position.
2309 *apos
= fp
->f_offset
= pos
;
2317 cyg_thread_delay(us
/ 10000 + 1);
2324 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2326 cyg_httpd_start_chunked("text");
2327 if (logCount
>= logSize
)
2329 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2331 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2332 cyg_httpd_end_chunked();
2336 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2338 // Filesystem operations
2339 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2340 static int logfs_umount(cyg_mtab_entry
*mte
);
2341 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2342 int mode
, cyg_file
*fte
);
2344 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2347 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2348 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2350 #include <cyg/io/devtab.h>
2352 //==========================================================================
2353 // Filesystem table entries
2355 // -------------------------------------------------------------------------
2357 // This defines the entry in the filesystem table.
2358 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2359 // we should never block in any filesystem operations.
2360 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2361 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2365 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2366 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2367 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2368 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2369 (cyg_fsop_link
*)cyg_fileio_erofs
,
2370 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2371 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2372 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2373 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2374 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2376 // -------------------------------------------------------------------------
2378 // This set of file operations are used for normal open files.
2380 static cyg_fileops logfs_fileops
=
2382 (cyg_fileop_read
*)cyg_fileio_erofs
,
2383 (cyg_fileop_write
*)logfs_fo_write
,
2384 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2385 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2389 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2390 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2391 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2394 // -------------------------------------------------------------------------
2396 // Process a mount request. This mainly finds root for the
2399 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2404 static int logfs_umount(cyg_mtab_entry
*mte
)
2409 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2410 int mode
, cyg_file
*file
)
2412 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2413 file
->f_type
= CYG_FILE_TYPE_FILE
;
2414 file
->f_ops
= &logfs_fileops
;
2421 // -------------------------------------------------------------------------
2423 // Write data to file.
2426 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2429 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2431 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2432 char *buf
= (char *) iov
->iov_base
;
2433 off_t len
= iov
->iov_len
;
2435 diag_write(buf
, len
);
2442 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2447 // -------------------------------------------------------------------------
2449 // Close a file. We just clear out the data pointer.
2451 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
)
2457 ramiodev_init( struct cyg_devtab_entry
*tab
)
2463 ramiodev_bread( cyg_io_handle_t handle
, void *buf
, cyg_uint32
*len
,
2466 if (*len
+pos
>ramblockdevice_size
)
2468 *len
=ramblockdevice_size
-pos
;
2470 memcpy(buf
, ramblockdevice
+pos
, *len
);
2475 ramiodev_bwrite( cyg_io_handle_t handle
, const void *buf
, cyg_uint32
*len
,
2478 if (((pos
%4)!=0)||(((*len
)%4)!=0))
2480 diag_printf("Unaligned write %d %d!", pos
, *len
);
2483 memcpy(ramblockdevice
+pos
, buf
, *len
);
2488 ramiodev_get_config( cyg_io_handle_t handle
,
2494 case CYG_IO_GET_CONFIG_FLASH_ERASE
:
2496 if ( *len
!= sizeof( cyg_io_flash_getconfig_erase_t
) )
2499 cyg_io_flash_getconfig_erase_t
*e
= (cyg_io_flash_getconfig_erase_t
*)buf
;
2500 char *startpos
= ramblockdevice
+ e
->offset
;
2502 if (((e
->offset
%(64*1024))!=0)||((e
->len
%(64*1024))!=0))
2504 diag_printf("Erease is not aligned %d %d\n", e
->offset
, e
->len
);
2507 memset(startpos
, 0xff, e
->len
);
2513 case CYG_IO_GET_CONFIG_FLASH_DEVSIZE
:
2515 if ( *len
!= sizeof( cyg_io_flash_getconfig_devsize_t
) )
2518 cyg_io_flash_getconfig_devsize_t
*d
=
2519 (cyg_io_flash_getconfig_devsize_t
*)buf
;
2521 d
->dev_size
= ramblockdevice_size
;
2526 case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE
:
2528 cyg_io_flash_getconfig_blocksize_t
*b
=
2529 (cyg_io_flash_getconfig_blocksize_t
*)buf
;
2530 if ( *len
!= sizeof( cyg_io_flash_getconfig_blocksize_t
) )
2533 // offset unused for now
2534 b
->block_size
= 64*1024;
2544 ramiodev_set_config( cyg_io_handle_t handle
,
2554 } // ramiodev_set_config()
2556 // get_config/set_config should be added later to provide the other flash
2557 // operations possible, like erase etc.
2559 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops
,
2563 &ramiodev_get_config
,
2564 &ramiodev_set_config
2568 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1
,
2571 &cyg_io_ramdev1_ops
,
2573 0, // No lookup required
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)