#define __USE_SYSBASE_H
#include <dos/dos.h>
#include <proto/dos.h>
#include <proto/exec.h>
extern UBYTE *_ProgramName;

static char VERSION[] = "\0$VER: gobsd 1.01 " __AMIGADATE__;
static char COPYRIGHT[] = "© 1995,1996 Michael van Elst";

#include "opts.h"
#include "config.h"
#include "load.h"

#define RB_AUTOBOOT    0
#define RB_ASKNAME     0x01
#define RB_SINGLE      0x02
#define RB_KDB         0x40

#define FOURMEG       (4*1024*1024)

void loader(), loaderend();

void fatal(STRPTR mess)
{
	print("FATAL: ");
	print(mess);
	print(".\n");
	exit(RETURN_FAIL);
}

void __main(UBYTE *cmdline)
{
	ULONG fast_size;
	ULONG chip_size;
	ULONG config_size;
	ULONG memlist_size;
	ULONG loader_size;
	UBYTE *fast_mem;
	UBYTE *kernel_mem;
	ULONG kernel_size;
	ULONG kernel_vers;
	ULONG copy_size;
	ULONG entry;
	ULONG symbols;
	ULONG boot_howto;
	ULONG boot_flags;
	ULONG more_flags;
	UBYTE *img_start;
	Loader startit;

	get_opts(cmdline);
	get_cpu_id();
	get_eclock();
	memlist_size = get_mem(&fast_mem, &fast_size, &chip_size);
	config_size  = get_config();
	loader_size  = (UBYTE *)loaderend - (UBYTE *)loader;

	if (options & RESERVE_FOUR_MEG) {
		if (fast_size < FOURMEG)
			fatal("Can't reserve 4 MB in first segment");
		fast_mem   += FOURMEG;
		fast_size -= FOURMEG;
	}

	if (memory_limit > 0 && memory_limit < fast_size)
		fast_size = memory_limit;

	if (options & BOOT_MULTIUSER)
		boot_howto = RB_AUTOBOOT;
	else
		boot_howto = RB_SINGLE;

	if (options & ASK_ROOT_DEVICE)
		boot_howto |= RB_ASKNAME;

	if (options & START_DEBUGGER)
		boot_howto |= RB_KDB;

	boot_flags = 0;
	if (options & USE_AGA_DISPLAY) {
		if (!aga)
			fatal("This machine has no AGA display");
		boot_flags |= 0x01;
	}
	if (options & TWO_SEGMENTS)
		boot_flags |= 0x02;
	if (options & MANY_SEGMENTS)
		boot_flags |= 0x04;

	more_flags = nosync_mask;
	img_start = NULL;    /* XXX assumes that chip memory starts at $0 */

	if (options & KERNEL_FROM_ROOT) {
		if (!loadKernel(driver_name, device_unit, volume_name, kernel_name,
		                config_size+memlist_size+loader_size,
		                &kernel_mem, &kernel_size,
		                &entry, &symbols, &kernel_vers))
			fatal("Couldn't load kernel from root disk");
	} else {
		if (!loadKernel(NULL, 0, NULL, kernel_name,
		                config_size+memlist_size+loader_size,
		                &kernel_mem, &kernel_size,
		                &entry, &symbols, &kernel_vers))
			fatal("Couldn't load kernel file");
	}

	copy_size = kernel_size + config_size + memlist_size;
	if (kernel_vers >= KVERS_FAST_LOAD) {
		if (copy_size > chip_size || (options & FASTMEM_IMAGE)) {
			if (copy_size > fast_size)
				fatal("Not enough fast memory for bootstrap");
			img_start  = fast_mem;
		}
	} else {
		if (options & FASTMEM_IMAGE)
			fatal("Kernel too old to start from fast memory");
		if (copy_size > chip_size)
			fatal("Not enough chip memory for bootstrap");
	}

	copy_config(&kernel_mem[kernel_size]);
	copy_mem(&kernel_mem[kernel_size+config_size]);
	startit = copy_loader((UBYTE *)loader, &kernel_mem[copy_size], loader_size);

	if (options & ASK_ROOT_DEVICE)
		print("Askboot...");
	else if (options & BOOT_MULTIUSER)
		print("Autobooting...");
	else
		print("Booting Single-User...");
	print("version #");
	printlong(kernel_vers);
	print("\n");
	
	print("Using ");
	printlong((fast_size & 0xfffff) ? fast_size >> 10 : fast_size >> 20);
	printchar((fast_size & 0xfffff) ? 'K' : 'M');
	print(" FASTMEM at 0x");
	printaddr(fast_mem);
	print(", ");
	printlong(chip_size >> 20);
	print("M CHIPMEM\n");

	if (options & TEST_ONLY) {
		print("more_flags = ");
		printaddr(more_flags);
		print(", machine = ");
		printlong(cpu_id >> 16);
		print(", att = ");
		printaddr(cpu_id & 0xffff);
		print("\n");
		exit(RETURN_OK);
	}

	Delay(2 * TICKS_PER_SECOND);
	if ((DOSBase->dl_lib.lib_Version >= 36 && CheckSignal(SIGBREAKF_CTRL_C))
	    || (SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) != 0) {
		print("**BREAK**\n");
		exit(RETURN_WARN);
	}

	disable_graphics();

	startit(kernel_mem, copy_size,
	        entry,
	        fast_mem, fast_size, chip_size,
	        boot_howto,
	        symbols,
	        cpu_id, eclock_freq, boot_flags, more_flags,
	        img_start);
	/*NOTREACHED*/
}
