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
, "Loaded %u bytes in %s", image_size
, duration_text
);
270 command_print(cmd_ctx
, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
276 if (retval
!=ERROR_OK
)
284 int handle_fast_load_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
287 return ERROR_COMMAND_SYNTAX_ERROR
;
290 LOG_ERROR("No image in memory");
296 for (i
=0; i
<fastload_num
;i
++)
299 target_t
*target
= get_current_target(cmd_ctx
);
300 if ((retval
= target_write_buffer(target
, fastload
[i
].address
, fastload
[i
].length
, fastload
[i
].data
)) != ERROR_OK
)
304 size
+=fastload
[i
].length
;
306 int after
=timeval_ms();
307 command_print(cmd_ctx
, "Loaded image %f kBytes/s", (float)(size
/1024.0)/((float)(after
-ms
)/1000.0));
312 /* Give TELNET a way to find out what version this is */
313 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
314 char **args
, int argc
)
318 return ERROR_COMMAND_SYNTAX_ERROR
;
322 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
323 } else if (strcmp("openocd", args
[0])==0)
326 revision
=atol(ZYLIN_OPENOCD
+strlen("XRevision: "));
327 command_print(cmd_ctx
, "%d", revision
);
328 } else if (strcmp("zy1000", args
[0])==0)
330 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
331 } else if (strcmp("date", args
[0])==0)
333 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
336 return ERROR_COMMAND_SYNTAX_ERROR
;
342 extern flash_driver_t
*flash_drivers
[];
343 extern target_type_t
*target_types
[];
345 #ifdef CYGPKG_PROFILE_GPROF
346 #include <cyg/profile/profile.h>
348 extern char _stext
, _etext
; // Defined by the linker
350 void start_profile(void)
352 // This starts up the system-wide profiling, gathering
353 // profile information on all of the code, with a 16 byte
354 // "bucket" size, at a rate of 100us/profile hit.
355 // Note: a bucket size of 16 will give pretty good function
356 // resolution. Much smaller and the buffer becomes
357 // much too large for very little gain.
358 // Note: a timer period of 100us is also a reasonable
359 // compromise. Any smaller and the overhead of
360 // handling the timter (profile) interrupt could
361 // swamp the system. A fast processor might get
362 // by with a smaller value, but a slow one could
363 // even be swamped by this value. If the value is
364 // too large, the usefulness of the profile is reduced.
366 // no more interrupts than 1/10ms.
367 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
368 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
369 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
373 // launch GDB server if a config file exists
374 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
376 bool foundFile
= false;
377 FILE *config_file
= NULL
;
378 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
379 config_file
= fopen(config_file_name
, "r");
384 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
385 if (retval
== ERROR_OK
)
391 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
396 command_print(cmd_ctx
, "No %s found", config_file_name
);
405 static char reboot_stack
[2048];
409 zylinjtag_reboot(cyg_addrword_t data
)
412 diag_printf("Rebooting in 100 ticks..\n");
413 cyg_thread_delay(100);
414 diag_printf("Unmounting /config..\n");
416 diag_printf("Rebooting..\n");
417 HAL_PLATFORM_RESET();
419 static cyg_thread zylinjtag_thread_object
;
420 static cyg_handle_t zylinjtag_thread_handle
;
428 (void *)reboot_stack
,
429 sizeof(reboot_stack
),
430 &zylinjtag_thread_handle
,
431 &zylinjtag_thread_object
);
432 cyg_thread_resume(zylinjtag_thread_handle
);
435 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
437 diag_printf("%s", line
);
442 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
444 LOG_USER_N("%s", line
);
449 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
450 char **args
, int argc
)
454 command_print(cmd_ctx
, "rm <filename>");
455 return ERROR_INVALID_ARGUMENTS
;
458 if (unlink(args
[0]) != 0)
460 command_print(cmd_ctx
, "failed: %d", errno
);
466 int loadFile(const char *fileName
, void **data
, int *len
);
468 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
469 char **args
, int argc
)
473 command_print(cmd_ctx
, "cat <filename>");
474 return ERROR_INVALID_ARGUMENTS
;
477 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
481 int retval
= loadFile(args
[0], &data
, &len
);
482 if (retval
== ERROR_OK
)
484 command_print(cmd_ctx
, "%s", data
);
489 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
494 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
495 char **args
, int argc
)
499 command_print(cmd_ctx
, "trunc <filename>");
500 return ERROR_INVALID_ARGUMENTS
;
503 FILE *config_file
= NULL
;
504 config_file
= fopen(args
[0], "w");
505 if (config_file
!= NULL
)
512 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
515 struct mallinfo info
;
519 command_print(cmd_ctx
, "meminfo");
520 return ERROR_INVALID_ARGUMENTS
;
527 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
529 prev
= info
.fordblks
;
531 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
536 static bool savePower
;
538 static void setPower(bool power
)
543 HAL_WRITE_UINT32(0x08000014, 0x8);
546 HAL_WRITE_UINT32(0x08000010, 0x8);
550 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
554 return ERROR_INVALID_ARGUMENTS
;
559 if (strcmp(args
[0], "on") == 0)
563 else if (strcmp(args
[0], "off") == 0)
568 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
569 return ERROR_INVALID_ARGUMENTS
;
573 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
578 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
579 char **args
, int argc
)
583 command_print(cmd_ctx
,
584 "append <filename> [<string1>, [<string2>, ...]]");
585 return ERROR_INVALID_ARGUMENTS
;
588 FILE *config_file
= NULL
;
589 config_file
= fopen(args
[0], "a");
590 if (config_file
!= NULL
)
593 fseek(config_file
, 0, SEEK_END
);
595 for (i
= 1; i
< argc
; i
++)
597 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
600 fwrite(" ", 1, 1, config_file
);
603 fwrite("\n", 1, 1, config_file
);
610 extern int telnet_socket
;
612 int readMore(int fd
, void *data
, int length
)
614 /* used in select() */
617 /* monitor sockets for acitvity */
620 /* listen for new connections */
621 FD_SET(fd
, &read_fds
);
623 // Maximum 5 seconds.
628 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
631 diag_printf("Timed out waiting for binary payload\n");
637 return read_socket(fd
, data
, length
);
640 int readAll(int fd
, void *data
, int length
)
645 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
646 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
656 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
661 return ERROR_INVALID_ARGUMENTS
;
663 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
664 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
668 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
672 return ERROR_INVALID_ARGUMENTS
;
674 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
678 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
682 return ERROR_INVALID_ARGUMENTS
;
685 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
689 int retval
= loadFile(args
[0], &data
, &len
);
690 if (retval
!= ERROR_OK
)
693 FILE *f
= fopen(args
[1], "wb");
695 retval
= ERROR_INVALID_ARGUMENTS
;
700 int chunk
= len
- pos
;
701 static const int maxChunk
= 512 * 1024; // ~1/sec
702 if (chunk
> maxChunk
)
707 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
708 retval
= ERROR_INVALID_ARGUMENTS
;
710 if (retval
!= ERROR_OK
)
715 command_print(cmd_ctx
, "%d", len
- pos
);
723 if (retval
== ERROR_OK
)
725 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
728 command_print(cmd_ctx
, "Failed: %d", retval
);
736 if (retval
!= ERROR_OK
)
742 #ifdef CYGPKG_PROFILE_GPROF
743 extern void start_profile();
745 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
747 command_print(cmd_ctx
, "Profiling started");
754 externC
void phi_init_all_network_interfaces();
756 command_context_t
*cmd_ctx
;
758 static bool webRunning
= false;
760 void keep_webserver()
762 // Target initialisation is only attempted at startup, so we sleep forever and
763 // let the http server bail us out(i.e. get config files set up).
764 diag_printf("OpenOCD has invoked exit().\n"
765 "Use web server to correct any configuration settings and reboot.\n");
769 // exit() will terminate the current thread and we we'll then sleep eternally or
770 // we'll have a reboot scheduled.
773 extern void printDccChar(char c
);
775 static char logBuffer
[128 * 1024];
776 static const int logSize
= sizeof(logBuffer
);
780 void _zylinjtag_diag_write_char(char c
, void **param
)
784 logBuffer
[writePtr
] = c
;
785 writePtr
= (writePtr
+ 1) % logSize
;
792 HAL_DIAG_WRITE_CHAR('\r');
794 HAL_DIAG_WRITE_CHAR(c
);
800 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
803 static void copyfile(char *name2
, char *name1
)
811 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
813 SHOW_RESULT( open
, fd1
);
815 fd2
= open(name2
, O_RDONLY
);
817 SHOW_RESULT( open
, fd2
);
821 done
= read(fd2
, buf
, IOSIZE
);
824 SHOW_RESULT( read
, done
);
828 if( done
== 0 ) break;
830 wrote
= write(fd1
, buf
, done
);
831 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
833 if( wrote
!= done
) break;
837 if( err
< 0 ) SHOW_RESULT( close
, err
);
840 if( err
< 0 ) SHOW_RESULT( close
, err
);
843 static void copydir(char *name
)
848 mkdir("/ram/cgi", 0777);
850 dirp
= opendir(name
);
851 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
855 struct dirent
*entry
= readdir(dirp
);
860 if (strcmp(entry
->d_name
, ".") == 0)
862 if (strcmp(entry
->d_name
, "..") == 0)
867 char fullPath
[PATH_MAX
];
868 strncpy(fullPath
, name
, PATH_MAX
);
869 strcat(fullPath
, "/");
870 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
872 if (stat(fullPath
, &buf
) == -1)
874 diag_printf("unable to read status from %s", fullPath
);
877 isDir
= S_ISDIR(buf
.st_mode
) != 0;
882 // diag_printf("<INFO>: entry %14s",entry->d_name);
883 char fullname
[PATH_MAX
];
884 char fullname2
[PATH_MAX
];
886 strcpy(fullname
, name
);
887 strcat(fullname
, entry
->d_name
);
889 strcpy(fullname2
, "/ram/cgi/");
890 strcat(fullname2
, entry
->d_name
);
891 // diag_printf("from %s to %s\n", fullname, fullname2);
892 copyfile(fullname
, fullname2
);
894 // diag_printf("\n");
897 err
= closedir(dirp
);
898 if( err
< 0 ) SHOW_RESULT( stat
, err
);
902 MTAB_ENTRY( romfs_mte1
,
906 (CYG_ADDRWORD
) &filedata
[0] );
909 void openocd_sleep_prelude()
911 cyg_mutex_unlock(&httpstate
.jim_lock
);
914 void openocd_sleep_postlude()
916 cyg_mutex_lock(&httpstate
.jim_lock
);
920 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
922 Jim_Obj
* const *argv
)
927 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
932 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
934 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
937 return del
? JIM_OK
: JIM_ERR
;
940 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
941 Jim_Obj
* const *argv
)
943 cyg_handle_t thread
= 0;
945 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
947 /* Loop over the threads, and generate a table row for
950 while (cyg_thread_get_next(&thread
, &id
))
952 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
954 cyg_thread_info info
;
957 cyg_thread_get_info(thread
, id
, &info
);
959 if (info
.name
== NULL
)
960 info
.name
= "<no name>";
962 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
963 info
.name
, strlen(info
.name
)));
965 /* Translate the state into a string.
968 state_string
= "RUN";
969 else if (info
.state
& 0x04)
970 state_string
= "SUSP";
972 switch (info
.state
& 0x1b)
975 state_string
= "SLEEP";
978 state_string
= "CNTSLEEP";
981 state_string
= "CREATE";
984 state_string
= "EXIT";
987 state_string
= "????";
991 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
992 state_string
, strlen(state_string
)));
994 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
995 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
996 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
998 Jim_ListAppendElement(interp
, threads
, threadObj
);
1000 Jim_SetResult( interp
, threads
);
1007 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
1009 Jim_Obj
* const *argv
)
1013 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1017 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
1020 dirp
= opendir(name
);
1025 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
1029 struct dirent
*entry
= NULL
;
1030 entry
= readdir(dirp
);
1034 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
1037 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
1041 Jim_SetResult(interp
, objPtr
);
1048 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
1050 Jim_Obj
* const *argv
)
1054 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1060 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1062 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
1065 if (length
< 0 && length
> (4096 * 1024))
1067 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1071 void *mem
= malloc(length
);
1075 target_t
*target
= get_current_target(cmd_ctx
);
1080 if ((address
% 4 == 0) && (count
% 4 == 0))
1086 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1092 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1093 Jim_SetResult(interp
, objPtr
);
1101 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1103 Jim_Obj
* const *argv
)
1107 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1112 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1115 int value
= *((volatile int *) address
);
1117 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1123 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1125 Jim_Obj
* const *argv
)
1129 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1134 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1137 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1140 *((volatile int *) address
) = value
;
1148 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1150 Jim_Obj
* const *argv
)
1154 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1164 if (retval
== JIM_OK
)
1166 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1177 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1179 Jim_Obj
* const *argv
)
1181 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1183 if (logCount
>= logSize
)
1185 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1187 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1189 Jim_SetResult(interp
, tclOutput
);
1194 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1196 Jim_Obj
* const *argv
)
1203 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1205 Jim_Obj
* const *argv
)
1209 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1212 strcpy(ifr
.ifr_name
, "eth0");
1214 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1223 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1226 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1227 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1228 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1229 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1230 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1231 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1232 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1234 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1236 Jim_SetResult(interp
, tclOutput
);
1242 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1244 Jim_Obj
* const *argv
)
1246 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1248 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1250 if (getifaddrs(&ifp
) < 0)
1255 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1260 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1261 salen
= sizeof(struct sockaddr_in
);
1262 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1263 salen
= sizeof(struct sockaddr_in6
);
1267 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1268 NI_NUMERICHOST
) < 0)
1273 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1280 Jim_SetResult(interp
, tclOutput
);
1285 extern Jim_Interp
*interp
;
1287 static void zylinjtag_startNetwork()
1289 // Bring TCP/IP up immediately before we're ready to accept commands.
1291 // That is as soon as a PING responds, we're accepting telnet sessions.
1292 #if defined(CYGPKG_NET_FREEBSD_STACK)
1293 phi_init_all_network_interfaces();
1299 diag_printf("Network not up and running\n");
1302 #if defined(CYGPKG_NET_FREEBSD_STACK)
1304 tftpd_start(69, &fileops
);
1307 cyg_httpd_init_tcl_interpreter();
1309 interp
= httpstate
.jim_interp
;
1311 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1312 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1313 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1314 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1315 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1316 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1317 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1318 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1319 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1320 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1321 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1327 diag_printf("Web server running\n");
1330 static bool readPowerDropout()
1333 // sample and clear power dropout
1334 HAL_WRITE_UINT32(0x08000010, 0x80);
1335 HAL_READ_UINT32(0x08000010, state
);
1337 powerDropout
= (state
& 0x80) != 0;
1338 return powerDropout
;
1344 // sample and clear SRST sensing
1345 HAL_WRITE_UINT32(0x08000010, 0x00000040);
1346 HAL_READ_UINT32(0x08000010, state
);
1348 srstAsserted
= (state
& 0x40) != 0;
1349 return srstAsserted
;
1352 // every 300ms we check for reset & powerdropout and issue a "reset halt" if
1356 static int sense_handler(void *priv
)
1358 struct command_context_s
*cmd_ctx
;
1359 cmd_ctx
= (struct command_context_s
*) priv
;
1361 static bool prevSrstAsserted
= false;
1362 static bool prevPowerdropout
= false;
1365 powerDropout
= readPowerDropout();
1368 powerRestored
= prevPowerdropout
&& !powerDropout
;
1371 LOG_USER("Sensed power restore.");
1374 cyg_tick_count_t current
= cyg_current_time();
1375 static cyg_tick_count_t lastPower
= 0;
1376 bool waitMore
= lastPower
+ 200 > current
;
1377 if (powerDropout
&& !waitMore
)
1379 LOG_USER("Sensed power dropout.");
1380 lastPower
= current
;
1383 bool srstAsserted
= readSRST();
1385 bool srstDeasserted
;
1386 srstDeasserted
= prevSrstAsserted
&& !srstAsserted
;
1388 static cyg_tick_count_t lastSrst
= 0;
1389 waitMore
= lastSrst
+ 200 > current
;
1390 if (srstDeasserted
&& !waitMore
)
1392 LOG_USER("Sensed nSRST deasserted");
1396 if (!prevSrstAsserted
&& srstAsserted
)
1398 LOG_USER("Sensed nSRST asserted");
1401 prevSrstAsserted
= srstAsserted
;
1402 prevPowerdropout
= powerDropout
;
1404 if (srstDeasserted
|| powerRestored
)
1406 /* Other than logging the event we can't do anything here.
1407 * Issuing a reset is a particularly bad idea as we might
1408 * be inside a reset already.
1418 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1422 char *infoStr
= "unknown";
1425 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1426 infoStr
= "undefined instruction";
1428 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1429 infoStr
= "software interrupt";
1431 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1432 infoStr
= "abort prefetch";
1434 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1435 infoStr
= "abort data";
1441 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1443 diag_printf("Dumping log\n---\n");
1444 if (logCount
>= logSize
)
1446 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1448 diag_write(logBuffer
, writePtr
);
1450 diag_printf("---\nLogdump complete.\n");
1451 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1452 diag_printf("\n---\nRebooting\n");
1453 HAL_PLATFORM_RESET();
1457 static void setHandler(cyg_code_t exception
)
1459 cyg_exception_handler_t
*old_handler
;
1460 cyg_addrword_t old_data
;
1462 cyg_exception_set_handler(exception
,
1463 print_exception_handler
,
1469 static cyg_thread zylinjtag_uart_thread_object
;
1470 static cyg_handle_t zylinjtag_uart_thread_handle
;
1471 static char uart_stack
[4096];
1473 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1474 static char backwardBuffer
[1024];
1476 static cyg_io_handle_t serial_handle
;
1478 void setNoDelay(int session
, int flag
)
1481 // This decreases latency dramatically for e.g. GDB load which
1482 // does not have a sliding window protocol
1484 // Can cause *lots* of TCP/IP packets to be sent and it would have
1485 // to be enabled/disabled on the fly to avoid the CPU being
1487 setsockopt(session
, /* socket affected */
1488 IPPROTO_TCP
, /* set option at TCP level */
1489 TCP_NODELAY
, /* name of option */
1490 (char *) &flag
, /* the cast is historical
1492 sizeof(int)); /* length of option value */
1502 } tcpipSent
[512 * 1024];
1506 zylinjtag_uart(cyg_addrword_t data
)
1508 int so_reuseaddr_option
= 1;
1511 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1513 LOG_ERROR("error creating socket: %s", strerror(errno
));
1517 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1519 struct sockaddr_in sin
;
1520 unsigned int address_size
;
1521 address_size
= sizeof(sin
);
1522 memset(&sin
, 0, sizeof(sin
));
1523 sin
.sin_family
= AF_INET
;
1524 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1525 sin
.sin_port
= htons(5555);
1527 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1529 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1533 if (listen(fd
, 1) == -1)
1535 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1538 // socket_nonblock(fd);
1543 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1549 setNoDelay(session
, 1);
1550 int oldopts
= fcntl(session
, F_GETFL
, 0);
1551 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1553 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1571 FD_ZERO(&write_fds
);
1574 FD_SET(session
, &read_fds
);
1576 FD_SET(serHandle
, &read_fds
);
1577 if (serHandle
> fd_max
)
1583 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1584 if ((actual
== 0) && (actual2
== 0))
1586 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1595 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1596 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1599 if (errno
!= EAGAIN
)
1612 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1620 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1622 // NB! Here it is important that we empty the TCP/IP read buffer
1623 // to make transmission tick right
1624 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1627 // this will block if there is no data at all
1628 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1640 /* Do not put things into the serial buffer if it has something to send
1641 * as that can cause a single byte to be sent at the time.
1645 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1648 if (errno
!= EAGAIN
)
1652 // The serial buffer is full
1663 tcpipSent
[cur
].req
= x
;
1664 tcpipSent
[cur
].actual
= y
;
1665 tcpipSent
[cur
].req2
= x2
;
1666 tcpipSent
[cur
].actual2
= y2
;
1676 for (i
= 0; i
< 1024; i
++)
1678 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1686 void startUart(void)
1688 cyg_thread_create(1,
1694 &zylinjtag_uart_thread_handle
,
1695 &zylinjtag_uart_thread_object
);
1696 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1697 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1702 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1706 command_print(cmd_ctx
, "usage: uart <baudrate>");
1707 return ERROR_INVALID_ARGUMENTS
;
1710 int baud
= atol(args
[0]);
1715 baud
= CYGNUM_SERIAL_BAUD_9600
;
1718 baud
= CYGNUM_SERIAL_BAUD_19200
;
1721 baud
= CYGNUM_SERIAL_BAUD_38400
;
1724 baud
= CYGNUM_SERIAL_BAUD_57600
;
1727 baud
= CYGNUM_SERIAL_BAUD_115200
;
1730 baud
= CYGNUM_SERIAL_BAUD_230400
;
1733 command_print(cmd_ctx
, "unsupported baudrate");
1734 return ERROR_INVALID_ARGUMENTS
;
1737 cyg_serial_info_t buf
;
1739 //get existing serial configuration
1740 len
= sizeof(cyg_serial_info_t
);
1742 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1743 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1746 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1751 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1754 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1761 bool logAllToSerial
= false;
1763 /* boolean parameter stored on config */
1764 bool boolParam(char *var
)
1766 bool result
= false;
1767 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1773 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1777 result
= strncmp((char *) data
, "1", len
) == 0;
1784 command_context_t
*setup_command_handler();
1786 int add_default_dirs(void)
1788 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1789 add_script_search_dir("/rom/lib/openocd");
1790 add_script_search_dir("/rom");
1794 int main(int argc
, char *argv
[])
1796 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1797 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1798 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1801 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1804 diag_printf("/dev/ser0 not found\n");
1808 setPower(true); // on by default
1810 atexit(keep_webserver
);
1812 err
= mount("", "/ram", "ramfs");
1815 diag_printf("unable to mount ramfs\n");
1820 sprintf(address
, "%p", &filedata
[0]);
1821 err
= mount(address
, "/rom", "romfs");
1824 diag_printf("unable to mount /rom\n");
1827 err
= mount("", "/log", "logfs");
1830 diag_printf("unable to mount logfs\n");
1833 err
= mount("", "/tftp", "tftpfs");
1836 diag_printf("unable to mount logfs\n");
1839 log
= fopen("/log/log", "w");
1842 diag_printf("Could not open log file /ram/log\n");
1846 diag_init_putc(_zylinjtag_diag_write_char
);
1848 // We want this in the log.
1849 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1850 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1854 err
= mount("/dev/flash1", "/config", "jffs2");
1857 diag_printf("unable to mount jffs\n");
1861 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1862 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1863 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1865 logAllToSerial
= boolParam("logserial");
1867 // We need the network & web server in case there is something wrong with
1868 // the config files that invoke exit()
1869 zylinjtag_startNetwork();
1871 /* we're going to access the jim interpreter from here on... */
1872 openocd_sleep_postlude();
1877 /* initialize commandline interface */
1878 command_context_t
*cmd_ctx
;
1879 cmd_ctx
= setup_command_handler();
1880 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1881 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1884 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1885 COMMAND_EXEC
, "show zy1000 version numbers");
1887 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1890 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1891 "same args as load_image, image stored in memory");
1893 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1894 "loads active fast load image to current target");
1896 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1897 "display file content");
1899 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1900 "truncate a file to 0 size");
1902 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1903 COMMAND_ANY
, "append a variable number of strings to a file");
1905 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1906 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1908 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1909 COMMAND_ANY
, "display available ram memory");
1911 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1912 COMMAND_ANY
, "copy a file <from> <to>");
1914 #ifdef CYGPKG_PROFILE_GPROF
1915 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1918 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1919 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1923 errVal
= log_init(cmd_ctx
);
1924 if (errVal
!= ERROR_OK
)
1926 diag_printf("log_init() failed %d\n", errVal
);
1930 set_log_output(cmd_ctx
, log
);
1932 LOG_DEBUG("log init complete");
1934 // diag_printf("Executing config files\n");
1938 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1939 command_run_line(cmd_ctx
, "debug_level 3");
1942 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1944 target_register_timer_callback(sense_handler
, 200, 1, cmd_ctx
);
1947 // diag_printf() is really invoked from many more places than we trust it
1948 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1950 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1951 // fingers that it doesn't cause any crashes.
1952 diag_printf("Init complete, GDB & telnet servers launched.\n");
1953 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1954 if (!logAllToSerial
)
1959 /* handle network connections */
1960 server_loop(cmd_ctx
);
1961 openocd_sleep_prelude();
1963 /* shut server down */
1966 /* free commandline interface */
1967 command_done(cmd_ctx
);
1977 cyg_httpd_exec_cgi_tcl(char *file_name
);
1978 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1980 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1984 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1986 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1987 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1989 #include <pkgconf/system.h>
1990 #include <pkgconf/hal.h>
1991 #include <pkgconf/kernel.h>
1992 #include <pkgconf/io_fileio.h>
1993 #include <pkgconf/fs_rom.h>
1995 #include <cyg/kernel/ktypes.h> // base kernel types
1996 #include <cyg/infra/cyg_trac.h> // tracing macros
1997 #include <cyg/infra/cyg_ass.h> // assertion macros
1999 #include <sys/types.h>
2001 #include <sys/stat.h>
2010 #include <cyg/fileio/fileio.h>
2012 #include <cyg/kernel/kapi.h>
2013 #include <cyg/infra/diag.h>
2015 //==========================================================================
2016 // Eventually we want to eXecute In Place from the ROM in a protected
2017 // environment, so we'll need executables to be aligned to a boundary
2018 // suitable for MMU protection. A suitable boundary would be the 4k
2019 // boundary in all the CPU architectures I am currently aware of.
2021 // Forward definitions
2023 // Filesystem operations
2024 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2025 static int tftpfs_umount(cyg_mtab_entry
*mte
);
2026 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2027 int mode
, cyg_file
*fte
);
2028 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2029 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2032 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2033 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
2034 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
2036 //==========================================================================
2037 // Filesystem table entries
2039 // -------------------------------------------------------------------------
2041 // This defines the entry in the filesystem table.
2042 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2043 // we should never block in any filesystem operations.
2045 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
2050 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2051 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2052 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2053 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2054 (cyg_fsop_link
*)cyg_fileio_erofs
,
2055 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2056 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2057 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2058 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2059 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2062 // -------------------------------------------------------------------------
2064 // This defines a single ROMFS loaded into ROM at the configured address
2066 // MTAB_ENTRY( rom_mte, // structure name
2067 // "/rom", // mount point
2068 // "romfs", // FIlesystem type
2069 // "", // hardware device
2070 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2074 // -------------------------------------------------------------------------
2076 // This set of file operations are used for normal open files.
2078 static cyg_fileops tftpfs_fileops
=
2083 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2087 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2088 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2089 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2092 // -------------------------------------------------------------------------
2094 // Process a mount request. This mainly finds root for the
2097 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2102 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2117 static void freeTftp(struct Tftp
*t
)
2130 static const int tftpMaxSize
= 8192 * 1024;
2131 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2132 int mode
, cyg_file
*file
)
2135 tftp
= malloc(sizeof(struct Tftp
));
2138 memset(tftp
, 0, sizeof(struct Tftp
));
2140 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2141 file
->f_type
= CYG_FILE_TYPE_FILE
;
2142 file
->f_ops
= &tftpfs_fileops
;
2147 tftp
->mem
= malloc(tftpMaxSize
);
2148 if (tftp
->mem
== NULL
)
2154 char *server
= strchr(name
, '/');
2161 tftp
->server
= malloc(server
- name
+ 1);
2162 if (tftp
->server
== NULL
)
2167 strncpy(tftp
->server
, name
, server
- name
);
2168 tftp
->server
[server
- name
] = 0;
2170 tftp
->file
= strdup(server
+ 1);
2171 if (tftp
->file
== NULL
)
2177 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2182 static int fetchTftp(struct Tftp
*tftp
)
2184 if (!tftp
->readFile
)
2187 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2189 if (tftp
->actual
< 0)
2198 // -------------------------------------------------------------------------
2199 // tftpfs_fo_write()
2200 // Read data from file.
2203 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2205 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2207 if (fetchTftp(tftp
) != ENOERR
)
2211 off_t pos
= fp
->f_offset
;
2213 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2215 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2216 char *buf
= (char *) iov
->iov_base
;
2217 off_t len
= iov
->iov_len
;
2219 if (len
+ pos
> tftp
->actual
)
2221 len
= tftp
->actual
- pos
;
2223 resid
+= iov
->iov_len
- len
;
2225 memcpy(buf
, tftp
->mem
+ pos
, len
);
2229 uio
->uio_resid
= resid
;
2237 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2239 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2242 off_t pos
= fp
->f_offset
;
2244 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2246 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2247 char *buf
= (char *) iov
->iov_base
;
2248 off_t len
= iov
->iov_len
;
2250 if (len
+ pos
> tftpMaxSize
)
2252 len
= tftpMaxSize
- pos
;
2254 resid
+= iov
->iov_len
- len
;
2256 memcpy(tftp
->mem
+ pos
, buf
, len
);
2260 uio
->uio_resid
= resid
;
2269 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2275 // -------------------------------------------------------------------------
2277 // Close a file. We just clear out the data pointer.
2279 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2281 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2286 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2294 // -------------------------------------------------------------------------
2296 // Seek to a new file position.
2298 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2300 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2303 if (fetchTftp(tftp
) != ENOERR
)
2309 // Pos is already where we want to be.
2313 // Add pos to current offset.
2314 pos
+= fp
->f_offset
;
2318 // Add pos to file size.
2319 pos
+= tftp
->actual
;
2326 // Check that pos is still within current file size, or at the
2328 if (pos
< 0 || pos
> tftp
->actual
)
2331 // All OK, set fp offset and return new position.
2332 *apos
= fp
->f_offset
= pos
;
2340 cyg_thread_delay(us
/ 10000 + 1);
2347 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2349 cyg_httpd_start_chunked("text");
2350 if (logCount
>= logSize
)
2352 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2354 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2355 cyg_httpd_end_chunked();
2359 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2361 // Filesystem operations
2362 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2363 static int logfs_umount(cyg_mtab_entry
*mte
);
2364 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2365 int mode
, cyg_file
*fte
);
2367 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2370 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2371 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2373 //==========================================================================
2374 // Filesystem table entries
2376 // -------------------------------------------------------------------------
2378 // This defines the entry in the filesystem table.
2379 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2380 // we should never block in any filesystem operations.
2381 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2382 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2386 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2387 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2388 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2389 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2390 (cyg_fsop_link
*)cyg_fileio_erofs
,
2391 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2392 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2393 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2394 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2395 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2397 // -------------------------------------------------------------------------
2399 // This set of file operations are used for normal open files.
2401 static cyg_fileops logfs_fileops
=
2403 (cyg_fileop_read
*)cyg_fileio_erofs
,
2404 (cyg_fileop_write
*)logfs_fo_write
,
2405 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2406 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2410 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2411 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2412 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2415 // -------------------------------------------------------------------------
2417 // Process a mount request. This mainly finds root for the
2420 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2425 static int logfs_umount(cyg_mtab_entry
*mte
)
2430 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2431 int mode
, cyg_file
*file
)
2433 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2434 file
->f_type
= CYG_FILE_TYPE_FILE
;
2435 file
->f_ops
= &logfs_fileops
;
2442 // -------------------------------------------------------------------------
2444 // Write data to file.
2447 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2450 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2452 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2453 char *buf
= (char *) iov
->iov_base
;
2454 off_t len
= iov
->iov_len
;
2456 diag_write(buf
, len
);
2463 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2468 // -------------------------------------------------------------------------
2470 // Close a file. We just clear out the data pointer.
2472 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)