/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2016 Google Inc
 *
 * 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; version 2 of the License.
 *
 * 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.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <stdarg.h>
#include <stdtypes.h>
#define die(x) { perror(x); exit(1); }
#define warn(x) { perror(x);  }

#include <x86emu/x86emu.h>
#include <console/console.h>
#include <arch/byteorder.h>
#include "device.h"

#include "testbios.h"
#include "pci-userspace.h"
int X86EMU_set_debug(int debug);

biosemu_device_t bios_device;

extern int teststart, testend;

#define BIOSMEM_SIZE (1024 * 1024)
unsigned char biosmem[BIOSMEM_SIZE];

int verbose = 0;

static unsigned char *mapitin(char *file, off_t where, size_t size)
{
	void *z;

	int fd = open(file, O_RDWR, 0);

	if (fd < 0)
		die(file);
	z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
	if (z == (void *) -1)
		die("mmap");
	close(fd);

	return z;
}

static unsigned short get_device(char *arg_val)
{
	unsigned short devfn=0;
	long bus=0,dev=0,fn=0,need_pack=0;
	char *tok;

	tok = strsep(&arg_val,":");
	if (arg_val != NULL) {
		bus = strtol(tok,0,16);
		need_pack = 1;
	}
	else {
		arg_val = tok;
	}

	tok = strsep(&arg_val,".");
	if (arg_val != NULL) {
		dev = strtol(tok,0,16);
		fn  = strtol(arg_val,0,16);
		need_pack = 1;
	}
	else {
		if (need_pack ==1 && (strlen(tok))) {
			dev = strtol(tok,0,16);
		}
	}

	if ( need_pack == 1) {
		devfn = bus<<8 | (dev<<3) | fn;
	}
	else {
		devfn = strtol(tok, 0, 0);
	}

	return devfn;
}

int printk(int msg_level, const char *fmt, ...)
{
	va_list args;
	int i;

	printf ("<%d> ", msg_level);
	va_start(args, fmt);
	i = vprintf(fmt, args);
	va_end(args);

	return i;
}

static void usage(char *name)
{
	printf
	    ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
	     name);
}

/* main entry into YABEL biosemu, arguments are:
 * *biosmem = pointer to virtual memory
 * biosmem_size = size of the virtual memory
 * *dev = pointer to the device to be initialised
 * rom_addr = address of the OptionROM to be executed, if this is = 0, YABEL
 * will look for an ExpansionROM BAR and use the code from there.
 */
u32
biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev, unsigned long
		rom_addr);


int main(int argc, char **argv)
{
	int ret;
	char *absegname = 0;
	void *abseg = 0;
	int c, trace = 0;
	unsigned char *cp;
	char *filename;
	ssize_t size = 0;
	int base = 0;
	int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
	int have_devfn = 0;
	int parse_rom = 0;
	//char *fsegname = 0;
	//unsigned char *fsegptr;
	unsigned short initialip = 0, initialcs = 0, devfn = 0;
	//X86EMU_intrFuncs intFuncs[256];
	int debugflag = 0;
	struct device *dev;

	//const char *optstring = "vh?b:i:c:s:tpd:";
	const char *optstring = "vh?b:i:c:s:tpd:";
	while (1) {
		int option_index = 0;
		static struct option long_options[] = {
			{"verbose", 0, 0, 'v'},
			{"help", 0, 0, 'h'},
			{"trace", 0, 0, 't'},
			{"base", 1, 0, 'b'},
			//{"fseg", 1, 0, 'f'},
			{"instructionpointer", 1, 0, 'i'},
			{"codesegment", 1, 0, 'c'},
			{"absegment", 1, 0, 'a'},
			{"size", 1, 0, 's'},
			{"parserom", 0, 0, 'p'},
			{"device", 1, 0, 'd'},
			{"debug", 1, 0, 'D'},
			{0, 0, 0, 0}
		};
		c = getopt_long(argc, argv, optstring, long_options, &option_index);
		if (c == -1)
			break;
		switch (c) {
		case 'v':
			verbose = 1;
			break;
		case 'h':
		case '?':
			usage(argv[0]);
			return 0;
		case 't':
			trace = 1;
			break;
		//case 'b':
		//	base = strtol(optarg, 0, 0);
		//	have_base = 1;
		//	break;
		case 'i':
			initialip = strtol(optarg, 0, 0);
			have_ip = 1;
			break;
		case 'c':
			initialcs = strtol(optarg, 0, 0);
			have_cs = 1;
			break;
		case 's':
			size = strtol(optarg, 0, 0);
			have_size = 1;
			break;
		case 'p':
			parse_rom = 1;
			break;
	//	case 'f':
	//		fsegname = optarg;
	//		break;
		case 'a':
			absegname = optarg;
			break;
		case 'd':
			devfn = get_device(optarg);
			have_devfn = 1;
			break;
		case 'D':
			debugflag = strtol(optarg, 0, 0);
			break;
		default:
			printf("Unknown option \n");
			usage(argv[0]);
			return 1;
		}
	}

	if (optind >= argc) {
		printf("Filename missing.\n");
		usage(argv[0]);
		return 1;
	}

	while (optind < argc) {
		printf("running file %s\n", argv[optind]);
		filename = argv[optind];
		optind++;
		/* normally we would do continue, but for
		 * now only one filename is supported.
		 */
		/* continue; */
		break;
	}

	if (!have_size) {
		printf("No size specified. defaulting to 32k\n");
		size = 32 * 1024;
	}
	if (!have_base) {
		printf("No base specified. defaulting to 0xc0000\n");
		base = 0xc0000;
	}
	//if (!have_cs) {
	//	printf("No initial code segment specified. defaulting to 0xc000\n");
	//	initialcs = 0xc000;
	//}
	if (!have_ip) {
		printf
		    ("No initial instruction pointer specified. defaulting to 0x0003\n");
		initialip = 0x0003;
	}

	if (parse_rom)
		printf("Parsing rom images not implemented.\n");

	//printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
#if 0
	if (initialip == 0x0003) {
		if ((devfn == 0) || (have_devfn == 0)) {
			printf("WARNING! It appears you are trying to run an option ROM.\n");
			printf("  (initial ip = 0x0003)\n");
			if (have_devfn) {
				printf("  However, the device you have specified is 0x00\n");
				printf("  It is very unlikely that your device is at this address\n");
				printf("  Please check your -d option\n");
			}
			else {
				printf("  Please specify a device with -d\n");
				printf("  The default is not likely to work\n");
			}
		}
	}
#endif

	if (absegname) {
		abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
		if (!abseg)
			die(absegname);
	}

	ioperm(0, 0x400, 1);

	if (iopl(3) < 0) {
		warn("iopl failed, continuing anyway");
	}

	/* Emergency sync ;-) */
	sync();
	sync();

	/* Setting up interrupt environment.
	 * basically this means initializing PCI and
	 * intXX handlers.
	 */
	pci_initialize();

#if 0
	for (i = 0; i < 256; i++)
		intFuncs[i] = do_int;
	X86EMU_setupIntrFuncs(intFuncs);
#endif
	cp = mapitin(filename, (off_t) 0, size);

	if (devfn) {
		printf("Loading ax with BusDevFn = %x\n",devfn);
	}

#if 0
	current->ax = devfn   ? devfn : 0xff;
	current->dx = 0x80;
	//      current->ip = 0;
	for (i = 0; i < size; i++)
		wrb(base + i, cp[i]);

	if (fsegname) {
		fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
		for (i = 0; i < 0x10000; i++)
			wrb(0xf0000 + i, fsegptr[i]);
	} else {
		const char *date = "01/01/99";
		for (i = i; date[i]; i++)
			wrb(0xffff5 + i, date[i]);
		wrb(0xffff7, '/');
		wrb(0xffffa, '/');
	}
	/* cpu setup */
	X86_AX = devfn ? devfn : 0xff;
	X86_DX = 0x80;
	X86_EIP = initialip;
	X86_CS = initialcs;

	/* Initialize stack and data segment */
	X86_SS = 0x0030;
	X86_DS = 0x0040;
	X86_SP = 0xfffe;
	/* We need a sane way to return from bios
	 * execution. A hlt instruction and a pointer
	 * to it, both kept on the stack, will do.
	 */
	pushw(0xf4f4);		/* hlt; hlt */
	pushw(X86_SS);
	pushw(X86_SP + 2);

	X86_ES = 0x0000;
#endif

	if (trace) {
		printf("Switching to single step mode.\n");
		//X86EMU_trace_on();
	}
	if (debugflag) {
		printf("Enable Debug = %x.\n",debugflag);
		//X86EMU_set_debug(debugflag);
	}
#if 0
	X86EMU_exec();
#endif

	ret = biosemu(biosmem, BIOSMEM_SIZE, dev, base);

#if 0
	current = &p;
	X86EMU_setMemBase(biosmem, sizeof(biosmem));
	M.abseg = (unsigned long)abseg;
	X86EMU_setupPioFuncs(&myfuncs);
#endif

	/* Cleaning up */
	pci_exit();

	return 0;
}
