1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
27 #include "configuration.h"
36 #include "telnet_server.h"
37 #include "gdb_server.h"
39 #include <time_support.h>
41 #include <sys/types.h>
49 #include <cyg/io/flash.h>
50 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
55 #include <cyg/fileio/fileio.h>
57 #include <cyg/athttpd/http.h>
58 #include <cyg/athttpd/socket.h>
59 #include <cyg/athttpd/handler.h>
60 #include <cyg/athttpd/cgi.h>
61 #include <cyg/athttpd/forms.h>
62 #include <cyg/discover/discover.h>
63 #include <cyg/hal/hal_diag.h>
64 #include <cyg/kernel/kapi.h>
65 #include <cyg/io/serialio.h>
66 #include <cyg/io/io.h>
67 #include <netinet/tcp.h>
69 #include <sys/ioctl.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
73 #include <arpa/inet.h>
74 #include <sys/types.h>
75 #include <sys/socket.h>
77 #include <netinet/in.h>
79 #include <arpa/inet.h>
88 #if defined(CYGPKG_NET_FREEBSD_STACK)
89 #include <tftp_support.h>
90 /* posix compatibility broken*/
91 struct tftpd_fileops fileops
=
93 (int (*)(const char *, int))open
,
95 (int (*)(int, const void *, int))write
,
96 ( int (*)(int, void *, int))read
101 #define ZYLIN_VERSION "1.47"
102 #define ZYLIN_DATE __DATE__
103 #define ZYLIN_TIME __TIME__
104 /* hmmm.... we can't pick up the right # during build if we've checked this out
105 * in Eclipse... arrggghh...*/
106 #define ZYLIN_OPENOCD "$Revision$"
107 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
108 #define ZYLIN_CONFIG_DIR "/config/settings"
110 void diag_write(char *buf
, int len
)
113 for (j
= 0; j
< len
; j
++)
115 diag_printf("%c", buf
[j
]);
119 static bool serialLog
= true;
120 static bool writeLog
= true;
132 static int fastload_num
;
133 static struct FastLoad
*fastload
;
135 static void free_fastload()
140 for (i
=0; i
<fastload_num
; i
++)
142 if (fastload
[i
].data
)
143 free(fastload
[i
].data
);
151 int handle_fast_load_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
157 u32 max_address
=0xffffffff;
166 if ((argc
< 1)||(argc
> 5))
168 return ERROR_COMMAND_SYNTAX_ERROR
;
171 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
174 image
.base_address_set
= 1;
175 image
.base_address
= strtoul(args
[1], NULL
, 0);
179 image
.base_address_set
= 0;
183 image
.start_address_set
= 0;
187 min_address
=strtoul(args
[3], NULL
, 0);
191 max_address
=strtoul(args
[4], NULL
, 0)+min_address
;
194 if (min_address
>max_address
)
196 return ERROR_COMMAND_SYNTAX_ERROR
;
199 duration_start_measure(&duration
);
201 if (image_open(&image
, args
[0], (argc
>= 3) ? args
[2] : NULL
) != ERROR_OK
)
208 fastload_num
=image
.num_sections
;
209 fastload
=(struct FastLoad
*)malloc(sizeof(struct FastLoad
)*image
.num_sections
);
215 memset(fastload
, 0, sizeof(struct FastLoad
)*image
.num_sections
);
216 for (i
= 0; i
< image
.num_sections
; i
++)
218 buffer
= malloc(image
.sections
[i
].size
);
221 command_print(cmd_ctx
, "error allocating buffer for section (%d bytes)", image
.sections
[i
].size
);
225 if ((retval
= image_read_section(&image
, i
, 0x0, image
.sections
[i
].size
, buffer
, &buf_cnt
)) != ERROR_OK
)
235 /* DANGER!!! beware of unsigned comparision here!!! */
237 if ((image
.sections
[i
].base_address
+buf_cnt
>=min_address
)&&
238 (image
.sections
[i
].base_address
<max_address
))
240 if (image
.sections
[i
].base_address
<min_address
)
242 /* clip addresses below */
243 offset
+=min_address
-image
.sections
[i
].base_address
;
247 if (image
.sections
[i
].base_address
+buf_cnt
>max_address
)
249 length
-=(image
.sections
[i
].base_address
+buf_cnt
)-max_address
;
252 fastload
[i
].address
=image
.sections
[i
].base_address
+offset
;
253 fastload
[i
].data
=malloc(length
);
254 if (fastload
[i
].data
==NULL
)
259 memcpy(fastload
[i
].data
, buffer
+offset
, length
);
260 fastload
[i
].length
=length
;
262 image_size
+= length
;
263 command_print(cmd_ctx
, "%u byte written at address 0x%8.8x", length
, image
.sections
[i
].base_address
+offset
);
269 duration_stop_measure(&duration
, &duration_text
);
270 if (retval
==ERROR_OK
)
272 command_print(cmd_ctx
, "Loaded %u bytes in %s", image_size
, duration_text
);
273 command_print(cmd_ctx
, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
279 if (retval
!=ERROR_OK
)
287 int handle_fast_load_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
290 return ERROR_COMMAND_SYNTAX_ERROR
;
293 LOG_ERROR("No image in memory");
299 for (i
=0; i
<fastload_num
;i
++)
302 target_t
*target
= get_current_target(cmd_ctx
);
303 if ((retval
= target_write_buffer(target
, fastload
[i
].address
, fastload
[i
].length
, fastload
[i
].data
)) != ERROR_OK
)
307 size
+=fastload
[i
].length
;
309 int after
=timeval_ms();
310 command_print(cmd_ctx
, "Loaded image %f kBytes/s", (float)(size
/1024.0)/((float)(after
-ms
)/1000.0));
315 /* Give TELNET a way to find out what version this is */
316 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
317 char **args
, int argc
)
321 return ERROR_COMMAND_SYNTAX_ERROR
;
325 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
326 } else if (strcmp("openocd", args
[0])==0)
329 revision
=atol(ZYLIN_OPENOCD
+strlen("XRevision: "));
330 command_print(cmd_ctx
, "%d", revision
);
331 } else if (strcmp("zy1000", args
[0])==0)
333 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
334 } else if (strcmp("date", args
[0])==0)
336 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
339 return ERROR_COMMAND_SYNTAX_ERROR
;
345 extern flash_driver_t
*flash_drivers
[];
346 extern target_type_t
*target_types
[];
348 #ifdef CYGPKG_PROFILE_GPROF
349 #include <cyg/profile/profile.h>
351 extern char _stext
, _etext
; // Defined by the linker
353 void start_profile(void)
355 // This starts up the system-wide profiling, gathering
356 // profile information on all of the code, with a 16 byte
357 // "bucket" size, at a rate of 100us/profile hit.
358 // Note: a bucket size of 16 will give pretty good function
359 // resolution. Much smaller and the buffer becomes
360 // much too large for very little gain.
361 // Note: a timer period of 100us is also a reasonable
362 // compromise. Any smaller and the overhead of
363 // handling the timter (profile) interrupt could
364 // swamp the system. A fast processor might get
365 // by with a smaller value, but a slow one could
366 // even be swamped by this value. If the value is
367 // too large, the usefulness of the profile is reduced.
369 // no more interrupts than 1/10ms.
370 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
371 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
372 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
376 // launch GDB server if a config file exists
377 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
379 bool foundFile
= false;
380 FILE *config_file
= NULL
;
381 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
382 config_file
= fopen(config_file_name
, "r");
387 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
388 if (retval
== ERROR_OK
)
394 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
399 command_print(cmd_ctx
, "No %s found", config_file_name
);
408 static char reboot_stack
[2048];
412 zylinjtag_reboot(cyg_addrword_t data
)
415 diag_printf("Rebooting in 100 ticks..\n");
416 cyg_thread_delay(100);
417 diag_printf("Unmounting /config..\n");
419 diag_printf("Rebooting..\n");
420 HAL_PLATFORM_RESET();
422 static cyg_thread zylinjtag_thread_object
;
423 static cyg_handle_t zylinjtag_thread_handle
;
431 (void *)reboot_stack
,
432 sizeof(reboot_stack
),
433 &zylinjtag_thread_handle
,
434 &zylinjtag_thread_object
);
435 cyg_thread_resume(zylinjtag_thread_handle
);
438 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
440 diag_printf("%s", line
);
445 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
447 LOG_USER_N("%s", line
);
452 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
453 char **args
, int argc
)
457 command_print(cmd_ctx
, "rm <filename>");
458 return ERROR_INVALID_ARGUMENTS
;
461 if (unlink(args
[0]) != 0)
463 command_print(cmd_ctx
, "failed: %d", errno
);
469 int loadFile(const char *fileName
, void **data
, int *len
);
471 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
472 char **args
, int argc
)
476 command_print(cmd_ctx
, "cat <filename>");
477 return ERROR_INVALID_ARGUMENTS
;
480 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
484 int retval
= loadFile(args
[0], &data
, &len
);
485 if (retval
== ERROR_OK
)
487 command_print(cmd_ctx
, "%s", data
);
492 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
497 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
498 char **args
, int argc
)
502 command_print(cmd_ctx
, "trunc <filename>");
503 return ERROR_INVALID_ARGUMENTS
;
506 FILE *config_file
= NULL
;
507 config_file
= fopen(args
[0], "w");
508 if (config_file
!= NULL
)
515 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
518 struct mallinfo info
;
522 command_print(cmd_ctx
, "meminfo");
523 return ERROR_INVALID_ARGUMENTS
;
530 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
532 prev
= info
.fordblks
;
534 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
539 static bool savePower
;
541 static void setPower(bool power
)
546 HAL_WRITE_UINT32(0x08000014, 0x8);
549 HAL_WRITE_UINT32(0x08000010, 0x8);
553 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
557 return ERROR_INVALID_ARGUMENTS
;
562 if (strcmp(args
[0], "on") == 0)
566 else if (strcmp(args
[0], "off") == 0)
571 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
572 return ERROR_INVALID_ARGUMENTS
;
576 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
581 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
582 char **args
, int argc
)
586 command_print(cmd_ctx
,
587 "append <filename> [<string1>, [<string2>, ...]]");
588 return ERROR_INVALID_ARGUMENTS
;
591 FILE *config_file
= NULL
;
592 config_file
= fopen(args
[0], "a");
593 if (config_file
!= NULL
)
596 fseek(config_file
, 0, SEEK_END
);
598 for (i
= 1; i
< argc
; i
++)
600 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
603 fwrite(" ", 1, 1, config_file
);
606 fwrite("\n", 1, 1, config_file
);
613 extern int telnet_socket
;
615 int readMore(int fd
, void *data
, int length
)
617 /* used in select() */
620 /* monitor sockets for acitvity */
623 /* listen for new connections */
624 FD_SET(fd
, &read_fds
);
626 // Maximum 5 seconds.
631 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
634 diag_printf("Timed out waiting for binary payload\n");
640 return read_socket(fd
, data
, length
);
643 int readAll(int fd
, void *data
, int length
)
648 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
649 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
659 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
664 return ERROR_INVALID_ARGUMENTS
;
666 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
667 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
671 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
675 return ERROR_INVALID_ARGUMENTS
;
677 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
681 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
685 return ERROR_INVALID_ARGUMENTS
;
688 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
692 int retval
= loadFile(args
[0], &data
, &len
);
693 if (retval
!= ERROR_OK
)
696 FILE *f
= fopen(args
[1], "wb");
698 retval
= ERROR_INVALID_ARGUMENTS
;
703 int chunk
= len
- pos
;
704 static const int maxChunk
= 512 * 1024; // ~1/sec
705 if (chunk
> maxChunk
)
710 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
711 retval
= ERROR_INVALID_ARGUMENTS
;
713 if (retval
!= ERROR_OK
)
718 command_print(cmd_ctx
, "%d", len
- pos
);
726 if (retval
== ERROR_OK
)
728 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
731 command_print(cmd_ctx
, "Failed: %d", retval
);
739 if (retval
!= ERROR_OK
)
745 #ifdef CYGPKG_PROFILE_GPROF
746 extern void start_profile();
748 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
750 command_print(cmd_ctx
, "Profiling started");
757 externC
void phi_init_all_network_interfaces();
759 command_context_t
*cmd_ctx
;
761 static bool webRunning
= false;
763 void keep_webserver()
765 // Target initialisation is only attempted at startup, so we sleep forever and
766 // let the http server bail us out(i.e. get config files set up).
767 diag_printf("OpenOCD has invoked exit().\n"
768 "Use web server to correct any configuration settings and reboot.\n");
772 // exit() will terminate the current thread and we we'll then sleep eternally or
773 // we'll have a reboot scheduled.
776 extern void printDccChar(char c
);
778 static char logBuffer
[128 * 1024];
779 static const int logSize
= sizeof(logBuffer
);
783 void _zylinjtag_diag_write_char(char c
, void **param
)
787 logBuffer
[writePtr
] = c
;
788 writePtr
= (writePtr
+ 1) % logSize
;
795 HAL_DIAG_WRITE_CHAR('\r');
797 HAL_DIAG_WRITE_CHAR(c
);
803 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
806 static void copyfile(char *name2
, char *name1
)
814 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
816 SHOW_RESULT( open
, fd1
);
818 fd2
= open(name2
, O_RDONLY
);
820 SHOW_RESULT( open
, fd2
);
824 done
= read(fd2
, buf
, IOSIZE
);
827 SHOW_RESULT( read
, done
);
831 if( done
== 0 ) break;
833 wrote
= write(fd1
, buf
, done
);
834 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
836 if( wrote
!= done
) break;
840 if( err
< 0 ) SHOW_RESULT( close
, err
);
843 if( err
< 0 ) SHOW_RESULT( close
, err
);
846 static void copydir(char *name
, char *destdir
)
851 dirp
= opendir(destdir
);
854 mkdir(destdir
, 0777);
857 err
= closedir(dirp
);
860 dirp
= opendir(name
);
861 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
865 struct dirent
*entry
= readdir(dirp
);
870 if (strcmp(entry
->d_name
, ".") == 0)
872 if (strcmp(entry
->d_name
, "..") == 0)
877 char fullPath
[PATH_MAX
];
878 strncpy(fullPath
, name
, PATH_MAX
);
879 strcat(fullPath
, "/");
880 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
882 if (stat(fullPath
, &buf
) == -1)
884 diag_printf("unable to read status from %s", fullPath
);
887 isDir
= S_ISDIR(buf
.st_mode
) != 0;
892 // diag_printf("<INFO>: entry %14s",entry->d_name);
893 char fullname
[PATH_MAX
];
894 char fullname2
[PATH_MAX
];
896 strcpy(fullname
, name
);
897 strcat(fullname
, "/");
898 strcat(fullname
, entry
->d_name
);
900 strcpy(fullname2
, destdir
);
901 strcat(fullname2
, "/");
902 strcat(fullname2
, entry
->d_name
);
903 // diag_printf("from %s to %s\n", fullname, fullname2);
904 copyfile(fullname
, fullname2
);
906 // diag_printf("\n");
909 err
= closedir(dirp
);
910 if( err
< 0 ) SHOW_RESULT( stat
, err
);
914 MTAB_ENTRY( romfs_mte1
,
918 (CYG_ADDRWORD
) &filedata
[0] );
921 void openocd_sleep_prelude()
923 cyg_mutex_unlock(&httpstate
.jim_lock
);
926 void openocd_sleep_postlude()
928 cyg_mutex_lock(&httpstate
.jim_lock
);
932 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
934 Jim_Obj
* const *argv
)
939 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
944 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
946 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
949 return del
? JIM_OK
: JIM_ERR
;
952 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
953 Jim_Obj
* const *argv
)
955 cyg_handle_t thread
= 0;
957 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
959 /* Loop over the threads, and generate a table row for
962 while (cyg_thread_get_next(&thread
, &id
))
964 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
966 cyg_thread_info info
;
969 cyg_thread_get_info(thread
, id
, &info
);
971 if (info
.name
== NULL
)
972 info
.name
= "<no name>";
974 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
975 info
.name
, strlen(info
.name
)));
977 /* Translate the state into a string.
980 state_string
= "RUN";
981 else if (info
.state
& 0x04)
982 state_string
= "SUSP";
984 switch (info
.state
& 0x1b)
987 state_string
= "SLEEP";
990 state_string
= "CNTSLEEP";
993 state_string
= "CREATE";
996 state_string
= "EXIT";
999 state_string
= "????";
1003 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
1004 state_string
, strlen(state_string
)));
1006 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
1007 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
1008 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
1010 Jim_ListAppendElement(interp
, threads
, threadObj
);
1012 Jim_SetResult( interp
, threads
);
1019 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
1021 Jim_Obj
* const *argv
)
1025 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1029 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
1032 dirp
= opendir(name
);
1037 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
1041 struct dirent
*entry
= NULL
;
1042 entry
= readdir(dirp
);
1046 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
1049 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
1053 Jim_SetResult(interp
, objPtr
);
1060 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
1062 Jim_Obj
* const *argv
)
1066 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1072 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1074 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
1077 if (length
< 0 && length
> (4096 * 1024))
1079 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1083 void *mem
= malloc(length
);
1087 target_t
*target
= get_current_target(cmd_ctx
);
1092 if ((address
% 4 == 0) && (count
% 4 == 0))
1098 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1104 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1105 Jim_SetResult(interp
, objPtr
);
1113 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1115 Jim_Obj
* const *argv
)
1119 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1124 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1127 int value
= *((volatile int *) address
);
1129 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1135 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1137 Jim_Obj
* const *argv
)
1141 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1146 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1149 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1152 *((volatile int *) address
) = value
;
1160 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1162 Jim_Obj
* const *argv
)
1166 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1176 if (retval
== JIM_OK
)
1178 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1189 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1191 Jim_Obj
* const *argv
)
1193 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1195 if (logCount
>= logSize
)
1197 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1199 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1201 Jim_SetResult(interp
, tclOutput
);
1206 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1208 Jim_Obj
* const *argv
)
1215 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1217 Jim_Obj
* const *argv
)
1220 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1222 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1224 Jim_SetResult(interp
, tclOutput
);
1230 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1232 Jim_Obj
* const *argv
)
1234 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1236 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1238 if (getifaddrs(&ifp
) < 0)
1243 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1248 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1249 salen
= sizeof(struct sockaddr_in
);
1250 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1251 salen
= sizeof(struct sockaddr_in6
);
1255 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1256 NI_NUMERICHOST
) < 0)
1261 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1268 Jim_SetResult(interp
, tclOutput
);
1273 extern Jim_Interp
*interp
;
1276 static void zylinjtag_startNetwork()
1278 // Bring TCP/IP up immediately before we're ready to accept commands.
1280 // That is as soon as a PING responds, we're accepting telnet sessions.
1281 #if defined(CYGPKG_NET_FREEBSD_STACK)
1282 phi_init_all_network_interfaces();
1288 diag_printf("Network not up and running\n");
1291 #if defined(CYGPKG_NET_FREEBSD_STACK)
1293 tftpd_start(69, &fileops
);
1296 cyg_httpd_init_tcl_interpreter();
1298 interp
= httpstate
.jim_interp
;
1300 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1301 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1302 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1303 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1304 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1305 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1306 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1307 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1308 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1309 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1310 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1316 diag_printf("Web server running\n");
1320 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1323 strcpy(ifr
.ifr_name
, "eth0");
1325 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1330 diag_printf("Can't obtain MAC address\n");
1335 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1336 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1337 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1338 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1339 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1340 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1341 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1344 discover_message
=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr
);
1354 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1358 char *infoStr
= "unknown";
1361 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1362 infoStr
= "undefined instruction";
1364 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1365 infoStr
= "software interrupt";
1367 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1368 infoStr
= "abort prefetch";
1370 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1371 infoStr
= "abort data";
1377 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1379 diag_printf("Dumping log\n---\n");
1380 if (logCount
>= logSize
)
1382 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1384 diag_write(logBuffer
, writePtr
);
1386 diag_printf("---\nLogdump complete.\n");
1387 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1388 diag_printf("\n---\nRebooting\n");
1389 HAL_PLATFORM_RESET();
1393 static void setHandler(cyg_code_t exception
)
1395 cyg_exception_handler_t
*old_handler
;
1396 cyg_addrword_t old_data
;
1398 cyg_exception_set_handler(exception
,
1399 print_exception_handler
,
1405 static cyg_thread zylinjtag_uart_thread_object
;
1406 static cyg_handle_t zylinjtag_uart_thread_handle
;
1407 static char uart_stack
[4096];
1409 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1410 static char backwardBuffer
[1024];
1412 static cyg_io_handle_t serial_handle
;
1414 void setNoDelay(int session
, int flag
)
1417 // This decreases latency dramatically for e.g. GDB load which
1418 // does not have a sliding window protocol
1420 // Can cause *lots* of TCP/IP packets to be sent and it would have
1421 // to be enabled/disabled on the fly to avoid the CPU being
1423 setsockopt(session
, /* socket affected */
1424 IPPROTO_TCP
, /* set option at TCP level */
1425 TCP_NODELAY
, /* name of option */
1426 (char *) &flag
, /* the cast is historical
1428 sizeof(int)); /* length of option value */
1438 } tcpipSent
[512 * 1024];
1442 zylinjtag_uart(cyg_addrword_t data
)
1444 int so_reuseaddr_option
= 1;
1447 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1449 LOG_ERROR("error creating socket: %s", strerror(errno
));
1453 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1455 struct sockaddr_in sin
;
1456 unsigned int address_size
;
1457 address_size
= sizeof(sin
);
1458 memset(&sin
, 0, sizeof(sin
));
1459 sin
.sin_family
= AF_INET
;
1460 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1461 sin
.sin_port
= htons(5555);
1463 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1465 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1469 if (listen(fd
, 1) == -1)
1471 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1474 // socket_nonblock(fd);
1479 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1485 setNoDelay(session
, 1);
1486 int oldopts
= fcntl(session
, F_GETFL
, 0);
1487 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1489 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1507 FD_ZERO(&write_fds
);
1510 FD_SET(session
, &read_fds
);
1512 FD_SET(serHandle
, &read_fds
);
1513 if (serHandle
> fd_max
)
1519 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1520 if ((actual
== 0) && (actual2
== 0))
1522 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1531 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1532 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1535 if (errno
!= EAGAIN
)
1548 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1556 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1558 // NB! Here it is important that we empty the TCP/IP read buffer
1559 // to make transmission tick right
1560 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1563 // this will block if there is no data at all
1564 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1576 /* Do not put things into the serial buffer if it has something to send
1577 * as that can cause a single byte to be sent at the time.
1581 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1584 if (errno
!= EAGAIN
)
1588 // The serial buffer is full
1599 tcpipSent
[cur
].req
= x
;
1600 tcpipSent
[cur
].actual
= y
;
1601 tcpipSent
[cur
].req2
= x2
;
1602 tcpipSent
[cur
].actual2
= y2
;
1612 for (i
= 0; i
< 1024; i
++)
1614 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1622 void startUart(void)
1624 cyg_thread_create(1,
1630 &zylinjtag_uart_thread_handle
,
1631 &zylinjtag_uart_thread_object
);
1632 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1633 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1638 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1640 static int current_baud
= 38400;
1643 command_print(cmd_ctx
, "%d", current_baud
);
1645 } else if (argc
!= 1)
1647 return ERROR_INVALID_ARGUMENTS
;
1650 current_baud
= atol(args
[0]);
1653 switch (current_baud
)
1656 baud
= CYGNUM_SERIAL_BAUD_9600
;
1659 baud
= CYGNUM_SERIAL_BAUD_19200
;
1662 baud
= CYGNUM_SERIAL_BAUD_38400
;
1665 baud
= CYGNUM_SERIAL_BAUD_57600
;
1668 baud
= CYGNUM_SERIAL_BAUD_115200
;
1671 baud
= CYGNUM_SERIAL_BAUD_230400
;
1674 command_print(cmd_ctx
, "unsupported baudrate");
1675 return ERROR_INVALID_ARGUMENTS
;
1678 cyg_serial_info_t buf
;
1680 //get existing serial configuration
1681 len
= sizeof(cyg_serial_info_t
);
1683 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1684 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1687 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1692 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1695 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1702 bool logAllToSerial
= false;
1704 /* boolean parameter stored on config */
1705 bool boolParam(char *var
)
1707 bool result
= false;
1708 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1714 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1718 result
= strncmp((char *) data
, "1", len
) == 0;
1725 command_context_t
*setup_command_handler();
1727 int add_default_dirs(void)
1729 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1730 add_script_search_dir("/rom/lib/openocd");
1731 add_script_search_dir("/rom");
1735 static cyg_uint8
*ramblockdevice
;
1736 static const int ramblockdevice_size
=4096*1024;
1737 int main(int argc
, char *argv
[])
1739 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1740 * need to allocate towards the end of the heap. */
1742 ramblockdevice
=(cyg_uint8
*)malloc(ramblockdevice_size
);
1743 memset(ramblockdevice
, 0xff, ramblockdevice_size
);
1745 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1746 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1747 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1750 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1753 diag_printf("/dev/ser0 not found\n");
1757 setPower(true); // on by default
1759 atexit(keep_webserver
);
1761 err
= mount("", "/ram", "ramfs");
1764 diag_printf("unable to mount ramfs\n");
1769 sprintf(address
, "%p", &filedata
[0]);
1770 err
= mount(address
, "/rom", "romfs");
1773 diag_printf("unable to mount /rom\n");
1776 err
= mount("", "/log", "logfs");
1779 diag_printf("unable to mount logfs\n");
1782 err
= mount("", "/tftp", "tftpfs");
1785 diag_printf("unable to mount logfs\n");
1788 log
= fopen("/log/log", "w");
1791 diag_printf("Could not open log file /ram/log\n");
1795 diag_init_putc(_zylinjtag_diag_write_char
);
1797 // We want this in the log.
1798 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1799 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1801 copydir("/rom", "/ram/cgi");
1803 err
= mount("/dev/flash1", "/config", "jffs2");
1806 diag_printf("unable to mount jffs\n");
1810 /* are we using a ram disk instead of a flash disk? This is used
1811 * for ZY1000 live demo...
1813 * copy over flash disk to ram block device
1815 if (boolParam("ramdisk"))
1817 diag_printf("Unmounting /config from flash and using ram instead\n");
1818 err
=umount("/config");
1821 diag_printf("unable to unmount jffs\n");
1825 err
= mount("/dev/flash1", "/config2", "jffs2");
1828 diag_printf("unable to mount jffs\n");
1832 err
= mount("/dev/ram", "/config", "jffs2");
1835 diag_printf("unable to mount ram block device\n");
1839 // copydir("/config2", "/config");
1840 copyfile("/config2/ip", "/config/ip");
1841 copydir("/config2/settings", "/config/settings");
1846 /* we're not going to use a ram block disk */
1847 free(ramblockdevice
);
1851 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1852 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1853 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1855 logAllToSerial
= boolParam("logserial");
1857 // We need the network & web server in case there is something wrong with
1858 // the config files that invoke exit()
1859 zylinjtag_startNetwork();
1861 /* we're going to access the jim interpreter from here on... */
1862 openocd_sleep_postlude();
1867 /* initialize commandline interface */
1868 command_context_t
*cmd_ctx
;
1869 cmd_ctx
= setup_command_handler();
1870 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1871 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1874 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1875 COMMAND_EXEC
, "show zy1000 version numbers");
1877 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1880 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1881 "same args as load_image, image stored in memory");
1883 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1884 "loads active fast load image to current target");
1886 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1887 "display file content");
1889 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1890 "truncate a file to 0 size");
1892 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1893 COMMAND_ANY
, "append a variable number of strings to a file");
1895 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1896 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1898 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1899 COMMAND_ANY
, "display available ram memory");
1901 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1902 COMMAND_ANY
, "copy a file <from> <to>");
1904 #ifdef CYGPKG_PROFILE_GPROF
1905 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1908 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1909 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1913 errVal
= log_init(cmd_ctx
);
1914 if (errVal
!= ERROR_OK
)
1916 diag_printf("log_init() failed %d\n", errVal
);
1920 set_log_output(cmd_ctx
, log
);
1922 LOG_DEBUG("log init complete");
1924 // diag_printf("Executing config files\n");
1928 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1929 command_run_line(cmd_ctx
, "debug_level 3");
1932 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1935 // diag_printf() is really invoked from many more places than we trust it
1936 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1938 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1939 // fingers that it doesn't cause any crashes.
1940 diag_printf("Init complete, GDB & telnet servers launched.\n");
1941 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1942 if (!logAllToSerial
)
1947 /* handle network connections */
1948 server_loop(cmd_ctx
);
1949 openocd_sleep_prelude();
1951 /* shut server down */
1954 /* free commandline interface */
1955 command_done(cmd_ctx
);
1965 cyg_httpd_exec_cgi_tcl(char *file_name
);
1966 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1968 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1972 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1974 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1975 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1977 #include <pkgconf/system.h>
1978 #include <pkgconf/hal.h>
1979 #include <pkgconf/kernel.h>
1980 #include <pkgconf/io_fileio.h>
1981 #include <pkgconf/fs_rom.h>
1983 #include <cyg/kernel/ktypes.h> // base kernel types
1984 #include <cyg/infra/cyg_trac.h> // tracing macros
1985 #include <cyg/infra/cyg_ass.h> // assertion macros
1987 #include <sys/types.h>
1989 #include <sys/stat.h>
1998 #include <cyg/fileio/fileio.h>
2000 #include <cyg/kernel/kapi.h>
2001 #include <cyg/infra/diag.h>
2003 //==========================================================================
2004 // Eventually we want to eXecute In Place from the ROM in a protected
2005 // environment, so we'll need executables to be aligned to a boundary
2006 // suitable for MMU protection. A suitable boundary would be the 4k
2007 // boundary in all the CPU architectures I am currently aware of.
2009 // Forward definitions
2011 // Filesystem operations
2012 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2013 static int tftpfs_umount(cyg_mtab_entry
*mte
);
2014 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2015 int mode
, cyg_file
*fte
);
2016 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2017 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2020 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2021 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
2022 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
2024 //==========================================================================
2025 // Filesystem table entries
2027 // -------------------------------------------------------------------------
2029 // This defines the entry in the filesystem table.
2030 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2031 // we should never block in any filesystem operations.
2033 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
2038 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2039 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2040 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2041 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2042 (cyg_fsop_link
*)cyg_fileio_erofs
,
2043 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2044 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2045 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2046 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2047 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2050 // -------------------------------------------------------------------------
2052 // This defines a single ROMFS loaded into ROM at the configured address
2054 // MTAB_ENTRY( rom_mte, // structure name
2055 // "/rom", // mount point
2056 // "romfs", // FIlesystem type
2057 // "", // hardware device
2058 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2062 // -------------------------------------------------------------------------
2064 // This set of file operations are used for normal open files.
2066 static cyg_fileops tftpfs_fileops
=
2071 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2075 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2076 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2077 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2080 // -------------------------------------------------------------------------
2082 // Process a mount request. This mainly finds root for the
2085 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2090 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2105 static void freeTftp(struct Tftp
*t
)
2118 static const int tftpMaxSize
= 8192 * 1024;
2119 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2120 int mode
, cyg_file
*file
)
2123 tftp
= malloc(sizeof(struct Tftp
));
2126 memset(tftp
, 0, sizeof(struct Tftp
));
2128 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2129 file
->f_type
= CYG_FILE_TYPE_FILE
;
2130 file
->f_ops
= &tftpfs_fileops
;
2135 tftp
->mem
= malloc(tftpMaxSize
);
2136 if (tftp
->mem
== NULL
)
2142 char *server
= strchr(name
, '/');
2149 tftp
->server
= malloc(server
- name
+ 1);
2150 if (tftp
->server
== NULL
)
2155 strncpy(tftp
->server
, name
, server
- name
);
2156 tftp
->server
[server
- name
] = 0;
2158 tftp
->file
= strdup(server
+ 1);
2159 if (tftp
->file
== NULL
)
2165 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2170 static int fetchTftp(struct Tftp
*tftp
)
2172 if (!tftp
->readFile
)
2175 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2177 if (tftp
->actual
< 0)
2186 // -------------------------------------------------------------------------
2187 // tftpfs_fo_write()
2188 // Read data from file.
2191 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2193 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2195 if (fetchTftp(tftp
) != ENOERR
)
2199 off_t pos
= fp
->f_offset
;
2201 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2203 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2204 char *buf
= (char *) iov
->iov_base
;
2205 off_t len
= iov
->iov_len
;
2207 if (len
+ pos
> tftp
->actual
)
2209 len
= tftp
->actual
- pos
;
2211 resid
+= iov
->iov_len
- len
;
2213 memcpy(buf
, tftp
->mem
+ pos
, len
);
2217 uio
->uio_resid
= resid
;
2225 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2227 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2230 off_t pos
= fp
->f_offset
;
2232 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2234 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2235 char *buf
= (char *) iov
->iov_base
;
2236 off_t len
= iov
->iov_len
;
2238 if (len
+ pos
> tftpMaxSize
)
2240 len
= tftpMaxSize
- pos
;
2242 resid
+= iov
->iov_len
- len
;
2244 memcpy(tftp
->mem
+ pos
, buf
, len
);
2248 uio
->uio_resid
= resid
;
2257 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2263 // -------------------------------------------------------------------------
2265 // Close a file. We just clear out the data pointer.
2267 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2269 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2274 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2282 // -------------------------------------------------------------------------
2284 // Seek to a new file position.
2286 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2288 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2291 if (fetchTftp(tftp
) != ENOERR
)
2297 // Pos is already where we want to be.
2301 // Add pos to current offset.
2302 pos
+= fp
->f_offset
;
2306 // Add pos to file size.
2307 pos
+= tftp
->actual
;
2314 // Check that pos is still within current file size, or at the
2316 if (pos
< 0 || pos
> tftp
->actual
)
2319 // All OK, set fp offset and return new position.
2320 *apos
= fp
->f_offset
= pos
;
2328 cyg_thread_delay(us
/ 10000 + 1);
2335 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2337 cyg_httpd_start_chunked("text");
2338 if (logCount
>= logSize
)
2340 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2342 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2343 cyg_httpd_end_chunked();
2347 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2349 // Filesystem operations
2350 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2351 static int logfs_umount(cyg_mtab_entry
*mte
);
2352 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2353 int mode
, cyg_file
*fte
);
2355 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2358 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2359 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2361 #include <cyg/io/devtab.h>
2363 //==========================================================================
2364 // Filesystem table entries
2366 // -------------------------------------------------------------------------
2368 // This defines the entry in the filesystem table.
2369 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2370 // we should never block in any filesystem operations.
2371 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2372 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2376 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2377 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2378 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2379 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2380 (cyg_fsop_link
*)cyg_fileio_erofs
,
2381 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2382 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2383 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2384 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2385 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2387 // -------------------------------------------------------------------------
2389 // This set of file operations are used for normal open files.
2391 static cyg_fileops logfs_fileops
=
2393 (cyg_fileop_read
*)cyg_fileio_erofs
,
2394 (cyg_fileop_write
*)logfs_fo_write
,
2395 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2396 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2400 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2401 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2402 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2405 // -------------------------------------------------------------------------
2407 // Process a mount request. This mainly finds root for the
2410 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2415 static int logfs_umount(cyg_mtab_entry
*mte
)
2420 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2421 int mode
, cyg_file
*file
)
2423 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2424 file
->f_type
= CYG_FILE_TYPE_FILE
;
2425 file
->f_ops
= &logfs_fileops
;
2432 // -------------------------------------------------------------------------
2434 // Write data to file.
2437 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2440 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2442 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2443 char *buf
= (char *) iov
->iov_base
;
2444 off_t len
= iov
->iov_len
;
2446 diag_write(buf
, len
);
2453 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2458 // -------------------------------------------------------------------------
2460 // Close a file. We just clear out the data pointer.
2462 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
)
2468 ramiodev_init( struct cyg_devtab_entry
*tab
)
2474 ramiodev_bread( cyg_io_handle_t handle
, void *buf
, cyg_uint32
*len
,
2477 if (*len
+pos
>ramblockdevice_size
)
2479 *len
=ramblockdevice_size
-pos
;
2481 memcpy(buf
, ramblockdevice
+pos
, *len
);
2486 ramiodev_bwrite( cyg_io_handle_t handle
, const void *buf
, cyg_uint32
*len
,
2489 if (((pos
%4)!=0)||(((*len
)%4)!=0))
2491 diag_printf("Unaligned write %d %d!", pos
, *len
);
2494 memcpy(ramblockdevice
+pos
, buf
, *len
);
2499 ramiodev_get_config( cyg_io_handle_t handle
,
2505 case CYG_IO_GET_CONFIG_FLASH_ERASE
:
2507 if ( *len
!= sizeof( cyg_io_flash_getconfig_erase_t
) )
2510 cyg_io_flash_getconfig_erase_t
*e
= (cyg_io_flash_getconfig_erase_t
*)buf
;
2511 char *startpos
= ramblockdevice
+ e
->offset
;
2513 if (((e
->offset
%(64*1024))!=0)||((e
->len
%(64*1024))!=0))
2515 diag_printf("Erease is not aligned %d %d\n", e
->offset
, e
->len
);
2518 memset(startpos
, 0xff, e
->len
);
2524 case CYG_IO_GET_CONFIG_FLASH_DEVSIZE
:
2526 if ( *len
!= sizeof( cyg_io_flash_getconfig_devsize_t
) )
2529 cyg_io_flash_getconfig_devsize_t
*d
=
2530 (cyg_io_flash_getconfig_devsize_t
*)buf
;
2532 d
->dev_size
= ramblockdevice_size
;
2537 case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE
:
2539 cyg_io_flash_getconfig_blocksize_t
*b
=
2540 (cyg_io_flash_getconfig_blocksize_t
*)buf
;
2541 if ( *len
!= sizeof( cyg_io_flash_getconfig_blocksize_t
) )
2544 // offset unused for now
2545 b
->block_size
= 64*1024;
2555 ramiodev_set_config( cyg_io_handle_t handle
,
2565 } // ramiodev_set_config()
2567 // get_config/set_config should be added later to provide the other flash
2568 // operations possible, like erase etc.
2570 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops
,
2574 &ramiodev_get_config
,
2575 &ramiodev_set_config
2579 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1
,
2582 &cyg_io_ramdev1_ops
,
2584 0, // No lookup required
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)