Skip to content
Snippets Groups Projects
ecosboard.c 59.3 KiB
Newer Older
/***************************************************************************
 *   Copyright (C) 2007-2008 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 "log.h"
#include "types.h"
#include "jtag.h"
#include "configuration.h"
#include "xsvf.h"
#include "target.h"
#include "flash.h"
#include "nand.h"
#include "pld.h"

#include "command.h"
#include "server.h"
#include "telnet_server.h"
#include "gdb_server.h"

#include <time_support.h>
#include <sys/time.h>
#include <sys/types.h>
#include <strings.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>
oharboe's avatar
oharboe committed
#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>

oharboe's avatar
oharboe committed

#include <unistd.h>
#include <stdio.h>
#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

oharboe's avatar
oharboe committed
#define ZYLIN_VERSION "1.47"
#define ZYLIN_DATE __DATE__
#define ZYLIN_TIME __TIME__
/* hmmm....  we can't pick up the right # during build if we've checked this out
 * in Eclipse... arrggghh...*/
#define ZYLIN_OPENOCD "$Revision$"
#define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
#define ZYLIN_CONFIG_DIR "/config/settings"

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];

struct FastLoad
{
	u32 address;
	u8 *data;
	int length;

};

static int fastload_num;
static struct FastLoad *fastload;

static void free_fastload()
{
	if (fastload!=NULL)
	{
		int i;
		for (i=0; i<fastload_num; i++)
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
		fastload=NULL;
	}
}


int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	u8 *buffer;
	u32 buf_cnt;
	u32 image_size;
	u32 min_address=0;
	u32 max_address=0xffffffff;
	int i;
	int retval;

	image_t image;

	duration_t duration;
	char *duration_text;

	if ((argc < 1)||(argc > 5))
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}

	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
	if (argc >= 2)
	{
		image.base_address_set = 1;
		image.base_address = strtoul(args[1], NULL, 0);
	}
	else
	{
		image.base_address_set = 0;
	}


	image.start_address_set = 0;

	if (argc>=4)
	{
		min_address=strtoul(args[3], NULL, 0);
	}
	if (argc>=5)
	{
		max_address=strtoul(args[4], NULL, 0)+min_address;
	}

	if (min_address>max_address)
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}

	duration_start_measure(&duration);

	if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
	{
		return ERROR_OK;
	}

	image_size = 0x0;
	retval = ERROR_OK;
	fastload_num=image.num_sections;
	fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
	if (fastload==NULL)
	{
		image_close(&image);
		return ERROR_FAIL;
	}
	memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
			break;
		}

		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
			break;
		}

		u32 offset=0;
		u32 length=buf_cnt;


		/* DANGER!!! beware of unsigned comparision here!!! */

		if ((image.sections[i].base_address+buf_cnt>=min_address)&&
				(image.sections[i].base_address<max_address))
		{
			if (image.sections[i].base_address<min_address)
			{
				/* clip addresses below */
				offset+=min_address-image.sections[i].base_address;
				length-=offset;
			}

			if (image.sections[i].base_address+buf_cnt>max_address)
			{
				length-=(image.sections[i].base_address+buf_cnt)-max_address;
			}

			fastload[i].address=image.sections[i].base_address+offset;
			fastload[i].data=malloc(length);
			if (fastload[i].data==NULL)
			{
				free(buffer);
				break;
			}
			memcpy(fastload[i].data, buffer+offset, length);
			fastload[i].length=length;

			image_size += length;
			command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);
		}

		free(buffer);
	}

	duration_stop_measure(&duration, &duration_text);
	if (retval==ERROR_OK)
	{
oharboe's avatar
oharboe committed
		command_print(cmd_ctx, "Loaded %u bytes in %s", image_size, duration_text);
		command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
	}
	free(duration_text);

	image_close(&image);

	if (retval!=ERROR_OK)
	{
		free_fastload();
	}

	return retval;
}

int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	if (argc>0)
		return ERROR_COMMAND_SYNTAX_ERROR;
	if (fastload==NULL)
	{
		LOG_ERROR("No image in memory");
		return ERROR_FAIL;
	}
	int i;
	int ms=timeval_ms();
	int size=0;
	for (i=0; i<fastload_num;i++)
	{
		int retval;
		target_t *target = get_current_target(cmd_ctx);
		if ((retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data)) != ERROR_OK)
		{
			return retval;
		}
		size+=fastload[i].length;
	}
	int after=timeval_ms();
	command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
	return ERROR_OK;
}


/* Give TELNET a way to find out what version this is */
int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,
		char **args, int argc)
{
	if (argc > 1)
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
	if (argc == 0)
	{
		command_print(cmd_ctx, ZYLIN_OPENOCD_VERSION);
	} else if (strcmp("openocd", args[0])==0)
	{
		int revision;
		revision=atol(ZYLIN_OPENOCD+strlen("XRevision: "));
		command_print(cmd_ctx, "%d", revision);
	} else if (strcmp("zy1000", args[0])==0)
	{
		command_print(cmd_ctx, "%s", ZYLIN_VERSION);
	} else if (strcmp("date", args[0])==0)
	{
		command_print(cmd_ctx, "%s", ZYLIN_DATE);
	} else
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}

	return ERROR_OK;
}

oharboe's avatar
oharboe committed



extern flash_driver_t *flash_drivers[];
extern target_type_t *target_types[];

#ifdef CYGPKG_PROFILE_GPROF
#include <cyg/profile/profile.h>

extern char _stext, _etext; // Defined by the linker

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(&_stext, &_etext, 16, 10000); // DRAM
	//profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
	profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
}
#endif

// launch GDB server if a config file exists
bool zylinjtag_parse_config_file(struct command_context_s *cmd_ctx, const char *config_file_name)
{
	bool foundFile = false;
	FILE *config_file = NULL;
	command_print(cmd_ctx, "executing config file %s", config_file_name);
	config_file = fopen(config_file_name, "r");
	if (config_file)
	{
		fclose(config_file);
		int retval;
		retval = command_run_linef(cmd_ctx, "script %s", config_file_name);
		if (retval == ERROR_OK)
		{
			foundFile = true;
		}
		else
		{
			command_print(cmd_ctx, "Failed executing %s %d", config_file_name, retval);
		}
	}
	else
	{
		command_print(cmd_ctx, "No %s found", config_file_name);
	}

	return foundFile;
}

extern int eth0_up;
static FILE *log;

static char reboot_stack[2048];


static void
zylinjtag_reboot(cyg_addrword_t data)
{
	serialLog = true;
	diag_printf("Rebooting in 100 ticks..\n");
	cyg_thread_delay(100);
	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);
}

int configuration_output_handler(struct command_context_s *context, const char* line)
{
	diag_printf("%s", line);

	return ERROR_OK;
}

int zy1000_configuration_output_handler_log(struct command_context_s *context, const char* line)
{
	LOG_USER_N("%s", line);

	return ERROR_OK;
}

int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
		char **args, int argc)
{
	if (argc != 1)
	{
		command_print(cmd_ctx, "rm <filename>");
		return ERROR_INVALID_ARGUMENTS;
	}

	if (unlink(args[0]) != 0)
	{
		command_print(cmd_ctx, "failed: %d", errno);
	}

	return ERROR_OK;
}

int loadFile(const char *fileName, void **data, int *len);

int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
		char **args, int argc)
{
	if (argc != 1)
	{
		command_print(cmd_ctx, "cat <filename>");
		return ERROR_INVALID_ARGUMENTS;
	}

	// NOTE!!! we only have line printing capability so we print the entire file as a single line.
	void *data;
	int len;

	int retval = loadFile(args[0], &data, &len);
	if (retval == ERROR_OK)
	{
		command_print(cmd_ctx, "%s", data);
		free(data);
	}
	else
	{
		command_print(cmd_ctx, "%s not found %d", args[0], retval);
	}

	return ERROR_OK;
}
int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
		char **args, int argc)
{
	if (argc != 1)
	{
		command_print(cmd_ctx, "trunc <filename>");
		return ERROR_INVALID_ARGUMENTS;
	}

	FILE *config_file = NULL;
	config_file = fopen(args[0], "w");
	if (config_file != NULL)
		fclose(config_file);

	return ERROR_OK;
}


int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	static int prev = 0;
	struct mallinfo info;

	if (argc != 0)
	{
		command_print(cmd_ctx, "meminfo");
		return ERROR_INVALID_ARGUMENTS;
	}

	info = mallinfo();

	if (prev > 0)
	{
		command_print(cmd_ctx, "Diff:            %d", prev - info.fordblks);
	}
	prev = info.fordblks;

	command_print(cmd_ctx, "Available ram:   %d", info.fordblks );

	return ERROR_OK;
}

static bool savePower;

static void setPower(bool power)
{
	savePower = power;
	if (power)
	{
oharboe's avatar
oharboe committed
		HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x14, 0x8);
oharboe's avatar
oharboe committed
		HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x10, 0x8);
	}
}

int handle_power_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	if (argc > 1)
	{
		return ERROR_INVALID_ARGUMENTS;
	}

	if (argc == 1)
	{
		if (strcmp(args[0], "on") == 0)
		{
			setPower(1);
		}
		else if (strcmp(args[0], "off") == 0)
		{
			setPower(0);
		} else
		{
			command_print(cmd_ctx, "arg is \"on\" or \"off\"");
			return ERROR_INVALID_ARGUMENTS;
		}
	}

	command_print(cmd_ctx, "Target power %s", savePower ? "on" : "off");

	return ERROR_OK;
}

int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
		char **args, int argc)
{
	if (argc < 1)
	{
		command_print(cmd_ctx,
				"append <filename> [<string1>, [<string2>, ...]]");
		return ERROR_INVALID_ARGUMENTS;
	}

	FILE *config_file = NULL;
	config_file = fopen(args[0], "a");
	if (config_file != NULL)
	{
		int i;
		fseek(config_file, 0, SEEK_END);

		for (i = 1; i < argc; i++)
		{
			fwrite(args[i], strlen(args[i]), 1, config_file);
			if (i != argc - 1)
			{
				fwrite(" ", 1, 1, config_file);
			}
		}
		fwrite("\n", 1, 1, config_file);
		fclose(config_file);
	}

	return ERROR_OK;
}

extern int telnet_socket;

int readMore(int fd, void *data, int length)
{
	/* used in select() */
	fd_set read_fds;

	/* monitor sockets for acitvity */
	int fd_max = 1;
	FD_ZERO(&read_fds);
	/* listen for new connections */
	FD_SET(fd, &read_fds);

	// Maximum 5 seconds.
	struct timeval tv;
	tv.tv_sec = 5;
	tv.tv_usec = 0;

	int retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
	if (retval == 0)
	{
		diag_printf("Timed out waiting for binary payload\n");
		return -1;
	}
	if (retval != 1)
		return -1;

	return read_socket(fd, data, length);
}

int readAll(int fd, void *data, int length)
{
	int pos = 0;
	for (;;)
	{
		int actual = readMore(fd, ((char *) data) + pos, length - pos);
		//		diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
		if (actual <= 0)
			return -1;
		pos += actual;
		if (pos == length)
			break;
	}
	return length;
}

int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	cyg_uint32 value;
	if (argc != 1)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
	HAL_READ_UINT32(strtoul(args[0], NULL, 0), value);
	command_print(cmd_ctx, "0x%x : 0x%x", strtoul(args[0], NULL, 0), value);
	return ERROR_OK;
}

int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	if (argc != 2)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
	HAL_WRITE_UINT32(strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0));
	return ERROR_OK;
}

int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	if (argc != 2)
	{
		return ERROR_INVALID_ARGUMENTS;
	}

	// NOTE!!! we only have line printing capability so we print the entire file as a single line.
	void *data;
	int len;

	int retval = loadFile(args[0], &data, &len);
	if (retval != ERROR_OK)
		return retval;

	FILE *f = fopen(args[1], "wb");
	if (f == NULL)
		retval = ERROR_INVALID_ARGUMENTS;

	int pos = 0;
	for (;;)
	{
		int chunk = len - pos;
		static const int maxChunk = 512 * 1024; // ~1/sec
		if (chunk > maxChunk)
		{
			chunk = maxChunk;
		}

		if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
			retval = ERROR_INVALID_ARGUMENTS;

		if (retval != ERROR_OK)
		{
			break;
		}

		command_print(cmd_ctx, "%d", len - pos);

		pos += chunk;

		if (pos == len)
			break;
	}

	if (retval == ERROR_OK)
	{
		command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
	} else
	{
		command_print(cmd_ctx, "Failed: %d", retval);
	}

	if (data != NULL)
		free(data);
	if (f != NULL)
		fclose(f);

	if (retval != ERROR_OK)
		unlink(args[1]);

	return retval;
}

#ifdef CYGPKG_PROFILE_GPROF
extern void start_profile();

int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *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();

command_context_t *cmd_ctx;

static bool webRunning = false;

void keep_webserver()
{
	// 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);
	}

oharboe's avatar
oharboe committed
#ifdef CYGPKG_HAL_ZYLIN_PHI
	printDccChar(c);
oharboe's avatar
oharboe committed
#endif
}

#define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)

#define IOSIZE 512
static void copyfile(char *name2, char *name1)
{

	int err;
	char buf[IOSIZE];
	int fd1, fd2;
	ssize_t done, wrote;

	fd1 = open(name1, O_WRONLY | O_CREAT);
	if (fd1 < 0)
		SHOW_RESULT( open, fd1 );

	fd2 = open(name2, O_RDONLY);
	if (fd2 < 0)
		SHOW_RESULT( open, fd2 );

	for (;;)
	{
		done = read(fd2, buf, IOSIZE );
		if (done < 0)
		{
			SHOW_RESULT( read, done );
			break;
		}

        if( done == 0 ) break;

		wrote = write(fd1, buf, done);
        if( wrote != done ) SHOW_RESULT( write, wrote );

        if( wrote != done ) break;
	}

	err = close(fd1);
    if( err < 0 ) SHOW_RESULT( close, err );

	err = close(fd2);
    if( err < 0 ) SHOW_RESULT( close, err );

}
static void copydir(char *name, char *destdir)
	dirp = opendir(destdir);
	if (dirp==NULL)
	{
		mkdir(destdir, 0777);
	} else
	{
		err = closedir(dirp);
	}

	dirp = opendir(name);
    if( dirp == NULL ) SHOW_RESULT( opendir, -1 );

	for (;;)
	{
		struct dirent *entry = readdir(dirp);

		if (entry == NULL)
			break;

		if (strcmp(entry->d_name, ".") == 0)
			continue;
		if (strcmp(entry->d_name, "..") == 0)
			continue;

		bool isDir = false;
		struct stat buf;
		char fullPath[PATH_MAX];
		strncpy(fullPath, name, PATH_MAX);
		strcat(fullPath, "/");
		strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));

		if (stat(fullPath, &buf) == -1)
		{
			diag_printf("unable to read status from %s", fullPath);
			break;
		}
		isDir = S_ISDIR(buf.st_mode) != 0;

		if (isDir)
			continue;

		//        diag_printf("<INFO>: entry %14s",entry->d_name);
		char fullname[PATH_MAX];
		char fullname2[PATH_MAX];

		strcpy(fullname, name);
		strcat(fullname, "/");
		strcat(fullname, entry->d_name);

		strcpy(fullname2, destdir);
		strcat(fullname2, "/");
		strcat(fullname2, entry->d_name);
		//        diag_printf("from %s to %s\n", fullname, fullname2);
		copyfile(fullname, fullname2);

		//       diag_printf("\n");
	}

	err = closedir(dirp);
    if( err < 0 ) SHOW_RESULT( stat, err );
}

#if 0
MTAB_ENTRY( romfs_mte1,
		"/rom",
		"romfs",
		"",
		(CYG_ADDRWORD) &filedata[0] );
#endif

void openocd_sleep_prelude()
{
	cyg_mutex_unlock(&httpstate.jim_lock);
}

void openocd_sleep_postlude()
{
	cyg_mutex_lock(&httpstate.jim_lock);
}

oharboe's avatar
oharboe committed

void format(void)
{
	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;
	void *err_addr;
	len = sizeof (e);

	e.offset = 0;
	e.len = ds.dev_size;
	e.err_address = &err_addr;

	diag_printf("Formatting 0x%08x bytes\n", 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%p\n", err, err_addr);
		reboot();
	}

	diag_printf("Flash formatted successfully\n");

	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(;;);
oharboe's avatar
oharboe committed
}