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
);
800 #ifdef CYGPKG_HAL_ZYLIN_PHI
805 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
808 static void copyfile(char *name2
, char *name1
)
816 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
818 SHOW_RESULT( open
, fd1
);
820 fd2
= open(name2
, O_RDONLY
);
822 SHOW_RESULT( open
, fd2
);
826 done
= read(fd2
, buf
, IOSIZE
);
829 SHOW_RESULT( read
, done
);
833 if( done
== 0 ) break;
835 wrote
= write(fd1
, buf
, done
);
836 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
838 if( wrote
!= done
) break;
842 if( err
< 0 ) SHOW_RESULT( close
, err
);
845 if( err
< 0 ) SHOW_RESULT( close
, err
);
848 static void copydir(char *name
, char *destdir
)
853 dirp
= opendir(destdir
);
856 mkdir(destdir
, 0777);
859 err
= closedir(dirp
);
862 dirp
= opendir(name
);
863 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
867 struct dirent
*entry
= readdir(dirp
);
872 if (strcmp(entry
->d_name
, ".") == 0)
874 if (strcmp(entry
->d_name
, "..") == 0)
879 char fullPath
[PATH_MAX
];
880 strncpy(fullPath
, name
, PATH_MAX
);
881 strcat(fullPath
, "/");
882 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
884 if (stat(fullPath
, &buf
) == -1)
886 diag_printf("unable to read status from %s", fullPath
);
889 isDir
= S_ISDIR(buf
.st_mode
) != 0;
894 // diag_printf("<INFO>: entry %14s",entry->d_name);
895 char fullname
[PATH_MAX
];
896 char fullname2
[PATH_MAX
];
898 strcpy(fullname
, name
);
899 strcat(fullname
, "/");
900 strcat(fullname
, entry
->d_name
);
902 strcpy(fullname2
, destdir
);
903 strcat(fullname2
, "/");
904 strcat(fullname2
, entry
->d_name
);
905 // diag_printf("from %s to %s\n", fullname, fullname2);
906 copyfile(fullname
, fullname2
);
908 // diag_printf("\n");
911 err
= closedir(dirp
);
912 if( err
< 0 ) SHOW_RESULT( stat
, err
);
916 MTAB_ENTRY( romfs_mte1
,
920 (CYG_ADDRWORD
) &filedata
[0] );
923 void openocd_sleep_prelude()
925 cyg_mutex_unlock(&httpstate
.jim_lock
);
928 void openocd_sleep_postlude()
930 cyg_mutex_lock(&httpstate
.jim_lock
);
934 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
936 Jim_Obj
* const *argv
)
941 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
946 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
948 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
951 return del
? JIM_OK
: JIM_ERR
;
954 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
955 Jim_Obj
* const *argv
)
957 cyg_handle_t thread
= 0;
959 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
961 /* Loop over the threads, and generate a table row for
964 while (cyg_thread_get_next(&thread
, &id
))
966 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
968 cyg_thread_info info
;
971 cyg_thread_get_info(thread
, id
, &info
);
973 if (info
.name
== NULL
)
974 info
.name
= "<no name>";
976 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
977 info
.name
, strlen(info
.name
)));
979 /* Translate the state into a string.
982 state_string
= "RUN";
983 else if (info
.state
& 0x04)
984 state_string
= "SUSP";
986 switch (info
.state
& 0x1b)
989 state_string
= "SLEEP";
992 state_string
= "CNTSLEEP";
995 state_string
= "CREATE";
998 state_string
= "EXIT";
1001 state_string
= "????";
1005 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
1006 state_string
, strlen(state_string
)));
1008 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
1009 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
1010 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
1012 Jim_ListAppendElement(interp
, threads
, threadObj
);
1014 Jim_SetResult( interp
, threads
);
1021 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
1023 Jim_Obj
* const *argv
)
1027 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1031 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
1034 dirp
= opendir(name
);
1039 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
1043 struct dirent
*entry
= NULL
;
1044 entry
= readdir(dirp
);
1048 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
1051 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
1055 Jim_SetResult(interp
, objPtr
);
1062 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
1064 Jim_Obj
* const *argv
)
1068 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1074 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1076 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
1079 if (length
< 0 && length
> (4096 * 1024))
1081 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1085 void *mem
= malloc(length
);
1089 target_t
*target
= get_current_target(cmd_ctx
);
1094 if ((address
% 4 == 0) && (count
% 4 == 0))
1100 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1106 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1107 Jim_SetResult(interp
, objPtr
);
1115 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1117 Jim_Obj
* const *argv
)
1121 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1126 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1129 int value
= *((volatile int *) address
);
1131 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1137 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1139 Jim_Obj
* const *argv
)
1143 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1148 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1151 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1154 *((volatile int *) address
) = value
;
1162 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1164 Jim_Obj
* const *argv
)
1168 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1178 if (retval
== JIM_OK
)
1180 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1191 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1193 Jim_Obj
* const *argv
)
1195 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1197 if (logCount
>= logSize
)
1199 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1201 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1203 Jim_SetResult(interp
, tclOutput
);
1208 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1210 Jim_Obj
* const *argv
)
1217 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1219 Jim_Obj
* const *argv
)
1222 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1224 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1226 Jim_SetResult(interp
, tclOutput
);
1232 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1234 Jim_Obj
* const *argv
)
1236 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1238 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1240 if (getifaddrs(&ifp
) < 0)
1245 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1250 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1251 salen
= sizeof(struct sockaddr_in
);
1252 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1253 salen
= sizeof(struct sockaddr_in6
);
1257 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1258 NI_NUMERICHOST
) < 0)
1263 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1270 Jim_SetResult(interp
, tclOutput
);
1275 extern Jim_Interp
*interp
;
1278 static void zylinjtag_startNetwork()
1280 // Bring TCP/IP up immediately before we're ready to accept commands.
1282 // That is as soon as a PING responds, we're accepting telnet sessions.
1283 #if defined(CYGPKG_NET_FREEBSD_STACK)
1284 phi_init_all_network_interfaces();
1290 diag_printf("Network not up and running\n");
1293 #if defined(CYGPKG_NET_FREEBSD_STACK)
1295 tftpd_start(69, &fileops
);
1298 cyg_httpd_init_tcl_interpreter();
1300 interp
= httpstate
.jim_interp
;
1302 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1303 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1304 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1305 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1306 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1307 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1308 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1309 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1310 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1311 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1312 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1318 diag_printf("Web server running\n");
1322 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1325 strcpy(ifr
.ifr_name
, "eth0");
1327 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1332 diag_printf("Can't obtain MAC address\n");
1337 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1338 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1339 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1340 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1341 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1342 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1343 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1346 discover_message
=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr
);
1356 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1360 char *infoStr
= "unknown";
1363 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1364 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1365 infoStr
= "undefined instruction";
1367 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1368 infoStr
= "software interrupt";
1370 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1371 infoStr
= "abort prefetch";
1373 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1374 infoStr
= "abort data";
1381 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1383 diag_printf("Dumping log\n---\n");
1384 if (logCount
>= logSize
)
1386 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1388 diag_write(logBuffer
, writePtr
);
1390 diag_printf("---\nLogdump complete.\n");
1391 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1392 diag_printf("\n---\nRebooting\n");
1393 HAL_PLATFORM_RESET();
1397 static void setHandler(cyg_code_t exception
)
1399 cyg_exception_handler_t
*old_handler
;
1400 cyg_addrword_t old_data
;
1402 cyg_exception_set_handler(exception
,
1403 print_exception_handler
,
1409 static cyg_thread zylinjtag_uart_thread_object
;
1410 static cyg_handle_t zylinjtag_uart_thread_handle
;
1411 static char uart_stack
[4096];
1413 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1414 static char backwardBuffer
[1024];
1416 static cyg_io_handle_t serial_handle
;
1418 void setNoDelay(int session
, int flag
)
1421 // This decreases latency dramatically for e.g. GDB load which
1422 // does not have a sliding window protocol
1424 // Can cause *lots* of TCP/IP packets to be sent and it would have
1425 // to be enabled/disabled on the fly to avoid the CPU being
1427 setsockopt(session
, /* socket affected */
1428 IPPROTO_TCP
, /* set option at TCP level */
1429 TCP_NODELAY
, /* name of option */
1430 (char *) &flag
, /* the cast is historical
1432 sizeof(int)); /* length of option value */
1442 } tcpipSent
[512 * 1024];
1446 zylinjtag_uart(cyg_addrword_t data
)
1448 int so_reuseaddr_option
= 1;
1451 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1453 LOG_ERROR("error creating socket: %s", strerror(errno
));
1457 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1459 struct sockaddr_in sin
;
1460 unsigned int address_size
;
1461 address_size
= sizeof(sin
);
1462 memset(&sin
, 0, sizeof(sin
));
1463 sin
.sin_family
= AF_INET
;
1464 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1465 sin
.sin_port
= htons(5555);
1467 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1469 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1473 if (listen(fd
, 1) == -1)
1475 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1478 // socket_nonblock(fd);
1483 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1489 setNoDelay(session
, 1);
1490 int oldopts
= fcntl(session
, F_GETFL
, 0);
1491 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1493 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1500 #ifdef CYGPKG_PROFILE_GPROF
1513 FD_ZERO(&write_fds
);
1516 FD_SET(session
, &read_fds
);
1518 FD_SET(serHandle
, &read_fds
);
1519 if (serHandle
> fd_max
)
1525 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1526 if ((actual
== 0) && (actual2
== 0))
1528 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1537 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1538 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1541 if (errno
!= EAGAIN
)
1554 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1562 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1564 // NB! Here it is important that we empty the TCP/IP read buffer
1565 // to make transmission tick right
1566 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1569 // this will block if there is no data at all
1570 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1582 /* Do not put things into the serial buffer if it has something to send
1583 * as that can cause a single byte to be sent at the time.
1587 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1590 if (errno
!= EAGAIN
)
1594 // The serial buffer is full
1605 tcpipSent
[cur
].req
= x
;
1606 tcpipSent
[cur
].actual
= y
;
1607 tcpipSent
[cur
].req2
= x2
;
1608 tcpipSent
[cur
].actual2
= y2
;
1618 for (i
= 0; i
< 1024; i
++)
1620 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1628 void startUart(void)
1630 cyg_thread_create(1,
1636 &zylinjtag_uart_thread_handle
,
1637 &zylinjtag_uart_thread_object
);
1638 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1639 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1644 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1646 static int current_baud
= 38400;
1649 command_print(cmd_ctx
, "%d", current_baud
);
1651 } else if (argc
!= 1)
1653 return ERROR_INVALID_ARGUMENTS
;
1656 current_baud
= atol(args
[0]);
1659 switch (current_baud
)
1662 baud
= CYGNUM_SERIAL_BAUD_9600
;
1665 baud
= CYGNUM_SERIAL_BAUD_19200
;
1668 baud
= CYGNUM_SERIAL_BAUD_38400
;
1671 baud
= CYGNUM_SERIAL_BAUD_57600
;
1674 baud
= CYGNUM_SERIAL_BAUD_115200
;
1677 baud
= CYGNUM_SERIAL_BAUD_230400
;
1680 command_print(cmd_ctx
, "unsupported baudrate");
1681 return ERROR_INVALID_ARGUMENTS
;
1684 cyg_serial_info_t buf
;
1686 //get existing serial configuration
1687 len
= sizeof(cyg_serial_info_t
);
1689 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1690 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1693 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1698 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1701 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1708 bool logAllToSerial
= false;
1710 /* boolean parameter stored on config */
1711 bool boolParam(char *var
)
1713 bool result
= false;
1714 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1720 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1724 result
= strncmp((char *) data
, "1", len
) == 0;
1731 command_context_t
*setup_command_handler();
1733 int add_default_dirs(void)
1735 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1736 add_script_search_dir("/rom/lib/openocd");
1737 add_script_search_dir("/rom");
1741 static cyg_uint8
*ramblockdevice
;
1742 static const int ramblockdevice_size
=4096*1024;
1743 int main(int argc
, char *argv
[])
1745 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1746 * need to allocate towards the end of the heap. */
1748 ramblockdevice
=(cyg_uint8
*)malloc(ramblockdevice_size
);
1749 memset(ramblockdevice
, 0xff, ramblockdevice_size
);
1751 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1752 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1753 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1754 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1758 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1761 diag_printf("/dev/ser0 not found\n");
1765 setPower(true); // on by default
1767 atexit(keep_webserver
);
1769 err
= mount("", "/ram", "ramfs");
1772 diag_printf("unable to mount ramfs\n");
1777 sprintf(address
, "%p", &filedata
[0]);
1778 err
= mount(address
, "/rom", "romfs");
1781 diag_printf("unable to mount /rom\n");
1784 err
= mount("", "/log", "logfs");
1787 diag_printf("unable to mount logfs\n");
1790 err
= mount("", "/tftp", "tftpfs");
1793 diag_printf("unable to mount logfs\n");
1796 log
= fopen("/log/log", "w");
1799 diag_printf("Could not open log file /ram/log\n");
1803 diag_init_putc(_zylinjtag_diag_write_char
);
1805 // We want this in the log.
1806 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1807 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1809 copydir("/rom", "/ram/cgi");
1811 err
= mount("/dev/flash1", "/config", "jffs2");
1814 diag_printf("unable to mount jffs\n");
1818 /* are we using a ram disk instead of a flash disk? This is used
1819 * for ZY1000 live demo...
1821 * copy over flash disk to ram block device
1823 if (boolParam("ramdisk"))
1825 diag_printf("Unmounting /config from flash and using ram instead\n");
1826 err
=umount("/config");
1829 diag_printf("unable to unmount jffs\n");
1833 err
= mount("/dev/flash1", "/config2", "jffs2");
1836 diag_printf("unable to mount jffs\n");
1840 err
= mount("/dev/ram", "/config", "jffs2");
1843 diag_printf("unable to mount ram block device\n");
1847 // copydir("/config2", "/config");
1848 copyfile("/config2/ip", "/config/ip");
1849 copydir("/config2/settings", "/config/settings");
1854 /* we're not going to use a ram block disk */
1855 free(ramblockdevice
);
1859 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1860 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1861 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1863 logAllToSerial
= boolParam("logserial");
1865 // We need the network & web server in case there is something wrong with
1866 // the config files that invoke exit()
1867 zylinjtag_startNetwork();
1869 /* we're going to access the jim interpreter from here on... */
1870 openocd_sleep_postlude();
1875 /* initialize commandline interface */
1876 command_context_t
*cmd_ctx
;
1877 cmd_ctx
= setup_command_handler();
1878 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1879 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1882 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1883 COMMAND_EXEC
, "show zy1000 version numbers");
1885 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1888 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1889 "same args as load_image, image stored in memory");
1891 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1892 "loads active fast load image to current target");
1894 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1895 "display file content");
1897 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1898 "truncate a file to 0 size");
1900 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1901 COMMAND_ANY
, "append a variable number of strings to a file");
1903 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1904 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1906 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1907 COMMAND_ANY
, "display available ram memory");
1909 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1910 COMMAND_ANY
, "copy a file <from> <to>");
1912 #ifdef CYGPKG_PROFILE_GPROF
1913 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1916 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1917 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1921 errVal
= log_init(cmd_ctx
);
1922 if (errVal
!= ERROR_OK
)
1924 diag_printf("log_init() failed %d\n", errVal
);
1928 set_log_output(cmd_ctx
, log
);
1930 LOG_DEBUG("log init complete");
1932 // diag_printf("Executing config files\n");
1936 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1937 command_run_line(cmd_ctx
, "debug_level 3");
1940 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1943 // diag_printf() is really invoked from many more places than we trust it
1944 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1946 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1947 // fingers that it doesn't cause any crashes.
1948 diag_printf("Init complete, GDB & telnet servers launched.\n");
1949 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1950 if (!logAllToSerial
)
1955 /* handle network connections */
1956 server_loop(cmd_ctx
);
1957 openocd_sleep_prelude();
1959 /* shut server down */
1962 /* free commandline interface */
1963 command_done(cmd_ctx
);
1973 cyg_httpd_exec_cgi_tcl(char *file_name
);
1974 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1976 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1980 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1982 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1983 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1985 #include <pkgconf/system.h>
1986 #include <pkgconf/hal.h>
1987 #include <pkgconf/kernel.h>
1988 #include <pkgconf/io_fileio.h>
1989 #include <pkgconf/fs_rom.h>
1991 #include <cyg/kernel/ktypes.h> // base kernel types
1992 #include <cyg/infra/cyg_trac.h> // tracing macros
1993 #include <cyg/infra/cyg_ass.h> // assertion macros
1995 #include <sys/types.h>
1997 #include <sys/stat.h>
2006 #include <cyg/fileio/fileio.h>
2008 #include <cyg/kernel/kapi.h>
2009 #include <cyg/infra/diag.h>
2011 //==========================================================================
2012 // Eventually we want to eXecute In Place from the ROM in a protected
2013 // environment, so we'll need executables to be aligned to a boundary
2014 // suitable for MMU protection. A suitable boundary would be the 4k
2015 // boundary in all the CPU architectures I am currently aware of.
2017 // Forward definitions
2019 // Filesystem operations
2020 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2021 static int tftpfs_umount(cyg_mtab_entry
*mte
);
2022 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2023 int mode
, cyg_file
*fte
);
2024 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2025 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2028 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2029 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
2030 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
2032 //==========================================================================
2033 // Filesystem table entries
2035 // -------------------------------------------------------------------------
2037 // This defines the entry in the filesystem table.
2038 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2039 // we should never block in any filesystem operations.
2041 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
2046 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2047 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2048 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2049 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2050 (cyg_fsop_link
*)cyg_fileio_erofs
,
2051 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2052 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2053 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2054 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2055 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2058 // -------------------------------------------------------------------------
2060 // This defines a single ROMFS loaded into ROM at the configured address
2062 // MTAB_ENTRY( rom_mte, // structure name
2063 // "/rom", // mount point
2064 // "romfs", // FIlesystem type
2065 // "", // hardware device
2066 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2070 // -------------------------------------------------------------------------
2072 // This set of file operations are used for normal open files.
2074 static cyg_fileops tftpfs_fileops
=
2079 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2083 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2084 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2085 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2088 // -------------------------------------------------------------------------
2090 // Process a mount request. This mainly finds root for the
2093 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2098 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2113 static void freeTftp(struct Tftp
*t
)
2126 static const int tftpMaxSize
= 8192 * 1024;
2127 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2128 int mode
, cyg_file
*file
)
2131 tftp
= malloc(sizeof(struct Tftp
));
2134 memset(tftp
, 0, sizeof(struct Tftp
));
2136 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2137 file
->f_type
= CYG_FILE_TYPE_FILE
;
2138 file
->f_ops
= &tftpfs_fileops
;
2143 tftp
->mem
= malloc(tftpMaxSize
);
2144 if (tftp
->mem
== NULL
)
2150 char *server
= strchr(name
, '/');
2157 tftp
->server
= malloc(server
- name
+ 1);
2158 if (tftp
->server
== NULL
)
2163 strncpy(tftp
->server
, name
, server
- name
);
2164 tftp
->server
[server
- name
] = 0;
2166 tftp
->file
= strdup(server
+ 1);
2167 if (tftp
->file
== NULL
)
2173 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2178 static int fetchTftp(struct Tftp
*tftp
)
2180 if (!tftp
->readFile
)
2183 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2185 if (tftp
->actual
< 0)
2194 // -------------------------------------------------------------------------
2195 // tftpfs_fo_write()
2196 // Read data from file.
2199 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2201 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2203 if (fetchTftp(tftp
) != ENOERR
)
2207 off_t pos
= fp
->f_offset
;
2209 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2211 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2212 char *buf
= (char *) iov
->iov_base
;
2213 off_t len
= iov
->iov_len
;
2215 if (len
+ pos
> tftp
->actual
)
2217 len
= tftp
->actual
- pos
;
2219 resid
+= iov
->iov_len
- len
;
2221 memcpy(buf
, tftp
->mem
+ pos
, len
);
2225 uio
->uio_resid
= resid
;
2233 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2235 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2238 off_t pos
= fp
->f_offset
;
2240 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2242 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2243 char *buf
= (char *) iov
->iov_base
;
2244 off_t len
= iov
->iov_len
;
2246 if (len
+ pos
> tftpMaxSize
)
2248 len
= tftpMaxSize
- pos
;
2250 resid
+= iov
->iov_len
- len
;
2252 memcpy(tftp
->mem
+ pos
, buf
, len
);
2256 uio
->uio_resid
= resid
;
2265 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2271 // -------------------------------------------------------------------------
2273 // Close a file. We just clear out the data pointer.
2275 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2277 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2282 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2290 // -------------------------------------------------------------------------
2292 // Seek to a new file position.
2294 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2296 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2299 if (fetchTftp(tftp
) != ENOERR
)
2305 // Pos is already where we want to be.
2309 // Add pos to current offset.
2310 pos
+= fp
->f_offset
;
2314 // Add pos to file size.
2315 pos
+= tftp
->actual
;
2322 // Check that pos is still within current file size, or at the
2324 if (pos
< 0 || pos
> tftp
->actual
)
2327 // All OK, set fp offset and return new position.
2328 *apos
= fp
->f_offset
= pos
;
2336 cyg_thread_delay(us
/ 10000 + 1);
2343 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2345 cyg_httpd_start_chunked("text");
2346 if (logCount
>= logSize
)
2348 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2350 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2351 cyg_httpd_end_chunked();
2355 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2357 // Filesystem operations
2358 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2359 static int logfs_umount(cyg_mtab_entry
*mte
);
2360 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2361 int mode
, cyg_file
*fte
);
2363 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2366 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2367 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2369 #include <cyg/io/devtab.h>
2371 //==========================================================================
2372 // Filesystem table entries
2374 // -------------------------------------------------------------------------
2376 // This defines the entry in the filesystem table.
2377 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2378 // we should never block in any filesystem operations.
2379 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2380 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2384 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2385 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2386 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2387 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2388 (cyg_fsop_link
*)cyg_fileio_erofs
,
2389 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2390 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2391 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2392 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2393 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2395 // -------------------------------------------------------------------------
2397 // This set of file operations are used for normal open files.
2399 static cyg_fileops logfs_fileops
=
2401 (cyg_fileop_read
*)cyg_fileio_erofs
,
2402 (cyg_fileop_write
*)logfs_fo_write
,
2403 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2404 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2408 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2409 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2410 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2413 // -------------------------------------------------------------------------
2415 // Process a mount request. This mainly finds root for the
2418 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2423 static int logfs_umount(cyg_mtab_entry
*mte
)
2428 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2429 int mode
, cyg_file
*file
)
2431 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2432 file
->f_type
= CYG_FILE_TYPE_FILE
;
2433 file
->f_ops
= &logfs_fileops
;
2440 // -------------------------------------------------------------------------
2442 // Write data to file.
2445 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2448 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2450 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2451 char *buf
= (char *) iov
->iov_base
;
2452 off_t len
= iov
->iov_len
;
2454 diag_write(buf
, len
);
2461 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2466 // -------------------------------------------------------------------------
2468 // Close a file. We just clear out the data pointer.
2470 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
)
2476 ramiodev_init( struct cyg_devtab_entry
*tab
)
2482 ramiodev_bread( cyg_io_handle_t handle
, void *buf
, cyg_uint32
*len
,
2485 if (*len
+pos
>ramblockdevice_size
)
2487 *len
=ramblockdevice_size
-pos
;
2489 memcpy(buf
, ramblockdevice
+pos
, *len
);
2494 ramiodev_bwrite( cyg_io_handle_t handle
, const void *buf
, cyg_uint32
*len
,
2497 if (((pos
%4)!=0)||(((*len
)%4)!=0))
2499 diag_printf("Unaligned write %d %d!", pos
, *len
);
2502 memcpy(ramblockdevice
+pos
, buf
, *len
);
2507 ramiodev_get_config( cyg_io_handle_t handle
,
2513 case CYG_IO_GET_CONFIG_FLASH_ERASE
:
2515 if ( *len
!= sizeof( cyg_io_flash_getconfig_erase_t
) )
2518 cyg_io_flash_getconfig_erase_t
*e
= (cyg_io_flash_getconfig_erase_t
*)buf
;
2519 char *startpos
= ramblockdevice
+ e
->offset
;
2521 if (((e
->offset
%(64*1024))!=0)||((e
->len
%(64*1024))!=0))
2523 diag_printf("Erease is not aligned %d %d\n", e
->offset
, e
->len
);
2526 memset(startpos
, 0xff, e
->len
);
2532 case CYG_IO_GET_CONFIG_FLASH_DEVSIZE
:
2534 if ( *len
!= sizeof( cyg_io_flash_getconfig_devsize_t
) )
2537 cyg_io_flash_getconfig_devsize_t
*d
=
2538 (cyg_io_flash_getconfig_devsize_t
*)buf
;
2540 d
->dev_size
= ramblockdevice_size
;
2545 case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE
:
2547 cyg_io_flash_getconfig_blocksize_t
*b
=
2548 (cyg_io_flash_getconfig_blocksize_t
*)buf
;
2549 if ( *len
!= sizeof( cyg_io_flash_getconfig_blocksize_t
) )
2552 // offset unused for now
2553 b
->block_size
= 64*1024;
2563 ramiodev_set_config( cyg_io_handle_t handle
,
2573 } // ramiodev_set_config()
2575 // get_config/set_config should be added later to provide the other flash
2576 // operations possible, like erase etc.
2578 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops
,
2582 &ramiodev_get_config
,
2583 &ramiodev_set_config
2587 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1
,
2590 &cyg_io_ramdev1_ops
,
2592 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)