Skip to content
Snippets Groups Projects
ecosboard.c 38 KiB
Newer Older
oharboe's avatar
oharboe committed
		 * for ZY1000 live demo...
		 *
		 * copy over flash disk to ram block device
		 */
		if (boolParam("ramdisk"))
oharboe's avatar
oharboe committed
			diag_printf("Unmounting /config from flash and using ram instead\n");
oharboe's avatar
oharboe committed
			if (err < 0)
			{
				diag_printf("unable to unmount jffs\n");
				reboot();
			}
oharboe's avatar
oharboe committed
			err = mount("/dev/flash1", "/config2", "jffs2");
			if (err < 0)
			{
				diag_printf("unable to mount jffs\n");
				reboot();
			}
oharboe's avatar
oharboe committed
			err = mount("", "/config", "ramfs");
oharboe's avatar
oharboe committed
			if (err < 0)
			{
				diag_printf("unable to mount ram block device\n");
				reboot();
			}
oharboe's avatar
oharboe committed
			copyfile("/config2/ip", "/config/ip");
			copydir("/config2/settings", "/config/settings");

			umount("/config2");
		}
zwelch's avatar
zwelch committed
	char *dirname = alloc_printf("%s/target", zylin_config_dir);
	free(dirname);
zwelch's avatar
zwelch committed
	dirname = alloc_printf("%s/board", zylin_config_dir);
	mkdir(dirname, 0777);
zwelch's avatar
zwelch committed
	dirname = alloc_printf("%s/event", zylin_config_dir);

	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 */
	cmd_ctx = setup_command_handler();
	command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
	command_context_mode(cmd_ctx, COMMAND_CONFIG);

#if BUILD_IOUTIL
	if (ioutil_init(cmd_ctx) != ERROR_OK)
	{
		return EXIT_FAILURE;
	}
#endif


#ifdef CYGPKG_PROFILE_GPROF
	register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
			COMMAND_ANY, NULL);
#endif

	register_command(cmd_ctx, NULL, "uart", handle_uart_command, COMMAND_ANY,
			"uart <baud>  - forward uart on port 5555");

	int errVal;
	errVal = log_init(cmd_ctx);
	if (errVal != ERROR_OK)
	{
		diag_printf("log_init() failed %d\n", errVal);
		exit(-1);
	}

	set_log_output(cmd_ctx, log);

	LOG_DEBUG("log init complete");

	//	diag_printf("Executing config files\n");

	if (logAllToSerial)
	{
zwelch's avatar
zwelch committed
				 "%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");
	/* 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);
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,
zwelch's avatar
zwelch committed
		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;
}