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.42"
100 #define ZYLIN_DATE __DATE__
101 #define ZYLIN_TIME __TIME__
102 #define ZYLIN_OPENOCD 921
103 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
104 #define ZYLIN_CONFIG_DIR "/config/settings"
106 void diag_write(char *buf
, int len
)
109 for (j
= 0; j
< len
; j
++)
111 diag_printf("%c", buf
[j
]);
115 static bool serialLog
= true;
116 static bool writeLog
= true;
127 static int fastload_num
;
128 static struct FastLoad
*fastload
;
130 static void free_fastload()
135 for (i
=0; i
<fastload_num
; i
++)
137 if (fastload
[i
].data
)
138 free(fastload
[i
].data
);
146 int handle_fast_load_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
152 u32 max_address
=0xffffffff;
161 if ((argc
< 1)||(argc
> 5))
163 return ERROR_COMMAND_SYNTAX_ERROR
;
166 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
169 image
.base_address_set
= 1;
170 image
.base_address
= strtoul(args
[1], NULL
, 0);
174 image
.base_address_set
= 0;
178 image
.start_address_set
= 0;
182 min_address
=strtoul(args
[3], NULL
, 0);
186 max_address
=strtoul(args
[4], NULL
, 0)+min_address
;
189 if (min_address
>max_address
)
191 return ERROR_COMMAND_SYNTAX_ERROR
;
194 duration_start_measure(&duration
);
196 if (image_open(&image
, args
[0], (argc
>= 3) ? args
[2] : NULL
) != ERROR_OK
)
203 fastload_num
=image
.num_sections
;
204 fastload
=(struct FastLoad
*)malloc(sizeof(struct FastLoad
)*image
.num_sections
);
210 memset(fastload
, 0, sizeof(struct FastLoad
)*image
.num_sections
);
211 for (i
= 0; i
< image
.num_sections
; i
++)
213 buffer
= malloc(image
.sections
[i
].size
);
216 command_print(cmd_ctx
, "error allocating buffer for section (%d bytes)", image
.sections
[i
].size
);
220 if ((retval
= image_read_section(&image
, i
, 0x0, image
.sections
[i
].size
, buffer
, &buf_cnt
)) != ERROR_OK
)
230 /* DANGER!!! beware of unsigned comparision here!!! */
232 if ((image
.sections
[i
].base_address
+buf_cnt
>=min_address
)&&
233 (image
.sections
[i
].base_address
<max_address
))
235 if (image
.sections
[i
].base_address
<min_address
)
237 /* clip addresses below */
238 offset
+=min_address
-image
.sections
[i
].base_address
;
242 if (image
.sections
[i
].base_address
+buf_cnt
>max_address
)
244 length
-=(image
.sections
[i
].base_address
+buf_cnt
)-max_address
;
247 fastload
[i
].address
=image
.sections
[i
].base_address
+offset
;
248 fastload
[i
].data
=malloc(length
);
249 if (fastload
[i
].data
==NULL
)
254 memcpy(fastload
[i
].data
, buffer
+offset
, length
);
255 fastload
[i
].length
=length
;
257 image_size
+= length
;
258 command_print(cmd_ctx
, "%u byte written at address 0x%8.8x", length
, image
.sections
[i
].base_address
+offset
);
264 duration_stop_measure(&duration
, &duration_text
);
265 if (retval
==ERROR_OK
)
267 command_print(cmd_ctx
, "downloaded %u byte in %s", image_size
, duration_text
);
273 if (retval
!=ERROR_OK
)
281 int handle_fast_load_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
284 return ERROR_COMMAND_SYNTAX_ERROR
;
287 LOG_ERROR("No image in memory");
293 for (i
=0; i
<fastload_num
;i
++)
296 target_t
*target
= get_current_target(cmd_ctx
);
297 if ((retval
= target_write_buffer(target
, fastload
[i
].address
, fastload
[i
].length
, fastload
[i
].data
)) != ERROR_OK
)
301 size
+=fastload
[i
].length
;
303 int after
=timeval_ms();
304 command_print(cmd_ctx
, "Loaded image %f kBytes/s", (float)(size
/1024.0)/((float)(after
-ms
)/1000.0));
309 /* Give TELNET a way to find out what version this is */
310 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
311 char **args
, int argc
)
315 return ERROR_COMMAND_SYNTAX_ERROR
;
319 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
320 } else if (strcmp("openocd", args
[0])==0)
322 command_print(cmd_ctx
, "%d", ZYLIN_OPENOCD
);
323 } else if (strcmp("zy1000", args
[0])==0)
325 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
326 } else if (strcmp("date", args
[0])==0)
328 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
331 return ERROR_COMMAND_SYNTAX_ERROR
;
337 extern flash_driver_t
*flash_drivers
[];
338 extern target_type_t
*target_types
[];
340 #ifdef CYGPKG_PROFILE_GPROF
341 #include <cyg/profile/profile.h>
343 extern char _stext
, _etext
; // Defined by the linker
345 void start_profile(void)
347 // This starts up the system-wide profiling, gathering
348 // profile information on all of the code, with a 16 byte
349 // "bucket" size, at a rate of 100us/profile hit.
350 // Note: a bucket size of 16 will give pretty good function
351 // resolution. Much smaller and the buffer becomes
352 // much too large for very little gain.
353 // Note: a timer period of 100us is also a reasonable
354 // compromise. Any smaller and the overhead of
355 // handling the timter (profile) interrupt could
356 // swamp the system. A fast processor might get
357 // by with a smaller value, but a slow one could
358 // even be swamped by this value. If the value is
359 // too large, the usefulness of the profile is reduced.
361 // no more interrupts than 1/10ms.
362 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
363 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
364 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
368 // launch GDB server if a config file exists
369 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
371 bool foundFile
= false;
372 FILE *config_file
= NULL
;
373 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
374 config_file
= fopen(config_file_name
, "r");
379 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
380 if (retval
== ERROR_OK
)
386 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
391 command_print(cmd_ctx
, "No %s found", config_file_name
);
400 static char reboot_stack
[2048];
404 zylinjtag_reboot(cyg_addrword_t data
)
407 diag_printf("Rebooting in 100 ticks..\n");
408 cyg_thread_delay(100);
409 diag_printf("Unmounting /config..\n");
411 diag_printf("Rebooting..\n");
412 HAL_PLATFORM_RESET();
414 static cyg_thread zylinjtag_thread_object
;
415 static cyg_handle_t zylinjtag_thread_handle
;
423 (void *)reboot_stack
,
424 sizeof(reboot_stack
),
425 &zylinjtag_thread_handle
,
426 &zylinjtag_thread_object
);
427 cyg_thread_resume(zylinjtag_thread_handle
);
430 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
432 diag_printf("%s", line
);
437 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
439 LOG_USER_N("%s", line
);
444 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
445 char **args
, int argc
)
449 command_print(cmd_ctx
, "rm <filename>");
450 return ERROR_INVALID_ARGUMENTS
;
453 if (unlink(args
[0]) != 0)
455 command_print(cmd_ctx
, "failed: %d", errno
);
461 int loadFile(const char *fileName
, void **data
, int *len
);
463 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
464 char **args
, int argc
)
468 command_print(cmd_ctx
, "cat <filename>");
469 return ERROR_INVALID_ARGUMENTS
;
472 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
476 int retval
= loadFile(args
[0], &data
, &len
);
477 if (retval
== ERROR_OK
)
479 command_print(cmd_ctx
, "%s", data
);
484 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
489 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
490 char **args
, int argc
)
494 command_print(cmd_ctx
, "trunc <filename>");
495 return ERROR_INVALID_ARGUMENTS
;
498 FILE *config_file
= NULL
;
499 config_file
= fopen(args
[0], "w");
500 if (config_file
!= NULL
)
507 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
510 struct mallinfo info
;
514 command_print(cmd_ctx
, "meminfo");
515 return ERROR_INVALID_ARGUMENTS
;
522 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
524 prev
= info
.fordblks
;
526 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
531 static bool savePower
;
533 static void setPower(bool power
)
538 HAL_WRITE_UINT32(0x08000014, 0x8);
541 HAL_WRITE_UINT32(0x08000010, 0x8);
545 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
549 return ERROR_INVALID_ARGUMENTS
;
554 if (strcmp(args
[0], "on") == 0)
558 else if (strcmp(args
[0], "off") == 0)
563 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
564 return ERROR_INVALID_ARGUMENTS
;
568 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
573 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
574 char **args
, int argc
)
578 command_print(cmd_ctx
,
579 "append <filename> [<string1>, [<string2>, ...]]");
580 return ERROR_INVALID_ARGUMENTS
;
583 FILE *config_file
= NULL
;
584 config_file
= fopen(args
[0], "a");
585 if (config_file
!= NULL
)
588 fseek(config_file
, 0, SEEK_END
);
590 for (i
= 1; i
< argc
; i
++)
592 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
595 fwrite(" ", 1, 1, config_file
);
598 fwrite("\n", 1, 1, config_file
);
605 extern int telnet_socket
;
607 int readMore(int fd
, void *data
, int length
)
609 /* used in select() */
612 /* monitor sockets for acitvity */
615 /* listen for new connections */
616 FD_SET(fd
, &read_fds
);
618 // Maximum 5 seconds.
623 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
626 diag_printf("Timed out waiting for binary payload\n");
632 return read_socket(fd
, data
, length
);
635 int readAll(int fd
, void *data
, int length
)
640 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
641 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
651 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
656 return ERROR_INVALID_ARGUMENTS
;
658 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
659 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
663 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
667 return ERROR_INVALID_ARGUMENTS
;
669 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
673 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
677 return ERROR_INVALID_ARGUMENTS
;
680 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
684 int retval
= loadFile(args
[0], &data
, &len
);
685 if (retval
!= ERROR_OK
)
688 FILE *f
= fopen(args
[1], "wb");
690 retval
= ERROR_INVALID_ARGUMENTS
;
695 int chunk
= len
- pos
;
696 static const int maxChunk
= 512 * 1024; // ~1/sec
697 if (chunk
> maxChunk
)
702 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
703 retval
= ERROR_INVALID_ARGUMENTS
;
705 if (retval
!= ERROR_OK
)
710 command_print(cmd_ctx
, "%d", len
- pos
);
718 if (retval
== ERROR_OK
)
720 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
723 command_print(cmd_ctx
, "Failed: %d", retval
);
731 if (retval
!= ERROR_OK
)
737 #ifdef CYGPKG_PROFILE_GPROF
738 extern void start_profile();
740 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
742 command_print(cmd_ctx
, "Profiling started");
749 externC
void phi_init_all_network_interfaces();
751 command_context_t
*cmd_ctx
;
753 static bool webRunning
= false;
755 void keep_webserver()
757 // Target initialisation is only attempted at startup, so we sleep forever and
758 // let the http server bail us out(i.e. get config files set up).
759 diag_printf("OpenOCD has invoked exit().\n"
760 "Use web server to correct any configuration settings and reboot.\n");
764 // exit() will terminate the current thread and we we'll then sleep eternally or
765 // we'll have a reboot scheduled.
768 extern void printDccChar(char c
);
770 static char logBuffer
[128 * 1024];
771 static const int logSize
= sizeof(logBuffer
);
775 void _zylinjtag_diag_write_char(char c
, void **param
)
779 logBuffer
[writePtr
] = c
;
780 writePtr
= (writePtr
+ 1) % logSize
;
787 HAL_DIAG_WRITE_CHAR('\r');
789 HAL_DIAG_WRITE_CHAR(c
);
795 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
798 static void copyfile(char *name2
, char *name1
)
806 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
808 SHOW_RESULT( open
, fd1
);
810 fd2
= open(name2
, O_RDONLY
);
812 SHOW_RESULT( open
, fd2
);
816 done
= read(fd2
, buf
, IOSIZE
);
819 SHOW_RESULT( read
, done
);
823 if( done
== 0 ) break;
825 wrote
= write(fd1
, buf
, done
);
826 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
828 if( wrote
!= done
) break;
832 if( err
< 0 ) SHOW_RESULT( close
, err
);
835 if( err
< 0 ) SHOW_RESULT( close
, err
);
838 static void copydir(char *name
)
843 mkdir("/ram/cgi", 0777);
845 dirp
= opendir(name
);
846 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
850 struct dirent
*entry
= readdir(dirp
);
855 if (strcmp(entry
->d_name
, ".") == 0)
857 if (strcmp(entry
->d_name
, "..") == 0)
862 char fullPath
[PATH_MAX
];
863 strncpy(fullPath
, name
, PATH_MAX
);
864 strcat(fullPath
, "/");
865 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
867 if (stat(fullPath
, &buf
) == -1)
869 diag_printf("unable to read status from %s", fullPath
);
872 isDir
= S_ISDIR(buf
.st_mode
) != 0;
877 // diag_printf("<INFO>: entry %14s",entry->d_name);
878 char fullname
[PATH_MAX
];
879 char fullname2
[PATH_MAX
];
881 strcpy(fullname
, name
);
882 strcat(fullname
, entry
->d_name
);
884 strcpy(fullname2
, "/ram/cgi/");
885 strcat(fullname2
, entry
->d_name
);
886 // diag_printf("from %s to %s\n", fullname, fullname2);
887 copyfile(fullname
, fullname2
);
889 // diag_printf("\n");
892 err
= closedir(dirp
);
893 if( err
< 0 ) SHOW_RESULT( stat
, err
);
897 MTAB_ENTRY( romfs_mte1
,
901 (CYG_ADDRWORD
) &filedata
[0] );
904 void openocd_sleep_prelude()
906 cyg_mutex_unlock(&httpstate
.jim_lock
);
909 void openocd_sleep_postlude()
911 cyg_mutex_lock(&httpstate
.jim_lock
);
915 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
917 Jim_Obj
* const *argv
)
922 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
927 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
929 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
932 return del
? JIM_OK
: JIM_ERR
;
936 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
938 Jim_Obj
* const *argv
)
942 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
946 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
949 dirp
= opendir(name
);
954 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
958 struct dirent
*entry
= NULL
;
959 entry
= readdir(dirp
);
963 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
966 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
970 Jim_SetResult(interp
, objPtr
);
977 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
979 Jim_Obj
* const *argv
)
983 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
989 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
991 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
994 if (length
< 0 && length
> (4096 * 1024))
996 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1000 void *mem
= malloc(length
);
1004 target_t
*target
= get_current_target(cmd_ctx
);
1009 if ((address
% 4 == 0) && (count
% 4 == 0))
1015 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1021 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1022 Jim_SetResult(interp
, objPtr
);
1030 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1032 Jim_Obj
* const *argv
)
1036 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1041 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1044 int value
= *((volatile int *) address
);
1046 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1052 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1054 Jim_Obj
* const *argv
)
1058 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1063 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1066 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1069 *((volatile int *) address
) = value
;
1077 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1079 Jim_Obj
* const *argv
)
1083 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1093 if (retval
== JIM_OK
)
1095 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1106 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1108 Jim_Obj
* const *argv
)
1110 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1112 if (logCount
>= logSize
)
1114 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1116 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1118 Jim_SetResult(interp
, tclOutput
);
1123 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1125 Jim_Obj
* const *argv
)
1132 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1134 Jim_Obj
* const *argv
)
1138 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1141 strcpy(ifr
.ifr_name
, "eth0");
1143 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1152 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1155 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1156 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1157 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1158 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1159 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1160 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1161 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1163 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1165 Jim_SetResult(interp
, tclOutput
);
1171 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1173 Jim_Obj
* const *argv
)
1175 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1177 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1179 if (getifaddrs(&ifp
) < 0)
1184 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1189 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1190 salen
= sizeof(struct sockaddr_in
);
1191 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1192 salen
= sizeof(struct sockaddr_in6
);
1196 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1197 NI_NUMERICHOST
) < 0)
1202 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1209 Jim_SetResult(interp
, tclOutput
);
1214 extern Jim_Interp
*interp
;
1216 static void zylinjtag_startNetwork()
1218 // Bring TCP/IP up immediately before we're ready to accept commands.
1220 // That is as soon as a PING responds, we're accepting telnet sessions.
1221 #if defined(CYGPKG_NET_FREEBSD_STACK)
1222 phi_init_all_network_interfaces();
1228 diag_printf("Network not up and running\n");
1231 #if defined(CYGPKG_NET_FREEBSD_STACK)
1233 tftpd_start(69, &fileops
);
1236 cyg_httpd_init_tcl_interpreter();
1238 interp
= httpstate
.jim_interp
;
1240 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1241 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1242 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1243 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1244 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1245 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1246 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1247 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1248 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1249 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1255 diag_printf("Web server running\n");
1258 static bool readPowerDropout()
1261 // sample and clear power dropout
1262 HAL_WRITE_UINT32(0x08000010, 0x80);
1263 HAL_READ_UINT32(0x08000010, state
);
1265 powerDropout
= (state
& 0x80) != 0;
1266 return powerDropout
;
1272 // sample and clear SRST sensing
1273 HAL_WRITE_UINT32(0x08000010, 0x00000040);
1274 HAL_READ_UINT32(0x08000010, state
);
1276 srstAsserted
= (state
& 0x40) != 0;
1277 return srstAsserted
;
1280 // every 300ms we check for reset & powerdropout and issue a "reset halt" if
1284 static int sense_handler(void *priv
)
1286 struct command_context_s
*cmd_ctx
;
1287 cmd_ctx
= (struct command_context_s
*) priv
;
1289 static bool prevSrstAsserted
= false;
1290 static bool prevPowerdropout
= false;
1293 powerDropout
= readPowerDropout();
1296 powerRestored
= prevPowerdropout
&& !powerDropout
;
1299 LOG_USER("Sensed power restore.");
1302 cyg_tick_count_t current
= cyg_current_time();
1303 static cyg_tick_count_t lastPower
= 0;
1304 bool waitMore
= lastPower
+ 200 > current
;
1305 if (powerDropout
&& !waitMore
)
1307 LOG_USER("Sensed power dropout.");
1308 lastPower
= current
;
1311 bool srstAsserted
= readSRST();
1313 bool srstDeasserted
;
1314 srstDeasserted
= prevSrstAsserted
&& !srstAsserted
;
1316 static cyg_tick_count_t lastSrst
= 0;
1317 waitMore
= lastSrst
+ 200 > current
;
1318 if (srstDeasserted
&& !waitMore
)
1320 LOG_USER("Sensed nSRST deasserted");
1324 if (!prevSrstAsserted
&& srstAsserted
)
1326 LOG_USER("Sensed nSRST asserted");
1329 prevSrstAsserted
= srstAsserted
;
1330 prevPowerdropout
= powerDropout
;
1332 if (srstDeasserted
|| powerRestored
)
1334 /* Other than logging the event we can't do anything here.
1335 * Issuing a reset is a particularly bad idea as we might
1336 * be inside a reset already.
1346 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1350 char *infoStr
= "unknown";
1353 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1354 infoStr
= "undefined instruction";
1356 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1357 infoStr
= "software interrupt";
1359 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1360 infoStr
= "abort prefetch";
1362 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1363 infoStr
= "abort data";
1369 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1371 diag_printf("Dumping log\n---\n");
1372 if (logCount
>= logSize
)
1374 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1376 diag_write(logBuffer
, writePtr
);
1378 diag_printf("---\nLogdump complete.\n");
1379 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1380 diag_printf("\n---\nRebooting\n");
1381 HAL_PLATFORM_RESET();
1385 static void setHandler(cyg_code_t exception
)
1387 cyg_exception_handler_t
*old_handler
;
1388 cyg_addrword_t old_data
;
1390 cyg_exception_set_handler(exception
,
1391 print_exception_handler
,
1397 static cyg_thread zylinjtag_uart_thread_object
;
1398 static cyg_handle_t zylinjtag_uart_thread_handle
;
1399 static char uart_stack
[4096];
1401 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1402 static char backwardBuffer
[1024];
1404 static cyg_io_handle_t serial_handle
;
1406 void setNoDelay(int session
, int flag
)
1409 // This decreases latency dramatically for e.g. GDB load which
1410 // does not have a sliding window protocol
1412 // Can cause *lots* of TCP/IP packets to be sent and it would have
1413 // to be enabled/disabled on the fly to avoid the CPU being
1415 setsockopt(session
, /* socket affected */
1416 IPPROTO_TCP
, /* set option at TCP level */
1417 TCP_NODELAY
, /* name of option */
1418 (char *) &flag
, /* the cast is historical
1420 sizeof(int)); /* length of option value */
1430 } tcpipSent
[512 * 1024];
1434 zylinjtag_uart(cyg_addrword_t data
)
1436 int so_reuseaddr_option
= 1;
1439 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1441 LOG_ERROR("error creating socket: %s", strerror(errno
));
1445 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1447 struct sockaddr_in sin
;
1448 unsigned int address_size
;
1449 address_size
= sizeof(sin
);
1450 memset(&sin
, 0, sizeof(sin
));
1451 sin
.sin_family
= AF_INET
;
1452 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1453 sin
.sin_port
= htons(5555);
1455 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1457 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1461 if (listen(fd
, 1) == -1)
1463 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1466 // socket_nonblock(fd);
1471 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1477 setNoDelay(session
, 1);
1478 int oldopts
= fcntl(session
, F_GETFL
, 0);
1479 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1481 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1499 FD_ZERO(&write_fds
);
1502 FD_SET(session
, &read_fds
);
1504 FD_SET(serHandle
, &read_fds
);
1505 if (serHandle
> fd_max
)
1511 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1512 if ((actual
== 0) && (actual2
== 0))
1514 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1523 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1524 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1527 if (errno
!= EAGAIN
)
1540 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1548 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1550 // NB! Here it is important that we empty the TCP/IP read buffer
1551 // to make transmission tick right
1552 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1555 // this will block if there is no data at all
1556 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1568 /* Do not put things into the serial buffer if it has something to send
1569 * as that can cause a single byte to be sent at the time.
1573 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1576 if (errno
!= EAGAIN
)
1580 // The serial buffer is full
1591 tcpipSent
[cur
].req
= x
;
1592 tcpipSent
[cur
].actual
= y
;
1593 tcpipSent
[cur
].req2
= x2
;
1594 tcpipSent
[cur
].actual2
= y2
;
1604 for (i
= 0; i
< 1024; i
++)
1606 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1614 void startUart(void)
1616 cyg_thread_create(1,
1622 &zylinjtag_uart_thread_handle
,
1623 &zylinjtag_uart_thread_object
);
1624 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1625 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1630 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1634 command_print(cmd_ctx
, "usage: uart <baudrate>");
1635 return ERROR_INVALID_ARGUMENTS
;
1638 int baud
= atol(args
[0]);
1643 baud
= CYGNUM_SERIAL_BAUD_9600
;
1646 baud
= CYGNUM_SERIAL_BAUD_19200
;
1649 baud
= CYGNUM_SERIAL_BAUD_38400
;
1652 baud
= CYGNUM_SERIAL_BAUD_57600
;
1655 baud
= CYGNUM_SERIAL_BAUD_115200
;
1658 baud
= CYGNUM_SERIAL_BAUD_230400
;
1661 command_print(cmd_ctx
, "unsupported baudrate");
1662 return ERROR_INVALID_ARGUMENTS
;
1665 cyg_serial_info_t buf
;
1667 //get existing serial configuration
1668 len
= sizeof(cyg_serial_info_t
);
1670 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1671 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1674 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1679 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1682 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1689 bool logAllToSerial
= false;
1691 /* boolean parameter stored on config */
1692 bool boolParam(char *var
)
1694 bool result
= false;
1695 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1701 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1705 result
= strncmp((char *) data
, "1", len
) == 0;
1712 command_context_t
*setup_command_handler();
1714 int add_default_dirs(void)
1716 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1717 add_script_search_dir("/rom/lib/openocd");
1718 add_script_search_dir("/rom");
1722 int main(int argc
, char *argv
[])
1724 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1725 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1726 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1729 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1732 diag_printf("/dev/ser0 not found\n");
1736 setPower(true); // on by default
1738 atexit(keep_webserver
);
1740 err
= mount("", "/ram", "ramfs");
1743 diag_printf("unable to mount ramfs\n");
1748 sprintf(address
, "%p", &filedata
[0]);
1749 err
= mount(address
, "/rom", "romfs");
1752 diag_printf("unable to mount /rom\n");
1755 err
= mount("", "/log", "logfs");
1758 diag_printf("unable to mount logfs\n");
1761 err
= mount("", "/tftp", "tftpfs");
1764 diag_printf("unable to mount logfs\n");
1767 log
= fopen("/log/log", "w");
1770 diag_printf("Could not open log file /ram/log\n");
1774 diag_init_putc(_zylinjtag_diag_write_char
);
1776 // We want this in the log.
1777 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1778 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1782 err
= mount("/dev/flash1", "/config", "jffs2");
1785 diag_printf("unable to mount jffs\n");
1789 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1790 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1791 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1793 logAllToSerial
= boolParam("logserial");
1795 // We need the network & web server in case there is something wrong with
1796 // the config files that invoke exit()
1797 zylinjtag_startNetwork();
1799 /* we're going to access the jim interpreter from here on... */
1800 openocd_sleep_postlude();
1805 /* initialize commandline interface */
1806 command_context_t
*cmd_ctx
;
1807 cmd_ctx
= setup_command_handler();
1808 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1809 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1812 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1813 COMMAND_EXEC
, "show zy1000 version numbers");
1815 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1818 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1819 "same args as load_image, image stored in memory");
1821 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1822 "loads active fast load image to current target");
1824 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1827 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1830 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1831 COMMAND_ANY
, "append <filname>");
1833 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1834 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1836 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1837 COMMAND_ANY
, "meminfo");
1839 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1840 COMMAND_ANY
, "cp <from> <to>");
1842 #ifdef CYGPKG_PROFILE_GPROF
1843 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1846 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1847 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1851 errVal
= log_init(cmd_ctx
);
1852 if (errVal
!= ERROR_OK
)
1854 diag_printf("log_init() failed %d\n", errVal
);
1858 set_log_output(cmd_ctx
, log
);
1860 LOG_DEBUG("log init complete");
1862 // diag_printf("Executing config files\n");
1866 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1867 command_run_line(cmd_ctx
, "debug_level 3");
1870 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1872 target_register_timer_callback(sense_handler
, 200, 1, cmd_ctx
);
1875 // diag_printf() is really invoked from many more places than we trust it
1876 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1878 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1879 // fingers that it doesn't cause any crashes.
1880 diag_printf("Init complete, GDB & telnet servers launched.\n");
1881 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1882 if (!logAllToSerial
)
1887 /* handle network connections */
1888 server_loop(cmd_ctx
);
1889 openocd_sleep_prelude();
1891 /* shut server down */
1894 /* free commandline interface */
1895 command_done(cmd_ctx
);
1905 cyg_httpd_exec_cgi_tcl(char *file_name
);
1906 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1908 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1912 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1914 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1915 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1917 #include <pkgconf/system.h>
1918 #include <pkgconf/hal.h>
1919 #include <pkgconf/kernel.h>
1920 #include <pkgconf/io_fileio.h>
1921 #include <pkgconf/fs_rom.h>
1923 #include <cyg/kernel/ktypes.h> // base kernel types
1924 #include <cyg/infra/cyg_trac.h> // tracing macros
1925 #include <cyg/infra/cyg_ass.h> // assertion macros
1927 #include <sys/types.h>
1929 #include <sys/stat.h>
1938 #include <cyg/fileio/fileio.h>
1940 #include <cyg/kernel/kapi.h>
1941 #include <cyg/infra/diag.h>
1943 //==========================================================================
1944 // Eventually we want to eXecute In Place from the ROM in a protected
1945 // environment, so we'll need executables to be aligned to a boundary
1946 // suitable for MMU protection. A suitable boundary would be the 4k
1947 // boundary in all the CPU architectures I am currently aware of.
1949 // Forward definitions
1951 // Filesystem operations
1952 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
1953 static int tftpfs_umount(cyg_mtab_entry
*mte
);
1954 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
1955 int mode
, cyg_file
*fte
);
1956 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
1957 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
1960 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
1961 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
1962 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
1964 //==========================================================================
1965 // Filesystem table entries
1967 // -------------------------------------------------------------------------
1969 // This defines the entry in the filesystem table.
1970 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1971 // we should never block in any filesystem operations.
1973 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
1978 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
1979 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
1980 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
1981 (cyg_fsop_rename
*)cyg_fileio_erofs
,
1982 (cyg_fsop_link
*)cyg_fileio_erofs
,
1983 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
1984 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
1985 (cyg_fsop_stat
*)cyg_fileio_erofs
,
1986 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
1987 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
1990 // -------------------------------------------------------------------------
1992 // This defines a single ROMFS loaded into ROM at the configured address
1994 // MTAB_ENTRY( rom_mte, // structure name
1995 // "/rom", // mount point
1996 // "romfs", // FIlesystem type
1997 // "", // hardware device
1998 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2002 // -------------------------------------------------------------------------
2004 // This set of file operations are used for normal open files.
2006 static cyg_fileops tftpfs_fileops
=
2011 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2015 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2016 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2017 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2020 // -------------------------------------------------------------------------
2022 // Process a mount request. This mainly finds root for the
2025 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2030 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2045 static void freeTftp(struct Tftp
*t
)
2058 static const int tftpMaxSize
= 8192 * 1024;
2059 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2060 int mode
, cyg_file
*file
)
2063 tftp
= malloc(sizeof(struct Tftp
));
2066 memset(tftp
, 0, sizeof(struct Tftp
));
2068 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2069 file
->f_type
= CYG_FILE_TYPE_FILE
;
2070 file
->f_ops
= &tftpfs_fileops
;
2075 tftp
->mem
= malloc(tftpMaxSize
);
2076 if (tftp
->mem
== NULL
)
2082 char *server
= strchr(name
, '/');
2089 tftp
->server
= malloc(server
- name
+ 1);
2090 if (tftp
->server
== NULL
)
2095 strncpy(tftp
->server
, name
, server
- name
);
2096 tftp
->server
[server
- name
] = 0;
2098 tftp
->file
= strdup(server
+ 1);
2099 if (tftp
->file
== NULL
)
2105 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2110 static int fetchTftp(struct Tftp
*tftp
)
2112 if (!tftp
->readFile
)
2115 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2117 if (tftp
->actual
< 0)
2126 // -------------------------------------------------------------------------
2127 // tftpfs_fo_write()
2128 // Read data from file.
2131 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2133 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2135 if (fetchTftp(tftp
) != ENOERR
)
2139 off_t pos
= fp
->f_offset
;
2141 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2143 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2144 char *buf
= (char *) iov
->iov_base
;
2145 off_t len
= iov
->iov_len
;
2147 if (len
+ pos
> tftp
->actual
)
2149 len
= tftp
->actual
- pos
;
2151 resid
+= iov
->iov_len
- len
;
2153 memcpy(buf
, tftp
->mem
+ pos
, len
);
2157 uio
->uio_resid
= resid
;
2165 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2167 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2170 off_t pos
= fp
->f_offset
;
2172 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2174 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2175 char *buf
= (char *) iov
->iov_base
;
2176 off_t len
= iov
->iov_len
;
2178 if (len
+ pos
> tftpMaxSize
)
2180 len
= tftpMaxSize
- pos
;
2182 resid
+= iov
->iov_len
- len
;
2184 memcpy(tftp
->mem
+ pos
, buf
, len
);
2188 uio
->uio_resid
= resid
;
2197 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2203 // -------------------------------------------------------------------------
2205 // Close a file. We just clear out the data pointer.
2207 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2209 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2214 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2222 // -------------------------------------------------------------------------
2224 // Seek to a new file position.
2226 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2228 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2231 if (fetchTftp(tftp
) != ENOERR
)
2237 // Pos is already where we want to be.
2241 // Add pos to current offset.
2242 pos
+= fp
->f_offset
;
2246 // Add pos to file size.
2247 pos
+= tftp
->actual
;
2254 // Check that pos is still within current file size, or at the
2256 if (pos
< 0 || pos
> tftp
->actual
)
2259 // All OK, set fp offset and return new position.
2260 *apos
= fp
->f_offset
= pos
;
2268 cyg_thread_delay(us
/ 10000 + 1);
2275 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2277 cyg_httpd_start_chunked("text");
2278 if (logCount
>= logSize
)
2280 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2282 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2283 cyg_httpd_end_chunked();
2287 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2289 // Filesystem operations
2290 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2291 static int logfs_umount(cyg_mtab_entry
*mte
);
2292 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2293 int mode
, cyg_file
*fte
);
2295 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2298 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2299 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2301 //==========================================================================
2302 // Filesystem table entries
2304 // -------------------------------------------------------------------------
2306 // This defines the entry in the filesystem table.
2307 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2308 // we should never block in any filesystem operations.
2309 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2310 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2314 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2315 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2316 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2317 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2318 (cyg_fsop_link
*)cyg_fileio_erofs
,
2319 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2320 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2321 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2322 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2323 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2325 // -------------------------------------------------------------------------
2327 // This set of file operations are used for normal open files.
2329 static cyg_fileops logfs_fileops
=
2331 (cyg_fileop_read
*)cyg_fileio_erofs
,
2332 (cyg_fileop_write
*)logfs_fo_write
,
2333 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2334 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2338 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2339 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2340 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2343 // -------------------------------------------------------------------------
2345 // Process a mount request. This mainly finds root for the
2348 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2353 static int logfs_umount(cyg_mtab_entry
*mte
)
2358 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2359 int mode
, cyg_file
*file
)
2361 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2362 file
->f_type
= CYG_FILE_TYPE_FILE
;
2363 file
->f_ops
= &logfs_fileops
;
2370 // -------------------------------------------------------------------------
2372 // Write data to file.
2375 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2378 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2380 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2381 char *buf
= (char *) iov
->iov_base
;
2382 off_t len
= iov
->iov_len
;
2384 diag_write(buf
, len
);
2391 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2396 // -------------------------------------------------------------------------
2398 // Close a file. We just clear out the data pointer.
2400 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)