#include <lib/libsa/stand.h>
#include <lib/libsa/loadfile.h>
#include <lib/libkern/libkern.h>
#include "vers.h"
#include "tty.h"
#include "defs_platform.h"
#include <arch/tsarmips/stand/common/bootinfo.h>

void main(void);

void doboot(char *);
void dohelp(char *);

static uint8_t bootinfo[BOOTINFO_SIZE];
struct btinfo_symtab bi_syms;
struct btinfo_fdt bi_fdt;
struct btinfo_cons bi_cons;

void
main()
{
#if 0
	static char input[80];
	char *c;
#endif
	void (*entry)(void *);
	u_long marks[MARK_MAX];
	int err;

	putchar('\n');
	printf("%s %s SocLib Bootstrap, Revision %s\n",
	    bootprog_name, bootprog_kernrev, bootprog_rev);
	memset(marks, 0, sizeof marks);
	bi_init(bootinfo);
#if 0
	for(;;) {
		c = input;
		input[0] = '\0';
		printf("> ");
		gets(input);
		printf("got %s\n", input);
		while(*c == ' ') c++;
		if(*c) {
			if (strcmp(input, "help") == 0)
				dohelp(NULL);
			if (strcmp(input, "help") == 0)
				dohelp(NULL);
			if (strcmp(input, "boot") == 0) {
				if (loadfile("netbsd", marks, LOAD_KERNEL) < 0)
					printf("boot: %s\n", strerror(errno));
				else
					printf("boot returned\n");
			}
		}
	}
#else
	marks[MARK_START] = 0;
	if (loadfile("netbsd", marks, LOAD_KERNEL) < 0) {
		printf("boot: %s\n", strerror(errno));
		goto bad;
	}
	bi_syms.nsym = marks[MARK_NSYM];
	bi_syms.ssym = marks[MARK_SYM];
	bi_syms.esym = marks[MARK_END];
	bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms));
	entry = (void *)marks[MARK_ENTRY];
	printf("Starting at %p, syms %d/0x%x/0x%x at %p\n\n",
	    entry, bi_syms.nsym, bi_syms.ssym, bi_syms.esym, bootinfo);

	err = fdt_parse_header((void *)0xbfd00000, fdt);
	if (err) {
		printf("bad fdt header %d at %p\n", err, (void *)0xbfd00000);
		goto bad;
	}
	fdt_walk(&fdt->fdt_root_node, "device_type", fdt_fill_cons, &bi_cons);
	if (bi_cons.cons_physaddr == 0 || bi_cons.cons_size == 0) {
		printf("console not found\n");
		goto bad;
	}
	printf("found tty at 0x%x/0x%x\n",
	    bi_cons.cons_physaddr, bi_cons.cons_size);
	bi_add(&bi_cons, BTINFO_CONS, sizeof(bi_cons));
	bi_fdt.fdt_physaddr = (uint32_t)fdt->fdt_header;
	bi_fdt.fdt_size = be32toh(fdt->fdt_header->fdt_totalsize);
	bi_add(&bi_fdt, BTINFO_FDT, sizeof(bi_fdt));

	(*entry)(bootinfo);
	printf("kernel returned\n");
#endif
bad:
	return;
}

void
dohelp(char *unused)
{
	printf("nothing for now\n");
}

void
putchar(int c)
{
	volatile uint32_t *tty = (uint32_t *)(intptr_t)TTY_BASE;
	tty[TTY_WRITE] = c;
}

int
getchar(void)
{
	int c;
	volatile uint32_t *tty = (uint32_t *)(intptr_t)TTY_BASE;

	for(;;) {
		if ((uint8_t)tty[TTY_STATUS] != 0) {
			c = tty[TTY_READ] & 0xff;
			if (c != '\r')
				return c;
		}
	}
}
