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/hal/hal_diag.h>
63 #include <cyg/kernel/kapi.h>
64 #include <cyg/io/serialio.h>
65 #include <cyg/io/io.h>
66 #include <netinet/tcp.h>
68 #include <sys/ioctl.h>
69 #include <sys/socket.h>
70 #include <netinet/in.h>
72 #include <arpa/inet.h>
73 #include <sys/types.h>
74 #include <sys/socket.h>
76 #include <netinet/in.h>
78 #include <arpa/inet.h>
86 #if defined(CYGPKG_NET_FREEBSD_STACK)
87 #include <tftp_support.h>
88 /* posix compatibility broken*/
89 struct tftpd_fileops fileops
=
91 (int (*)(const char *, int))open
,
93 (int (*)(int, const void *, int))write
,
94 ( int (*)(int, void *, int))read
99 #define ZYLIN_VERSION "1.45"
100 #define ZYLIN_DATE __DATE__
101 #define ZYLIN_TIME __TIME__
102 /* hmmm.... we can't pick up the right # during build if we've checked this out
103 * in Eclipse... arrggghh...*/
104 #define ZYLIN_OPENOCD "$Revision$"
105 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
106 #define ZYLIN_CONFIG_DIR "/config/settings"
108 void diag_write(char *buf
, int len
)
111 for (j
= 0; j
< len
; j
++)
113 diag_printf("%c", buf
[j
]);
117 static bool serialLog
= true;
118 static bool writeLog
= true;
129 static int fastload_num
;
130 static struct FastLoad
*fastload
;
132 static void free_fastload()
137 for (i
=0; i
<fastload_num
; i
++)
139 if (fastload
[i
].data
)
140 free(fastload
[i
].data
);
148 int handle_fast_load_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
154 u32 max_address
=0xffffffff;
163 if ((argc
< 1)||(argc
> 5))
165 return ERROR_COMMAND_SYNTAX_ERROR
;
168 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
171 image
.base_address_set
= 1;
172 image
.base_address
= strtoul(args
[1], NULL
, 0);
176 image
.base_address_set
= 0;
180 image
.start_address_set
= 0;
184 min_address
=strtoul(args
[3], NULL
, 0);
188 max_address
=strtoul(args
[4], NULL
, 0)+min_address
;
191 if (min_address
>max_address
)
193 return ERROR_COMMAND_SYNTAX_ERROR
;
196 duration_start_measure(&duration
);
198 if (image_open(&image
, args
[0], (argc
>= 3) ? args
[2] : NULL
) != ERROR_OK
)
205 fastload_num
=image
.num_sections
;
206 fastload
=(struct FastLoad
*)malloc(sizeof(struct FastLoad
)*image
.num_sections
);
212 memset(fastload
, 0, sizeof(struct FastLoad
)*image
.num_sections
);
213 for (i
= 0; i
< image
.num_sections
; i
++)
215 buffer
= malloc(image
.sections
[i
].size
);
218 command_print(cmd_ctx
, "error allocating buffer for section (%d bytes)", image
.sections
[i
].size
);
222 if ((retval
= image_read_section(&image
, i
, 0x0, image
.sections
[i
].size
, buffer
, &buf_cnt
)) != ERROR_OK
)
232 /* DANGER!!! beware of unsigned comparision here!!! */
234 if ((image
.sections
[i
].base_address
+buf_cnt
>=min_address
)&&
235 (image
.sections
[i
].base_address
<max_address
))
237 if (image
.sections
[i
].base_address
<min_address
)
239 /* clip addresses below */
240 offset
+=min_address
-image
.sections
[i
].base_address
;
244 if (image
.sections
[i
].base_address
+buf_cnt
>max_address
)
246 length
-=(image
.sections
[i
].base_address
+buf_cnt
)-max_address
;
249 fastload
[i
].address
=image
.sections
[i
].base_address
+offset
;
250 fastload
[i
].data
=malloc(length
);
251 if (fastload
[i
].data
==NULL
)
256 memcpy(fastload
[i
].data
, buffer
+offset
, length
);
257 fastload
[i
].length
=length
;
259 image_size
+= length
;
260 command_print(cmd_ctx
, "%u byte written at address 0x%8.8x", length
, image
.sections
[i
].base_address
+offset
);
266 duration_stop_measure(&duration
, &duration_text
);
267 if (retval
==ERROR_OK
)
269 command_print(cmd_ctx
, "downloaded %u byte in %s", image_size
, duration_text
);
275 if (retval
!=ERROR_OK
)
283 int handle_fast_load_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
286 return ERROR_COMMAND_SYNTAX_ERROR
;
289 LOG_ERROR("No image in memory");
295 for (i
=0; i
<fastload_num
;i
++)
298 target_t
*target
= get_current_target(cmd_ctx
);
299 if ((retval
= target_write_buffer(target
, fastload
[i
].address
, fastload
[i
].length
, fastload
[i
].data
)) != ERROR_OK
)
303 size
+=fastload
[i
].length
;
305 int after
=timeval_ms();
306 command_print(cmd_ctx
, "Loaded image %f kBytes/s", (float)(size
/1024.0)/((float)(after
-ms
)/1000.0));
311 /* Give TELNET a way to find out what version this is */
312 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
313 char **args
, int argc
)
317 return ERROR_COMMAND_SYNTAX_ERROR
;
321 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
322 } else if (strcmp("openocd", args
[0])==0)
325 revision
=atol(ZYLIN_OPENOCD
+strlen("XRevision: "));
326 command_print(cmd_ctx
, "%d", revision
);
327 } else if (strcmp("zy1000", args
[0])==0)
329 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
330 } else if (strcmp("date", args
[0])==0)
332 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
335 return ERROR_COMMAND_SYNTAX_ERROR
;
341 extern flash_driver_t
*flash_drivers
[];
342 extern target_type_t
*target_types
[];
344 #ifdef CYGPKG_PROFILE_GPROF
345 #include <cyg/profile/profile.h>
347 extern char _stext
, _etext
; // Defined by the linker
349 void start_profile(void)
351 // This starts up the system-wide profiling, gathering
352 // profile information on all of the code, with a 16 byte
353 // "bucket" size, at a rate of 100us/profile hit.
354 // Note: a bucket size of 16 will give pretty good function
355 // resolution. Much smaller and the buffer becomes
356 // much too large for very little gain.
357 // Note: a timer period of 100us is also a reasonable
358 // compromise. Any smaller and the overhead of
359 // handling the timter (profile) interrupt could
360 // swamp the system. A fast processor might get
361 // by with a smaller value, but a slow one could
362 // even be swamped by this value. If the value is
363 // too large, the usefulness of the profile is reduced.
365 // no more interrupts than 1/10ms.
366 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
367 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
368 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
372 // launch GDB server if a config file exists
373 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
375 bool foundFile
= false;
376 FILE *config_file
= NULL
;
377 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
378 config_file
= fopen(config_file_name
, "r");
383 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
384 if (retval
== ERROR_OK
)
390 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
395 command_print(cmd_ctx
, "No %s found", config_file_name
);
404 static char reboot_stack
[2048];
408 zylinjtag_reboot(cyg_addrword_t data
)
411 diag_printf("Rebooting in 100 ticks..\n");
412 cyg_thread_delay(100);
413 diag_printf("Unmounting /config..\n");
415 diag_printf("Rebooting..\n");
416 HAL_PLATFORM_RESET();
418 static cyg_thread zylinjtag_thread_object
;
419 static cyg_handle_t zylinjtag_thread_handle
;
427 (void *)reboot_stack
,
428 sizeof(reboot_stack
),
429 &zylinjtag_thread_handle
,
430 &zylinjtag_thread_object
);
431 cyg_thread_resume(zylinjtag_thread_handle
);
434 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
436 diag_printf("%s", line
);
441 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
443 LOG_USER_N("%s", line
);
448 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
449 char **args
, int argc
)
453 command_print(cmd_ctx
, "rm <filename>");
454 return ERROR_INVALID_ARGUMENTS
;
457 if (unlink(args
[0]) != 0)
459 command_print(cmd_ctx
, "failed: %d", errno
);
465 int loadFile(const char *fileName
, void **data
, int *len
);
467 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
468 char **args
, int argc
)
472 command_print(cmd_ctx
, "cat <filename>");
473 return ERROR_INVALID_ARGUMENTS
;
476 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
480 int retval
= loadFile(args
[0], &data
, &len
);
481 if (retval
== ERROR_OK
)
483 command_print(cmd_ctx
, "%s", data
);
488 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
493 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
494 char **args
, int argc
)
498 command_print(cmd_ctx
, "trunc <filename>");
499 return ERROR_INVALID_ARGUMENTS
;
502 FILE *config_file
= NULL
;
503 config_file
= fopen(args
[0], "w");
504 if (config_file
!= NULL
)
511 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
514 struct mallinfo info
;
518 command_print(cmd_ctx
, "meminfo");
519 return ERROR_INVALID_ARGUMENTS
;
526 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
528 prev
= info
.fordblks
;
530 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
535 static bool savePower
;
537 static void setPower(bool power
)
542 HAL_WRITE_UINT32(0x08000014, 0x8);
545 HAL_WRITE_UINT32(0x08000010, 0x8);
549 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
553 return ERROR_INVALID_ARGUMENTS
;
558 if (strcmp(args
[0], "on") == 0)
562 else if (strcmp(args
[0], "off") == 0)
567 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
568 return ERROR_INVALID_ARGUMENTS
;
572 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
577 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
578 char **args
, int argc
)
582 command_print(cmd_ctx
,
583 "append <filename> [<string1>, [<string2>, ...]]");
584 return ERROR_INVALID_ARGUMENTS
;
587 FILE *config_file
= NULL
;
588 config_file
= fopen(args
[0], "a");
589 if (config_file
!= NULL
)
592 fseek(config_file
, 0, SEEK_END
);
594 for (i
= 1; i
< argc
; i
++)
596 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
599 fwrite(" ", 1, 1, config_file
);
602 fwrite("\n", 1, 1, config_file
);
609 extern int telnet_socket
;
611 int readMore(int fd
, void *data
, int length
)
613 /* used in select() */
616 /* monitor sockets for acitvity */
619 /* listen for new connections */
620 FD_SET(fd
, &read_fds
);
622 // Maximum 5 seconds.
627 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
630 diag_printf("Timed out waiting for binary payload\n");
636 return read_socket(fd
, data
, length
);
639 int readAll(int fd
, void *data
, int length
)
644 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
645 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
655 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
660 return ERROR_INVALID_ARGUMENTS
;
662 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
663 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
667 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
671 return ERROR_INVALID_ARGUMENTS
;
673 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
677 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
681 return ERROR_INVALID_ARGUMENTS
;
684 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
688 int retval
= loadFile(args
[0], &data
, &len
);
689 if (retval
!= ERROR_OK
)
692 FILE *f
= fopen(args
[1], "wb");
694 retval
= ERROR_INVALID_ARGUMENTS
;
699 int chunk
= len
- pos
;
700 static const int maxChunk
= 512 * 1024; // ~1/sec
701 if (chunk
> maxChunk
)
706 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
707 retval
= ERROR_INVALID_ARGUMENTS
;
709 if (retval
!= ERROR_OK
)
714 command_print(cmd_ctx
, "%d", len
- pos
);
722 if (retval
== ERROR_OK
)
724 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
727 command_print(cmd_ctx
, "Failed: %d", retval
);
735 if (retval
!= ERROR_OK
)
741 #ifdef CYGPKG_PROFILE_GPROF
742 extern void start_profile();
744 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
746 command_print(cmd_ctx
, "Profiling started");
753 externC
void phi_init_all_network_interfaces();
755 command_context_t
*cmd_ctx
;
757 static bool webRunning
= false;
759 void keep_webserver()
761 // Target initialisation is only attempted at startup, so we sleep forever and
762 // let the http server bail us out(i.e. get config files set up).
763 diag_printf("OpenOCD has invoked exit().\n"
764 "Use web server to correct any configuration settings and reboot.\n");
768 // exit() will terminate the current thread and we we'll then sleep eternally or
769 // we'll have a reboot scheduled.
772 extern void printDccChar(char c
);
774 static char logBuffer
[128 * 1024];
775 static const int logSize
= sizeof(logBuffer
);
779 void _zylinjtag_diag_write_char(char c
, void **param
)
783 logBuffer
[writePtr
] = c
;
784 writePtr
= (writePtr
+ 1) % logSize
;
791 HAL_DIAG_WRITE_CHAR('\r');
793 HAL_DIAG_WRITE_CHAR(c
);
799 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
802 static void copyfile(char *name2
, char *name1
)
810 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
812 SHOW_RESULT( open
, fd1
);
814 fd2
= open(name2
, O_RDONLY
);
816 SHOW_RESULT( open
, fd2
);
820 done
= read(fd2
, buf
, IOSIZE
);
823 SHOW_RESULT( read
, done
);
827 if( done
== 0 ) break;
829 wrote
= write(fd1
, buf
, done
);
830 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
832 if( wrote
!= done
) break;
836 if( err
< 0 ) SHOW_RESULT( close
, err
);
839 if( err
< 0 ) SHOW_RESULT( close
, err
);
842 static void copydir(char *name
)
847 mkdir("/ram/cgi", 0777);
849 dirp
= opendir(name
);
850 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
854 struct dirent
*entry
= readdir(dirp
);
859 if (strcmp(entry
->d_name
, ".") == 0)
861 if (strcmp(entry
->d_name
, "..") == 0)
866 char fullPath
[PATH_MAX
];
867 strncpy(fullPath
, name
, PATH_MAX
);
868 strcat(fullPath
, "/");
869 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
871 if (stat(fullPath
, &buf
) == -1)
873 diag_printf("unable to read status from %s", fullPath
);
876 isDir
= S_ISDIR(buf
.st_mode
) != 0;
881 // diag_printf("<INFO>: entry %14s",entry->d_name);
882 char fullname
[PATH_MAX
];
883 char fullname2
[PATH_MAX
];
885 strcpy(fullname
, name
);
886 strcat(fullname
, entry
->d_name
);
888 strcpy(fullname2
, "/ram/cgi/");
889 strcat(fullname2
, entry
->d_name
);
890 // diag_printf("from %s to %s\n", fullname, fullname2);
891 copyfile(fullname
, fullname2
);
893 // diag_printf("\n");
896 err
= closedir(dirp
);
897 if( err
< 0 ) SHOW_RESULT( stat
, err
);
901 MTAB_ENTRY( romfs_mte1
,
905 (CYG_ADDRWORD
) &filedata
[0] );
908 void openocd_sleep_prelude()
910 cyg_mutex_unlock(&httpstate
.jim_lock
);
913 void openocd_sleep_postlude()
915 cyg_mutex_lock(&httpstate
.jim_lock
);
919 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
921 Jim_Obj
* const *argv
)
926 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
931 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
933 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
936 return del
? JIM_OK
: JIM_ERR
;
939 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
940 Jim_Obj
* const *argv
)
942 cyg_handle_t thread
= 0;
944 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
946 /* Loop over the threads, and generate a table row for
949 while (cyg_thread_get_next(&thread
, &id
))
951 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
953 cyg_thread_info info
;
956 cyg_thread_get_info(thread
, id
, &info
);
958 if (info
.name
== NULL
)
959 info
.name
= "<no name>";
961 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
962 info
.name
, strlen(info
.name
)));
964 /* Translate the state into a string.
967 state_string
= "RUN";
968 else if (info
.state
& 0x04)
969 state_string
= "SUSP";
971 switch (info
.state
& 0x1b)
974 state_string
= "SLEEP";
977 state_string
= "CNTSLEEP";
980 state_string
= "CREATE";
983 state_string
= "EXIT";
986 state_string
= "????";
990 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
991 state_string
, strlen(state_string
)));
993 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
994 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
995 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
997 Jim_ListAppendElement(interp
, threads
, threadObj
);
999 Jim_SetResult( interp
, threads
);
1006 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
1008 Jim_Obj
* const *argv
)
1012 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1016 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
1019 dirp
= opendir(name
);
1024 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
1028 struct dirent
*entry
= NULL
;
1029 entry
= readdir(dirp
);
1033 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
1036 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
1040 Jim_SetResult(interp
, objPtr
);
1047 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
1049 Jim_Obj
* const *argv
)
1053 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1059 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1061 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
1064 if (length
< 0 && length
> (4096 * 1024))
1066 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1070 void *mem
= malloc(length
);
1074 target_t
*target
= get_current_target(cmd_ctx
);
1079 if ((address
% 4 == 0) && (count
% 4 == 0))
1085 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1091 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1092 Jim_SetResult(interp
, objPtr
);
1100 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1102 Jim_Obj
* const *argv
)
1106 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1111 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1114 int value
= *((volatile int *) address
);
1116 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1122 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1124 Jim_Obj
* const *argv
)
1128 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1133 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1136 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1139 *((volatile int *) address
) = value
;
1147 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1149 Jim_Obj
* const *argv
)
1153 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1163 if (retval
== JIM_OK
)
1165 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1176 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1178 Jim_Obj
* const *argv
)
1180 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1182 if (logCount
>= logSize
)
1184 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1186 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1188 Jim_SetResult(interp
, tclOutput
);
1193 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1195 Jim_Obj
* const *argv
)
1202 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1204 Jim_Obj
* const *argv
)
1208 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1211 strcpy(ifr
.ifr_name
, "eth0");
1213 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1222 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1225 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1226 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1227 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1228 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1229 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1230 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1231 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1233 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1235 Jim_SetResult(interp
, tclOutput
);
1241 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1243 Jim_Obj
* const *argv
)
1245 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1247 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1249 if (getifaddrs(&ifp
) < 0)
1254 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1259 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1260 salen
= sizeof(struct sockaddr_in
);
1261 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1262 salen
= sizeof(struct sockaddr_in6
);
1266 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1267 NI_NUMERICHOST
) < 0)
1272 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1279 Jim_SetResult(interp
, tclOutput
);
1284 extern Jim_Interp
*interp
;
1286 static void zylinjtag_startNetwork()
1288 // Bring TCP/IP up immediately before we're ready to accept commands.
1290 // That is as soon as a PING responds, we're accepting telnet sessions.
1291 #if defined(CYGPKG_NET_FREEBSD_STACK)
1292 phi_init_all_network_interfaces();
1298 diag_printf("Network not up and running\n");
1301 #if defined(CYGPKG_NET_FREEBSD_STACK)
1303 tftpd_start(69, &fileops
);
1306 cyg_httpd_init_tcl_interpreter();
1308 interp
= httpstate
.jim_interp
;
1310 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1311 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1312 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1313 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1314 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1315 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1316 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1317 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1318 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1319 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1320 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1326 diag_printf("Web server running\n");
1329 static bool readPowerDropout()
1332 // sample and clear power dropout
1333 HAL_WRITE_UINT32(0x08000010, 0x80);
1334 HAL_READ_UINT32(0x08000010, state
);
1336 powerDropout
= (state
& 0x80) != 0;
1337 return powerDropout
;
1343 // sample and clear SRST sensing
1344 HAL_WRITE_UINT32(0x08000010, 0x00000040);
1345 HAL_READ_UINT32(0x08000010, state
);
1347 srstAsserted
= (state
& 0x40) != 0;
1348 return srstAsserted
;
1351 // every 300ms we check for reset & powerdropout and issue a "reset halt" if
1355 static int sense_handler(void *priv
)
1357 struct command_context_s
*cmd_ctx
;
1358 cmd_ctx
= (struct command_context_s
*) priv
;
1360 static bool prevSrstAsserted
= false;
1361 static bool prevPowerdropout
= false;
1364 powerDropout
= readPowerDropout();
1367 powerRestored
= prevPowerdropout
&& !powerDropout
;
1370 LOG_USER("Sensed power restore.");
1373 cyg_tick_count_t current
= cyg_current_time();
1374 static cyg_tick_count_t lastPower
= 0;
1375 bool waitMore
= lastPower
+ 200 > current
;
1376 if (powerDropout
&& !waitMore
)
1378 LOG_USER("Sensed power dropout.");
1379 lastPower
= current
;
1382 bool srstAsserted
= readSRST();
1384 bool srstDeasserted
;
1385 srstDeasserted
= prevSrstAsserted
&& !srstAsserted
;
1387 static cyg_tick_count_t lastSrst
= 0;
1388 waitMore
= lastSrst
+ 200 > current
;
1389 if (srstDeasserted
&& !waitMore
)
1391 LOG_USER("Sensed nSRST deasserted");
1395 if (!prevSrstAsserted
&& srstAsserted
)
1397 LOG_USER("Sensed nSRST asserted");
1400 prevSrstAsserted
= srstAsserted
;
1401 prevPowerdropout
= powerDropout
;
1403 if (srstDeasserted
|| powerRestored
)
1405 /* Other than logging the event we can't do anything here.
1406 * Issuing a reset is a particularly bad idea as we might
1407 * be inside a reset already.
1417 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1421 char *infoStr
= "unknown";
1424 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1425 infoStr
= "undefined instruction";
1427 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1428 infoStr
= "software interrupt";
1430 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1431 infoStr
= "abort prefetch";
1433 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1434 infoStr
= "abort data";
1440 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1442 diag_printf("Dumping log\n---\n");
1443 if (logCount
>= logSize
)
1445 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1447 diag_write(logBuffer
, writePtr
);
1449 diag_printf("---\nLogdump complete.\n");
1450 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1451 diag_printf("\n---\nRebooting\n");
1452 HAL_PLATFORM_RESET();
1456 static void setHandler(cyg_code_t exception
)
1458 cyg_exception_handler_t
*old_handler
;
1459 cyg_addrword_t old_data
;
1461 cyg_exception_set_handler(exception
,
1462 print_exception_handler
,
1468 static cyg_thread zylinjtag_uart_thread_object
;
1469 static cyg_handle_t zylinjtag_uart_thread_handle
;
1470 static char uart_stack
[4096];
1472 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1473 static char backwardBuffer
[1024];
1475 static cyg_io_handle_t serial_handle
;
1477 void setNoDelay(int session
, int flag
)
1480 // This decreases latency dramatically for e.g. GDB load which
1481 // does not have a sliding window protocol
1483 // Can cause *lots* of TCP/IP packets to be sent and it would have
1484 // to be enabled/disabled on the fly to avoid the CPU being
1486 setsockopt(session
, /* socket affected */
1487 IPPROTO_TCP
, /* set option at TCP level */
1488 TCP_NODELAY
, /* name of option */
1489 (char *) &flag
, /* the cast is historical
1491 sizeof(int)); /* length of option value */
1501 } tcpipSent
[512 * 1024];
1505 zylinjtag_uart(cyg_addrword_t data
)
1507 int so_reuseaddr_option
= 1;
1510 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1512 LOG_ERROR("error creating socket: %s", strerror(errno
));
1516 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1518 struct sockaddr_in sin
;
1519 unsigned int address_size
;
1520 address_size
= sizeof(sin
);
1521 memset(&sin
, 0, sizeof(sin
));
1522 sin
.sin_family
= AF_INET
;
1523 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1524 sin
.sin_port
= htons(5555);
1526 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1528 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1532 if (listen(fd
, 1) == -1)
1534 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1537 // socket_nonblock(fd);
1542 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1548 setNoDelay(session
, 1);
1549 int oldopts
= fcntl(session
, F_GETFL
, 0);
1550 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1552 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1570 FD_ZERO(&write_fds
);
1573 FD_SET(session
, &read_fds
);
1575 FD_SET(serHandle
, &read_fds
);
1576 if (serHandle
> fd_max
)
1582 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1583 if ((actual
== 0) && (actual2
== 0))
1585 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1594 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1595 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1598 if (errno
!= EAGAIN
)
1611 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1619 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1621 // NB! Here it is important that we empty the TCP/IP read buffer
1622 // to make transmission tick right
1623 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1626 // this will block if there is no data at all
1627 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1639 /* Do not put things into the serial buffer if it has something to send
1640 * as that can cause a single byte to be sent at the time.
1644 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1647 if (errno
!= EAGAIN
)
1651 // The serial buffer is full
1662 tcpipSent
[cur
].req
= x
;
1663 tcpipSent
[cur
].actual
= y
;
1664 tcpipSent
[cur
].req2
= x2
;
1665 tcpipSent
[cur
].actual2
= y2
;
1675 for (i
= 0; i
< 1024; i
++)
1677 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1685 void startUart(void)
1687 cyg_thread_create(1,
1693 &zylinjtag_uart_thread_handle
,
1694 &zylinjtag_uart_thread_object
);
1695 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1696 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1701 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1705 command_print(cmd_ctx
, "usage: uart <baudrate>");
1706 return ERROR_INVALID_ARGUMENTS
;
1709 int baud
= atol(args
[0]);
1714 baud
= CYGNUM_SERIAL_BAUD_9600
;
1717 baud
= CYGNUM_SERIAL_BAUD_19200
;
1720 baud
= CYGNUM_SERIAL_BAUD_38400
;
1723 baud
= CYGNUM_SERIAL_BAUD_57600
;
1726 baud
= CYGNUM_SERIAL_BAUD_115200
;
1729 baud
= CYGNUM_SERIAL_BAUD_230400
;
1732 command_print(cmd_ctx
, "unsupported baudrate");
1733 return ERROR_INVALID_ARGUMENTS
;
1736 cyg_serial_info_t buf
;
1738 //get existing serial configuration
1739 len
= sizeof(cyg_serial_info_t
);
1741 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1742 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1745 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1750 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1753 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1760 bool logAllToSerial
= false;
1762 /* boolean parameter stored on config */
1763 bool boolParam(char *var
)
1765 bool result
= false;
1766 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1772 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1776 result
= strncmp((char *) data
, "1", len
) == 0;
1783 command_context_t
*setup_command_handler();
1785 int add_default_dirs(void)
1787 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1788 add_script_search_dir("/rom/lib/openocd");
1789 add_script_search_dir("/rom");
1793 int main(int argc
, char *argv
[])
1795 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1796 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1797 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1800 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1803 diag_printf("/dev/ser0 not found\n");
1807 setPower(true); // on by default
1809 atexit(keep_webserver
);
1811 err
= mount("", "/ram", "ramfs");
1814 diag_printf("unable to mount ramfs\n");
1819 sprintf(address
, "%p", &filedata
[0]);
1820 err
= mount(address
, "/rom", "romfs");
1823 diag_printf("unable to mount /rom\n");
1826 err
= mount("", "/log", "logfs");
1829 diag_printf("unable to mount logfs\n");
1832 err
= mount("", "/tftp", "tftpfs");
1835 diag_printf("unable to mount logfs\n");
1838 log
= fopen("/log/log", "w");
1841 diag_printf("Could not open log file /ram/log\n");
1845 diag_init_putc(_zylinjtag_diag_write_char
);
1847 // We want this in the log.
1848 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1849 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1853 err
= mount("/dev/flash1", "/config", "jffs2");
1856 diag_printf("unable to mount jffs\n");
1860 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1861 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1862 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1864 logAllToSerial
= boolParam("logserial");
1866 // We need the network & web server in case there is something wrong with
1867 // the config files that invoke exit()
1868 zylinjtag_startNetwork();
1870 /* we're going to access the jim interpreter from here on... */
1871 openocd_sleep_postlude();
1876 /* initialize commandline interface */
1877 command_context_t
*cmd_ctx
;
1878 cmd_ctx
= setup_command_handler();
1879 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1880 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1883 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1884 COMMAND_EXEC
, "show zy1000 version numbers");
1886 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1889 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1890 "same args as load_image, image stored in memory");
1892 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1893 "loads active fast load image to current target");
1895 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1896 "display file content");
1898 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1899 "truncate a file to 0 size");
1901 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1902 COMMAND_ANY
, "append a variable number of strings to a file");
1904 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1905 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1907 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1908 COMMAND_ANY
, "display available ram memory");
1910 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1911 COMMAND_ANY
, "copy a file <from> <to>");
1913 #ifdef CYGPKG_PROFILE_GPROF
1914 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1917 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1918 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1922 errVal
= log_init(cmd_ctx
);
1923 if (errVal
!= ERROR_OK
)
1925 diag_printf("log_init() failed %d\n", errVal
);
1929 set_log_output(cmd_ctx
, log
);
1931 LOG_DEBUG("log init complete");
1933 // diag_printf("Executing config files\n");
1937 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1938 command_run_line(cmd_ctx
, "debug_level 3");
1941 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1943 target_register_timer_callback(sense_handler
, 200, 1, cmd_ctx
);
1946 // diag_printf() is really invoked from many more places than we trust it
1947 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1949 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1950 // fingers that it doesn't cause any crashes.
1951 diag_printf("Init complete, GDB & telnet servers launched.\n");
1952 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1953 if (!logAllToSerial
)
1958 /* handle network connections */
1959 server_loop(cmd_ctx
);
1960 openocd_sleep_prelude();
1962 /* shut server down */
1965 /* free commandline interface */
1966 command_done(cmd_ctx
);
1976 cyg_httpd_exec_cgi_tcl(char *file_name
);
1977 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1979 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1983 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1985 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1986 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1988 #include <pkgconf/system.h>
1989 #include <pkgconf/hal.h>
1990 #include <pkgconf/kernel.h>
1991 #include <pkgconf/io_fileio.h>
1992 #include <pkgconf/fs_rom.h>
1994 #include <cyg/kernel/ktypes.h> // base kernel types
1995 #include <cyg/infra/cyg_trac.h> // tracing macros
1996 #include <cyg/infra/cyg_ass.h> // assertion macros
1998 #include <sys/types.h>
2000 #include <sys/stat.h>
2009 #include <cyg/fileio/fileio.h>
2011 #include <cyg/kernel/kapi.h>
2012 #include <cyg/infra/diag.h>
2014 //==========================================================================
2015 // Eventually we want to eXecute In Place from the ROM in a protected
2016 // environment, so we'll need executables to be aligned to a boundary
2017 // suitable for MMU protection. A suitable boundary would be the 4k
2018 // boundary in all the CPU architectures I am currently aware of.
2020 // Forward definitions
2022 // Filesystem operations
2023 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2024 static int tftpfs_umount(cyg_mtab_entry
*mte
);
2025 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2026 int mode
, cyg_file
*fte
);
2027 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2028 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2031 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2032 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
2033 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
2035 //==========================================================================
2036 // Filesystem table entries
2038 // -------------------------------------------------------------------------
2040 // This defines the entry in the filesystem table.
2041 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2042 // we should never block in any filesystem operations.
2044 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
2049 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2050 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2051 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2052 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2053 (cyg_fsop_link
*)cyg_fileio_erofs
,
2054 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2055 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2056 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2057 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2058 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2061 // -------------------------------------------------------------------------
2063 // This defines a single ROMFS loaded into ROM at the configured address
2065 // MTAB_ENTRY( rom_mte, // structure name
2066 // "/rom", // mount point
2067 // "romfs", // FIlesystem type
2068 // "", // hardware device
2069 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2073 // -------------------------------------------------------------------------
2075 // This set of file operations are used for normal open files.
2077 static cyg_fileops tftpfs_fileops
=
2082 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2086 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2087 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2088 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2091 // -------------------------------------------------------------------------
2093 // Process a mount request. This mainly finds root for the
2096 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2101 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2116 static void freeTftp(struct Tftp
*t
)
2129 static const int tftpMaxSize
= 8192 * 1024;
2130 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2131 int mode
, cyg_file
*file
)
2134 tftp
= malloc(sizeof(struct Tftp
));
2137 memset(tftp
, 0, sizeof(struct Tftp
));
2139 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2140 file
->f_type
= CYG_FILE_TYPE_FILE
;
2141 file
->f_ops
= &tftpfs_fileops
;
2146 tftp
->mem
= malloc(tftpMaxSize
);
2147 if (tftp
->mem
== NULL
)
2153 char *server
= strchr(name
, '/');
2160 tftp
->server
= malloc(server
- name
+ 1);
2161 if (tftp
->server
== NULL
)
2166 strncpy(tftp
->server
, name
, server
- name
);
2167 tftp
->server
[server
- name
] = 0;
2169 tftp
->file
= strdup(server
+ 1);
2170 if (tftp
->file
== NULL
)
2176 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2181 static int fetchTftp(struct Tftp
*tftp
)
2183 if (!tftp
->readFile
)
2186 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2188 if (tftp
->actual
< 0)
2197 // -------------------------------------------------------------------------
2198 // tftpfs_fo_write()
2199 // Read data from file.
2202 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2204 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2206 if (fetchTftp(tftp
) != ENOERR
)
2210 off_t pos
= fp
->f_offset
;
2212 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2214 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2215 char *buf
= (char *) iov
->iov_base
;
2216 off_t len
= iov
->iov_len
;
2218 if (len
+ pos
> tftp
->actual
)
2220 len
= tftp
->actual
- pos
;
2222 resid
+= iov
->iov_len
- len
;
2224 memcpy(buf
, tftp
->mem
+ pos
, len
);
2228 uio
->uio_resid
= resid
;
2236 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2238 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2241 off_t pos
= fp
->f_offset
;
2243 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2245 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2246 char *buf
= (char *) iov
->iov_base
;
2247 off_t len
= iov
->iov_len
;
2249 if (len
+ pos
> tftpMaxSize
)
2251 len
= tftpMaxSize
- pos
;
2253 resid
+= iov
->iov_len
- len
;
2255 memcpy(tftp
->mem
+ pos
, buf
, len
);
2259 uio
->uio_resid
= resid
;
2268 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2274 // -------------------------------------------------------------------------
2276 // Close a file. We just clear out the data pointer.
2278 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2280 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2285 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2293 // -------------------------------------------------------------------------
2295 // Seek to a new file position.
2297 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2299 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2302 if (fetchTftp(tftp
) != ENOERR
)
2308 // Pos is already where we want to be.
2312 // Add pos to current offset.
2313 pos
+= fp
->f_offset
;
2317 // Add pos to file size.
2318 pos
+= tftp
->actual
;
2325 // Check that pos is still within current file size, or at the
2327 if (pos
< 0 || pos
> tftp
->actual
)
2330 // All OK, set fp offset and return new position.
2331 *apos
= fp
->f_offset
= pos
;
2339 cyg_thread_delay(us
/ 10000 + 1);
2346 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2348 cyg_httpd_start_chunked("text");
2349 if (logCount
>= logSize
)
2351 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2353 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2354 cyg_httpd_end_chunked();
2358 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2360 // Filesystem operations
2361 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2362 static int logfs_umount(cyg_mtab_entry
*mte
);
2363 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2364 int mode
, cyg_file
*fte
);
2366 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2369 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2370 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2372 //==========================================================================
2373 // Filesystem table entries
2375 // -------------------------------------------------------------------------
2377 // This defines the entry in the filesystem table.
2378 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2379 // we should never block in any filesystem operations.
2380 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2381 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2385 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2386 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2387 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2388 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2389 (cyg_fsop_link
*)cyg_fileio_erofs
,
2390 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2391 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2392 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2393 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2394 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2396 // -------------------------------------------------------------------------
2398 // This set of file operations are used for normal open files.
2400 static cyg_fileops logfs_fileops
=
2402 (cyg_fileop_read
*)cyg_fileio_erofs
,
2403 (cyg_fileop_write
*)logfs_fo_write
,
2404 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2405 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2409 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2410 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2411 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2414 // -------------------------------------------------------------------------
2416 // Process a mount request. This mainly finds root for the
2419 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2424 static int logfs_umount(cyg_mtab_entry
*mte
)
2429 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2430 int mode
, cyg_file
*file
)
2432 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2433 file
->f_type
= CYG_FILE_TYPE_FILE
;
2434 file
->f_ops
= &logfs_fileops
;
2441 // -------------------------------------------------------------------------
2443 // Write data to file.
2446 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2449 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2451 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2452 char *buf
= (char *) iov
->iov_base
;
2453 off_t len
= iov
->iov_len
;
2455 diag_write(buf
, len
);
2462 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2467 // -------------------------------------------------------------------------
2469 // Close a file. We just clear out the data pointer.
2471 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)