#include <lib/libsa/stand.h>
#include <lib/libsa/loadfile.h>
#include <lib/libkern/libkern.h>
#include <sys/param.h>
#include <sys/exec.h>
#include <sys/exec_elf.h>
#include "common.h"
#include "bootinfo.h"
#include "start.h"
char *kernelnames[] = {
"netbsd", "netbsd.gz",
"netbsd.old",
"onetbsd",
"gennetbsd",
"nfsnetbsd",
NULL
};
void main (char *);
char *getboot(char *, char*);
static int devcanon(char *);
#define OPT_MAX PATH_MAX
static int loadit(char *name, u_long *marks)
{
printf("Loading: %s\n", name);
memset(marks, 0, sizeof(*marks) * MARK_MAX);
return (loadfile(name, marks, LOAD_ALL));
}
void
main(char *stack_top)
{
int autoboot = 1, win;
char *name, **namep, *dev, *kernel;
char bootpath[PATH_MAX], options[OPT_MAX];
uint32_t entry;
u_long marks[MARK_MAX];
struct btinfo_symtab bi_syms;
struct btinfo_bootpath bi_bpath;
init_board();
setheap((void *)(0x81000000-(1024*1024)), (void *)0x81000000);
Delay(200000);
printf("Hit any char to boot..");
(void)GetChar();
printf("\n");
printf("NetBSD/emips " NETBSD_VERS " " BOOT_TYPE_NAME " Bootstrap, Revision %s\n",
bootprog_rev);
bi_init(BOOTINFO_ADDR);
dev = "0/ace(0,0)/";
kernel = kernelnames[0];
options[0] = 0;
win = 0;
for (;!win;) {
strcpy(bootpath, dev);
strcat(bootpath, kernel);
name = getboot(bootpath,options);
if (name != NULL) {
win = (loadit(name, marks) == 0);
} else if (autoboot)
break;
autoboot = 0;
}
if (!win) {
for (namep = kernelnames, win = 0; *namep != NULL && !win;
namep++) {
kernel = *namep;
strcpy(bootpath, dev);
strcat(bootpath, kernel);
win = (loadit(bootpath, marks) == 0);
if (win) {
name = bootpath;
}
}
}
if (!win)
goto fail;
strncpy(bi_bpath.bootpath, name, BTINFO_BOOTPATH_LEN);
bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath));
entry = marks[MARK_ENTRY];
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));
printf("Starting at 0x%x\n\n", entry);
call_kernel(entry, name, options, BOOTINFO_MAGIC, bootinfo);
(void)printf("KERNEL RETURNED!\n");
fail:
(void)printf("Boot failed! Halting...\n");
}
static inline int
parse(char *cmd, char *kname, char *optarg)
{
char *arg = cmd;
char *ep, *p;
int c, i;
while ((c = *arg++)) {
if (c == ' ' || c == '\t' || c == '\n')
continue;
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
ep = p;
if (*p)
*p++ = 0;
if (c == '-') {
while ((c = *arg++)) {
*optarg++ = c;
}
*optarg = 0;
} else {
arg--;
if ((i = ep - arg)) {
if ((size_t)i >= PATH_MAX)
return -1;
memcpy(kname, arg, i + 1);
}
}
arg = p;
}
return 0;
}
static inline void
getstr(char *cmd, int c)
{
char *s;
s = cmd;
if (c == 0)
c = GetChar();
for (;;) {
switch (c) {
case 0:
break;
case '\177':
case '\b':
if (s > cmd) {
s--;
printf("\b \b");
}
break;
case '\n':
case '\r':
*s = 0;
return;
default:
if ((s - cmd) < (PATH_MAX - 1))
*s++ = c;
xputchar(c);
}
c = GetChar();
}
}
char *getboot(char *kname, char* optarg)
{
char c = 0;
char cmd[PATH_MAX];
printf("\nDefault: %s%s %s\nboot: ", (*optarg) ? "-" : "", optarg, kname);
if ((c = GetChar()) == -1)
return NULL;
cmd[0] = 0;
getstr(cmd,c);
xputchar('\n');
if (parse(cmd,kname,optarg))
xputchar('\a');
else if (devcanon(kname) == 0)
return kname;
return NULL;
}
static int
devcanon(char *fname)
{
int ctlr = 0, unit = 0, part = 0;
int c;
char device_name[20];
char file_name[PATH_MAX];
const char *cp;
char *ncp;
cp = fname;
ncp = device_name;
if ((c = *cp) >= '0' && c <= '9') {
ctlr = c - '0';
c = *++cp;
if (c != '/')
return (ENXIO);
c = *++cp;
}
while ((c = *cp) != '\0') {
if ((c == '(') || (c == '/')) {
cp++;
break;
}
if (ncp < device_name + sizeof(device_name) - 1)
*ncp++ = c;
cp++;
}
if (ncp == device_name) {
strcpy(device_name,"ace");
ncp += 3;
}
if ((c = *cp) >= '0' && c <= '9') {
unit = c - '0';
c = *++cp;
}
if (c == ',') {
if ((c = *++cp) >= '0' && c <= '9') {
part = c - '0';
c = *++cp;
}
}
if (c == ')')
c = *++cp;
if (c == '/')
cp++;
*ncp = '\0';
strcpy(file_name, (*cp) ? cp : kernelnames[0]);
snprintf(fname, PATH_MAX, "%c/%s(%c,%c)/%s",
ctlr + '0', device_name, unit + '0', part + '0', file_name);
return (0);
}