1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
27 #include "configuration.h"
36 #include "telnet_server.h"
37 #include "gdb_server.h"
39 #include <time_support.h>
41 #include <sys/types.h>
49 #include <cyg/io/flash.h>
50 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
55 #include <cyg/fileio/fileio.h>
57 #include <cyg/athttpd/http.h>
58 #include <cyg/athttpd/socket.h>
59 #include <cyg/athttpd/handler.h>
60 #include <cyg/athttpd/cgi.h>
61 #include <cyg/athttpd/forms.h>
62 #include <cyg/hal/hal_diag.h>
63 #include <cyg/kernel/kapi.h>
64 #include <cyg/io/serialio.h>
65 #include <cyg/io/io.h>
66 #include <netinet/tcp.h>
68 #include <sys/ioctl.h>
69 #include <sys/socket.h>
70 #include <netinet/in.h>
72 #include <arpa/inet.h>
73 #include <sys/types.h>
74 #include <sys/socket.h>
76 #include <netinet/in.h>
78 #include <arpa/inet.h>
86 #if defined(CYGPKG_NET_FREEBSD_STACK)
87 #include <tftp_support.h>
88 /* posix compatibility broken*/
89 struct tftpd_fileops fileops
=
91 (int (*)(const char *, int))open
,
93 (int (*)(int, const void *, int))write
,
94 ( int (*)(int, void *, int))read
99 #define ZYLIN_VERSION "1.43"
100 #define ZYLIN_DATE __DATE__
101 #define ZYLIN_TIME __TIME__
102 /* hmmm.... we can't pick up the right # during build if we've checked this out
103 * in Eclipse... arrggghh...*/
104 #define ZYLIN_OPENOCD 1005
105 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
106 #define ZYLIN_CONFIG_DIR "/config/settings"
108 void diag_write(char *buf
, int len
)
111 for (j
= 0; j
< len
; j
++)
113 diag_printf("%c", buf
[j
]);
117 static bool serialLog
= true;
118 static bool writeLog
= true;
129 static int fastload_num
;
130 static struct FastLoad
*fastload
;
132 static void free_fastload()
137 for (i
=0; i
<fastload_num
; i
++)
139 if (fastload
[i
].data
)
140 free(fastload
[i
].data
);
148 int handle_fast_load_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
154 u32 max_address
=0xffffffff;
163 if ((argc
< 1)||(argc
> 5))
165 return ERROR_COMMAND_SYNTAX_ERROR
;
168 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
171 image
.base_address_set
= 1;
172 image
.base_address
= strtoul(args
[1], NULL
, 0);
176 image
.base_address_set
= 0;
180 image
.start_address_set
= 0;
184 min_address
=strtoul(args
[3], NULL
, 0);
188 max_address
=strtoul(args
[4], NULL
, 0)+min_address
;
191 if (min_address
>max_address
)
193 return ERROR_COMMAND_SYNTAX_ERROR
;
196 duration_start_measure(&duration
);
198 if (image_open(&image
, args
[0], (argc
>= 3) ? args
[2] : NULL
) != ERROR_OK
)
205 fastload_num
=image
.num_sections
;
206 fastload
=(struct FastLoad
*)malloc(sizeof(struct FastLoad
)*image
.num_sections
);
212 memset(fastload
, 0, sizeof(struct FastLoad
)*image
.num_sections
);
213 for (i
= 0; i
< image
.num_sections
; i
++)
215 buffer
= malloc(image
.sections
[i
].size
);
218 command_print(cmd_ctx
, "error allocating buffer for section (%d bytes)", image
.sections
[i
].size
);
222 if ((retval
= image_read_section(&image
, i
, 0x0, image
.sections
[i
].size
, buffer
, &buf_cnt
)) != ERROR_OK
)
232 /* DANGER!!! beware of unsigned comparision here!!! */
234 if ((image
.sections
[i
].base_address
+buf_cnt
>=min_address
)&&
235 (image
.sections
[i
].base_address
<max_address
))
237 if (image
.sections
[i
].base_address
<min_address
)
239 /* clip addresses below */
240 offset
+=min_address
-image
.sections
[i
].base_address
;
244 if (image
.sections
[i
].base_address
+buf_cnt
>max_address
)
246 length
-=(image
.sections
[i
].base_address
+buf_cnt
)-max_address
;
249 fastload
[i
].address
=image
.sections
[i
].base_address
+offset
;
250 fastload
[i
].data
=malloc(length
);
251 if (fastload
[i
].data
==NULL
)
256 memcpy(fastload
[i
].data
, buffer
+offset
, length
);
257 fastload
[i
].length
=length
;
259 image_size
+= length
;
260 command_print(cmd_ctx
, "%u byte written at address 0x%8.8x", length
, image
.sections
[i
].base_address
+offset
);
266 duration_stop_measure(&duration
, &duration_text
);
267 if (retval
==ERROR_OK
)
269 command_print(cmd_ctx
, "downloaded %u byte in %s", image_size
, duration_text
);
275 if (retval
!=ERROR_OK
)
283 int handle_fast_load_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
286 return ERROR_COMMAND_SYNTAX_ERROR
;
289 LOG_ERROR("No image in memory");
295 for (i
=0; i
<fastload_num
;i
++)
298 target_t
*target
= get_current_target(cmd_ctx
);
299 if ((retval
= target_write_buffer(target
, fastload
[i
].address
, fastload
[i
].length
, fastload
[i
].data
)) != ERROR_OK
)
303 size
+=fastload
[i
].length
;
305 int after
=timeval_ms();
306 command_print(cmd_ctx
, "Loaded image %f kBytes/s", (float)(size
/1024.0)/((float)(after
-ms
)/1000.0));
311 /* Give TELNET a way to find out what version this is */
312 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
313 char **args
, int argc
)
317 return ERROR_COMMAND_SYNTAX_ERROR
;
321 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
322 } else if (strcmp("openocd", args
[0])==0)
324 command_print(cmd_ctx
, "%d", ZYLIN_OPENOCD
);
325 } else if (strcmp("zy1000", args
[0])==0)
327 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
328 } else if (strcmp("date", args
[0])==0)
330 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
333 return ERROR_COMMAND_SYNTAX_ERROR
;
339 extern flash_driver_t
*flash_drivers
[];
340 extern target_type_t
*target_types
[];
342 #ifdef CYGPKG_PROFILE_GPROF
343 #include <cyg/profile/profile.h>
345 extern char _stext
, _etext
; // Defined by the linker
347 void start_profile(void)
349 // This starts up the system-wide profiling, gathering
350 // profile information on all of the code, with a 16 byte
351 // "bucket" size, at a rate of 100us/profile hit.
352 // Note: a bucket size of 16 will give pretty good function
353 // resolution. Much smaller and the buffer becomes
354 // much too large for very little gain.
355 // Note: a timer period of 100us is also a reasonable
356 // compromise. Any smaller and the overhead of
357 // handling the timter (profile) interrupt could
358 // swamp the system. A fast processor might get
359 // by with a smaller value, but a slow one could
360 // even be swamped by this value. If the value is
361 // too large, the usefulness of the profile is reduced.
363 // no more interrupts than 1/10ms.
364 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
365 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
366 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
370 // launch GDB server if a config file exists
371 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
373 bool foundFile
= false;
374 FILE *config_file
= NULL
;
375 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
376 config_file
= fopen(config_file_name
, "r");
381 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
382 if (retval
== ERROR_OK
)
388 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
393 command_print(cmd_ctx
, "No %s found", config_file_name
);
402 static char reboot_stack
[2048];
406 zylinjtag_reboot(cyg_addrword_t data
)
409 diag_printf("Rebooting in 100 ticks..\n");
410 cyg_thread_delay(100);
411 diag_printf("Unmounting /config..\n");
413 diag_printf("Rebooting..\n");
414 HAL_PLATFORM_RESET();
416 static cyg_thread zylinjtag_thread_object
;
417 static cyg_handle_t zylinjtag_thread_handle
;
425 (void *)reboot_stack
,
426 sizeof(reboot_stack
),
427 &zylinjtag_thread_handle
,
428 &zylinjtag_thread_object
);
429 cyg_thread_resume(zylinjtag_thread_handle
);
432 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
434 diag_printf("%s", line
);
439 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
441 LOG_USER_N("%s", line
);
446 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
447 char **args
, int argc
)
451 command_print(cmd_ctx
, "rm <filename>");
452 return ERROR_INVALID_ARGUMENTS
;
455 if (unlink(args
[0]) != 0)
457 command_print(cmd_ctx
, "failed: %d", errno
);
463 int loadFile(const char *fileName
, void **data
, int *len
);
465 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
466 char **args
, int argc
)
470 command_print(cmd_ctx
, "cat <filename>");
471 return ERROR_INVALID_ARGUMENTS
;
474 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
478 int retval
= loadFile(args
[0], &data
, &len
);
479 if (retval
== ERROR_OK
)
481 command_print(cmd_ctx
, "%s", data
);
486 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
491 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
492 char **args
, int argc
)
496 command_print(cmd_ctx
, "trunc <filename>");
497 return ERROR_INVALID_ARGUMENTS
;
500 FILE *config_file
= NULL
;
501 config_file
= fopen(args
[0], "w");
502 if (config_file
!= NULL
)
509 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
512 struct mallinfo info
;
516 command_print(cmd_ctx
, "meminfo");
517 return ERROR_INVALID_ARGUMENTS
;
524 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
526 prev
= info
.fordblks
;
528 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
533 static bool savePower
;
535 static void setPower(bool power
)
540 HAL_WRITE_UINT32(0x08000014, 0x8);
543 HAL_WRITE_UINT32(0x08000010, 0x8);
547 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
551 return ERROR_INVALID_ARGUMENTS
;
556 if (strcmp(args
[0], "on") == 0)
560 else if (strcmp(args
[0], "off") == 0)
565 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
566 return ERROR_INVALID_ARGUMENTS
;
570 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
575 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
576 char **args
, int argc
)
580 command_print(cmd_ctx
,
581 "append <filename> [<string1>, [<string2>, ...]]");
582 return ERROR_INVALID_ARGUMENTS
;
585 FILE *config_file
= NULL
;
586 config_file
= fopen(args
[0], "a");
587 if (config_file
!= NULL
)
590 fseek(config_file
, 0, SEEK_END
);
592 for (i
= 1; i
< argc
; i
++)
594 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
597 fwrite(" ", 1, 1, config_file
);
600 fwrite("\n", 1, 1, config_file
);
607 extern int telnet_socket
;
609 int readMore(int fd
, void *data
, int length
)
611 /* used in select() */
614 /* monitor sockets for acitvity */
617 /* listen for new connections */
618 FD_SET(fd
, &read_fds
);
620 // Maximum 5 seconds.
625 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
628 diag_printf("Timed out waiting for binary payload\n");
634 return read_socket(fd
, data
, length
);
637 int readAll(int fd
, void *data
, int length
)
642 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
643 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
653 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
658 return ERROR_INVALID_ARGUMENTS
;
660 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
661 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
665 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
669 return ERROR_INVALID_ARGUMENTS
;
671 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
675 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
679 return ERROR_INVALID_ARGUMENTS
;
682 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
686 int retval
= loadFile(args
[0], &data
, &len
);
687 if (retval
!= ERROR_OK
)
690 FILE *f
= fopen(args
[1], "wb");
692 retval
= ERROR_INVALID_ARGUMENTS
;
697 int chunk
= len
- pos
;
698 static const int maxChunk
= 512 * 1024; // ~1/sec
699 if (chunk
> maxChunk
)
704 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
705 retval
= ERROR_INVALID_ARGUMENTS
;
707 if (retval
!= ERROR_OK
)
712 command_print(cmd_ctx
, "%d", len
- pos
);
720 if (retval
== ERROR_OK
)
722 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
725 command_print(cmd_ctx
, "Failed: %d", retval
);
733 if (retval
!= ERROR_OK
)
739 #ifdef CYGPKG_PROFILE_GPROF
740 extern void start_profile();
742 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
744 command_print(cmd_ctx
, "Profiling started");
751 externC
void phi_init_all_network_interfaces();
753 command_context_t
*cmd_ctx
;
755 static bool webRunning
= false;
757 void keep_webserver()
759 // Target initialisation is only attempted at startup, so we sleep forever and
760 // let the http server bail us out(i.e. get config files set up).
761 diag_printf("OpenOCD has invoked exit().\n"
762 "Use web server to correct any configuration settings and reboot.\n");
766 // exit() will terminate the current thread and we we'll then sleep eternally or
767 // we'll have a reboot scheduled.
770 extern void printDccChar(char c
);
772 static char logBuffer
[128 * 1024];
773 static const int logSize
= sizeof(logBuffer
);
777 void _zylinjtag_diag_write_char(char c
, void **param
)
781 logBuffer
[writePtr
] = c
;
782 writePtr
= (writePtr
+ 1) % logSize
;
789 HAL_DIAG_WRITE_CHAR('\r');
791 HAL_DIAG_WRITE_CHAR(c
);
797 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
800 static void copyfile(char *name2
, char *name1
)
808 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
810 SHOW_RESULT( open
, fd1
);
812 fd2
= open(name2
, O_RDONLY
);
814 SHOW_RESULT( open
, fd2
);
818 done
= read(fd2
, buf
, IOSIZE
);
821 SHOW_RESULT( read
, done
);
825 if( done
== 0 ) break;
827 wrote
= write(fd1
, buf
, done
);
828 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
830 if( wrote
!= done
) break;
834 if( err
< 0 ) SHOW_RESULT( close
, err
);
837 if( err
< 0 ) SHOW_RESULT( close
, err
);
840 static void copydir(char *name
)
845 mkdir("/ram/cgi", 0777);
847 dirp
= opendir(name
);
848 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
852 struct dirent
*entry
= readdir(dirp
);
857 if (strcmp(entry
->d_name
, ".") == 0)
859 if (strcmp(entry
->d_name
, "..") == 0)
864 char fullPath
[PATH_MAX
];
865 strncpy(fullPath
, name
, PATH_MAX
);
866 strcat(fullPath
, "/");
867 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
869 if (stat(fullPath
, &buf
) == -1)
871 diag_printf("unable to read status from %s", fullPath
);
874 isDir
= S_ISDIR(buf
.st_mode
) != 0;
879 // diag_printf("<INFO>: entry %14s",entry->d_name);
880 char fullname
[PATH_MAX
];
881 char fullname2
[PATH_MAX
];
883 strcpy(fullname
, name
);
884 strcat(fullname
, entry
->d_name
);
886 strcpy(fullname2
, "/ram/cgi/");
887 strcat(fullname2
, entry
->d_name
);
888 // diag_printf("from %s to %s\n", fullname, fullname2);
889 copyfile(fullname
, fullname2
);
891 // diag_printf("\n");
894 err
= closedir(dirp
);
895 if( err
< 0 ) SHOW_RESULT( stat
, err
);
899 MTAB_ENTRY( romfs_mte1
,
903 (CYG_ADDRWORD
) &filedata
[0] );
906 void openocd_sleep_prelude()
908 cyg_mutex_unlock(&httpstate
.jim_lock
);
911 void openocd_sleep_postlude()
913 cyg_mutex_lock(&httpstate
.jim_lock
);
917 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
919 Jim_Obj
* const *argv
)
924 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
929 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
931 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
934 return del
? JIM_OK
: JIM_ERR
;
938 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
940 Jim_Obj
* const *argv
)
944 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
948 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
951 dirp
= opendir(name
);
956 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
960 struct dirent
*entry
= NULL
;
961 entry
= readdir(dirp
);
965 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
968 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
972 Jim_SetResult(interp
, objPtr
);
979 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
981 Jim_Obj
* const *argv
)
985 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
991 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
993 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
996 if (length
< 0 && length
> (4096 * 1024))
998 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1002 void *mem
= malloc(length
);
1006 target_t
*target
= get_current_target(cmd_ctx
);
1011 if ((address
% 4 == 0) && (count
% 4 == 0))
1017 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1023 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1024 Jim_SetResult(interp
, objPtr
);
1032 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1034 Jim_Obj
* const *argv
)
1038 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1043 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1046 int value
= *((volatile int *) address
);
1048 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1054 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1056 Jim_Obj
* const *argv
)
1060 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1065 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1068 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1071 *((volatile int *) address
) = value
;
1079 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1081 Jim_Obj
* const *argv
)
1085 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1095 if (retval
== JIM_OK
)
1097 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1108 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1110 Jim_Obj
* const *argv
)
1112 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1114 if (logCount
>= logSize
)
1116 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1118 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1120 Jim_SetResult(interp
, tclOutput
);
1125 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1127 Jim_Obj
* const *argv
)
1134 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1136 Jim_Obj
* const *argv
)
1140 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1143 strcpy(ifr
.ifr_name
, "eth0");
1145 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1154 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1157 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1158 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1159 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1160 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1161 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1162 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1163 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1165 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1167 Jim_SetResult(interp
, tclOutput
);
1173 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1175 Jim_Obj
* const *argv
)
1177 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1179 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1181 if (getifaddrs(&ifp
) < 0)
1186 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1191 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1192 salen
= sizeof(struct sockaddr_in
);
1193 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1194 salen
= sizeof(struct sockaddr_in6
);
1198 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1199 NI_NUMERICHOST
) < 0)
1204 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1211 Jim_SetResult(interp
, tclOutput
);
1216 extern Jim_Interp
*interp
;
1218 static void zylinjtag_startNetwork()
1220 // Bring TCP/IP up immediately before we're ready to accept commands.
1222 // That is as soon as a PING responds, we're accepting telnet sessions.
1223 #if defined(CYGPKG_NET_FREEBSD_STACK)
1224 phi_init_all_network_interfaces();
1230 diag_printf("Network not up and running\n");
1233 #if defined(CYGPKG_NET_FREEBSD_STACK)
1235 tftpd_start(69, &fileops
);
1238 cyg_httpd_init_tcl_interpreter();
1240 interp
= httpstate
.jim_interp
;
1242 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1243 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1244 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1245 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1246 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1247 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1248 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1249 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1250 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1251 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1257 diag_printf("Web server running\n");
1260 static bool readPowerDropout()
1263 // sample and clear power dropout
1264 HAL_WRITE_UINT32(0x08000010, 0x80);
1265 HAL_READ_UINT32(0x08000010, state
);
1267 powerDropout
= (state
& 0x80) != 0;
1268 return powerDropout
;
1274 // sample and clear SRST sensing
1275 HAL_WRITE_UINT32(0x08000010, 0x00000040);
1276 HAL_READ_UINT32(0x08000010, state
);
1278 srstAsserted
= (state
& 0x40) != 0;
1279 return srstAsserted
;
1282 // every 300ms we check for reset & powerdropout and issue a "reset halt" if
1286 static int sense_handler(void *priv
)
1288 struct command_context_s
*cmd_ctx
;
1289 cmd_ctx
= (struct command_context_s
*) priv
;
1291 static bool prevSrstAsserted
= false;
1292 static bool prevPowerdropout
= false;
1295 powerDropout
= readPowerDropout();
1298 powerRestored
= prevPowerdropout
&& !powerDropout
;
1301 LOG_USER("Sensed power restore.");
1304 cyg_tick_count_t current
= cyg_current_time();
1305 static cyg_tick_count_t lastPower
= 0;
1306 bool waitMore
= lastPower
+ 200 > current
;
1307 if (powerDropout
&& !waitMore
)
1309 LOG_USER("Sensed power dropout.");
1310 lastPower
= current
;
1313 bool srstAsserted
= readSRST();
1315 bool srstDeasserted
;
1316 srstDeasserted
= prevSrstAsserted
&& !srstAsserted
;
1318 static cyg_tick_count_t lastSrst
= 0;
1319 waitMore
= lastSrst
+ 200 > current
;
1320 if (srstDeasserted
&& !waitMore
)
1322 LOG_USER("Sensed nSRST deasserted");
1326 if (!prevSrstAsserted
&& srstAsserted
)
1328 LOG_USER("Sensed nSRST asserted");
1331 prevSrstAsserted
= srstAsserted
;
1332 prevPowerdropout
= powerDropout
;
1334 if (srstDeasserted
|| powerRestored
)
1336 /* Other than logging the event we can't do anything here.
1337 * Issuing a reset is a particularly bad idea as we might
1338 * be inside a reset already.
1348 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1352 char *infoStr
= "unknown";
1355 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1356 infoStr
= "undefined instruction";
1358 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1359 infoStr
= "software interrupt";
1361 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1362 infoStr
= "abort prefetch";
1364 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1365 infoStr
= "abort data";
1371 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1373 diag_printf("Dumping log\n---\n");
1374 if (logCount
>= logSize
)
1376 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1378 diag_write(logBuffer
, writePtr
);
1380 diag_printf("---\nLogdump complete.\n");
1381 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1382 diag_printf("\n---\nRebooting\n");
1383 HAL_PLATFORM_RESET();
1387 static void setHandler(cyg_code_t exception
)
1389 cyg_exception_handler_t
*old_handler
;
1390 cyg_addrword_t old_data
;
1392 cyg_exception_set_handler(exception
,
1393 print_exception_handler
,
1399 static cyg_thread zylinjtag_uart_thread_object
;
1400 static cyg_handle_t zylinjtag_uart_thread_handle
;
1401 static char uart_stack
[4096];
1403 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1404 static char backwardBuffer
[1024];
1406 static cyg_io_handle_t serial_handle
;
1408 void setNoDelay(int session
, int flag
)
1411 // This decreases latency dramatically for e.g. GDB load which
1412 // does not have a sliding window protocol
1414 // Can cause *lots* of TCP/IP packets to be sent and it would have
1415 // to be enabled/disabled on the fly to avoid the CPU being
1417 setsockopt(session
, /* socket affected */
1418 IPPROTO_TCP
, /* set option at TCP level */
1419 TCP_NODELAY
, /* name of option */
1420 (char *) &flag
, /* the cast is historical
1422 sizeof(int)); /* length of option value */
1432 } tcpipSent
[512 * 1024];
1436 zylinjtag_uart(cyg_addrword_t data
)
1438 int so_reuseaddr_option
= 1;
1441 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1443 LOG_ERROR("error creating socket: %s", strerror(errno
));
1447 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1449 struct sockaddr_in sin
;
1450 unsigned int address_size
;
1451 address_size
= sizeof(sin
);
1452 memset(&sin
, 0, sizeof(sin
));
1453 sin
.sin_family
= AF_INET
;
1454 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1455 sin
.sin_port
= htons(5555);
1457 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1459 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1463 if (listen(fd
, 1) == -1)
1465 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1468 // socket_nonblock(fd);
1473 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1479 setNoDelay(session
, 1);
1480 int oldopts
= fcntl(session
, F_GETFL
, 0);
1481 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1483 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1501 FD_ZERO(&write_fds
);
1504 FD_SET(session
, &read_fds
);
1506 FD_SET(serHandle
, &read_fds
);
1507 if (serHandle
> fd_max
)
1513 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1514 if ((actual
== 0) && (actual2
== 0))
1516 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1525 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1526 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1529 if (errno
!= EAGAIN
)
1542 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1550 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1552 // NB! Here it is important that we empty the TCP/IP read buffer
1553 // to make transmission tick right
1554 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1557 // this will block if there is no data at all
1558 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1570 /* Do not put things into the serial buffer if it has something to send
1571 * as that can cause a single byte to be sent at the time.
1575 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1578 if (errno
!= EAGAIN
)
1582 // The serial buffer is full
1593 tcpipSent
[cur
].req
= x
;
1594 tcpipSent
[cur
].actual
= y
;
1595 tcpipSent
[cur
].req2
= x2
;
1596 tcpipSent
[cur
].actual2
= y2
;
1606 for (i
= 0; i
< 1024; i
++)
1608 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1616 void startUart(void)
1618 cyg_thread_create(1,
1624 &zylinjtag_uart_thread_handle
,
1625 &zylinjtag_uart_thread_object
);
1626 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1627 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1632 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1636 command_print(cmd_ctx
, "usage: uart <baudrate>");
1637 return ERROR_INVALID_ARGUMENTS
;
1640 int baud
= atol(args
[0]);
1645 baud
= CYGNUM_SERIAL_BAUD_9600
;
1648 baud
= CYGNUM_SERIAL_BAUD_19200
;
1651 baud
= CYGNUM_SERIAL_BAUD_38400
;
1654 baud
= CYGNUM_SERIAL_BAUD_57600
;
1657 baud
= CYGNUM_SERIAL_BAUD_115200
;
1660 baud
= CYGNUM_SERIAL_BAUD_230400
;
1663 command_print(cmd_ctx
, "unsupported baudrate");
1664 return ERROR_INVALID_ARGUMENTS
;
1667 cyg_serial_info_t buf
;
1669 //get existing serial configuration
1670 len
= sizeof(cyg_serial_info_t
);
1672 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1673 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1676 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1681 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1684 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1691 bool logAllToSerial
= false;
1693 /* boolean parameter stored on config */
1694 bool boolParam(char *var
)
1696 bool result
= false;
1697 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1703 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1707 result
= strncmp((char *) data
, "1", len
) == 0;
1714 command_context_t
*setup_command_handler();
1716 int add_default_dirs(void)
1718 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1719 add_script_search_dir("/rom/lib/openocd");
1720 add_script_search_dir("/rom");
1724 int main(int argc
, char *argv
[])
1726 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1727 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1728 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1731 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1734 diag_printf("/dev/ser0 not found\n");
1738 setPower(true); // on by default
1740 atexit(keep_webserver
);
1742 err
= mount("", "/ram", "ramfs");
1745 diag_printf("unable to mount ramfs\n");
1750 sprintf(address
, "%p", &filedata
[0]);
1751 err
= mount(address
, "/rom", "romfs");
1754 diag_printf("unable to mount /rom\n");
1757 err
= mount("", "/log", "logfs");
1760 diag_printf("unable to mount logfs\n");
1763 err
= mount("", "/tftp", "tftpfs");
1766 diag_printf("unable to mount logfs\n");
1769 log
= fopen("/log/log", "w");
1772 diag_printf("Could not open log file /ram/log\n");
1776 diag_init_putc(_zylinjtag_diag_write_char
);
1778 // We want this in the log.
1779 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1780 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1784 err
= mount("/dev/flash1", "/config", "jffs2");
1787 diag_printf("unable to mount jffs\n");
1791 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1792 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1793 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1795 logAllToSerial
= boolParam("logserial");
1797 // We need the network & web server in case there is something wrong with
1798 // the config files that invoke exit()
1799 zylinjtag_startNetwork();
1801 /* we're going to access the jim interpreter from here on... */
1802 openocd_sleep_postlude();
1807 /* initialize commandline interface */
1808 command_context_t
*cmd_ctx
;
1809 cmd_ctx
= setup_command_handler();
1810 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1811 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1814 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1815 COMMAND_EXEC
, "show zy1000 version numbers");
1817 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1820 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1821 "same args as load_image, image stored in memory");
1823 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1824 "loads active fast load image to current target");
1826 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1829 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1832 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1833 COMMAND_ANY
, "append <filname>");
1835 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1836 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1838 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1839 COMMAND_ANY
, "meminfo");
1841 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1842 COMMAND_ANY
, "cp <from> <to>");
1844 #ifdef CYGPKG_PROFILE_GPROF
1845 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1848 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1849 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1853 errVal
= log_init(cmd_ctx
);
1854 if (errVal
!= ERROR_OK
)
1856 diag_printf("log_init() failed %d\n", errVal
);
1860 set_log_output(cmd_ctx
, log
);
1862 LOG_DEBUG("log init complete");
1864 // diag_printf("Executing config files\n");
1868 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1869 command_run_line(cmd_ctx
, "debug_level 3");
1872 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
1874 target_register_timer_callback(sense_handler
, 200, 1, cmd_ctx
);
1877 // diag_printf() is really invoked from many more places than we trust it
1878 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1880 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1881 // fingers that it doesn't cause any crashes.
1882 diag_printf("Init complete, GDB & telnet servers launched.\n");
1883 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
1884 if (!logAllToSerial
)
1889 /* handle network connections */
1890 server_loop(cmd_ctx
);
1891 openocd_sleep_prelude();
1893 /* shut server down */
1896 /* free commandline interface */
1897 command_done(cmd_ctx
);
1907 cyg_httpd_exec_cgi_tcl(char *file_name
);
1908 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
1910 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1914 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
1916 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
1917 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
1919 #include <pkgconf/system.h>
1920 #include <pkgconf/hal.h>
1921 #include <pkgconf/kernel.h>
1922 #include <pkgconf/io_fileio.h>
1923 #include <pkgconf/fs_rom.h>
1925 #include <cyg/kernel/ktypes.h> // base kernel types
1926 #include <cyg/infra/cyg_trac.h> // tracing macros
1927 #include <cyg/infra/cyg_ass.h> // assertion macros
1929 #include <sys/types.h>
1931 #include <sys/stat.h>
1940 #include <cyg/fileio/fileio.h>
1942 #include <cyg/kernel/kapi.h>
1943 #include <cyg/infra/diag.h>
1945 //==========================================================================
1946 // Eventually we want to eXecute In Place from the ROM in a protected
1947 // environment, so we'll need executables to be aligned to a boundary
1948 // suitable for MMU protection. A suitable boundary would be the 4k
1949 // boundary in all the CPU architectures I am currently aware of.
1951 // Forward definitions
1953 // Filesystem operations
1954 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
1955 static int tftpfs_umount(cyg_mtab_entry
*mte
);
1956 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
1957 int mode
, cyg_file
*fte
);
1958 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
1959 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
1962 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
1963 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
1964 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
1966 //==========================================================================
1967 // Filesystem table entries
1969 // -------------------------------------------------------------------------
1971 // This defines the entry in the filesystem table.
1972 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1973 // we should never block in any filesystem operations.
1975 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
1980 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
1981 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
1982 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
1983 (cyg_fsop_rename
*)cyg_fileio_erofs
,
1984 (cyg_fsop_link
*)cyg_fileio_erofs
,
1985 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
1986 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
1987 (cyg_fsop_stat
*)cyg_fileio_erofs
,
1988 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
1989 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
1992 // -------------------------------------------------------------------------
1994 // This defines a single ROMFS loaded into ROM at the configured address
1996 // MTAB_ENTRY( rom_mte, // structure name
1997 // "/rom", // mount point
1998 // "romfs", // FIlesystem type
1999 // "", // hardware device
2000 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2004 // -------------------------------------------------------------------------
2006 // This set of file operations are used for normal open files.
2008 static cyg_fileops tftpfs_fileops
=
2013 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2017 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2018 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2019 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2022 // -------------------------------------------------------------------------
2024 // Process a mount request. This mainly finds root for the
2027 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2032 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2047 static void freeTftp(struct Tftp
*t
)
2060 static const int tftpMaxSize
= 8192 * 1024;
2061 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2062 int mode
, cyg_file
*file
)
2065 tftp
= malloc(sizeof(struct Tftp
));
2068 memset(tftp
, 0, sizeof(struct Tftp
));
2070 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2071 file
->f_type
= CYG_FILE_TYPE_FILE
;
2072 file
->f_ops
= &tftpfs_fileops
;
2077 tftp
->mem
= malloc(tftpMaxSize
);
2078 if (tftp
->mem
== NULL
)
2084 char *server
= strchr(name
, '/');
2091 tftp
->server
= malloc(server
- name
+ 1);
2092 if (tftp
->server
== NULL
)
2097 strncpy(tftp
->server
, name
, server
- name
);
2098 tftp
->server
[server
- name
] = 0;
2100 tftp
->file
= strdup(server
+ 1);
2101 if (tftp
->file
== NULL
)
2107 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2112 static int fetchTftp(struct Tftp
*tftp
)
2114 if (!tftp
->readFile
)
2117 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2119 if (tftp
->actual
< 0)
2128 // -------------------------------------------------------------------------
2129 // tftpfs_fo_write()
2130 // Read data from file.
2133 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2135 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2137 if (fetchTftp(tftp
) != ENOERR
)
2141 off_t pos
= fp
->f_offset
;
2143 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2145 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2146 char *buf
= (char *) iov
->iov_base
;
2147 off_t len
= iov
->iov_len
;
2149 if (len
+ pos
> tftp
->actual
)
2151 len
= tftp
->actual
- pos
;
2153 resid
+= iov
->iov_len
- len
;
2155 memcpy(buf
, tftp
->mem
+ pos
, len
);
2159 uio
->uio_resid
= resid
;
2167 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2169 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2172 off_t pos
= fp
->f_offset
;
2174 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2176 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2177 char *buf
= (char *) iov
->iov_base
;
2178 off_t len
= iov
->iov_len
;
2180 if (len
+ pos
> tftpMaxSize
)
2182 len
= tftpMaxSize
- pos
;
2184 resid
+= iov
->iov_len
- len
;
2186 memcpy(tftp
->mem
+ pos
, buf
, len
);
2190 uio
->uio_resid
= resid
;
2199 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2205 // -------------------------------------------------------------------------
2207 // Close a file. We just clear out the data pointer.
2209 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2211 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2216 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2224 // -------------------------------------------------------------------------
2226 // Seek to a new file position.
2228 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2230 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2233 if (fetchTftp(tftp
) != ENOERR
)
2239 // Pos is already where we want to be.
2243 // Add pos to current offset.
2244 pos
+= fp
->f_offset
;
2248 // Add pos to file size.
2249 pos
+= tftp
->actual
;
2256 // Check that pos is still within current file size, or at the
2258 if (pos
< 0 || pos
> tftp
->actual
)
2261 // All OK, set fp offset and return new position.
2262 *apos
= fp
->f_offset
= pos
;
2270 cyg_thread_delay(us
/ 10000 + 1);
2277 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2279 cyg_httpd_start_chunked("text");
2280 if (logCount
>= logSize
)
2282 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2284 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2285 cyg_httpd_end_chunked();
2289 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2291 // Filesystem operations
2292 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2293 static int logfs_umount(cyg_mtab_entry
*mte
);
2294 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2295 int mode
, cyg_file
*fte
);
2297 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2300 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2301 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2303 //==========================================================================
2304 // Filesystem table entries
2306 // -------------------------------------------------------------------------
2308 // This defines the entry in the filesystem table.
2309 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2310 // we should never block in any filesystem operations.
2311 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2312 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2316 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2317 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2318 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2319 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2320 (cyg_fsop_link
*)cyg_fileio_erofs
,
2321 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2322 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2323 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2324 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2325 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2327 // -------------------------------------------------------------------------
2329 // This set of file operations are used for normal open files.
2331 static cyg_fileops logfs_fileops
=
2333 (cyg_fileop_read
*)cyg_fileio_erofs
,
2334 (cyg_fileop_write
*)logfs_fo_write
,
2335 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2336 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2340 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2341 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2342 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2345 // -------------------------------------------------------------------------
2347 // Process a mount request. This mainly finds root for the
2350 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2355 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
*file
)
2363 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2364 file
->f_type
= CYG_FILE_TYPE_FILE
;
2365 file
->f_ops
= &logfs_fileops
;
2372 // -------------------------------------------------------------------------
2374 // Write data to file.
2377 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2380 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2382 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2383 char *buf
= (char *) iov
->iov_base
;
2384 off_t len
= iov
->iov_len
;
2386 diag_write(buf
, len
);
2393 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2398 // -------------------------------------------------------------------------
2400 // Close a file. We just clear out the data pointer.
2402 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
)
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)