
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>

#include "monitor.h"
#include "srec.h"
#include "boot_cmds.h"
#include "ufpb_cmds.h"
#include "serial.h"

#include "target.h"

#define CMD_NONE 0
#define CMD_MONITOR 1
#define CMD_LOADSREC 2

int verbose = 0;
int cmd = CMD_NONE;

void usage(void)
{
	printf("usage: ufpb_tool [board selection] [options] [commands]\n\n");
	printf("board selection:\n")
;	printf("-b board   : selects target hardware\n");
	printf("             only \"hms_evb_h8s2633f\" is supported\n\n");
	printf("options:\n");
	printf("-v         : be more verbose\n");
	printf("-p port    : selects serial port\n\n");
	printf("commands, at least one must be present:\n");
	printf("-l file    : upload srec file\n");
	printf("-r address : run at address (hex)\n");
	printf("-m         : start interactive monitor\n\n");
	exit(1);
}

void cmd_set_once(int new_cmd)
{
	if (cmd != CMD_NONE) {
		usage();
	}
	cmd = new_cmd;
}

int main(int argc, char **argv)
{
	int fd, file_fd, ret = 0;
	char *port = "/dev/ttyS0";
	char *srec_file = NULL;
	int opt;
	unsigned char *board = NULL;
	int do_run = 0;
	unsigned int run_address = 0;

	while ((opt = getopt(argc, argv, "vmp:b:l:r:")) != -1) {
		switch (opt) {
		case 'v':
			verbose++;
			break;
		case 'p':
			port = optarg;
			break;
		case 'b':
			if (strcasecmp(optarg, "hms_evb_h8s2633f") == 0) {
				board = optarg;
			}
			else {
				usage();
			}
			break;
		case 'm':
			cmd_set_once(CMD_MONITOR);
			break;
		case 'l':
			cmd_set_once(CMD_LOADSREC);
			srec_file = optarg;
			break;
		case 'r':
			if (sscanf(optarg, "%x", &run_address) != 1) {
				usage();
			}
			do_run = 1;
			break;
		}
	}

	if ((cmd == CMD_NONE) || ((cmd == CMD_MONITOR) && do_run)) {
		usage();
	}

	fd = serial_open(port);

	if (fd < 0) {
		return 1;
	}

	if (boot_hello(fd) < 0) {
		if (verbose) {
			printf("booting board via ufpb.\n");
		}
		if (ufpb_cmds_init(fd, hms_evb_h8s2633f, 
				   sizeof(hms_evb_h8s2633f)) < 0) {
			ret = 1;
		}
	}
	else {
		if (verbose) {
			printf("monitor already loaded, skipping boot.\n");
		}
	}

	if (!ret) {

		switch(cmd) {
			
		case CMD_MONITOR:
			monitor(fd);
			break;
			
		case CMD_LOADSREC:

			if (verbose) {
				printf("loading file.\n");
			}

			file_fd = open(srec_file, O_RDONLY);
			
			if (file_fd < 0) {
				perror("open");
				ret = 1;
			}
			else {
				srec_parse(file_fd, fd, 0);
				close(file_fd);
			}
			break;
		}
	}

	if (!ret) {
		while (do_run) {
			if (boot_address_set(fd, run_address) < 0) {
				ret = 1;
				break;
			}

			if (boot_run(fd) < 0) {
				ret = 1;
				break;
			}

			if (verbose) {
				printf("running from 0x%08x\n", run_address);
			}
			break;
		}
	}

	close(fd);
	
	return ret;
}
	







