/*
* Where configuration info is left for the loaded programme.
* This will turn into a structure as more is done by the boot loader
* (e.g. why parse the .ini file twice?).
* There are 3584 bytes available at CONFADDR.
*/
#define BOOTARGS ((char*)CONFADDR)
#define BOOTARGSLEN (16*KiB) /* limit in devenv.c */
#define MAXCONF 64
#define MAXCONFLINE 160
/* store plan9.ini contents here at least until we stash them in #ec */
static char confname[MAXCONF][KNAMELEN];
static char confval[MAXCONF][MAXCONFLINE];
static int nconf;
/* convert to name=value\n format */
for(q=p; *q; q++) {
q += strlen(q);
*q = '=';
q += strlen(q);
*q = '\n';
}
n = q - p + 1;
if(n >= BOOTARGSLEN)
error("kernel configuration too large");
memmove(BOOTARGS, p, n);
memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
poperror();
free(p);
}
/*
* assumes that we have loaded our /cfg/pxe/mac file at 0x1000 with
* tftp in u-boot. no longer uses malloc, so can be called early.
*/
static void
plan9iniinit(void)
{
char *k, *v, *next;
k = (char *)CONFADDR;
if(!isascii(*k))
return;
for(; k && *k != '\0'; k = next) {
if (!isascii(*k)) /* sanity check */
break;
next = strchr(k, '\n');
if (next)
*next++ = '\0';
if (*k == '\0' || *k == '\n' || *k == '#')
continue;
v = strchr(k, '=');
if(v == nil)
continue; /* mal-formed line */
*v++ = '\0';
/* l.s has already printed "Plan 9 from Be" */
// m = mach; /* now done in l.s */
/* realign data seg; apparently -H0 -R4096 does not pad the text seg */
if (vfy != 0xcafebabe) {
// wave('<'); wave('-');
memmove(bdata, etext, edata - bdata);
}
/*
* once data segment is in place, always zero bss since we may
* have been loaded by another Plan 9 kernel.
*/
memset(edata, 0, end - edata); /* zero BSS */
cacheuwbinv();
l2cacheuwbinv();
if (vfy != 0xcafebabe)
panic("data segment misaligned");
vfy = 0;
wave('l');
machinit();
mmuinit();
quotefmtinstall();
/* want plan9.ini to be able to affect memory sizing in confinit */
plan9iniinit(); /* before we step on plan9.ini in low memory */
trapinit(); /* so confinit can probe memory to size it */
confinit(); /* figures out amount of memory */
/* xinit prints (if it can), so finish up the banner here. */
delay(500);
iprint("l Labs\n\n");
delay(500);
xinit();
/*
* Printinit will cause the first malloc call.
* (printinit->qopen->malloc) unless any of the
* above (like clockinit) do an irqenable, which
* will call malloc.
* If the system dies here it's probably due
* to malloc(->xalloc) not being initialised
* correctly, or the data segment is misaligned
* (it's amazing how far you can get with
* things like that completely broken).
*
* (Should be) boilerplate from here on.
*/
/*
* the new kernel is already loaded at address `code'
* of size `size' and entry point `entry'.
*/
void
reboot(void *entry, void *code, ulong size)
{
void (*f)(ulong, ulong, ulong);
writeconf();
cpushutdown();
/* turn off buffered serial console */
serialoq = nil;
kprintoq = nil;
screenputs = nil;
/* shutdown devices */
chandevshutdown();
/* call off the dog */
clockshutdown();
splhi();
intrsoff();
/* setup reboot trampoline function */
f = (void*)REBOOTADDR;
memmove(f, rebootcode, sizeof(rebootcode));
cacheuwbinv();
l2cacheuwbinv();
/* off we go - never to return */
(*f)(PADDR(entry), PADDR(code), size);
}
/*
* starting place for first process
*/
void
init0(void)
{
char buf[2*KNAMELEN], **sp;
int i;
dmatest(); /* needs `up' set, so can't do it earlier */
chandevinit();
i8250console(); /* might be redundant, but harmless */
if(serialoq == nil)
panic("init0: nil serialoq");
normalprint = 1;
/*
* see if all that memory exists; if not, find out how much does.
* trapinit must have been called first.
*/
if (gotmem(memsize) < 0 && gotmem(256*MB) < 0 && gotmem(128*MB) < 0) {
iprint("can't find any memory, assuming %dMB\n", Minmem / MB);
memsize = Minmem;
}
conf.npage = 0;
pa = PADDR(PGROUND((uintptr)end));
/*
* we assume that the kernel is at the beginning of one of the
* contiguous chunks of memory and fits therein.
*/
for(i=0; i<nelem(conf.mem); i++){
/* take kernel out of allocatable space */
if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
conf.mem[i].base = pa;
/*
* Guess how much is taken by the large permanent
* datastructures. Mntcache and Mntrpc are not accounted for.
*/
kpages = conf.npage - conf.upages;
kpages *= BY2PG;
kpages -= conf.upages*sizeof(Page)
+ conf.nproc*sizeof(Proc)
+ conf.nimage*sizeof(Image)
+ conf.nswap
+ conf.nswppo*sizeof(Page*);
mainmem->maxsize = kpages;
if(!cpuserver)
/*
* give terminals lots of image memory, too; the dynamic
* allocation will balance the load properly, hopefully.
* be careful with 32-bit overflow.
*/
imagmem->maxsize = kpages;
// archconfinit();
}
int
cmpswap(long *addr, long old, long new)
{
return cas32(addr, old, new);
}