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
;
348 extern flash_driver_t
*flash_drivers
[];
349 extern target_type_t
*target_types
[];
351 #ifdef CYGPKG_PROFILE_GPROF
352 #include <cyg/profile/profile.h>
354 extern char _stext
, _etext
; // Defined by the linker
356 void start_profile(void)
358 // This starts up the system-wide profiling, gathering
359 // profile information on all of the code, with a 16 byte
360 // "bucket" size, at a rate of 100us/profile hit.
361 // Note: a bucket size of 16 will give pretty good function
362 // resolution. Much smaller and the buffer becomes
363 // much too large for very little gain.
364 // Note: a timer period of 100us is also a reasonable
365 // compromise. Any smaller and the overhead of
366 // handling the timter (profile) interrupt could
367 // swamp the system. A fast processor might get
368 // by with a smaller value, but a slow one could
369 // even be swamped by this value. If the value is
370 // too large, the usefulness of the profile is reduced.
372 // no more interrupts than 1/10ms.
373 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
374 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
375 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
379 // launch GDB server if a config file exists
380 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
382 bool foundFile
= false;
383 FILE *config_file
= NULL
;
384 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
385 config_file
= fopen(config_file_name
, "r");
390 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
391 if (retval
== ERROR_OK
)
397 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
402 command_print(cmd_ctx
, "No %s found", config_file_name
);
411 static char reboot_stack
[2048];
415 zylinjtag_reboot(cyg_addrword_t data
)
418 diag_printf("Rebooting in 100 ticks..\n");
419 cyg_thread_delay(100);
420 diag_printf("Unmounting /config..\n");
422 diag_printf("Rebooting..\n");
423 HAL_PLATFORM_RESET();
425 static cyg_thread zylinjtag_thread_object
;
426 static cyg_handle_t zylinjtag_thread_handle
;
434 (void *)reboot_stack
,
435 sizeof(reboot_stack
),
436 &zylinjtag_thread_handle
,
437 &zylinjtag_thread_object
);
438 cyg_thread_resume(zylinjtag_thread_handle
);
441 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
443 diag_printf("%s", line
);
448 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
450 LOG_USER_N("%s", line
);
455 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
456 char **args
, int argc
)
460 command_print(cmd_ctx
, "rm <filename>");
461 return ERROR_INVALID_ARGUMENTS
;
464 if (unlink(args
[0]) != 0)
466 command_print(cmd_ctx
, "failed: %d", errno
);
472 int loadFile(const char *fileName
, void **data
, int *len
);
474 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
475 char **args
, int argc
)
479 command_print(cmd_ctx
, "cat <filename>");
480 return ERROR_INVALID_ARGUMENTS
;
483 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
487 int retval
= loadFile(args
[0], &data
, &len
);
488 if (retval
== ERROR_OK
)
490 command_print(cmd_ctx
, "%s", data
);
495 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
500 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
501 char **args
, int argc
)
505 command_print(cmd_ctx
, "trunc <filename>");
506 return ERROR_INVALID_ARGUMENTS
;
509 FILE *config_file
= NULL
;
510 config_file
= fopen(args
[0], "w");
511 if (config_file
!= NULL
)
518 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
521 struct mallinfo info
;
525 command_print(cmd_ctx
, "meminfo");
526 return ERROR_INVALID_ARGUMENTS
;
533 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
535 prev
= info
.fordblks
;
537 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
542 static bool savePower
;
544 static void setPower(bool power
)
549 HAL_WRITE_UINT32(ZY1000_JTAG_BASE
+0x14, 0x8);
552 HAL_WRITE_UINT32(ZY1000_JTAG_BASE
+0x10, 0x8);
556 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
560 return ERROR_INVALID_ARGUMENTS
;
565 if (strcmp(args
[0], "on") == 0)
569 else if (strcmp(args
[0], "off") == 0)
574 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
575 return ERROR_INVALID_ARGUMENTS
;
579 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
584 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
585 char **args
, int argc
)
589 command_print(cmd_ctx
,
590 "append <filename> [<string1>, [<string2>, ...]]");
591 return ERROR_INVALID_ARGUMENTS
;
594 FILE *config_file
= NULL
;
595 config_file
= fopen(args
[0], "a");
596 if (config_file
!= NULL
)
599 fseek(config_file
, 0, SEEK_END
);
601 for (i
= 1; i
< argc
; i
++)
603 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
606 fwrite(" ", 1, 1, config_file
);
609 fwrite("\n", 1, 1, config_file
);
616 extern int telnet_socket
;
618 int readMore(int fd
, void *data
, int length
)
620 /* used in select() */
623 /* monitor sockets for acitvity */
626 /* listen for new connections */
627 FD_SET(fd
, &read_fds
);
629 // Maximum 5 seconds.
634 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
637 diag_printf("Timed out waiting for binary payload\n");
643 return read_socket(fd
, data
, length
);
646 int readAll(int fd
, void *data
, int length
)
651 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
652 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
662 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
667 return ERROR_INVALID_ARGUMENTS
;
669 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
670 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
674 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
678 return ERROR_INVALID_ARGUMENTS
;
680 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
684 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
688 return ERROR_INVALID_ARGUMENTS
;
691 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
695 int retval
= loadFile(args
[0], &data
, &len
);
696 if (retval
!= ERROR_OK
)
699 FILE *f
= fopen(args
[1], "wb");
701 retval
= ERROR_INVALID_ARGUMENTS
;
706 int chunk
= len
- pos
;
707 static const int maxChunk
= 512 * 1024; // ~1/sec
708 if (chunk
> maxChunk
)
713 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
714 retval
= ERROR_INVALID_ARGUMENTS
;
716 if (retval
!= ERROR_OK
)
721 command_print(cmd_ctx
, "%d", len
- pos
);
729 if (retval
== ERROR_OK
)
731 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
734 command_print(cmd_ctx
, "Failed: %d", retval
);
742 if (retval
!= ERROR_OK
)
748 #ifdef CYGPKG_PROFILE_GPROF
749 extern void start_profile();
751 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
753 command_print(cmd_ctx
, "Profiling started");
760 externC
void phi_init_all_network_interfaces();
762 command_context_t
*cmd_ctx
;
764 static bool webRunning
= false;
766 void keep_webserver()
768 // Target initialisation is only attempted at startup, so we sleep forever and
769 // let the http server bail us out(i.e. get config files set up).
770 diag_printf("OpenOCD has invoked exit().\n"
771 "Use web server to correct any configuration settings and reboot.\n");
775 // exit() will terminate the current thread and we we'll then sleep eternally or
776 // we'll have a reboot scheduled.
779 extern void printDccChar(char c
);
781 static char logBuffer
[128 * 1024];
782 static const int logSize
= sizeof(logBuffer
);
786 void _zylinjtag_diag_write_char(char c
, void **param
)
790 logBuffer
[writePtr
] = c
;
791 writePtr
= (writePtr
+ 1) % logSize
;
798 HAL_DIAG_WRITE_CHAR('\r');
800 HAL_DIAG_WRITE_CHAR(c
);
803 #ifdef CYGPKG_HAL_ZYLIN_PHI
808 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
811 static void copyfile(char *name2
, char *name1
)
819 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
821 SHOW_RESULT( open
, fd1
);
823 fd2
= open(name2
, O_RDONLY
);
825 SHOW_RESULT( open
, fd2
);
829 done
= read(fd2
, buf
, IOSIZE
);
832 SHOW_RESULT( read
, done
);
836 if( done
== 0 ) break;
838 wrote
= write(fd1
, buf
, done
);
839 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
841 if( wrote
!= done
) break;
845 if( err
< 0 ) SHOW_RESULT( close
, err
);
848 if( err
< 0 ) SHOW_RESULT( close
, err
);
851 static void copydir(char *name
, char *destdir
)
856 dirp
= opendir(destdir
);
859 mkdir(destdir
, 0777);
862 err
= closedir(dirp
);
865 dirp
= opendir(name
);
866 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
870 struct dirent
*entry
= readdir(dirp
);
875 if (strcmp(entry
->d_name
, ".") == 0)
877 if (strcmp(entry
->d_name
, "..") == 0)
882 char fullPath
[PATH_MAX
];
883 strncpy(fullPath
, name
, PATH_MAX
);
884 strcat(fullPath
, "/");
885 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
887 if (stat(fullPath
, &buf
) == -1)
889 diag_printf("unable to read status from %s", fullPath
);
892 isDir
= S_ISDIR(buf
.st_mode
) != 0;
897 // diag_printf("<INFO>: entry %14s",entry->d_name);
898 char fullname
[PATH_MAX
];
899 char fullname2
[PATH_MAX
];
901 strcpy(fullname
, name
);
902 strcat(fullname
, "/");
903 strcat(fullname
, entry
->d_name
);
905 strcpy(fullname2
, destdir
);
906 strcat(fullname2
, "/");
907 strcat(fullname2
, entry
->d_name
);
908 // diag_printf("from %s to %s\n", fullname, fullname2);
909 copyfile(fullname
, fullname2
);
911 // diag_printf("\n");
914 err
= closedir(dirp
);
915 if( err
< 0 ) SHOW_RESULT( stat
, err
);
919 MTAB_ENTRY( romfs_mte1
,
923 (CYG_ADDRWORD
) &filedata
[0] );
926 void openocd_sleep_prelude()
928 cyg_mutex_unlock(&httpstate
.jim_lock
);
931 void openocd_sleep_postlude()
933 cyg_mutex_lock(&httpstate
.jim_lock
);
939 diag_printf("Formatting JFFS2...\n");
941 cyg_io_handle_t handle
;
944 err
= cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1
, &handle
);
947 diag_printf("Flash Error cyg_io_lookup: %d\n", err
);
953 cyg_io_flash_getconfig_devsize_t ds
;
955 err
= cyg_io_get_config(handle
,
956 CYG_IO_GET_CONFIG_FLASH_DEVSIZE
, &ds
, &len
);
959 diag_printf("Flash error cyg_io_get_config %d\n", err
);
963 cyg_io_flash_getconfig_erase_t e
;
969 e
.err_address
= &err_addr
;
971 diag_printf("Formatting 0x%08x bytes\n", ds
.dev_size
);
972 err
= cyg_io_get_config(handle
, CYG_IO_GET_CONFIG_FLASH_ERASE
,
976 diag_printf("Flash erase error %d offset 0x%p\n", err
, err_addr
);
980 diag_printf("Flash formatted successfully\n");
988 zylinjtag_Jim_Command_format_jffs2(Jim_Interp
*interp
,
990 Jim_Obj
* const *argv
)
1003 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
1005 Jim_Obj
* const *argv
)
1010 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
1015 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
1017 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
1020 return del
? JIM_OK
: JIM_ERR
;
1023 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
1024 Jim_Obj
* const *argv
)
1026 cyg_handle_t thread
= 0;
1028 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
1030 /* Loop over the threads, and generate a table row for
1033 while (cyg_thread_get_next(&thread
, &id
))
1035 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
1037 cyg_thread_info info
;
1040 cyg_thread_get_info(thread
, id
, &info
);
1042 if (info
.name
== NULL
)
1043 info
.name
= "<no name>";
1045 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
1046 info
.name
, strlen(info
.name
)));
1048 /* Translate the state into a string.
1050 if (info
.state
== 0)
1051 state_string
= "RUN";
1052 else if (info
.state
& 0x04)
1053 state_string
= "SUSP";
1055 switch (info
.state
& 0x1b)
1058 state_string
= "SLEEP";
1061 state_string
= "CNTSLEEP";
1064 state_string
= "CREATE";
1067 state_string
= "EXIT";
1070 state_string
= "????";
1074 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
1075 state_string
, strlen(state_string
)));
1077 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
1078 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
1079 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
1081 Jim_ListAppendElement(interp
, threads
, threadObj
);
1083 Jim_SetResult( interp
, threads
);
1090 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
1092 Jim_Obj
* const *argv
)
1096 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1100 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
1103 dirp
= opendir(name
);
1108 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
1112 struct dirent
*entry
= NULL
;
1113 entry
= readdir(dirp
);
1117 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
1120 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
1124 Jim_SetResult(interp
, objPtr
);
1131 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
1133 Jim_Obj
* const *argv
)
1137 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1143 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1145 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
1148 if (length
< 0 && length
> (4096 * 1024))
1150 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1154 void *mem
= malloc(length
);
1158 target_t
*target
= get_current_target(cmd_ctx
);
1163 if ((address
% 4 == 0) && (count
% 4 == 0))
1169 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1175 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1176 Jim_SetResult(interp
, objPtr
);
1184 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1186 Jim_Obj
* const *argv
)
1190 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1195 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1198 int value
= *((volatile int *) address
);
1200 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1206 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1208 Jim_Obj
* const *argv
)
1212 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1217 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1220 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1223 *((volatile int *) address
) = value
;
1231 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1233 Jim_Obj
* const *argv
)
1237 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1247 if (retval
== JIM_OK
)
1249 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1260 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1262 Jim_Obj
* const *argv
)
1264 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1266 if (logCount
>= logSize
)
1268 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1270 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1272 Jim_SetResult(interp
, tclOutput
);
1277 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1279 Jim_Obj
* const *argv
)
1286 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1288 Jim_Obj
* const *argv
)
1291 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1293 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1295 Jim_SetResult(interp
, tclOutput
);
1301 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1303 Jim_Obj
* const *argv
)
1305 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1307 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1309 if (getifaddrs(&ifp
) < 0)
1314 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1319 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1320 salen
= sizeof(struct sockaddr_in
);
1321 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1322 salen
= sizeof(struct sockaddr_in6
);
1326 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1327 NI_NUMERICHOST
) < 0)
1332 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1339 Jim_SetResult(interp
, tclOutput
);
1344 extern Jim_Interp
*interp
;
1347 static void zylinjtag_startNetwork()
1349 // Bring TCP/IP up immediately before we're ready to accept commands.
1351 // That is as soon as a PING responds, we're accepting telnet sessions.
1352 #if defined(CYGPKG_NET_FREEBSD_STACK)
1353 phi_init_all_network_interfaces();
1359 diag_printf("Network not up and running\n");
1362 #if defined(CYGPKG_NET_FREEBSD_STACK)
1364 tftpd_start(69, &fileops
);
1367 cyg_httpd_init_tcl_interpreter();
1369 interp
= httpstate
.jim_interp
;
1371 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1372 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1373 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1374 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1375 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1376 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1377 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1378 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1379 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1380 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1381 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1382 Jim_CreateCommand(httpstate
.jim_interp
, "format_jffs2", zylinjtag_Jim_Command_format_jffs2
, NULL
, NULL
);
1388 diag_printf("Web server running\n");
1392 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1395 strcpy(ifr
.ifr_name
, "eth0");
1397 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1402 diag_printf("Can't obtain MAC address\n");
1407 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1408 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1409 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1410 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1411 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1412 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1413 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1416 discover_message
=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr
);
1426 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1430 char *infoStr
= "unknown";
1433 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1434 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1435 infoStr
= "undefined instruction";
1437 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1438 infoStr
= "software interrupt";
1440 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1441 infoStr
= "abort prefetch";
1443 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1444 infoStr
= "abort data";
1451 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1453 diag_printf("Dumping log\n---\n");
1454 if (logCount
>= logSize
)
1456 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1458 diag_write(logBuffer
, writePtr
);
1460 diag_printf("---\nLogdump complete.\n");
1461 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1462 diag_printf("\n---\nRebooting\n");
1463 HAL_PLATFORM_RESET();
1467 static void setHandler(cyg_code_t exception
)
1469 cyg_exception_handler_t
*old_handler
;
1470 cyg_addrword_t old_data
;
1472 cyg_exception_set_handler(exception
,
1473 print_exception_handler
,
1479 static cyg_thread zylinjtag_uart_thread_object
;
1480 static cyg_handle_t zylinjtag_uart_thread_handle
;
1481 static char uart_stack
[4096];
1483 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1484 static char backwardBuffer
[1024];
1487 void setNoDelay(int session
, int flag
)
1490 // This decreases latency dramatically for e.g. GDB load which
1491 // does not have a sliding window protocol
1493 // Can cause *lots* of TCP/IP packets to be sent and it would have
1494 // to be enabled/disabled on the fly to avoid the CPU being
1496 setsockopt(session
, /* socket affected */
1497 IPPROTO_TCP
, /* set option at TCP level */
1498 TCP_NODELAY
, /* name of option */
1499 (char *) &flag
, /* the cast is historical
1501 sizeof(int)); /* length of option value */
1511 } tcpipSent
[512 * 1024];
1515 zylinjtag_uart(cyg_addrword_t data
)
1517 int so_reuseaddr_option
= 1;
1520 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1522 LOG_ERROR("error creating socket: %s", strerror(errno
));
1526 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1528 struct sockaddr_in sin
;
1529 unsigned int address_size
;
1530 address_size
= sizeof(sin
);
1531 memset(&sin
, 0, sizeof(sin
));
1532 sin
.sin_family
= AF_INET
;
1533 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1534 sin
.sin_port
= htons(5555);
1536 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1538 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1542 if (listen(fd
, 1) == -1)
1544 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1547 // socket_nonblock(fd);
1552 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1558 setNoDelay(session
, 1);
1559 int oldopts
= fcntl(session
, F_GETFL
, 0);
1560 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1562 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1569 #ifdef CYGPKG_PROFILE_GPROF
1582 FD_ZERO(&write_fds
);
1585 FD_SET(session
, &read_fds
);
1587 FD_SET(serHandle
, &read_fds
);
1588 if (serHandle
> fd_max
)
1594 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1595 if ((actual
== 0) && (actual2
== 0))
1597 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1606 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1607 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1610 if (errno
!= EAGAIN
)
1623 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1631 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1633 // NB! Here it is important that we empty the TCP/IP read buffer
1634 // to make transmission tick right
1635 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1638 // this will block if there is no data at all
1639 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1651 /* Do not put things into the serial buffer if it has something to send
1652 * as that can cause a single byte to be sent at the time.
1656 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1659 if (errno
!= EAGAIN
)
1663 // The serial buffer is full
1674 tcpipSent
[cur
].req
= x
;
1675 tcpipSent
[cur
].actual
= y
;
1676 tcpipSent
[cur
].req2
= x2
;
1677 tcpipSent
[cur
].actual2
= y2
;
1687 for (i
= 0; i
< 1024; i
++)
1689 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1697 void startUart(void)
1699 cyg_thread_create(1,
1705 &zylinjtag_uart_thread_handle
,
1706 &zylinjtag_uart_thread_object
);
1707 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1708 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1713 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1715 static int current_baud
= 38400;
1718 command_print(cmd_ctx
, "%d", current_baud
);
1720 } else if (argc
!= 1)
1722 return ERROR_INVALID_ARGUMENTS
;
1725 current_baud
= atol(args
[0]);
1728 switch (current_baud
)
1731 baud
= CYGNUM_SERIAL_BAUD_9600
;
1734 baud
= CYGNUM_SERIAL_BAUD_19200
;
1737 baud
= CYGNUM_SERIAL_BAUD_38400
;
1740 baud
= CYGNUM_SERIAL_BAUD_57600
;
1743 baud
= CYGNUM_SERIAL_BAUD_115200
;
1746 baud
= CYGNUM_SERIAL_BAUD_230400
;
1749 command_print(cmd_ctx
, "unsupported baudrate");
1750 return ERROR_INVALID_ARGUMENTS
;
1753 cyg_serial_info_t buf
;
1755 //get existing serial configuration
1756 len
= sizeof(cyg_serial_info_t
);
1758 cyg_io_handle_t serial_handle
;
1760 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1763 LOG_ERROR("/dev/ser0 not found\n");
1768 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1769 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1772 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1777 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1780 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1787 bool logAllToSerial
= false;
1789 /* boolean parameter stored on config */
1790 bool boolParam(char *var
)
1792 bool result
= false;
1793 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1799 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1803 result
= strncmp((char *) data
, "1", len
) == 0;
1810 command_context_t
*setup_command_handler();
1812 int add_default_dirs(void)
1814 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1815 add_script_search_dir("/rom/lib/openocd");
1816 add_script_search_dir("/rom");
1820 static cyg_uint8
*ramblockdevice
;
1821 static const int ramblockdevice_size
=4096*1024;
1822 int main(int argc
, char *argv
[])
1824 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1825 * need to allocate towards the end of the heap. */
1827 ramblockdevice
=(cyg_uint8
*)malloc(ramblockdevice_size
);
1828 memset(ramblockdevice
, 0xff, ramblockdevice_size
);
1832 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1833 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1834 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1835 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1840 setPower(true); // on by default
1842 atexit(keep_webserver
);
1844 err
= mount("", "/ram", "ramfs");
1847 diag_printf("unable to mount ramfs\n");
1852 sprintf(address
, "%p", &filedata
[0]);
1853 err
= mount(address
, "/rom", "romfs");
1856 diag_printf("unable to mount /rom\n");
1859 err
= mount("", "/log", "logfs");
1862 diag_printf("unable to mount logfs\n");
1865 err
= mount("", "/tftp", "tftpfs");
1868 diag_printf("unable to mount logfs\n");
1871 log
= fopen("/log/log", "w");
1874 diag_printf("Could not open log file /ram/log\n");
1878 diag_init_putc(_zylinjtag_diag_write_char
);
1880 // We want this in the log.
1881 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1882 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1884 copydir("/rom", "/ram/cgi");
1886 err
= mount("/dev/flash1", "/config", "jffs2");
1889 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1890 err
= mount("", "/config", "ramfs");
1893 diag_printf("unable to mount /config as ramdisk.\n");
1898 /* are we using a ram disk instead of a flash disk? This is used
1899 * for ZY1000 live demo...
1901 * copy over flash disk to ram block device
1903 if (boolParam("ramdisk"))
1905 diag_printf("Unmounting /config from flash and using ram instead\n");
1906 err
=umount("/config");
1909 diag_printf("unable to unmount jffs\n");
1913 err
= mount("/dev/flash1", "/config2", "jffs2");
1916 diag_printf("unable to mount jffs\n");
1920 err
= mount("/dev/ram", "/config", "jffs2");
1923 diag_printf("unable to mount ram block device\n");
1927 // copydir("/config2", "/config");
1928 copyfile("/config2/ip", "/config/ip");
1929 copydir("/config2/settings", "/config/settings");
1934 /* we're not going to use a ram block disk */
1935 free(ramblockdevice
);
1940 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1941 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1942 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1944 logAllToSerial
= boolParam("logserial");
1946 // We need the network & web server in case there is something wrong with
1947 // the config files that invoke exit()
1948 zylinjtag_startNetwork();
1950 /* we're going to access the jim interpreter from here on... */
1951 openocd_sleep_postlude();
1956 /* initialize commandline interface */
1957 command_context_t
*cmd_ctx
;
1958 cmd_ctx
= setup_command_handler();
1959 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1960 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1963 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1964 COMMAND_EXEC
, "show zy1000 version numbers");
1966 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1969 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1970 "same args as load_image, image stored in memory");
1972 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1973 "loads active fast load image to current target");
1975 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1976 "display file content");
1978 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1979 "truncate a file to 0 size");
1981 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1982 COMMAND_ANY
, "append a variable number of strings to a file");
1984 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1985 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1987 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1988 COMMAND_ANY
, "display available ram memory");
1990 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1991 COMMAND_ANY
, "copy a file <from> <to>");
1993 #ifdef CYGPKG_PROFILE_GPROF
1994 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1997 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1998 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
2002 errVal
= log_init(cmd_ctx
);
2003 if (errVal
!= ERROR_OK
)
2005 diag_printf("log_init() failed %d\n", errVal
);
2009 set_log_output(cmd_ctx
, log
);
2011 LOG_DEBUG("log init complete");
2013 // diag_printf("Executing config files\n");
2017 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
2018 command_run_line(cmd_ctx
, "debug_level 3");
2021 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
2024 // diag_printf() is really invoked from many more places than we trust it
2025 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
2027 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
2028 // fingers that it doesn't cause any crashes.
2029 diag_printf("Init complete, GDB & telnet servers launched.\n");
2030 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
2031 if (!logAllToSerial
)
2036 /* handle network connections */
2037 server_loop(cmd_ctx
);
2038 openocd_sleep_prelude();
2040 /* shut server down */
2043 /* free commandline interface */
2044 command_done(cmd_ctx
);
2054 cyg_httpd_exec_cgi_tcl(char *file_name
);
2055 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
2057 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
2061 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
2063 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
2064 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
2066 #include <pkgconf/system.h>
2067 #include <pkgconf/hal.h>
2068 #include <pkgconf/kernel.h>
2069 #include <pkgconf/io_fileio.h>
2070 #include <pkgconf/fs_rom.h>
2072 #include <cyg/kernel/ktypes.h> // base kernel types
2073 #include <cyg/infra/cyg_trac.h> // tracing macros
2074 #include <cyg/infra/cyg_ass.h> // assertion macros
2076 #include <sys/types.h>
2078 #include <sys/stat.h>
2087 #include <cyg/fileio/fileio.h>
2089 #include <cyg/kernel/kapi.h>
2090 #include <cyg/infra/diag.h>
2092 //==========================================================================
2093 // Eventually we want to eXecute In Place from the ROM in a protected
2094 // environment, so we'll need executables to be aligned to a boundary
2095 // suitable for MMU protection. A suitable boundary would be the 4k
2096 // boundary in all the CPU architectures I am currently aware of.
2098 // Forward definitions
2100 // Filesystem operations
2101 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2102 static int tftpfs_umount(cyg_mtab_entry
*mte
);
2103 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2104 int mode
, cyg_file
*fte
);
2105 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2106 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2109 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2110 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
2111 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
2113 //==========================================================================
2114 // Filesystem table entries
2116 // -------------------------------------------------------------------------
2118 // This defines the entry in the filesystem table.
2119 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2120 // we should never block in any filesystem operations.
2122 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
2127 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2128 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2129 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2130 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2131 (cyg_fsop_link
*)cyg_fileio_erofs
,
2132 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2133 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2134 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2135 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2136 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2139 // -------------------------------------------------------------------------
2141 // This defines a single ROMFS loaded into ROM at the configured address
2143 // MTAB_ENTRY( rom_mte, // structure name
2144 // "/rom", // mount point
2145 // "romfs", // FIlesystem type
2146 // "", // hardware device
2147 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2151 // -------------------------------------------------------------------------
2153 // This set of file operations are used for normal open files.
2155 static cyg_fileops tftpfs_fileops
=
2160 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2164 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2165 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2166 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2169 // -------------------------------------------------------------------------
2171 // Process a mount request. This mainly finds root for the
2174 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2179 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2194 static void freeTftp(struct Tftp
*t
)
2207 static const int tftpMaxSize
= 8192 * 1024;
2208 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2209 int mode
, cyg_file
*file
)
2212 tftp
= malloc(sizeof(struct Tftp
));
2215 memset(tftp
, 0, sizeof(struct Tftp
));
2217 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2218 file
->f_type
= CYG_FILE_TYPE_FILE
;
2219 file
->f_ops
= &tftpfs_fileops
;
2224 tftp
->mem
= malloc(tftpMaxSize
);
2225 if (tftp
->mem
== NULL
)
2231 char *server
= strchr(name
, '/');
2238 tftp
->server
= malloc(server
- name
+ 1);
2239 if (tftp
->server
== NULL
)
2244 strncpy(tftp
->server
, name
, server
- name
);
2245 tftp
->server
[server
- name
] = 0;
2247 tftp
->file
= strdup(server
+ 1);
2248 if (tftp
->file
== NULL
)
2254 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2259 static int fetchTftp(struct Tftp
*tftp
)
2261 if (!tftp
->readFile
)
2264 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2266 if (tftp
->actual
< 0)
2275 // -------------------------------------------------------------------------
2276 // tftpfs_fo_write()
2277 // Read data from file.
2280 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2282 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2284 if (fetchTftp(tftp
) != ENOERR
)
2288 off_t pos
= fp
->f_offset
;
2290 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2292 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2293 char *buf
= (char *) iov
->iov_base
;
2294 off_t len
= iov
->iov_len
;
2296 if (len
+ pos
> tftp
->actual
)
2298 len
= tftp
->actual
- pos
;
2300 resid
+= iov
->iov_len
- len
;
2302 memcpy(buf
, tftp
->mem
+ pos
, len
);
2306 uio
->uio_resid
= resid
;
2314 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2316 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2319 off_t pos
= fp
->f_offset
;
2321 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2323 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2324 char *buf
= (char *) iov
->iov_base
;
2325 off_t len
= iov
->iov_len
;
2327 if (len
+ pos
> tftpMaxSize
)
2329 len
= tftpMaxSize
- pos
;
2331 resid
+= iov
->iov_len
- len
;
2333 memcpy(tftp
->mem
+ pos
, buf
, len
);
2337 uio
->uio_resid
= resid
;
2346 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2352 // -------------------------------------------------------------------------
2354 // Close a file. We just clear out the data pointer.
2356 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2358 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2363 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2371 // -------------------------------------------------------------------------
2373 // Seek to a new file position.
2375 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2377 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2380 if (fetchTftp(tftp
) != ENOERR
)
2386 // Pos is already where we want to be.
2390 // Add pos to current offset.
2391 pos
+= fp
->f_offset
;
2395 // Add pos to file size.
2396 pos
+= tftp
->actual
;
2403 // Check that pos is still within current file size, or at the
2405 if (pos
< 0 || pos
> tftp
->actual
)
2408 // All OK, set fp offset and return new position.
2409 *apos
= fp
->f_offset
= pos
;
2417 cyg_thread_delay(us
/ 10000 + 1);
2424 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2426 cyg_httpd_start_chunked("text");
2427 if (logCount
>= logSize
)
2429 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2431 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2432 cyg_httpd_end_chunked();
2436 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2438 // Filesystem operations
2439 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2440 static int logfs_umount(cyg_mtab_entry
*mte
);
2441 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2442 int mode
, cyg_file
*fte
);
2444 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2447 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2448 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2450 #include <cyg/io/devtab.h>
2452 //==========================================================================
2453 // Filesystem table entries
2455 // -------------------------------------------------------------------------
2457 // This defines the entry in the filesystem table.
2458 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2459 // we should never block in any filesystem operations.
2460 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2461 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2465 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2466 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2467 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2468 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2469 (cyg_fsop_link
*)cyg_fileio_erofs
,
2470 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2471 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2472 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2473 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2474 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2476 // -------------------------------------------------------------------------
2478 // This set of file operations are used for normal open files.
2480 static cyg_fileops logfs_fileops
=
2482 (cyg_fileop_read
*)cyg_fileio_erofs
,
2483 (cyg_fileop_write
*)logfs_fo_write
,
2484 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2485 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2489 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2490 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2491 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2494 // -------------------------------------------------------------------------
2496 // Process a mount request. This mainly finds root for the
2499 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2504 static int logfs_umount(cyg_mtab_entry
*mte
)
2509 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2510 int mode
, cyg_file
*file
)
2512 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2513 file
->f_type
= CYG_FILE_TYPE_FILE
;
2514 file
->f_ops
= &logfs_fileops
;
2521 // -------------------------------------------------------------------------
2523 // Write data to file.
2526 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2529 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2531 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2532 char *buf
= (char *) iov
->iov_base
;
2533 off_t len
= iov
->iov_len
;
2535 diag_write(buf
, len
);
2542 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2547 // -------------------------------------------------------------------------
2549 // Close a file. We just clear out the data pointer.
2551 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
)
2557 ramiodev_init( struct cyg_devtab_entry
*tab
)
2563 ramiodev_bread( cyg_io_handle_t handle
, void *buf
, cyg_uint32
*len
,
2566 if (*len
+pos
>ramblockdevice_size
)
2568 *len
=ramblockdevice_size
-pos
;
2570 memcpy(buf
, ramblockdevice
+pos
, *len
);
2575 ramiodev_bwrite( cyg_io_handle_t handle
, const void *buf
, cyg_uint32
*len
,
2578 if (((pos
%4)!=0)||(((*len
)%4)!=0))
2580 diag_printf("Unaligned write %d %d!", pos
, *len
);
2583 memcpy(ramblockdevice
+pos
, buf
, *len
);
2588 ramiodev_get_config( cyg_io_handle_t handle
,
2594 case CYG_IO_GET_CONFIG_FLASH_ERASE
:
2596 if ( *len
!= sizeof( cyg_io_flash_getconfig_erase_t
) )
2599 cyg_io_flash_getconfig_erase_t
*e
= (cyg_io_flash_getconfig_erase_t
*)buf
;
2600 char *startpos
= ramblockdevice
+ e
->offset
;
2602 if (((e
->offset
%(64*1024))!=0)||((e
->len
%(64*1024))!=0))
2604 diag_printf("Erease is not aligned %d %d\n", e
->offset
, e
->len
);
2607 memset(startpos
, 0xff, e
->len
);
2613 case CYG_IO_GET_CONFIG_FLASH_DEVSIZE
:
2615 if ( *len
!= sizeof( cyg_io_flash_getconfig_devsize_t
) )
2618 cyg_io_flash_getconfig_devsize_t
*d
=
2619 (cyg_io_flash_getconfig_devsize_t
*)buf
;
2621 d
->dev_size
= ramblockdevice_size
;
2626 case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE
:
2628 cyg_io_flash_getconfig_blocksize_t
*b
=
2629 (cyg_io_flash_getconfig_blocksize_t
*)buf
;
2630 if ( *len
!= sizeof( cyg_io_flash_getconfig_blocksize_t
) )
2633 // offset unused for now
2634 b
->block_size
= 64*1024;
2644 ramiodev_set_config( cyg_io_handle_t handle
,
2654 } // ramiodev_set_config()
2656 // get_config/set_config should be added later to provide the other flash
2657 // operations possible, like erase etc.
2659 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops
,
2663 &ramiodev_get_config
,
2664 &ramiodev_set_config
2668 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1
,
2671 &cyg_io_ramdev1_ops
,
2673 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)