change #include "jtag.h" to <jtag/jtag.h>
[fw/openocd] / src / ecosboard.c
index 44c0f0b9bf6d25b00a826064ffaff5374eb8f0a6..b42a777cd4aba65978f7a79ccf9c73c87834e1e7 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007-2008 by Ã˜yvind Harboe                              *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-\r
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include "log.h"\r
-#include "types.h"\r
-#include "jtag.h"\r
-#include "configuration.h"\r
-#include "xsvf.h"\r
-#include "target.h"\r
-#include "flash.h"\r
-#include "nand.h"\r
-#include "pld.h"\r
-\r
-#include "command.h"\r
-#include "server.h"\r
-#include "telnet_server.h"\r
-#include "gdb_server.h"\r
-\r
-#include <time_support.h>\r
-#include <sys/time.h>\r
-#include <sys/types.h>\r
-#include <strings.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <unistd.h>\r
-#include <errno.h>\r
-\r
-#include <cyg/io/flash.h>\r
-#include <pkgconf/fs_jffs2.h>  // Address of JFFS2\r
-#include <network.h>\r
-\r
-#include <fcntl.h>\r
-#include <sys/stat.h>\r
-#include <cyg/fileio/fileio.h>\r
-#include <dirent.h>\r
-#include <cyg/athttpd/http.h>\r
-#include <cyg/athttpd/socket.h>\r
-#include <cyg/athttpd/handler.h>\r
-#include <cyg/athttpd/cgi.h>\r
-#include <cyg/athttpd/forms.h>\r
-#include <cyg/hal/hal_diag.h>\r
-#include <cyg/kernel/kapi.h>\r
-#include <cyg/io/serialio.h>\r
-#include <cyg/io/io.h>\r
-#include <netinet/tcp.h>\r
-#include "rom.h"\r
-#include <sys/ioctl.h>\r
-#include <sys/socket.h>\r
-#include <netinet/in.h>\r
-#include <net/if.h>\r
-#include <arpa/inet.h>\r
-#include <sys/types.h>\r
-#include <sys/socket.h>\r
-#include <netdb.h>\r
-#include <netinet/in.h>\r
-#include <unistd.h>\r
-#include <arpa/inet.h>\r
-#include <stdio.h>\r
-#include <ifaddrs.h>\r
-#include <string.h>\r
-\r
-#include <unistd.h>\r
-#include <stdio.h>\r
-#define MAX_IFS 64\r
-#if defined(CYGPKG_NET_FREEBSD_STACK)\r
-#include <tftp_support.h>\r
-/* posix compatibility broken*/\r
-struct tftpd_fileops fileops =\r
-{\r
-       (int (*)(const char *, int))open,\r
-       close,\r
-       (int (*)(int, const void *, int))write,\r
-       ( int (*)(int, void *, int))read\r
-};\r
-\r
-#endif\r
-\r
-#define ZYLIN_VERSION "1.42"\r
-#define ZYLIN_DATE __DATE__\r
-#define ZYLIN_TIME __TIME__\r
-#define ZYLIN_OPENOCD 921\r
-#define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME\r
-#define ZYLIN_CONFIG_DIR "/config/settings"\r
-\r
-void diag_write(char *buf, int len)\r
-{\r
-       int j;\r
-       for (j = 0; j < len; j++)\r
-       {\r
-               diag_printf("%c", buf[j]);\r
-       }\r
-}\r
-\r
-static bool serialLog = true;\r
-static bool writeLog = true;\r
-\r
-\r
-struct FastLoad\r
-{\r
-       u32 address;\r
-       u8 *data;\r
-       int length;\r
-\r
-};\r
-\r
-static int fastload_num;\r
-static struct FastLoad *fastload;\r
-\r
-static void free_fastload()\r
-{\r
-       if (fastload!=NULL)\r
-       {\r
-               int i;\r
-               for (i=0; i<fastload_num; i++)\r
-               {\r
-                       if (fastload[i].data)\r
-                               free(fastload[i].data);\r
-               }\r
-               free(fastload);\r
-               fastload=NULL;\r
-       }\r
-}\r
-\r
-\r
-int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       u8 *buffer;\r
-       u32 buf_cnt;\r
-       u32 image_size;\r
-       u32 min_address=0;\r
-       u32 max_address=0xffffffff;\r
-       int i;\r
-       int retval;\r
-\r
-       image_t image;\r
-\r
-       duration_t duration;\r
-       char *duration_text;\r
-\r
-       if ((argc < 1)||(argc > 5))\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */\r
-       if (argc >= 2)\r
-       {\r
-               image.base_address_set = 1;\r
-               image.base_address = strtoul(args[1], NULL, 0);\r
-       }\r
-       else\r
-       {\r
-               image.base_address_set = 0;\r
-       }\r
-\r
-\r
-       image.start_address_set = 0;\r
-\r
-       if (argc>=4)\r
-       {\r
-               min_address=strtoul(args[3], NULL, 0);\r
-       }\r
-       if (argc>=5)\r
-       {\r
-               max_address=strtoul(args[4], NULL, 0)+min_address;\r
-       }\r
-\r
-       if (min_address>max_address)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       duration_start_measure(&duration);\r
-\r
-       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       image_size = 0x0;\r
-       retval = ERROR_OK;\r
-       fastload_num=image.num_sections;\r
-       fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);\r
-       if (fastload==NULL)\r
-       {\r
-               image_close(&image);\r
-               return ERROR_FAIL;\r
-       }\r
-       memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);\r
-       for (i = 0; i < image.num_sections; i++)\r
-       {\r
-               buffer = malloc(image.sections[i].size);\r
-               if (buffer == NULL)\r
-               {\r
-                       command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);\r
-                       break;\r
-               }\r
-\r
-               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)\r
-               {\r
-                       free(buffer);\r
-                       break;\r
-               }\r
-\r
-               u32 offset=0;\r
-               u32 length=buf_cnt;\r
-\r
-\r
-               /* DANGER!!! beware of unsigned comparision here!!! */\r
-\r
-               if ((image.sections[i].base_address+buf_cnt>=min_address)&&\r
-                               (image.sections[i].base_address<max_address))\r
-               {\r
-                       if (image.sections[i].base_address<min_address)\r
-                       {\r
-                               /* clip addresses below */\r
-                               offset+=min_address-image.sections[i].base_address;\r
-                               length-=offset;\r
-                       }\r
-\r
-                       if (image.sections[i].base_address+buf_cnt>max_address)\r
-                       {\r
-                               length-=(image.sections[i].base_address+buf_cnt)-max_address;\r
-                       }\r
-\r
-                       fastload[i].address=image.sections[i].base_address+offset;\r
-                       fastload[i].data=malloc(length);\r
-                       if (fastload[i].data==NULL)\r
-                       {\r
-                               free(buffer);\r
-                               break;\r
-                       }\r
-                       memcpy(fastload[i].data, buffer+offset, length);\r
-                       fastload[i].length=length;\r
-\r
-                       image_size += length;\r
-                       command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);\r
-               }\r
-\r
-               free(buffer);\r
-       }\r
-\r
-       duration_stop_measure(&duration, &duration_text);\r
-       if (retval==ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);\r
-       }\r
-       free(duration_text);\r
-\r
-       image_close(&image);\r
-\r
-       if (retval!=ERROR_OK)\r
-       {\r
-               free_fastload();\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc>0)\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       if (fastload==NULL)\r
-       {\r
-               LOG_ERROR("No image in memory");\r
-               return ERROR_FAIL;\r
-       }\r
-       int i;\r
-       int ms=timeval_ms();\r
-       int size=0;\r
-       for (i=0; i<fastload_num;i++)\r
-       {\r
-               int retval;\r
-               target_t *target = get_current_target(cmd_ctx);\r
-               if ((retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data)) != ERROR_OK)\r
-               {\r
-                       return retval;\r
-               }\r
-               size+=fastload[i].length;\r
-       }\r
-       int after=timeval_ms();\r
-       command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-/* Give TELNET a way to find out what version this is */\r
-int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,\r
-               char **args, int argc)\r
-{\r
-       if (argc > 1)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-       if (argc == 0)\r
-       {\r
-               command_print(cmd_ctx, ZYLIN_OPENOCD_VERSION);\r
-       } else if (strcmp("openocd", args[0])==0)\r
-       {\r
-               command_print(cmd_ctx, "%d", ZYLIN_OPENOCD);\r
-       } else if (strcmp("zy1000", args[0])==0)\r
-       {\r
-               command_print(cmd_ctx, "%s", ZYLIN_VERSION);\r
-       } else if (strcmp("date", args[0])==0)\r
-       {\r
-               command_print(cmd_ctx, "%s", ZYLIN_DATE);\r
-       } else\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-extern flash_driver_t *flash_drivers[];\r
-extern target_type_t *target_types[];\r
-\r
-#ifdef CYGPKG_PROFILE_GPROF\r
-#include <cyg/profile/profile.h>\r
-\r
-extern char _stext, _etext; // Defined by the linker\r
-\r
-void start_profile(void)\r
-{\r
-       // This starts up the system-wide profiling, gathering\r
-       // profile information on all of the code, with a 16 byte\r
-       // "bucket" size, at a rate of 100us/profile hit.\r
-       // Note: a bucket size of 16 will give pretty good function\r
-       //       resolution.  Much smaller and the buffer becomes\r
-       //       much too large for very little gain.\r
-       // Note: a timer period of 100us is also a reasonable\r
-       //       compromise.  Any smaller and the overhead of\r
-       //       handling the timter (profile) interrupt could\r
-       //       swamp the system.  A fast processor might get\r
-       //       by with a smaller value, but a slow one could\r
-       //       even be swamped by this value.  If the value is\r
-       //       too large, the usefulness of the profile is reduced.\r
-\r
-       // no more interrupts than 1/10ms.\r
-       //    profile_on(&_stext, &_etext, 16, 10000); // DRAM\r
-       //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM\r
-       profile_on(0, &_etext, 16, 10000); // SRAM & DRAM\r
-}\r
-#endif\r
-\r
-// launch GDB server if a config file exists\r
-bool zylinjtag_parse_config_file(struct command_context_s *cmd_ctx, const char *config_file_name)\r
-{\r
-       bool foundFile = false;\r
-       FILE *config_file = NULL;\r
-       command_print(cmd_ctx, "executing config file %s", config_file_name);\r
-       config_file = fopen(config_file_name, "r");\r
-       if (config_file)\r
-       {\r
-               fclose(config_file);\r
-               int retval;\r
-               retval = command_run_linef(cmd_ctx, "script %s", config_file_name);\r
-               if (retval == ERROR_OK)\r
-               {\r
-                       foundFile = true;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "Failed executing %s %d", config_file_name, retval);\r
-               }\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "No %s found", config_file_name);\r
-       }\r
-\r
-       return foundFile;\r
-}\r
-\r
-extern int eth0_up;\r
-static FILE *log;\r
-\r
-static char reboot_stack[2048];\r
-\r
-\r
-static void\r
-zylinjtag_reboot(cyg_addrword_t data)\r
-{\r
-       serialLog = true;\r
-       diag_printf("Rebooting in 100 ticks..\n");\r
-       cyg_thread_delay(100);\r
-       diag_printf("Unmounting /config..\n");\r
-       umount("/config");\r
-       diag_printf("Rebooting..\n");\r
-       HAL_PLATFORM_RESET();\r
-}\r
-static cyg_thread zylinjtag_thread_object;\r
-static cyg_handle_t zylinjtag_thread_handle;\r
-\r
-void reboot(void)\r
-{\r
-    cyg_thread_create(1,\r
-                      zylinjtag_reboot,\r
-                      (cyg_addrword_t)0,\r
-                      "reboot Thread",\r
-                      (void *)reboot_stack,\r
-                      sizeof(reboot_stack),\r
-                      &zylinjtag_thread_handle,\r
-                      &zylinjtag_thread_object);\r
-       cyg_thread_resume(zylinjtag_thread_handle);\r
-}\r
-\r
-int configuration_output_handler(struct command_context_s *context, const char* line)\r
-{\r
-       diag_printf("%s", line);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int zy1000_configuration_output_handler_log(struct command_context_s *context, const char* line)\r
-{\r
-       LOG_USER_N("%s", line);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,\r
-               char **args, int argc)\r
-{\r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "rm <filename>");\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       if (unlink(args[0]) != 0)\r
-       {\r
-               command_print(cmd_ctx, "failed: %d", errno);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int loadFile(const char *fileName, void **data, int *len);\r
-\r
-int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,\r
-               char **args, int argc)\r
-{\r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "cat <filename>");\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       // NOTE!!! we only have line printing capability so we print the entire file as a single line.\r
-       void *data;\r
-       int len;\r
-\r
-       int retval = loadFile(args[0], &data, &len);\r
-       if (retval == ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "%s", data);\r
-               free(data);\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "%s not found %d", args[0], retval);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,\r
-               char **args, int argc)\r
-{\r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "trunc <filename>");\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       FILE *config_file = NULL;\r
-       config_file = fopen(args[0], "w");\r
-       if (config_file != NULL)\r
-               fclose(config_file);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       static int prev = 0;\r
-       struct mallinfo info;\r
-\r
-       if (argc != 0)\r
-       {\r
-               command_print(cmd_ctx, "meminfo");\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       info = mallinfo();\r
-\r
-       if (prev > 0)\r
-       {\r
-               command_print(cmd_ctx, "Diff:            %d", prev - info.fordblks);\r
-       }\r
-       prev = info.fordblks;\r
-\r
-       command_print(cmd_ctx, "Available ram:   %d", info.fordblks );\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-static bool savePower;\r
-\r
-static void setPower(bool power)\r
-{\r
-       savePower = power;\r
-       if (power)\r
-       {\r
-               HAL_WRITE_UINT32(0x08000014, 0x8);\r
-       } else\r
-       {\r
-               HAL_WRITE_UINT32(0x08000010, 0x8);\r
-       }\r
-}\r
-\r
-int handle_power_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc > 1)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       if (argc == 1)\r
-       {\r
-               if (strcmp(args[0], "on") == 0)\r
-               {\r
-                       setPower(1);\r
-               }\r
-               else if (strcmp(args[0], "off") == 0)\r
-               {\r
-                       setPower(0);\r
-               } else\r
-               {\r
-                       command_print(cmd_ctx, "arg is \"on\" or \"off\"");\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-               }\r
-       }\r
-\r
-       command_print(cmd_ctx, "Target power %s", savePower ? "on" : "off");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,\r
-               char **args, int argc)\r
-{\r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx,\r
-                               "append <filename> [<string1>, [<string2>, ...]]");\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       FILE *config_file = NULL;\r
-       config_file = fopen(args[0], "a");\r
-       if (config_file != NULL)\r
-       {\r
-               int i;\r
-               fseek(config_file, 0, SEEK_END);\r
-\r
-               for (i = 1; i < argc; i++)\r
-               {\r
-                       fwrite(args[i], strlen(args[i]), 1, config_file);\r
-                       if (i != argc - 1)\r
-                       {\r
-                               fwrite(" ", 1, 1, config_file);\r
-                       }\r
-               }\r
-               fwrite("\n", 1, 1, config_file);\r
-               fclose(config_file);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-extern int telnet_socket;\r
-\r
-int readMore(int fd, void *data, int length)\r
-{\r
-       /* used in select() */\r
-       fd_set read_fds;\r
-\r
-       /* monitor sockets for acitvity */\r
-       int fd_max = 1;\r
-       FD_ZERO(&read_fds);\r
-       /* listen for new connections */\r
-       FD_SET(fd, &read_fds);\r
-\r
-       // Maximum 5 seconds.\r
-       struct timeval tv;\r
-       tv.tv_sec = 5;\r
-       tv.tv_usec = 0;\r
-\r
-       int retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);\r
-       if (retval == 0)\r
-       {\r
-               diag_printf("Timed out waiting for binary payload\n");\r
-               return -1;\r
-       }\r
-       if (retval != 1)\r
-               return -1;\r
-\r
-       return read_socket(fd, data, length);\r
-}\r
-\r
-int readAll(int fd, void *data, int length)\r
-{\r
-       int pos = 0;\r
-       for (;;)\r
-       {\r
-               int actual = readMore(fd, ((char *) data) + pos, length - pos);\r
-               //              diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);\r
-               if (actual <= 0)\r
-                       return -1;\r
-               pos += actual;\r
-               if (pos == length)\r
-                       break;\r
-       }\r
-       return length;\r
-}\r
-\r
-int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       cyg_uint32 value;\r
-       if (argc != 1)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-       HAL_READ_UINT32(strtoul(args[0], NULL, 0), value);\r
-       command_print(cmd_ctx, "0x%x : 0x%x", strtoul(args[0], NULL, 0), value);\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc != 2)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-       HAL_WRITE_UINT32(strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0));\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc != 2)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       // NOTE!!! we only have line printing capability so we print the entire file as a single line.\r
-       void *data;\r
-       int len;\r
-\r
-       int retval = loadFile(args[0], &data, &len);\r
-       if (retval != ERROR_OK)\r
-               return retval;\r
-\r
-       FILE *f = fopen(args[1], "wb");\r
-       if (f == NULL)\r
-               retval = ERROR_INVALID_ARGUMENTS;\r
-\r
-       int pos = 0;\r
-       for (;;)\r
-       {\r
-               int chunk = len - pos;\r
-               static const int maxChunk = 512 * 1024; // ~1/sec\r
-               if (chunk > maxChunk)\r
-               {\r
-                       chunk = maxChunk;\r
-               }\r
-\r
-               if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))\r
-                       retval = ERROR_INVALID_ARGUMENTS;\r
-\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       break;\r
-               }\r
-\r
-               command_print(cmd_ctx, "%d", len - pos);\r
-\r
-               pos += chunk;\r
-\r
-               if (pos == len)\r
-                       break;\r
-       }\r
-\r
-       if (retval == ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);\r
-       } else\r
-       {\r
-               command_print(cmd_ctx, "Failed: %d", retval);\r
-       }\r
-\r
-       if (data != NULL)\r
-               free(data);\r
-       if (f != NULL)\r
-               fclose(f);\r
-\r
-       if (retval != ERROR_OK)\r
-               unlink(args[1]);\r
-\r
-       return retval;\r
-}\r
-\r
-#ifdef CYGPKG_PROFILE_GPROF\r
-extern void start_profile();\r
-\r
-int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       command_print(cmd_ctx, "Profiling started");\r
-       start_profile();\r
-       return ERROR_OK;\r
-}\r
-\r
-#endif\r
-\r
-externC void phi_init_all_network_interfaces();\r
-\r
-command_context_t *cmd_ctx;\r
-\r
-static bool webRunning = false;\r
-\r
-void keep_webserver()\r
-{\r
-       // Target initialisation is only attempted at startup, so we sleep forever and\r
-       // let the http server bail us out(i.e. get config files set up).\r
-       diag_printf("OpenOCD has invoked exit().\n"\r
-               "Use web server to correct any configuration settings and reboot.\n");\r
-       if (!webRunning)\r
-               reboot();\r
-\r
-       // exit() will terminate the current thread and we we'll then sleep eternally or\r
-       // we'll have a reboot scheduled.\r
-}\r
-\r
-extern void printDccChar(char c);\r
-\r
-static char logBuffer[128 * 1024];\r
-static const int logSize = sizeof(logBuffer);\r
-int writePtr = 0;\r
-int logCount = 0;\r
-\r
-void _zylinjtag_diag_write_char(char c, void **param)\r
-{\r
-       if (writeLog)\r
-       {\r
-               logBuffer[writePtr] = c;\r
-               writePtr = (writePtr + 1) % logSize;\r
-               logCount++;\r
-       }\r
-       if (serialLog)\r
-       {\r
-               if (c == '\n')\r
-               {\r
-                       HAL_DIAG_WRITE_CHAR('\r');\r
-               }\r
-               HAL_DIAG_WRITE_CHAR(c);\r
-       }\r
-\r
-       printDccChar(c);\r
-}\r
-\r
-#define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)\r
-\r
-#define IOSIZE 512\r
-static void copyfile(char *name2, char *name1)\r
-{\r
-\r
-       int err;\r
-       char buf[IOSIZE];\r
-       int fd1, fd2;\r
-       ssize_t done, wrote;\r
-\r
-       fd1 = open(name1, O_WRONLY | O_CREAT);\r
-       if (fd1 < 0)\r
-               SHOW_RESULT( open, fd1 );\r
-\r
-       fd2 = open(name2, O_RDONLY);\r
-       if (fd2 < 0)\r
-               SHOW_RESULT( open, fd2 );\r
-\r
-       for (;;)\r
-       {\r
-               done = read(fd2, buf, IOSIZE );\r
-               if (done < 0)\r
-               {\r
-                       SHOW_RESULT( read, done );\r
-                       break;\r
-               }\r
-\r
-        if( done == 0 ) break;\r
-\r
-               wrote = write(fd1, buf, done);\r
-        if( wrote != done ) SHOW_RESULT( write, wrote );\r
-\r
-        if( wrote != done ) break;\r
-       }\r
-\r
-       err = close(fd1);\r
-    if( err < 0 ) SHOW_RESULT( close, err );\r
-\r
-       err = close(fd2);\r
-    if( err < 0 ) SHOW_RESULT( close, err );\r
-\r
-}\r
-static void copydir(char *name)\r
-{\r
-       int err;\r
-       DIR *dirp;\r
-\r
-       mkdir("/ram/cgi", 0777);\r
-\r
-       dirp = opendir(name);\r
-    if( dirp == NULL ) SHOW_RESULT( opendir, -1 );\r
-\r
-       for (;;)\r
-       {\r
-               struct dirent *entry = readdir(dirp);\r
-\r
-               if (entry == NULL)\r
-                       break;\r
-\r
-               if (strcmp(entry->d_name, ".") == 0)\r
-                       continue;\r
-               if (strcmp(entry->d_name, "..") == 0)\r
-                       continue;\r
-\r
-               bool isDir = false;\r
-               struct stat buf;\r
-               char fullPath[PATH_MAX];\r
-               strncpy(fullPath, name, PATH_MAX);\r
-               strcat(fullPath, "/");\r
-               strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));\r
-\r
-               if (stat(fullPath, &buf) == -1)\r
-               {\r
-                       diag_printf("unable to read status from %s", fullPath);\r
-                       break;\r
-               }\r
-               isDir = S_ISDIR(buf.st_mode) != 0;\r
-\r
-               if (isDir)\r
-                       continue;\r
-\r
-               //        diag_printf("<INFO>: entry %14s",entry->d_name);\r
-               char fullname[PATH_MAX];\r
-               char fullname2[PATH_MAX];\r
-\r
-               strcpy(fullname, name);\r
-               strcat(fullname, entry->d_name);\r
-\r
-               strcpy(fullname2, "/ram/cgi/");\r
-               strcat(fullname2, entry->d_name);\r
-               //        diag_printf("from %s to %s\n", fullname, fullname2);\r
-               copyfile(fullname, fullname2);\r
-\r
-               //       diag_printf("\n");\r
-       }\r
-\r
-       err = closedir(dirp);\r
-    if( err < 0 ) SHOW_RESULT( stat, err );\r
-}\r
-\r
-#if 0\r
-MTAB_ENTRY( romfs_mte1,\r
-               "/rom",\r
-               "romfs",\r
-               "",\r
-               (CYG_ADDRWORD) &filedata[0] );\r
-#endif\r
-\r
-void openocd_sleep_prelude()\r
-{\r
-       cyg_mutex_unlock(&httpstate.jim_lock);\r
-}\r
-\r
-void openocd_sleep_postlude()\r
-{\r
-       cyg_mutex_lock(&httpstate.jim_lock);\r
-}\r
-\r
-static int\r
-zylinjtag_Jim_Command_rm(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       int del;\r
-       if (argc != 2)\r
-       {\r
-               Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       del = 0;\r
-       if (unlink(Jim_GetString(argv[1], NULL)) == 0)\r
-               del = 1;\r
-       if (rmdir(Jim_GetString(argv[1], NULL)) == 0)\r
-               del = 1;\r
-\r
-       return del ? JIM_OK : JIM_ERR;\r
-}\r
-\r
-static int\r
-zylinjtag_Jim_Command_ls(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       if (argc != 2)\r
-       {\r
-               Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       char *name = (char*) Jim_GetString(argv[1], NULL);\r
-\r
-       DIR *dirp = NULL;\r
-       dirp = opendir(name);\r
-       if (dirp == NULL)\r
-       {\r
-               return JIM_ERR;\r
-       }\r
-       Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);\r
-\r
-       for (;;)\r
-       {\r
-               struct dirent *entry = NULL;\r
-               entry = readdir(dirp);\r
-               if (entry == NULL)\r
-                       break;\r
-\r
-               if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))\r
-                       continue;\r
-\r
-        Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));\r
-       }\r
-       closedir(dirp);\r
-\r
-       Jim_SetResult(interp, objPtr);\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-\r
-static int\r
-zylinjtag_Jim_Command_getmem(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       if (argc != 3)\r
-       {\r
-               Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       long address;\r
-       long length;\r
-       if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)\r
-               return JIM_ERR;\r
-       if (Jim_GetLong(interp, argv[2], &length) != JIM_OK)\r
-               return JIM_ERR;\r
-\r
-       if (length < 0 && length > (4096 * 1024))\r
-       {\r
-               Jim_WrongNumArgs(interp, 1, argv, "getmem ?dir?");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       void *mem = malloc(length);\r
-       if (mem == NULL)\r
-               return JIM_ERR;\r
-\r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       int retval;\r
-       int size = 1;\r
-       int count = length;\r
-       if ((address % 4 == 0) && (count % 4 == 0))\r
-       {\r
-               size = 4;\r
-               count /= 4;\r
-       }\r
-\r
-       if ((retval  = target->type->read_memory(target, address, size, count, mem)) != ERROR_OK)\r
-       {\r
-               free(mem);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       Jim_Obj *objPtr = Jim_NewStringObj(interp, mem, length);\r
-       Jim_SetResult(interp, objPtr);\r
-\r
-       free(mem);\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-static int\r
-zylinjtag_Jim_Command_peek(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       if (argc != 2)\r
-       {\r
-               Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       long address;\r
-       if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)\r
-               return JIM_ERR;\r
-\r
-       int value = *((volatile int *) address);\r
-\r
-       Jim_SetResult(interp, Jim_NewIntObj(interp, value));\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-static int\r
-zylinjtag_Jim_Command_poke(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       if (argc != 3)\r
-       {\r
-               Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       long address;\r
-       if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)\r
-               return JIM_ERR;\r
-       long value;\r
-       if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)\r
-               return JIM_ERR;\r
-\r
-       *((volatile int *) address) = value;\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-\r
-\r
-static int\r
-zylinjtag_Jim_Command_flash(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       int retval;\r
-       u32 base = 0;\r
-       flash_bank_t *t = get_flash_bank_by_num_noprobe(0);\r
-       if (t != NULL)\r
-       {\r
-               base = t->base;\r
-               retval = JIM_OK;\r
-    } else\r
-       {\r
-               retval = JIM_ERR;\r
-       }\r
-\r
-       if (retval == JIM_OK)\r
-       {\r
-               Jim_SetResult(interp, Jim_NewIntObj(interp, base));\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-static int\r
-zylinjtag_Jim_Command_log(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);\r
-\r
-       if (logCount >= logSize)\r
-       {\r
-       Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer+logCount%logSize, logSize-logCount%logSize);\r
-       }\r
-       Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);\r
-\r
-       Jim_SetResult(interp, tclOutput);\r
-       return JIM_OK;\r
-}\r
-\r
-static int\r
-zylinjtag_Jim_Command_reboot(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       reboot();\r
-       return JIM_OK;\r
-}\r
-\r
-static int\r
-zylinjtag_Jim_Command_mac(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       int s;\r
-       struct ifreq ifr;\r
-       s = socket(AF_INET, SOCK_DGRAM, 0);\r
-       if (s >= 0)\r
-       {\r
-               strcpy(ifr.ifr_name, "eth0");\r
-               int res;\r
-               res = ioctl(s, SIOCGIFHWADDR, &ifr);\r
-               close(s);\r
-\r
-               if (res < 0)\r
-               {\r
-                       return JIM_OK;\r
-               }\r
-       }\r
-\r
-       Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);\r
-\r
-       char hwaddr[512];\r
-       sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",\r
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],\r
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],\r
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],\r
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],\r
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],\r
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);\r
-\r
-       Jim_AppendString(httpstate.jim_interp, tclOutput, hwaddr, strlen(hwaddr));\r
-\r
-       Jim_SetResult(interp, tclOutput);\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-static int\r
-zylinjtag_Jim_Command_ip(Jim_Interp *interp,\r
-                                   int argc,\r
-               Jim_Obj * const *argv)\r
-{\r
-       Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);\r
-\r
-       struct ifaddrs *ifa = NULL, *ifp = NULL;\r
-\r
-       if (getifaddrs(&ifp) < 0)\r
-       {\r
-               return JIM_ERR;\r
-       }\r
-\r
-       for (ifa = ifp; ifa; ifa = ifa->ifa_next)\r
-       {\r
-               char ip[200];\r
-               socklen_t salen;\r
-\r
-               if (ifa->ifa_addr->sa_family == AF_INET)\r
-                       salen = sizeof(struct sockaddr_in);\r
-               else if (ifa->ifa_addr->sa_family == AF_INET6)\r
-                       salen = sizeof(struct sockaddr_in6);\r
-               else\r
-                       continue;\r
-\r
-               if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,\r
-                               NI_NUMERICHOST) < 0)\r
-               {\r
-                       continue;\r
-               }\r
-\r
-               Jim_AppendString(httpstate.jim_interp, tclOutput, ip, strlen(ip));\r
-               break;\r
-\r
-       }\r
-\r
-       freeifaddrs(ifp);\r
-\r
-       Jim_SetResult(interp, tclOutput);\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-extern Jim_Interp *interp;\r
-\r
-static void zylinjtag_startNetwork()\r
-{\r
-       // Bring TCP/IP up immediately before we're ready to accept commands.\r
-       //\r
-       // That is as soon as a PING responds, we're accepting telnet sessions.\r
-#if defined(CYGPKG_NET_FREEBSD_STACK)\r
-       phi_init_all_network_interfaces();\r
-#else\r
-       lwip_init();\r
-#endif\r
-       if (!eth0_up)\r
-       {\r
-               diag_printf("Network not up and running\n");\r
-               exit(-1);\r
-       }\r
-#if defined(CYGPKG_NET_FREEBSD_STACK)\r
-       /*start TFTP*/\r
-       tftpd_start(69, &fileops);\r
-#endif\r
-\r
-       cyg_httpd_init_tcl_interpreter();\r
-\r
-       interp = httpstate.jim_interp;\r
-\r
-    Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "reboot", zylinjtag_Jim_Command_reboot, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "zy1000_flash", zylinjtag_Jim_Command_flash, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "getmem", zylinjtag_Jim_Command_getmem, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "mac", zylinjtag_Jim_Command_mac, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "ip", zylinjtag_Jim_Command_ip, NULL, NULL);\r
-    Jim_CreateCommand(httpstate.jim_interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);\r
-\r
-       cyg_httpd_start();\r
-\r
-       webRunning = true;\r
-\r
-       diag_printf("Web server running\n");\r
-}\r
-\r
-static bool readPowerDropout()\r
-{\r
-       cyg_uint32 state;\r
-       // sample and clear power dropout\r
-       HAL_WRITE_UINT32(0x08000010, 0x80);\r
-       HAL_READ_UINT32(0x08000010, state);\r
-       bool powerDropout;\r
-       powerDropout = (state & 0x80) != 0;\r
-       return powerDropout;\r
-}\r
-\r
-bool readSRST()\r
-{\r
-       cyg_uint32 state;\r
-       // sample and clear SRST sensing\r
-       HAL_WRITE_UINT32(0x08000010, 0x00000040);\r
-       HAL_READ_UINT32(0x08000010, state);\r
-       bool srstAsserted;\r
-       srstAsserted = (state & 0x40) != 0;\r
-       return srstAsserted;\r
-}\r
-\r
-// every 300ms we check for reset & powerdropout and issue a "reset halt" if\r
-// so.\r
-\r
-\r
-static int sense_handler(void *priv)\r
-{\r
-       struct command_context_s *cmd_ctx;\r
-       cmd_ctx = (struct command_context_s *) priv;\r
-\r
-       static bool prevSrstAsserted = false;\r
-       static bool prevPowerdropout = false;\r
-\r
-       bool powerDropout;\r
-       powerDropout = readPowerDropout();\r
-\r
-       bool powerRestored;\r
-       powerRestored = prevPowerdropout && !powerDropout;\r
-       if (powerRestored)\r
-       {\r
-               LOG_USER("Sensed power restore.");\r
-       }\r
-\r
-       cyg_tick_count_t current = cyg_current_time();\r
-       static cyg_tick_count_t lastPower = 0;\r
-       bool waitMore = lastPower + 200 > current;\r
-       if (powerDropout && !waitMore)\r
-       {\r
-               LOG_USER("Sensed power dropout.");\r
-               lastPower = current;\r
-       }\r
-\r
-       bool srstAsserted = readSRST();\r
-\r
-       bool srstDeasserted;\r
-       srstDeasserted = prevSrstAsserted && !srstAsserted;\r
-\r
-       static cyg_tick_count_t lastSrst = 0;\r
-       waitMore = lastSrst + 200 > current;\r
-       if (srstDeasserted && !waitMore)\r
-       {\r
-               LOG_USER("Sensed nSRST deasserted");\r
-               lastSrst = current;\r
-       }\r
-\r
-       if (!prevSrstAsserted && srstAsserted)\r
-       {\r
-               LOG_USER("Sensed nSRST asserted");\r
-       }\r
-\r
-       prevSrstAsserted = srstAsserted;\r
-       prevPowerdropout = powerDropout;\r
-\r
-       if (srstDeasserted || powerRestored)\r
-       {\r
-               /* Other than logging the event we can't do anything here.\r
-                * Issuing a reset is a particularly bad idea as we might\r
-                * be inside a reset already.\r
-                */\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-\r
-static void\r
-print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_t info)\r
-{\r
-       writeLog = false;\r
-       serialLog = true;\r
-       char *infoStr = "unknown";\r
-       switch (exception)\r
-       {\r
-       case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:\r
-               infoStr = "undefined instruction";\r
-               break;\r
-       case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:\r
-               infoStr = "software interrupt";\r
-               break;\r
-       case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:\r
-               infoStr = "abort prefetch";\r
-               break;\r
-       case CYGNUM_HAL_VECTOR_ABORT_DATA:\r
-               infoStr = "abort data";\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-\r
-       diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);\r
-\r
-       diag_printf("Dumping log\n---\n");\r
-       if (logCount >= logSize)\r
-       {\r
-               diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);\r
-       }\r
-       diag_write(logBuffer, writePtr);\r
-\r
-       diag_printf("---\nLogdump complete.\n");\r
-       diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);\r
-       diag_printf("\n---\nRebooting\n");\r
-       HAL_PLATFORM_RESET();\r
-\r
-}\r
-\r
-static void setHandler(cyg_code_t exception)\r
-{\r
-       cyg_exception_handler_t *old_handler;\r
-       cyg_addrword_t old_data;\r
-\r
-       cyg_exception_set_handler(exception,\r
-       print_exception_handler,\r
-       0,\r
-       &old_handler,\r
-       &old_data);\r
-}\r
-\r
-static cyg_thread zylinjtag_uart_thread_object;\r
-static cyg_handle_t zylinjtag_uart_thread_handle;\r
-static char uart_stack[4096];\r
-\r
-static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!\r
-static char backwardBuffer[1024];\r
-\r
-static cyg_io_handle_t serial_handle;\r
-\r
-void setNoDelay(int session, int flag)\r
-{\r
-#if 1\r
-       // This decreases latency dramatically for e.g. GDB load which\r
-       // does not have a sliding window protocol\r
-       //\r
-       // Can cause *lots* of TCP/IP packets to be sent and it would have\r
-       // to be enabled/disabled on the fly to avoid the CPU being\r
-       // overloaded...\r
-       setsockopt(session, /* socket affected */\r
-       IPPROTO_TCP, /* set option at TCP level */\r
-       TCP_NODELAY, /* name of option */\r
-       (char *) &flag, /* the cast is historical\r
-        cruft */\r
-       sizeof(int)); /* length of option value */\r
-#endif\r
-}\r
-\r
-struct\r
-{\r
-       int req;\r
-       int actual;\r
-       int req2;\r
-       int actual2;\r
-} tcpipSent[512 * 1024];\r
-int cur;\r
-\r
-static void\r
-zylinjtag_uart(cyg_addrword_t data)\r
-{\r
-       int so_reuseaddr_option = 1;\r
-\r
-       int fd;\r
-       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)\r
-       {\r
-               LOG_ERROR("error creating socket: %s", strerror(errno));\r
-               exit(-1);\r
-       }\r
-\r
-       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));\r
-\r
-       struct sockaddr_in sin;\r
-       unsigned int address_size;\r
-       address_size = sizeof(sin);\r
-       memset(&sin, 0, sizeof(sin));\r
-       sin.sin_family = AF_INET;\r
-       sin.sin_addr.s_addr = INADDR_ANY;\r
-       sin.sin_port = htons(5555);\r
-\r
-       if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)\r
-       {\r
-               LOG_ERROR("couldn't bind to socket: %s", strerror(errno));\r
-               exit(-1);\r
-       }\r
-\r
-       if (listen(fd, 1) == -1)\r
-       {\r
-               LOG_ERROR("couldn't listen on socket: %s", strerror(errno));\r
-               exit(-1);\r
-       }\r
-       //      socket_nonblock(fd);\r
-\r
-\r
-       for (;;)\r
-       {\r
-               int session = accept(fd, (struct sockaddr *) &sin, &address_size);\r
-               if (session < 0)\r
-               {\r
-                       continue;\r
-               }\r
-\r
-               setNoDelay(session, 1);\r
-               int oldopts = fcntl(session, F_GETFL, 0);\r
-               fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //\r
-\r
-               int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);\r
-               if (serHandle < 0)\r
-               {\r
-                       close(session);\r
-                       continue;\r
-               }\r
-\r
-               start_profile();\r
-               int actual = 0;\r
-               int actual2 = 0;\r
-               int pos, pos2;\r
-               pos = 0;\r
-               pos2 = 0;\r
-               cur = 0;\r
-               for (;;)\r
-               {\r
-                       fd_set write_fds;\r
-                       fd_set read_fds;\r
-                       FD_ZERO(&write_fds);\r
-                       FD_ZERO(&read_fds);\r
-                       int fd_max = -1;\r
-                       FD_SET(session, &read_fds);\r
-                       fd_max = session;\r
-                       FD_SET(serHandle, &read_fds);\r
-                       if (serHandle > fd_max)\r
-                       {\r
-                               fd_max = serHandle;\r
-                       }\r
-                       /* Wait... */\r
-\r
-                       cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received\r
-                       if ((actual == 0) && (actual2 == 0))\r
-                       {\r
-                               int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);\r
-                               if (retval <= 0)\r
-                               {\r
-                                       break;\r
-                               }\r
-                       }\r
-\r
-                       if (actual2 <= 0)\r
-                       {\r
-                               memset(backwardBuffer, 's', sizeof(backwardBuffer));\r
-                               actual2=read(serHandle, backwardBuffer, sizeof(backwardBuffer));\r
-                               if (actual2 < 0)\r
-                               {\r
-                                       if (errno != EAGAIN)\r
-                                       {\r
-                                               goto closeSession;\r
-                                       }\r
-                                       actual2 = 0;\r
-                               }\r
-                               pos2 = 0;\r
-                       }\r
-\r
-                       int x = actual2;\r
-                       int y = 0;\r
-                       if (actual2 > 0)\r
-                       {\r
-                               int written = write(session, backwardBuffer + pos2, actual2);\r
-                               if (written <= 0)\r
-                                       goto closeSession;\r
-                               actual2 -= written;\r
-                               pos2 += written;\r
-                               y = written;\r
-                       }\r
-\r
-                       if (FD_ISSET(session, &read_fds)&&(sizeof(forwardBuffer)>actual))\r
-                       {\r
-                               // NB! Here it is important that we empty the TCP/IP read buffer\r
-                               // to make transmission tick right\r
-                               memmove(forwardBuffer, forwardBuffer + pos, actual);\r
-                               pos = 0;\r
-                               int t;\r
-                               // this will block if there is no data at all\r
-                               t=read_socket(session, forwardBuffer+actual, sizeof(forwardBuffer)-actual);\r
-                               if (t <= 0)\r
-                               {\r
-                                       goto closeSession;\r
-                               }\r
-                               actual += t;\r
-                       }\r
-\r
-                       int x2 = actual;\r
-                       int y2 = 0;\r
-                       if (actual > 0)\r
-                       {\r
-                               /* Do not put things into the serial buffer if it has something to send\r
-                                * as that can cause a single byte to be sent at the time.\r
-                                *\r
-                                *\r
-                                */\r
-                               int written = write(serHandle, forwardBuffer + pos, actual);\r
-                               if (written < 0)\r
-                               {\r
-                                       if (errno != EAGAIN)\r
-                                       {\r
-                                               goto closeSession;\r
-                                       }\r
-                                       // The serial buffer is full\r
-                                       written = 0;\r
-                               } else\r
-                               {\r
-                                       actual -= written;\r
-                                       pos += written;\r
-                               }\r
-                               y2 = written;\r
-                       }\r
-                       if (cur < 1024)\r
-                       {\r
-                               tcpipSent[cur].req = x;\r
-                               tcpipSent[cur].actual = y;\r
-                               tcpipSent[cur].req2 = x2;\r
-                               tcpipSent[cur].actual2 = y2;\r
-                               cur++;\r
-                       }\r
-\r
-               }\r
-           closeSession:\r
-           close(session);\r
-               close(serHandle);\r
-\r
-               int i;\r
-               for (i = 0; i < 1024; i++)\r
-               {\r
-               diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual, tcpipSent[i].req2, tcpipSent[i].actual2);\r
-\r
-               }\r
-       }\r
-       close(fd);\r
-\r
-}\r
-\r
-void startUart(void)\r
-{\r
-    cyg_thread_create(1,\r
-                      zylinjtag_uart,\r
-                      (cyg_addrword_t)0,\r
-                      "uart thread",\r
-                      (void *)uart_stack,\r
-                      sizeof(uart_stack),\r
-                      &zylinjtag_uart_thread_handle,\r
-                      &zylinjtag_uart_thread_object);\r
-       cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop\r
-       cyg_thread_resume(zylinjtag_uart_thread_handle);\r
-}\r
-\r
-\r
-\r
-int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: uart <baudrate>");\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       int baud = atol(args[0]);\r
-\r
-       switch (baud)\r
-       {\r
-       case 9600:\r
-               baud = CYGNUM_SERIAL_BAUD_9600;\r
-               break;\r
-       case 19200:\r
-               baud = CYGNUM_SERIAL_BAUD_19200;\r
-               break;\r
-       case 38400:\r
-               baud = CYGNUM_SERIAL_BAUD_38400;\r
-               break;\r
-       case 57600:\r
-               baud = CYGNUM_SERIAL_BAUD_57600;\r
-               break;\r
-       case 115200:\r
-               baud = CYGNUM_SERIAL_BAUD_115200;\r
-               break;\r
-       case 230400:\r
-               baud = CYGNUM_SERIAL_BAUD_230400;\r
-               break;\r
-       default:\r
-               command_print(cmd_ctx, "unsupported baudrate");\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       cyg_serial_info_t buf;\r
-       cyg_uint32 len = 1;\r
-       //get existing serial configuration\r
-       len = sizeof(cyg_serial_info_t);\r
-       int err;\r
-       err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);\r
-       err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf, &len);\r
-       if (err != ENOERR)\r
-       {\r
-               command_print(cmd_ctx, "Failed to get serial port settings %d", err);\r
-               return ERROR_OK;\r
-       }\r
-       buf.baud = baud;\r
-\r
-       err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf, &len);\r
-       if (err != ENOERR)\r
-       {\r
-               command_print(cmd_ctx, "Failed to set serial port settings %d", err);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-bool logAllToSerial = false;\r
-\r
-/* boolean parameter stored on config */\r
-bool boolParam(char *var)\r
-{\r
-       bool result = false;\r
-       char *name = alloc_printf(ZYLIN_CONFIG_DIR "/%s", var);\r
-       if (name == NULL)\r
-               return result;\r
-\r
-       void *data;\r
-       int len;\r
-       if (loadFile(name, &data, &len) == ERROR_OK)\r
-       {\r
-               if (len > 1)\r
-                       len = 1;\r
-               result = strncmp((char *) data, "1", len) == 0;\r
-               free(data);\r
-       }\r
-       free(name);\r
-       return result;\r
-}\r
-\r
-command_context_t *setup_command_handler();\r
-\r
-int add_default_dirs(void)\r
-{\r
-       add_script_search_dir(ZYLIN_CONFIG_DIR);\r
-       add_script_search_dir("/rom/lib/openocd");\r
-       add_script_search_dir("/rom");\r
-       return ERROR_OK;\r
-}\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-       setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);\r
-       setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);\r
-       setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);\r
-\r
-       int err;\r
-       err = cyg_io_lookup("/dev/ser0", &serial_handle);\r
-       if (err != ENOERR)\r
-       {\r
-               diag_printf("/dev/ser0 not found\n");\r
-               reboot();\r
-       }\r
-\r
-       setPower(true); // on by default\r
-\r
-       atexit(keep_webserver);\r
-\r
-       err = mount("", "/ram", "ramfs");\r
-       if (err < 0)\r
-       {\r
-               diag_printf("unable to mount ramfs\n");\r
-       }\r
-       chdir("/ram");\r
-\r
-       char address[16];\r
-       sprintf(address, "%p", &filedata[0]);\r
-       err = mount(address, "/rom", "romfs");\r
-       if (err < 0)\r
-       {\r
-               diag_printf("unable to mount /rom\n");\r
-       }\r
-\r
-       err = mount("", "/log", "logfs");\r
-       if (err < 0)\r
-       {\r
-               diag_printf("unable to mount logfs\n");\r
-       }\r
-\r
-       err = mount("", "/tftp", "tftpfs");\r
-       if (err < 0)\r
-       {\r
-               diag_printf("unable to mount logfs\n");\r
-       }\r
-\r
-       log = fopen("/log/log", "w");\r
-       if (log == NULL)\r
-       {\r
-               diag_printf("Could not open log file /ram/log\n");\r
-               exit(-1);\r
-       }\r
-\r
-       diag_init_putc(_zylinjtag_diag_write_char);\r
-\r
-       // We want this in the log.\r
-       diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");\r
-       diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);\r
-\r
-       copydir("/rom/");\r
-\r
-       err = mount("/dev/flash1", "/config", "jffs2");\r
-       if (err < 0)\r
-       {\r
-               diag_printf("unable to mount jffs\n");\r
-       }\r
-\r
-\r
-       mkdir(ZYLIN_CONFIG_DIR, 0777);\r
-       mkdir(ZYLIN_CONFIG_DIR "/target", 0777);\r
-       mkdir(ZYLIN_CONFIG_DIR "/event", 0777);\r
-\r
-       logAllToSerial = boolParam("logserial");\r
-\r
-       // We need the network & web server in case there is something wrong with\r
-       // the config files that invoke exit()\r
-       zylinjtag_startNetwork();\r
-\r
-       /* we're going to access the jim interpreter from here on... */\r
-       openocd_sleep_postlude();\r
-       startUart();\r
-\r
-       add_default_dirs();\r
-\r
-       /* initialize commandline interface */\r
-       command_context_t *cmd_ctx;\r
-       cmd_ctx = setup_command_handler();\r
-       command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);\r
-       command_context_mode(cmd_ctx, COMMAND_CONFIG);\r
-\r
-\r
-       register_command(cmd_ctx, NULL, "zy1000_version", handle_zy1000_version_command,\r
-                       COMMAND_EXEC, "show zy1000 version numbers");\r
-\r
-       register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,\r
-                       "rm <filname>");\r
-\r
-       register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,\r
-                       "same args as load_image, image stored in memory");\r
-\r
-       register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY,\r
-                       "loads active fast load image to current target");\r
-\r
-       register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,\r
-                       "cat <filname>");\r
-\r
-       register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,\r
-                       "trunc <filname>");\r
-\r
-       register_command(cmd_ctx, NULL, "append_file", handle_append_command,\r
-                       COMMAND_ANY, "append <filname>");\r
-\r
-       register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,\r
-                       "power <on/off> - turn power switch to target on/off. No arguments - print status.");\r
-\r
-       register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,\r
-                       COMMAND_ANY, "meminfo");\r
-\r
-       register_command(cmd_ctx, NULL, "cp", handle_cp_command,\r
-                                        COMMAND_ANY, "cp <from> <to>");\r
-\r
-#ifdef CYGPKG_PROFILE_GPROF\r
-       register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,\r
-                       COMMAND_ANY, NULL);\r
-#endif\r
-       register_command(cmd_ctx, NULL, "uart", handle_uart_command,\r
-                                        COMMAND_ANY, "uart <baud>  - forward uart on port 5555");\r
-\r
-\r
-       int errVal;\r
-       errVal = log_init(cmd_ctx);\r
-       if (errVal != ERROR_OK)\r
-       {\r
-               diag_printf("log_init() failed %d\n", errVal);\r
-               exit(-1);\r
-       }\r
-\r
-       set_log_output(cmd_ctx, log);\r
-\r
-       LOG_DEBUG("log init complete");\r
-\r
-       //      diag_printf("Executing config files\n");\r
-\r
-       if (logAllToSerial)\r
-       {\r
-               diag_printf(ZYLIN_CONFIG_DIR "/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");\r
-               command_run_line(cmd_ctx, "debug_level 3");\r
-       }\r
-\r
-       zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");\r
-\r
-       target_register_timer_callback(sense_handler, 200, 1, cmd_ctx);\r
-\r
-       // FIX!!!  Yuk!\r
-       // diag_printf() is really invoked from many more places than we trust it\r
-       // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).\r
-       //\r
-       // Disabling it here is safe and gives us enough logged debug output for now. Crossing\r
-       // fingers that it doesn't cause any crashes.\r
-       diag_printf("Init complete, GDB & telnet servers launched.\n");\r
-       command_set_output_handler(cmd_ctx, zy1000_configuration_output_handler_log, NULL);\r
-       if (!logAllToSerial)\r
-       {\r
-               serialLog = false;\r
-       }\r
-\r
-       /* handle network connections */\r
-       server_loop(cmd_ctx);\r
-       openocd_sleep_prelude();\r
-\r
-       /* shut server down */\r
-       server_quit();\r
-\r
-       /* free commandline interface */\r
-       command_done(cmd_ctx);\r
-       umount("/config");\r
-\r
-       exit(0);\r
-       for (;;);\r
-}\r
-\r
-\r
-\r
-cyg_int32\r
-cyg_httpd_exec_cgi_tcl(char *file_name);\r
-cyg_int32 homeForm(CYG_HTTPD_STATE *p)\r
-{\r
-       cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");\r
-       return 0;\r
-}\r
-\r
-CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);\r
-\r
-CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");\r
-CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");\r
-\r
-#include <pkgconf/system.h>\r
-#include <pkgconf/hal.h>\r
-#include <pkgconf/kernel.h>\r
-#include <pkgconf/io_fileio.h>\r
-#include <pkgconf/fs_rom.h>\r
-\r
-#include <cyg/kernel/ktypes.h>         // base kernel types\r
-#include <cyg/infra/cyg_trac.h>        // tracing macros\r
-#include <cyg/infra/cyg_ass.h>         // assertion macros\r
-#include <unistd.h>\r
-#include <sys/types.h>\r
-#include <fcntl.h>\r
-#include <sys/stat.h>\r
-#include <errno.h>\r
-#include <dirent.h>\r
-\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#include <cyg/fileio/fileio.h>\r
-\r
-#include <cyg/kernel/kapi.h>\r
-#include <cyg/infra/diag.h>\r
-\r
-//==========================================================================\r
-// Eventually we want to eXecute In Place from the ROM in a protected\r
-// environment, so we'll need executables to be aligned to a boundary\r
-// suitable for MMU protection. A suitable boundary would be the 4k\r
-// boundary in all the CPU architectures I am currently aware of.\r
-\r
-// Forward definitions\r
-\r
-// Filesystem operations\r
-static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);\r
-static int tftpfs_umount(cyg_mtab_entry *mte);\r
-static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
-               int mode, cyg_file *fte);\r
-static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);\r
-static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);\r
-\r
-// File operations\r
-static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);\r
-static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);\r
-static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);\r
-\r
-//==========================================================================\r
-// Filesystem table entries\r
-\r
-// -------------------------------------------------------------------------\r
-// Fstab entry.\r
-// This defines the entry in the filesystem table.\r
-// For simplicity we use _FILESYSTEM synchronization for all accesses since\r
-// we should never block in any filesystem operations.\r
-#if 1\r
-FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,\r
-               CYG_SYNCMODE_NONE,\r
-               tftpfs_mount,\r
-               tftpfs_umount,\r
-               tftpfs_open,\r
-               (cyg_fsop_unlink *)cyg_fileio_erofs,\r
-               (cyg_fsop_mkdir *)cyg_fileio_erofs,\r
-               (cyg_fsop_rmdir *)cyg_fileio_erofs,\r
-               (cyg_fsop_rename *)cyg_fileio_erofs,\r
-               (cyg_fsop_link *)cyg_fileio_erofs,\r
-               (cyg_fsop_opendir *)cyg_fileio_erofs,\r
-               (cyg_fsop_chdir *)cyg_fileio_erofs,\r
-               (cyg_fsop_stat *)cyg_fileio_erofs,\r
-               (cyg_fsop_getinfo *)cyg_fileio_erofs,\r
-               (cyg_fsop_setinfo *)cyg_fileio_erofs);\r
-#endif\r
-\r
-// -------------------------------------------------------------------------\r
-// mtab entry.\r
-// This defines a single ROMFS loaded into ROM at the configured address\r
-//\r
-// MTAB_ENTRY( rom_mte,        // structure name\r
-//             "/rom",         // mount point\r
-//             "romfs",        // FIlesystem type\r
-//             "",             // hardware device\r
-//  (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS  // Address in ROM\r
-//           );\r
-\r
-\r
-// -------------------------------------------------------------------------\r
-// File operations.\r
-// This set of file operations are used for normal open files.\r
-\r
-static cyg_fileops tftpfs_fileops =\r
-{\r
-       tftpfs_fo_read,\r
-       tftpfs_fo_write,\r
-       tftpfs_fo_lseek,\r
-       (cyg_fileop_ioctl *)cyg_fileio_erofs,\r
-    cyg_fileio_seltrue,\r
-    tftpfs_fo_fsync,\r
-    tftpfs_fo_close,\r
-               (cyg_fileop_fstat *) cyg_fileio_erofs,\r
-               (cyg_fileop_getinfo *) cyg_fileio_erofs,\r
-       (cyg_fileop_setinfo *)cyg_fileio_erofs,\r
-};\r
-\r
-// -------------------------------------------------------------------------\r
-// tftpfs_mount()\r
-// Process a mount request. This mainly finds root for the\r
-// filesystem.\r
-\r
-static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)\r
-{\r
-       return ENOERR;\r
-}\r
-\r
-static int tftpfs_umount(cyg_mtab_entry *mte)\r
-{\r
-       return ENOERR;\r
-}\r
-\r
-struct Tftp\r
-{\r
-       int write;\r
-       int readFile;\r
-       cyg_uint8 *mem;\r
-       int actual;\r
-       char *server;\r
-       char *file;\r
-};\r
-\r
-static void freeTftp(struct Tftp *t)\r
-{\r
-       if (t == NULL)\r
-               return;\r
-       if (t->mem)\r
-               free(t->mem);\r
-       if (t->server)\r
-               free(t->server);\r
-       if (t->file)\r
-               free(t->file);\r
-       free(t);\r
-}\r
-\r
-static const int tftpMaxSize = 8192 * 1024;\r
-static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
-               int mode, cyg_file *file)\r
-{\r
-       struct Tftp *tftp;\r
-       tftp = malloc(sizeof(struct Tftp));\r
-       if (tftp == NULL)\r
-               return EMFILE;\r
-       memset(tftp, 0, sizeof(struct Tftp));\r
-\r
-       file->f_flag |= mode & CYG_FILE_MODE_MASK;\r
-       file->f_type = CYG_FILE_TYPE_FILE;\r
-       file->f_ops = &tftpfs_fileops;\r
-       file->f_offset = 0;\r
-       file->f_data = 0;\r
-       file->f_xops = 0;\r
-\r
-       tftp->mem = malloc(tftpMaxSize);\r
-       if (tftp->mem == NULL)\r
-       {\r
-               freeTftp(tftp);\r
-               return EMFILE;\r
-       }\r
-\r
-       char *server = strchr(name, '/');\r
-       if (server == NULL)\r
-       {\r
-               freeTftp(tftp);\r
-               return EMFILE;\r
-       }\r
-\r
-       tftp->server = malloc(server - name + 1);\r
-       if (tftp->server == NULL)\r
-       {\r
-               freeTftp(tftp);\r
-               return EMFILE;\r
-       }\r
-       strncpy(tftp->server, name, server - name);\r
-       tftp->server[server - name] = 0;\r
-\r
-       tftp->file = strdup(server + 1);\r
-       if (tftp->file == NULL)\r
-       {\r
-               freeTftp(tftp);\r
-               return EMFILE;\r
-       }\r
-\r
-       file->f_data = (CYG_ADDRWORD) tftp;\r
-\r
-       return ENOERR;\r
-}\r
-\r
-static int fetchTftp(struct Tftp *tftp)\r
-{\r
-       if (!tftp->readFile)\r
-       {\r
-               int err;\r
-           tftp->actual = tftp_client_get( tftp->file, tftp->server, 0, tftp->mem, tftpMaxSize,   TFTP_OCTET, &err);\r
-\r
-               if (tftp->actual < 0)\r
-               {\r
-                       return EMFILE;\r
-               }\r
-               tftp->readFile = 1;\r
-       }\r
-       return ENOERR;\r
-}\r
-\r
-// -------------------------------------------------------------------------\r
-// tftpfs_fo_write()\r
-// Read data from file.\r
-\r
-static int\r
-tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)\r
-{\r
-       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
-\r
-       if (fetchTftp(tftp) != ENOERR)\r
-               return EMFILE;\r
-\r
-       int i;\r
-       off_t pos = fp->f_offset;\r
-       int resid = 0;\r
-       for (i = 0; i < uio->uio_iovcnt; i++)\r
-       {\r
-               cyg_iovec *iov = &uio->uio_iov[i];\r
-               char *buf = (char *) iov->iov_base;\r
-               off_t len = iov->iov_len;\r
-\r
-               if (len + pos > tftp->actual)\r
-               {\r
-                       len = tftp->actual - pos;\r
-               }\r
-               resid += iov->iov_len - len;\r
-\r
-               memcpy(buf, tftp->mem + pos, len);\r
-               pos += len;\r
-\r
-       }\r
-       uio->uio_resid = resid;\r
-       fp->f_offset = pos;\r
-\r
-       return ENOERR;\r
-}\r
-\r
-\r
-static int\r
-tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)\r
-{\r
-       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
-\r
-       int i;\r
-       off_t pos = fp->f_offset;\r
-       int resid = 0;\r
-       for (i = 0; i < uio->uio_iovcnt; i++)\r
-       {\r
-               cyg_iovec *iov = &uio->uio_iov[i];\r
-               char *buf = (char *) iov->iov_base;\r
-               off_t len = iov->iov_len;\r
-\r
-               if (len + pos > tftpMaxSize)\r
-               {\r
-                       len = tftpMaxSize - pos;\r
-               }\r
-               resid += iov->iov_len - len;\r
-\r
-               memcpy(tftp->mem + pos, buf, len);\r
-               pos += len;\r
-\r
-       }\r
-       uio->uio_resid = resid;\r
-       fp->f_offset = pos;\r
-\r
-       tftp->write = 1;\r
-\r
-       return ENOERR;\r
-}\r
-\r
-static int\r
-tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)\r
-{\r
-       int error = ENOERR;\r
-       return error;\r
-}\r
-\r
-// -------------------------------------------------------------------------\r
-// romfs_fo_close()\r
-// Close a file. We just clear out the data pointer.\r
-\r
-static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)\r
-{\r
-       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
-       int error = ENOERR;\r
-\r
-       if (tftp->write)\r
-       {\r
-           tftp_client_put( tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,   TFTP_OCTET, &error);\r
-       }\r
-\r
-       freeTftp(tftp);\r
-       fp->f_data = 0;\r
-       return error;\r
-}\r
-\r
-// -------------------------------------------------------------------------\r
-// romfs_fo_lseek()\r
-// Seek to a new file position.\r
-\r
-static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)\r
-{\r
-       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
-       off_t pos = *apos;\r
-\r
-       if (fetchTftp(tftp) != ENOERR)\r
-               return EMFILE;\r
-\r
-       switch (whence)\r
-       {\r
-       case SEEK_SET:\r
-               // Pos is already where we want to be.\r
-               break;\r
-\r
-       case SEEK_CUR:\r
-               // Add pos to current offset.\r
-               pos += fp->f_offset;\r
-               break;\r
-\r
-       case SEEK_END:\r
-               // Add pos to file size.\r
-               pos += tftp->actual;\r
-               break;\r
-\r
-       default:\r
-               return EINVAL;\r
-       }\r
-\r
-       // Check that pos is still within current file size, or at the\r
-       // very end.\r
-       if (pos < 0 || pos > tftp->actual)\r
-               return EINVAL;\r
-\r
-       // All OK, set fp offset and return new position.\r
-       *apos = fp->f_offset = pos;\r
-\r
-       return ENOERR;\r
-}\r
-\r
-void usleep(int us)\r
-{\r
-       if (us > 10000)\r
-               cyg_thread_delay(us / 10000 + 1);\r
-       else\r
-               HAL_DELAY_US(us);\r
-}\r
-\r
-// Chunked version.\r
-cyg_int32\r
-show_log_entry(CYG_HTTPD_STATE *phttpstate)\r
-{\r
-       cyg_httpd_start_chunked("text");\r
-       if (logCount >= logSize)\r
-       {\r
-        cyg_httpd_write_chunked(logBuffer+logCount%logSize, logSize-logCount%logSize);\r
-       }\r
-       cyg_httpd_write_chunked(logBuffer, writePtr);\r
-       cyg_httpd_end_chunked();\r
-       return -1;\r
-}\r
-\r
-CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);\r
-\r
-// Filesystem operations\r
-static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);\r
-static int logfs_umount(cyg_mtab_entry *mte);\r
-static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
-               int mode, cyg_file *fte);\r
-static int\r
-logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);\r
-\r
-// File operations\r
-static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);\r
-static int logfs_fo_close(struct CYG_FILE_TAG *fp);\r
-\r
-//==========================================================================\r
-// Filesystem table entries\r
-\r
-// -------------------------------------------------------------------------\r
-// Fstab entry.\r
-// This defines the entry in the filesystem table.\r
-// For simplicity we use _FILESYSTEM synchronization for all accesses since\r
-// we should never block in any filesystem operations.\r
-FSTAB_ENTRY( logfs_fste, "logfs", 0,\r
-               CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,\r
-               logfs_mount,\r
-               logfs_umount,\r
-               logfs_open,\r
-               (cyg_fsop_unlink *)cyg_fileio_erofs,\r
-               (cyg_fsop_mkdir *)cyg_fileio_erofs,\r
-               (cyg_fsop_rmdir *)cyg_fileio_erofs,\r
-               (cyg_fsop_rename *)cyg_fileio_erofs,\r
-               (cyg_fsop_link *)cyg_fileio_erofs,\r
-               (cyg_fsop_opendir *)cyg_fileio_erofs,\r
-               (cyg_fsop_chdir *)cyg_fileio_erofs,\r
-               (cyg_fsop_stat *)cyg_fileio_erofs,\r
-               (cyg_fsop_getinfo *)cyg_fileio_erofs,\r
-               (cyg_fsop_setinfo *)cyg_fileio_erofs);\r
-\r
-// -------------------------------------------------------------------------\r
-// File operations.\r
-// This set of file operations are used for normal open files.\r
-\r
-static cyg_fileops logfs_fileops =\r
-{\r
-       (cyg_fileop_read *)cyg_fileio_erofs,\r
-    (cyg_fileop_write *)logfs_fo_write,\r
-               (cyg_fileop_lseek *) cyg_fileio_erofs,\r
-       (cyg_fileop_ioctl *)cyg_fileio_erofs,\r
-    cyg_fileio_seltrue,\r
-    logfs_fo_fsync,\r
-    logfs_fo_close,\r
-       (cyg_fileop_fstat *)cyg_fileio_erofs,\r
-               (cyg_fileop_getinfo *) cyg_fileio_erofs,\r
-       (cyg_fileop_setinfo *)cyg_fileio_erofs,\r
-};\r
-\r
-// -------------------------------------------------------------------------\r
-// logfs_mount()\r
-// Process a mount request. This mainly finds root for the\r
-// filesystem.\r
-\r
-static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)\r
-{\r
-       return ENOERR;\r
-}\r
-\r
-static int logfs_umount(cyg_mtab_entry *mte)\r
-{\r
-       return ENOERR;\r
-}\r
-\r
-static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
-               int mode, cyg_file *file)\r
-{\r
-       file->f_flag |= mode & CYG_FILE_MODE_MASK;\r
-       file->f_type = CYG_FILE_TYPE_FILE;\r
-       file->f_ops = &logfs_fileops;\r
-       file->f_offset = 0;\r
-       file->f_data = 0;\r
-       file->f_xops = 0;\r
-       return ENOERR;\r
-}\r
-\r
-// -------------------------------------------------------------------------\r
-// logfs_fo_write()\r
-// Write data to file.\r
-\r
-static int\r
-logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)\r
-{\r
-       int i;\r
-       for (i = 0; i < uio->uio_iovcnt; i++)\r
-       {\r
-               cyg_iovec *iov = &uio->uio_iov[i];\r
-               char *buf = (char *) iov->iov_base;\r
-               off_t len = iov->iov_len;\r
-\r
-               diag_write(buf, len);\r
-       }\r
-       uio->uio_resid = 0;\r
-\r
-       return ENOERR;\r
-}\r
-static int\r
-logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)\r
-{\r
-       return ENOERR;\r
-}\r
-\r
-// -------------------------------------------------------------------------\r
-// romfs_fo_close()\r
-// Close a file. We just clear out the data pointer.\r
-\r
-static int logfs_fo_close(struct CYG_FILE_TAG *fp)\r
-{\r
-       return ENOERR;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007-2009 by Ã˜yvind Harboe                              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/types.h>
+#include <jtag/jtag.h>
+#include <helper/ioutil.h>
+#include <helper/configuration.h>
+#include "xsvf.h"
+#include "svf.h"
+#include "nand.h"
+#include "pld.h"
+
+#include "server.h"
+#include "telnet_server.h"
+#include "gdb_server.h"
+#include "openocd.h"
+
+#include <time_support.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <cyg/io/flash.h>
+#include <pkgconf/fs_jffs2.h>  // Address of JFFS2
+#include <network.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <cyg/fileio/fileio.h>
+#include <dirent.h>
+#include <cyg/athttpd/http.h>
+#include <cyg/athttpd/socket.h>
+#include <cyg/athttpd/handler.h>
+#include <cyg/athttpd/cgi.h>
+#include <cyg/athttpd/forms.h>
+#include <cyg/discover/discover.h>
+#include <cyg/hal/hal_diag.h>
+#include <cyg/kernel/kapi.h>
+#include <cyg/io/serialio.h>
+#include <cyg/io/io.h>
+#include <netinet/tcp.h>
+#include "rom.h"
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <ifaddrs.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <stdio.h>
+
+#include <openocd.h>
+
+#ifdef CYGPKG_HAL_NIOS2
+#define ZY1000_SER_DEV "/dev/uart_0"
+#else
+#define ZY1000_SER_DEV "/dev/ser0"
+
+#endif
+
+
+#define MAX_IFS 64
+#if defined(CYGPKG_NET_FREEBSD_STACK)
+#include <tftp_support.h>
+/* posix compatibility broken*/
+struct tftpd_fileops fileops =
+{
+       (int (*)(const char *, int))open,
+       close,
+       (int (*)(int, const void *, int))write,
+       (int (*)(int, void *, int))read
+};
+
+#endif
+
+
+void diag_write(char *buf, int len)
+{
+       int j;
+       for (j = 0; j < len; j++)
+       {
+               diag_printf("%c", buf[j]);
+       }
+}
+
+static bool serialLog = true;
+static bool writeLog = true;
+
+char hwaddr[512];
+
+
+extern struct flash_driver *flash_drivers[];
+extern struct target_type *target_types[];
+
+#ifdef CYGPKG_PROFILE_GPROF
+#include <cyg/profile/profile.h>
+
+extern char _stext, _etext; // Defined by the linker
+
+static char *start_of_code=&_stext;
+static char *end_of_code=&_etext;
+
+void start_profile(void)
+{
+       // This starts up the system-wide profiling, gathering
+       // profile information on all of the code, with a 16 byte
+       // "bucket" size, at a rate of 100us/profile hit.
+       // Note: a bucket size of 16 will give pretty good function
+       //       resolution.  Much smaller and the buffer becomes
+       //       much too large for very little gain.
+       // Note: a timer period of 100us is also a reasonable
+       //       compromise.  Any smaller and the overhead of
+       //       handling the timter (profile) interrupt could
+       //       swamp the system.  A fast processor might get
+       //       by with a smaller value, but a slow one could
+       //       even be swamped by this value.  If the value is
+       //       too large, the usefulness of the profile is reduced.
+
+       // no more interrupts than 1/10ms.
+       //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
+       //      profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
+       profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
+}
+#endif
+
+static FILE *log;
+
+static char reboot_stack[2048];
+
+static void zylinjtag_reboot(cyg_addrword_t data)
+{
+       serialLog = true;
+       diag_printf("Rebooting in 500 ticks..\n");
+       cyg_thread_delay(500);
+       diag_printf("Unmounting /config..\n");
+       umount("/config");
+       diag_printf("Rebooting..\n");
+       HAL_PLATFORM_RESET();
+}
+static cyg_thread zylinjtag_thread_object;
+static cyg_handle_t zylinjtag_thread_handle;
+
+void reboot(void)
+{
+       cyg_thread_create(1, zylinjtag_reboot, (cyg_addrword_t) 0, "reboot Thread",
+                       (void *) reboot_stack, sizeof(reboot_stack),
+                       &zylinjtag_thread_handle, &zylinjtag_thread_object);
+       cyg_thread_resume(zylinjtag_thread_handle);
+}
+
+static char zylinjtag_reboot_port_stack[2048];
+static cyg_thread zylinjtag_reboot_port_thread_object;
+static cyg_handle_t zylinjtag_reboot_port_thread_handle;
+
+static void zylinjtag_reboot_port_task(cyg_addrword_t data)
+{
+       int so_reuseaddr_option = 1;
+
+       int fd;
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+       {
+               LOG_ERROR("error creating socket: %s", strerror(errno));
+               exit(-1);
+       }
+
+       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
+                       sizeof(int));
+
+       struct sockaddr_in sin;
+       unsigned int address_size;
+       address_size = sizeof(sin);
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = INADDR_ANY;
+       sin.sin_port = htons(1234);
+
+       if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
+       {
+               LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
+               exit(-1);
+       }
+
+       if (listen(fd, 1) == -1)
+       {
+               LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
+               exit(-1);
+       }
+       //      socket_nonblock(fd);
+
+
+       accept(fd, (struct sockaddr *) &sin, &address_size);
+
+       diag_printf("Got reboot signal on port 1234");
+
+       reboot();
+
+}
+
+void reboot_port(void)
+{
+       cyg_thread_create(1, zylinjtag_reboot_port_task, (cyg_addrword_t) 0, "wait for reboot signal on port 1234",
+                       (void *) zylinjtag_reboot_port_stack, sizeof(zylinjtag_reboot_port_stack),
+                       &zylinjtag_reboot_port_thread_handle, &zylinjtag_reboot_port_thread_object);
+       cyg_thread_resume(zylinjtag_reboot_port_thread_handle);
+}
+
+int configuration_output_handler(struct command_context *context,
+               const char* line)
+{
+       diag_printf("%s", line);
+
+       return ERROR_OK;
+}
+
+int zy1000_configuration_output_handler_log(struct command_context *context,
+               const char* line)
+{
+       LOG_USER_N("%s", line);
+
+       return ERROR_OK;
+}
+
+#ifdef CYGPKG_PROFILE_GPROF
+
+int eCosBoard_handle_eCosBoard_profile_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc)
+{
+       command_print(cmd_ctx, "Profiling started");
+       start_profile();
+       return ERROR_OK;
+}
+
+#endif
+
+externC void phi_init_all_network_interfaces(void);
+
+struct command_context *cmd_ctx;
+
+static bool webRunning = false;
+
+void keep_webserver(void)
+{
+       // Target initialisation is only attempted at startup, so we sleep forever and
+       // let the http server bail us out(i.e. get config files set up).
+       diag_printf("OpenOCD has invoked exit().\n"
+               "Use web server to correct any configuration settings and reboot.\n");
+       if (!webRunning)
+               reboot();
+
+       // exit() will terminate the current thread and we we'll then sleep eternally or
+       // we'll have a reboot scheduled.
+}
+
+extern void printDccChar(char c);
+
+static char logBuffer[128 * 1024];
+static const int logSize = sizeof(logBuffer);
+int writePtr = 0;
+int logCount = 0;
+
+void _zylinjtag_diag_write_char(char c, void **param)
+{
+       if (writeLog)
+       {
+               logBuffer[writePtr] = c;
+               writePtr = (writePtr + 1) % logSize;
+               logCount++;
+       }
+       if (serialLog)
+       {
+               if (c == '\n')
+               {
+                       HAL_DIAG_WRITE_CHAR('\r');
+               }
+               HAL_DIAG_WRITE_CHAR(c);
+       }
+
+#ifdef CYGPKG_HAL_ZYLIN_PHI
+       printDccChar(c);
+#endif
+}
+
+void copyfile(char *name2, char *name1);
+
+void copydir(char *name, char *destdir);
+
+#if 0
+MTAB_ENTRY(romfs_mte1,
+               "/rom",
+               "romfs",
+               "",
+               (CYG_ADDRWORD) &filedata[0]);
+#endif
+
+void openocd_sleep_prelude(void)
+{
+       cyg_mutex_unlock(&httpstate.jim_lock);
+}
+
+void openocd_sleep_postlude(void)
+{
+       cyg_mutex_lock(&httpstate.jim_lock);
+}
+
+void format(void)
+{
+#ifdef CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1
+       diag_printf("Formatting JFFS2...\n");
+
+       cyg_io_handle_t handle;
+
+       Cyg_ErrNo err;
+       err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
+       if (err != ENOERR)
+       {
+               diag_printf("Flash Error cyg_io_lookup: %d\n", err);
+               reboot();
+       }
+
+       cyg_uint32 len;
+       cyg_io_flash_getconfig_devsize_t ds;
+       len = sizeof(ds);
+       err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
+       if (err != ENOERR)
+       {
+               diag_printf("Flash error cyg_io_get_config %d\n", err);
+               reboot();
+       }
+
+       cyg_io_flash_getconfig_erase_t e;
+       len = sizeof(e);
+
+       e.offset = 0;
+       e.len = ds.dev_size;
+
+       diag_printf("Formatting 0x%08x bytes\n", (int)ds.dev_size);
+       err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len);
+       if (err != ENOERR)
+       {
+               diag_printf("Flash erase error %d offset 0x%08x\n", err, e.err_address);
+               reboot();
+       }
+
+       diag_printf("Flash formatted successfully\n");
+#endif
+
+       reboot();
+}
+
+static int zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       if (argc != 1)
+       {
+               return JIM_ERR;
+       }
+
+       format();
+       for (;;)
+               ;
+}
+
+static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       cyg_handle_t thread = 0;
+       cyg_uint16 id = 0;
+       Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
+
+       /* Loop over the threads, and generate a table row for
+        * each.
+        */
+       while (cyg_thread_get_next(&thread, &id))
+       {
+               Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
+
+               cyg_thread_info info;
+               char *state_string;
+
+               cyg_thread_get_info(thread, id, &info);
+
+               if (info.name == NULL)
+                       info.name = "<no name>";
+
+               Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
+                               info.name, strlen(info.name)));
+
+               /* Translate the state into a string.
+                */
+               if (info.state == 0)
+                       state_string = "RUN";
+               else if (info.state & 0x04)
+                       state_string = "SUSP";
+               else
+                       switch (info.state & 0x1b)
+                       {
+                       case 0x01:
+                               state_string = "SLEEP";
+                               break;
+                       case 0x02:
+                               state_string = "CNTSLEEP";
+                               break;
+                       case 0x08:
+                               state_string = "CREATE";
+                               break;
+                       case 0x10:
+                               state_string = "EXIT";
+                               break;
+                       default:
+                               state_string = "????";
+                               break;
+                       }
+
+               Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
+                               state_string, strlen(state_string)));
+
+               Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, id));
+               Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
+                               info.set_pri));
+               Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
+                               info.cur_pri));
+
+               Jim_ListAppendElement(interp, threads, threadObj);
+       }
+       Jim_SetResult(interp, threads);
+
+       return JIM_OK;
+}
+
+static int zylinjtag_Jim_Command_log(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
+
+       if (logCount >= logSize)
+       {
+               Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer + logCount
+                               % logSize, logSize - logCount % logSize);
+       }
+       Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
+
+       Jim_SetResult(interp, tclOutput);
+       return JIM_OK;
+}
+
+static int zylinjtag_Jim_Command_reboot(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       reboot();
+       return JIM_OK;
+}
+
+static void zylinjtag_startNetwork(void)
+{
+       // Bring TCP/IP up immediately before we're ready to accept commands.
+       //
+       // That is as soon as a PING responds, we're accepting telnet sessions.
+#if defined(CYGPKG_NET_FREEBSD_STACK)
+       phi_init_all_network_interfaces();
+#else
+       lwip_init();
+#endif
+       if (!eth0_up)
+       {
+               diag_printf("Network not up and running\n");
+               exit(-1);
+       }
+
+       /* very first thing we want is a reboot capability */
+       reboot_port();
+
+#if defined(CYGPKG_NET_FREEBSD_STACK)
+       /*start TFTP*/
+       tftpd_start(69, &fileops);
+#endif
+
+       cyg_httpd_init_tcl_interpreter();
+
+       Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
+                       NULL, NULL);
+       Jim_CreateCommand(httpstate.jim_interp, "zy1000_reboot",
+                       zylinjtag_Jim_Command_reboot, NULL, NULL);
+       Jim_CreateCommand(httpstate.jim_interp, "threads",
+                       zylinjtag_Jim_Command_threads, NULL, NULL);
+       Jim_CreateCommand(httpstate.jim_interp, "format_jffs2",
+                       zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
+
+       cyg_httpd_start();
+
+       webRunning = true;
+
+       diag_printf("Web server running\n");
+
+       int s;
+       struct ifreq ifr;
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s >= 0)
+       {
+               strcpy(ifr.ifr_name, "eth0");
+               int res;
+               res = ioctl(s, SIOCGIFHWADDR, &ifr);
+               close(s);
+
+               if (res < 0)
+               {
+                       diag_printf("Can't obtain MAC address\n");
+                       reboot();
+               }
+       }
+
+       sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
+
+       discover_message
+                       = alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
+
+       discover_launch();
+}
+
+static void print_exception_handler(cyg_addrword_t data, cyg_code_t exception,
+               cyg_addrword_t info)
+{
+       writeLog = false;
+       serialLog = true;
+       char *infoStr = "unknown";
+       switch (exception)
+       {
+#ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
+       case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
+       infoStr = "undefined instruction";
+       break;
+       case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
+       infoStr = "software interrupt";
+       break;
+       case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
+       infoStr = "abort prefetch";
+       break;
+       case CYGNUM_HAL_VECTOR_ABORT_DATA:
+       infoStr = "abort data";
+       break;
+#endif
+       default:
+               break;
+       }
+
+       diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
+
+       diag_printf("Dumping log\n---\n");
+       if (logCount >= logSize)
+       {
+               diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
+       }
+       diag_write(logBuffer, writePtr);
+
+       diag_printf("---\nLogdump complete.\n");
+       diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
+       diag_printf("\n---\nRebooting\n");
+       HAL_PLATFORM_RESET();
+
+}
+
+#ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
+static void setHandler(cyg_code_t exception)
+{
+       cyg_exception_handler_t *old_handler;
+       cyg_addrword_t old_data;
+
+       cyg_exception_set_handler(exception, print_exception_handler, 0,
+                       &old_handler, &old_data);
+}
+#endif
+
+static cyg_thread zylinjtag_uart_thread_object;
+static cyg_handle_t zylinjtag_uart_thread_handle;
+static char uart_stack[4096];
+
+static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
+static char backwardBuffer[1024];
+
+void setNoDelay(int session, int flag)
+{
+#if 1
+       // This decreases latency dramatically for e.g. GDB load which
+       // does not have a sliding window protocol
+       //
+       // Can cause *lots* of TCP/IP packets to be sent and it would have
+       // to be enabled/disabled on the fly to avoid the CPU being
+       // overloaded...
+       setsockopt(session, /* socket affected */
+       IPPROTO_TCP, /* set option at TCP level */
+       TCP_NODELAY, /* name of option */
+       (char *) &flag, /* the cast is historical
+        cruft */
+       sizeof(int)); /* length of option value */
+#endif
+}
+
+#define TEST_TCPIP() 0
+
+#if TEST_TCPIP
+struct
+{
+       int req;
+       int actual;
+       int req2;
+       int actual2;
+} tcpipSent[512 * 1024];
+int cur;
+#endif
+
+static void zylinjtag_uart(cyg_addrword_t data)
+{
+       int so_reuseaddr_option = 1;
+
+       int fd;
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+       {
+               LOG_ERROR("error creating socket: %s", strerror(errno));
+               exit(-1);
+       }
+
+       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
+                       sizeof(int));
+
+       struct sockaddr_in sin;
+       unsigned int address_size;
+       address_size = sizeof(sin);
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = INADDR_ANY;
+       sin.sin_port = htons(5555);
+
+       if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
+       {
+               LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
+               exit(-1);
+       }
+
+       if (listen(fd, 1) == -1)
+       {
+               LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
+               exit(-1);
+       }
+       //      socket_nonblock(fd);
+
+
+       for (;;)
+       {
+               int session = accept(fd, (struct sockaddr *) &sin, &address_size);
+               if (session < 0)
+               {
+                       continue;
+               }
+
+               setNoDelay(session, 1);
+               int oldopts = fcntl(session, F_GETFL, 0);
+               fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
+
+               int serHandle = open(ZY1000_SER_DEV, O_RDWR | O_NONBLOCK);
+               if (serHandle < 0)
+               {
+                       close(session);
+                       continue;
+               }
+
+#ifdef CYGPKG_PROFILE_GPROF
+               start_profile();
+#endif
+               size_t actual = 0;
+               size_t actual2 = 0;
+               size_t pos, pos2;
+               pos = 0;
+               pos2 = 0;
+#if TEST_TCPIP
+               cur = 0;
+#endif
+               for (;;)
+               {
+                       fd_set write_fds;
+                       fd_set read_fds;
+                       FD_ZERO(&write_fds);
+                       FD_ZERO(&read_fds);
+                       int fd_max = -1;
+                       FD_SET(session, &read_fds);
+                       fd_max = session;
+                       FD_SET(serHandle, &read_fds);
+                       if (serHandle > fd_max)
+                       {
+                               fd_max = serHandle;
+                       }
+                       /* Wait... */
+
+                       cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
+                       if ((actual == 0) && (actual2 == 0))
+                       {
+                               int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
+                               if (retval <= 0)
+                               {
+                                       break;
+                               }
+                       }
+
+                       if (actual2 <= 0)
+                       {
+                               memset(backwardBuffer, 's', sizeof(backwardBuffer));
+                               int t;
+                               t = read(serHandle, backwardBuffer,
+                                               sizeof(backwardBuffer));
+                               actual2 = t;
+                               if (t < 0)
+                               {
+                                       if (errno != EAGAIN)
+                                       {
+                                               goto closeSession;
+                                       }
+                                       actual2 = 0;
+                               }
+                               pos2 = 0;
+                       }
+
+                       size_t y = 0;
+                       if (actual2 > 0)
+                       {
+                               int written = write(session, backwardBuffer + pos2, actual2);
+                               if (written <= 0)
+                                       goto closeSession;
+                               actual2 -= written;
+                               pos2 += written;
+                               y = written;
+                       }
+
+                       if (FD_ISSET(session, &read_fds)
+                                       && (sizeof(forwardBuffer) > actual))
+                       {
+                               // NB! Here it is important that we empty the TCP/IP read buffer
+                               // to make transmission tick right
+                               memmove(forwardBuffer, forwardBuffer + pos, actual);
+                               pos = 0;
+                               int t;
+                               // this will block if there is no data at all
+                               t = read_socket(session, forwardBuffer + actual,
+                                               sizeof(forwardBuffer) - actual);
+                               if (t <= 0)
+                               {
+                                       goto closeSession;
+                               }
+                               actual += t;
+                       }
+
+                       int y2 = 0;
+                       if (actual > 0)
+                       {
+                               /* Do not put things into the serial buffer if it has something to send
+                                * as that can cause a single byte to be sent at the time.
+                                *
+                                *
+                                */
+                               int written = write(serHandle, forwardBuffer + pos, actual);
+                               if (written < 0)
+                               {
+                                       if (errno != EAGAIN)
+                                       {
+                                               goto closeSession;
+                                       }
+                                       // The serial buffer is full
+                                       written = 0;
+                               }
+                               else
+                               {
+                                       actual -= written;
+                                       pos += written;
+                               }
+                               y2 = written;
+                       }
+#if TEST_TCPIP
+                       if (cur < 1024)
+                       {
+                               tcpipSent[cur].req = x;
+                               tcpipSent[cur].actual = y;
+                               tcpipSent[cur].req2 = x2;
+                               tcpipSent[cur].actual2 = y2;
+                               cur++;
+                       }
+#endif
+               }
+               closeSession: close(session);
+               close(serHandle);
+
+#if TEST_TCPIP
+               int i;
+               for (i = 0; i < 1024; i++)
+               {
+                       diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual,
+                                       tcpipSent[i].req2, tcpipSent[i].actual2);
+
+               }
+#endif
+       }
+       close(fd);
+
+}
+
+void startUart(void)
+{
+       cyg_thread_create(1, zylinjtag_uart, (cyg_addrword_t) 0, "uart thread",
+                       (void *) uart_stack, sizeof(uart_stack),
+                       &zylinjtag_uart_thread_handle, &zylinjtag_uart_thread_object);
+       cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
+       cyg_thread_resume(zylinjtag_uart_thread_handle);
+}
+
+static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       static int current_baud = 38400;
+       if (argc == 1)
+       {
+               command_print(cmd_ctx, "%d", current_baud);
+               return JIM_OK;
+       }
+       else if (argc != 2)
+       {
+               return JIM_ERR;
+       }
+
+       long new_baudrate;
+       if (Jim_GetLong(interp, argv[1], &new_baudrate) != JIM_OK)
+               return JIM_ERR;
+
+       current_baud = new_baudrate;
+
+       int baud;
+       switch (current_baud)
+       {
+       case 9600:
+               baud = CYGNUM_SERIAL_BAUD_9600;
+               break;
+       case 19200:
+               baud = CYGNUM_SERIAL_BAUD_19200;
+               break;
+       case 38400:
+               baud = CYGNUM_SERIAL_BAUD_38400;
+               break;
+       case 57600:
+               baud = CYGNUM_SERIAL_BAUD_57600;
+               break;
+       case 115200:
+               baud = CYGNUM_SERIAL_BAUD_115200;
+               break;
+       case 230400:
+               baud = CYGNUM_SERIAL_BAUD_230400;
+               break;
+       default:
+               command_print(cmd_ctx, "unsupported baudrate");
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       cyg_serial_info_t buf;
+       cyg_uint32 len = 1;
+       //get existing serial configuration
+       len = sizeof(cyg_serial_info_t);
+       int err;
+       cyg_io_handle_t serial_handle;
+
+       err = cyg_io_lookup(ZY1000_SER_DEV, &serial_handle);
+       if (err != ENOERR)
+       {
+               LOG_ERROR("Could not open serial port\n");
+               return JIM_ERR;
+       }
+
+       err = cyg_io_get_config(serial_handle,
+                       CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
+       err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf,
+                       &len);
+       if (err != ENOERR)
+       {
+               LOG_ERROR("Failed to get serial port settings %d", err);
+               return JIM_ERR;
+       }
+       buf.baud = baud;
+
+       err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf,
+                       &len);
+       if (err != ENOERR)
+       {
+               LOG_ERROR("Failed to set serial port settings %d", err);
+               return JIM_ERR;
+       }
+
+       return JIM_OK;
+}
+
+bool logAllToSerial = false;
+
+
+int boolParam(char *var);
+
+
+static const char *zylin_config_dir="/config/settings";
+
+static int add_default_dirs(void)
+{
+       add_script_search_dir(zylin_config_dir);
+       add_script_search_dir("/rom/lib/openocd");
+       add_script_search_dir("/rom");
+       return ERROR_OK;
+}
+
+int main(int argc, char *argv[])
+{
+       /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
+        * need to allocate towards the end of the heap.  */
+
+#ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
+       setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
+       setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
+       setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
+#endif
+
+       int err;
+
+       atexit(keep_webserver);
+
+       diag_init_putc(_zylinjtag_diag_write_char);
+       // We want this in the log.
+       diag_printf("Zylin ZY1000.\n");
+
+       err = mount("", "/ram", "ramfs");
+       if (err < 0)
+       {
+               diag_printf("unable to mount ramfs\n");
+       }
+       chdir("/ram");
+
+       char address[16];
+       sprintf(address, "%p", &filedata[0]);
+       err = mount(address, "/rom", "romfs");
+       if (err < 0)
+       {
+               diag_printf("unable to mount /rom\n");
+       }
+
+       err = mount("", "/log", "logfs");
+       if (err < 0)
+       {
+               diag_printf("unable to mount logfs\n");
+       }
+
+       err = mount("", "/tftp", "tftpfs");
+       if (err < 0)
+       {
+               diag_printf("unable to mount logfs\n");
+       }
+
+       log = fopen("/log/log", "w");
+       if (log == NULL)
+       {
+               diag_printf("Could not open log file /ram/log\n");
+               exit(-1);
+       }
+
+
+       copydir("/rom", "/ram/cgi");
+
+       err = mount("/dev/flash1", "/config", "jffs2");
+       if (err < 0)
+       {
+               diag_printf("unable to mount jffs2, falling back to ram disk..\n");
+               err = mount("", "/config", "ramfs");
+               if (err < 0)
+               {
+                       diag_printf("unable to mount /config as ramdisk.\n");
+                       reboot();
+               }
+       }
+       else
+       {
+               /* are we using a ram disk instead of a flash disk? This is used
+                * for ZY1000 live demo...
+                *
+                * copy over flash disk to ram block device
+                */
+               if (boolParam("ramdisk"))
+               {
+                       diag_printf("Unmounting /config from flash and using ram instead\n");
+                       err = umount("/config");
+                       if (err < 0)
+                       {
+                               diag_printf("unable to unmount jffs\n");
+                               reboot();
+                       }
+
+                       err = mount("/dev/flash1", "/config2", "jffs2");
+                       if (err < 0)
+                       {
+                               diag_printf("unable to mount jffs\n");
+                               reboot();
+                       }
+
+                       err = mount("", "/config", "ramfs");
+                       if (err < 0)
+                       {
+                               diag_printf("unable to mount ram block device\n");
+                               reboot();
+                       }
+
+                       //              copydir("/config2", "/config");
+                       copyfile("/config2/ip", "/config/ip");
+                       copydir("/config2/settings", "/config/settings");
+
+                       umount("/config2");
+               }
+       }
+
+       mkdir(zylin_config_dir, 0777);
+       char *dirname = alloc_printf("%s/target", zylin_config_dir);
+       mkdir(dirname, 0777);
+       free(dirname);
+       dirname = alloc_printf("%s/board", zylin_config_dir);
+       mkdir(dirname, 0777);
+       free(dirname);
+       dirname = alloc_printf("%s/event", zylin_config_dir);
+       mkdir(dirname, 0777);
+       free(dirname);
+
+       logAllToSerial = boolParam("logserial");
+
+       // We need the network & web server in case there is something wrong with
+       // the config files that invoke exit()
+       zylinjtag_startNetwork();
+
+       /* we're going to access the jim interpreter from here on... */
+       openocd_sleep_postlude();
+       startUart();
+
+       add_default_dirs();
+
+       /* initialize commandline interface */
+       struct command_context * cmd_ctx;
+       struct command_context *setup_command_handler(Jim_Interp *interp);
+       cmd_ctx = setup_command_handler(httpstate.jim_interp);
+       command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
+       command_context_mode(cmd_ctx, COMMAND_CONFIG);
+
+       if (ioutil_init(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+
+#ifdef CYGPKG_PROFILE_GPROF
+       COMMAND_REGISTER(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
+                       COMMAND_ANY, NULL);
+#endif
+
+       Jim_CreateCommand(httpstate.jim_interp, "uart", zylinjtag_Jim_Command_uart, NULL, NULL);
+
+
+       log_init();
+
+       set_log_output(cmd_ctx, log);
+
+       LOG_DEBUG("log init complete");
+
+       //      diag_printf("Executing config files\n");
+
+       if (logAllToSerial)
+       {
+               diag_printf(
+                                "%s/logserial = 1 => sending log output to serial port using \"debug_level 3\" as default.\n", zylin_config_dir);
+               command_run_line(cmd_ctx, "debug_level 3");
+       }
+
+       command_run_linef(cmd_ctx, "script /rom/openocd.cfg");
+
+       int ret;
+       ret = server_init(cmd_ctx);
+       if (ERROR_OK != ret)
+               return EXIT_FAILURE;
+
+       /* we MUST always run the init command as it will launch telnet sessions */
+       command_run_line(cmd_ctx, "init");
+
+       // FIX!!!  Yuk!
+       // diag_printf() is really invoked from many more places than we trust it
+       // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
+       //
+       // Disabling it here is safe and gives us enough logged debug output for now. Crossing
+       // fingers that it doesn't cause any crashes.
+       diag_printf("Init complete, GDB & telnet servers launched.\n");
+       command_set_output_handler(cmd_ctx,
+                       zy1000_configuration_output_handler_log, NULL);
+       if (!logAllToSerial)
+       {
+               serialLog = false;
+       }
+
+       /* handle network connections */
+       server_loop(cmd_ctx);
+       openocd_sleep_prelude();
+
+       /* shut server down */
+       server_quit();
+
+       /* free commandline interface */
+       command_done(cmd_ctx);
+       umount("/config");
+
+       exit(0);
+       for (;;)
+               ;
+}
+
+cyg_int32 cyg_httpd_exec_cgi_tcl(char *file_name);
+cyg_int32 homeForm(CYG_HTTPD_STATE *p)
+{
+       cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
+       return 0;
+}
+
+CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
+
+CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
+CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
+
+#include <pkgconf/system.h>
+#include <pkgconf/hal.h>
+#include <pkgconf/kernel.h>
+#include <pkgconf/io_fileio.h>
+#include <pkgconf/fs_rom.h>
+
+#include <cyg/kernel/ktypes.h>         // base kernel types
+#include <cyg/infra/cyg_trac.h>        // tracing macros
+#include <cyg/infra/cyg_ass.h>         // assertion macros
+#include <cyg/fileio/fileio.h>
+#include <cyg/kernel/kapi.h>
+#include <cyg/infra/diag.h>
+
+//==========================================================================
+// Eventually we want to eXecute In Place from the ROM in a protected
+// environment, so we'll need executables to be aligned to a boundary
+// suitable for MMU protection. A suitable boundary would be the 4k
+// boundary in all the CPU architectures I am currently aware of.
+
+// Forward definitions
+
+// Filesystem operations
+static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
+static int tftpfs_umount(cyg_mtab_entry *mte);
+static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
+               int mode, cyg_file *fte);
+static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
+static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
+
+// File operations
+static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
+static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
+static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
+
+//==========================================================================
+// Filesystem table entries
+
+// -------------------------------------------------------------------------
+// Fstab entry.
+// This defines the entry in the filesystem table.
+// For simplicity we use _FILESYSTEM synchronization for all accesses since
+// we should never block in any filesystem operations.
+#if 1
+FSTAB_ENTRY(tftpfs_fste, "tftpfs", 0,
+               CYG_SYNCMODE_NONE,
+               tftpfs_mount,
+               tftpfs_umount,
+               tftpfs_open,
+               (cyg_fsop_unlink *)cyg_fileio_erofs,
+               (cyg_fsop_mkdir *)cyg_fileio_erofs,
+               (cyg_fsop_rmdir *)cyg_fileio_erofs,
+               (cyg_fsop_rename *)cyg_fileio_erofs,
+               (cyg_fsop_link *)cyg_fileio_erofs,
+               (cyg_fsop_opendir *)cyg_fileio_erofs,
+               (cyg_fsop_chdir *)cyg_fileio_erofs,
+               (cyg_fsop_stat *)cyg_fileio_erofs,
+               (cyg_fsop_getinfo *)cyg_fileio_erofs,
+               (cyg_fsop_setinfo *)cyg_fileio_erofs);
+#endif
+
+// -------------------------------------------------------------------------
+// mtab entry.
+// This defines a single ROMFS loaded into ROM at the configured address
+//
+// MTAB_ENTRY(rom_mte, // structure name
+//             "/rom",         // mount point
+//             "romfs",        // FIlesystem type
+//             "",             // hardware device
+//  (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS  // Address in ROM
+//);
+
+
+// -------------------------------------------------------------------------
+// File operations.
+// This set of file operations are used for normal open files.
+
+static cyg_fileops tftpfs_fileops =
+{ tftpfs_fo_read, tftpfs_fo_write, tftpfs_fo_lseek,
+               (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
+               tftpfs_fo_fsync, tftpfs_fo_close,
+               (cyg_fileop_fstat *) cyg_fileio_erofs,
+               (cyg_fileop_getinfo *) cyg_fileio_erofs,
+               (cyg_fileop_setinfo *) cyg_fileio_erofs, };
+
+// -------------------------------------------------------------------------
+// tftpfs_mount()
+// Process a mount request. This mainly finds root for the
+// filesystem.
+
+static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
+{
+       return ENOERR;
+}
+
+static int tftpfs_umount(cyg_mtab_entry *mte)
+{
+       return ENOERR;
+}
+
+struct Tftp
+{
+       int write;
+       int readFile;
+       cyg_uint8 *mem;
+       int actual;
+       char *server;
+       char *file;
+};
+
+static void freeTftp(struct Tftp *t)
+{
+       if (t == NULL)
+               return;
+       if (t->mem)
+               free(t->mem);
+       if (t->server)
+               free(t->server);
+       if (t->file)
+               free(t->file);
+       free(t);
+}
+
+static const int tftpMaxSize = 8192 * 1024;
+static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
+               int mode, cyg_file *file)
+{
+       struct Tftp *tftp;
+       tftp = malloc(sizeof(struct Tftp));
+       if (tftp == NULL)
+               return EMFILE;
+       memset(tftp, 0, sizeof(struct Tftp));
+
+       file->f_flag |= mode & CYG_FILE_MODE_MASK;
+       file->f_type = CYG_FILE_TYPE_FILE;
+       file->f_ops = &tftpfs_fileops;
+       file->f_offset = 0;
+       file->f_data = 0;
+       file->f_xops = 0;
+
+       tftp->mem = malloc(tftpMaxSize);
+       if (tftp->mem == NULL)
+       {
+               freeTftp(tftp);
+               return EMFILE;
+       }
+
+       char *server = strchr(name, '/');
+       if (server == NULL)
+       {
+               freeTftp(tftp);
+               return EMFILE;
+       }
+
+       tftp->server = malloc(server - name + 1);
+       if (tftp->server == NULL)
+       {
+               freeTftp(tftp);
+               return EMFILE;
+       }
+       strncpy(tftp->server, name, server - name);
+       tftp->server[server - name] = 0;
+
+       tftp->file = strdup(server + 1);
+       if (tftp->file == NULL)
+       {
+               freeTftp(tftp);
+               return EMFILE;
+       }
+
+       file->f_data = (CYG_ADDRWORD) tftp;
+
+       return ENOERR;
+}
+
+static int fetchTftp(struct Tftp *tftp)
+{
+       if (!tftp->readFile)
+       {
+               int err;
+               tftp->actual = tftp_client_get(tftp->file, tftp->server, 0, tftp->mem,
+                               tftpMaxSize, TFTP_OCTET, &err);
+
+               if (tftp->actual < 0)
+               {
+                       return EMFILE;
+               }
+               tftp->readFile = 1;
+       }
+       return ENOERR;
+}
+
+// -------------------------------------------------------------------------
+// tftpfs_fo_write()
+// Read data from file.
+
+static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
+{
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;
+
+       if (fetchTftp(tftp) != ENOERR)
+               return EMFILE;
+
+       int i;
+       off_t pos = fp->f_offset;
+       int resid = 0;
+       for (i = 0; i < uio->uio_iovcnt; i++)
+       {
+               cyg_iovec *iov = &uio->uio_iov[i];
+               char *buf = (char *) iov->iov_base;
+               off_t len = iov->iov_len;
+
+               if (len + pos > tftp->actual)
+               {
+                       len = tftp->actual - pos;
+               }
+               resid += iov->iov_len - len;
+
+               memcpy(buf, tftp->mem + pos, len);
+               pos += len;
+
+       }
+       uio->uio_resid = resid;
+       fp->f_offset = pos;
+
+       return ENOERR;
+}
+
+static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
+{
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;
+
+       int i;
+       off_t pos = fp->f_offset;
+       int resid = 0;
+       for (i = 0; i < uio->uio_iovcnt; i++)
+       {
+               cyg_iovec *iov = &uio->uio_iov[i];
+               char *buf = (char *) iov->iov_base;
+               off_t len = iov->iov_len;
+
+               if (len + pos > tftpMaxSize)
+               {
+                       len = tftpMaxSize - pos;
+               }
+               resid += iov->iov_len - len;
+
+               memcpy(tftp->mem + pos, buf, len);
+               pos += len;
+
+       }
+       uio->uio_resid = resid;
+       fp->f_offset = pos;
+
+       tftp->write = 1;
+
+       return ENOERR;
+}
+
+static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
+{
+       int error = ENOERR;
+       return error;
+}
+
+// -------------------------------------------------------------------------
+// romfs_fo_close()
+// Close a file. We just clear out the data pointer.
+
+static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
+{
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;
+       int error = ENOERR;
+
+       if (tftp->write)
+       {
+               tftp_client_put(tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,
+                               TFTP_OCTET, &error);
+       }
+
+       freeTftp(tftp);
+       fp->f_data = 0;
+       return error;
+}
+
+// -------------------------------------------------------------------------
+// romfs_fo_lseek()
+// Seek to a new file position.
+
+static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
+{
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;
+       off_t pos = *apos;
+
+       if (fetchTftp(tftp) != ENOERR)
+               return EMFILE;
+
+       switch (whence)
+       {
+       case SEEK_SET:
+               // Pos is already where we want to be.
+               break;
+
+       case SEEK_CUR:
+               // Add pos to current offset.
+               pos += fp->f_offset;
+               break;
+
+       case SEEK_END:
+               // Add pos to file size.
+               pos += tftp->actual;
+               break;
+
+       default:
+               return EINVAL;
+       }
+
+       // Check that pos is still within current file size, or at the
+       // very end.
+       if (pos < 0 || pos > tftp->actual)
+               return EINVAL;
+
+       // All OK, set fp offset and return new position.
+       *apos = fp->f_offset = pos;
+
+       return ENOERR;
+}
+
+void usleep(int us)
+{
+       if (us > 10000)
+               cyg_thread_delay(us / 10000 + 1);
+       else
+               HAL_DELAY_US(us);
+}
+
+// Chunked version.
+cyg_int32 show_log_entry(CYG_HTTPD_STATE *phttpstate)
+{
+       cyg_httpd_start_chunked("text");
+       if (logCount >= logSize)
+       {
+               cyg_httpd_write_chunked(logBuffer + logCount % logSize, logSize
+                               - logCount % logSize);
+       }
+       cyg_httpd_write_chunked(logBuffer, writePtr);
+       cyg_httpd_end_chunked();
+       return -1;
+}
+
+CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
+
+// Filesystem operations
+static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
+static int logfs_umount(cyg_mtab_entry *mte);
+static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
+               int mode, cyg_file *fte);
+static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
+
+// File operations
+static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
+static int logfs_fo_close(struct CYG_FILE_TAG *fp);
+
+#include <cyg/io/devtab.h>
+
+//==========================================================================
+// Filesystem table entries
+
+// -------------------------------------------------------------------------
+// Fstab entry.
+// This defines the entry in the filesystem table.
+// For simplicity we use _FILESYSTEM synchronization for all accesses since
+// we should never block in any filesystem operations.
+FSTAB_ENTRY(logfs_fste, "logfs", 0,
+               CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
+               logfs_mount,
+               logfs_umount,
+               logfs_open,
+               (cyg_fsop_unlink *)cyg_fileio_erofs,
+               (cyg_fsop_mkdir *)cyg_fileio_erofs,
+               (cyg_fsop_rmdir *)cyg_fileio_erofs,
+               (cyg_fsop_rename *)cyg_fileio_erofs,
+               (cyg_fsop_link *)cyg_fileio_erofs,
+               (cyg_fsop_opendir *)cyg_fileio_erofs,
+               (cyg_fsop_chdir *)cyg_fileio_erofs,
+               (cyg_fsop_stat *)cyg_fileio_erofs,
+               (cyg_fsop_getinfo *)cyg_fileio_erofs,
+               (cyg_fsop_setinfo *)cyg_fileio_erofs);
+
+// -------------------------------------------------------------------------
+// File operations.
+// This set of file operations are used for normal open files.
+
+static cyg_fileops logfs_fileops =
+{ (cyg_fileop_read *) cyg_fileio_erofs, (cyg_fileop_write *) logfs_fo_write,
+               (cyg_fileop_lseek *) cyg_fileio_erofs,
+               (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
+               logfs_fo_fsync, logfs_fo_close, (cyg_fileop_fstat *) cyg_fileio_erofs,
+               (cyg_fileop_getinfo *) cyg_fileio_erofs,
+               (cyg_fileop_setinfo *) cyg_fileio_erofs, };
+
+// -------------------------------------------------------------------------
+// logfs_mount()
+// Process a mount request. This mainly finds root for the
+// filesystem.
+
+static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
+{
+       return ENOERR;
+}
+
+static int logfs_umount(cyg_mtab_entry *mte)
+{
+       return ENOERR;
+}
+
+static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
+               int mode, cyg_file *file)
+{
+       file->f_flag |= mode & CYG_FILE_MODE_MASK;
+       file->f_type = CYG_FILE_TYPE_FILE;
+       file->f_ops = &logfs_fileops;
+       file->f_offset = 0;
+       file->f_data = 0;
+       file->f_xops = 0;
+       return ENOERR;
+}
+
+// -------------------------------------------------------------------------
+// logfs_fo_write()
+// Write data to file.
+
+static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
+{
+       int i;
+       for (i = 0; i < uio->uio_iovcnt; i++)
+       {
+               cyg_iovec *iov = &uio->uio_iov[i];
+               char *buf = (char *) iov->iov_base;
+               off_t len = iov->iov_len;
+
+               diag_write(buf, len);
+       }
+       uio->uio_resid = 0;
+
+       return ENOERR;
+}
+static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
+{
+       return ENOERR;
+}
+
+// -------------------------------------------------------------------------
+// romfs_fo_close()
+// Close a file. We just clear out the data pointer.
+
+static int logfs_fo_close(struct CYG_FILE_TAG *fp)
+{
+       return ENOERR;
+}
+
+int loadFile(const char *fileName, void **data, int *len);
+
+/* boolean parameter stored on config */
+int boolParam(char *var)
+{
+       bool result = false;
+       char *name = alloc_printf("%s/%s", zylin_config_dir, var);
+       if (name == NULL)
+               return result;
+
+       void *data;
+       int len;
+       if (loadFile(name, &data, &len) == ERROR_OK)
+       {
+               if (len > 1)
+                       len = 1;
+               result = strncmp((char *) data, "1", len) == 0;
+               free(data);
+       }
+       free(name);
+       return result;
+}
+