2 #include "../port/lib.h"
14 * Where configuration info is left for the loaded programme.
15 * This will turn into a structure as more is done by the boot loader
16 * (e.g. why parse the .ini file twice?).
17 * There are 3584 bytes available at CONFADDR.
19 #define BOOTARGS ((char*)CONFADDR)
20 #define BOOTARGSLEN (16*KiB) /* limit in devenv.c */
22 #define MAXCONFLINE 160
25 Minmem = 256*MB, /* conservative default */
28 #define isascii(c) ((uchar)(c) > 0 && (uchar)(c) < 0177)
30 uintptr kseg0 = KZERO;
31 Mach* machaddr[MAXMACH];
34 * Option arguments from the command line.
35 * oargv[0] is the boot file.
36 * Optionsinit() is called from multiboot()
37 * or some other machine-dependent place
41 static char* oargv[20];
42 static char oargb[128];
44 static char oenv[4096];
46 static uintptr sp; /* XXX - must go - user stack of init proc */
52 /* store plan9.ini contents here at least until we stash them in #ec */
53 static char confname[MAXCONF][KNAMELEN];
54 static char confval[MAXCONF][MAXCONFLINE];
62 for(i = 0; i < nconf; i++)
63 if(cistrcmp(confname[i], name) == 0)
80 addconf(char *name, char *val)
86 if(val == nil || nconf >= MAXCONF)
89 strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
92 strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
108 /* convert to name=value\n format */
117 error("kernel configuration too large");
118 memmove(BOOTARGS, p, n);
119 memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
125 * assumes that we have loaded our /cfg/pxe/mac file at 0x1000 with
126 * tftp in u-boot. no longer uses malloc, so can be called early.
133 k = (char *)CONFADDR;
137 for(; k && *k != '\0'; k = next) {
138 if (!isascii(*k)) /* sanity check */
140 next = strchr(k, '\n');
144 if (*k == '\0' || *k == '\n' || *k == '#')
148 continue; /* mal-formed line */
161 o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
162 if(getenv("bootargs", o, o - oargb) != nil)
165 oargblen = strlen(oargb);
166 oargc = tokenize(oargb, oargv, nelem(oargv)-1);
171 getenv(char* name, char* buf, int n)
177 if((e = strchr(p, '=')) == nil)
179 for(q = name; p < e; p++){
184 if(p == e && *q == 0){
185 strecpy(buf, buf+n, e+1);
198 extern char bdata[], edata[], end[], etext[];
199 static ulong vfy = 0xcafebabe;
201 /* l.s has already printed "Plan 9 from Be" */
202 // m = mach; /* now done in l.s */
204 /* realign data seg; apparently -H0 -R4096 does not pad the text seg */
205 if (vfy != 0xcafebabe) {
206 // wave('<'); wave('-');
207 memmove(bdata, etext, edata - bdata);
210 * once data segment is in place, always zero bss since we may
211 * have been loaded by another Plan 9 kernel.
213 memset(edata, 0, end - edata); /* zero BSS */
217 if (vfy != 0xcafebabe)
218 panic("data segment misaligned");
225 optionsinit("/boot/boot boot");
228 /* want plan9.ini to be able to affect memory sizing in confinit */
229 plan9iniinit(); /* before we step on plan9.ini in low memory */
231 trapinit(); /* so confinit can probe memory to size it */
232 confinit(); /* figures out amount of memory */
233 /* xinit prints (if it can), so finish up the banner here. */
235 iprint("l Labs\n\n");
239 mainmem->flags |= POOL_ANTAGONISM /* | POOL_PARANOIA */ ;
242 * Printinit will cause the first malloc call.
243 * (printinit->qopen->malloc) unless any of the
244 * above (like clockinit) do an irqenable, which
246 * If the system dies here it's probably due
247 * to malloc(->xalloc) not being initialised
248 * correctly, or the data segment is misaligned
249 * (it's amazing how far you can get with
250 * things like that completely broken).
252 * (Should be) boilerplate from here on.
255 archreset(); /* configure clock signals */
256 clockinit(); /* start clocks */
260 delay(250); /* let uart catch up */
274 chandevreset(); /* most devices are discovered here */
276 // i8250console(); /* too early; see init0 */
289 // memset(m, 0, sizeof(Mach)); /* done by l.s, now contains stack */
291 machaddr[m->machno] = m;
305 shutdown(int ispanic)
311 active.ispanic = ispanic;
312 else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
314 once = active.machs & (1<<m->machno);
315 active.machs &= ~(1<<m->machno);
320 iprint("cpu%d: exiting\n", m->machno);
322 for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
324 if(active.machs == 0 && consactive() == 0)
331 * exit kernel either on a panic or user request
342 isaconfig(char *class, int ctlrno, ISAConf *isa)
347 snprint(cc, sizeof cc, "%s%d", class, ctlrno);
353 isa->nopt = tokenize(p, isa->opt, NISAOPT);
354 for(i = 0; i < isa->nopt; i++){
356 if(cistrncmp(p, "type=", 5) == 0)
358 else if(cistrncmp(p, "port=", 5) == 0)
359 isa->port = strtoul(p+5, &p, 0);
360 else if(cistrncmp(p, "irq=", 4) == 0)
361 isa->irq = strtoul(p+4, &p, 0);
362 else if(cistrncmp(p, "dma=", 4) == 0)
363 isa->dma = strtoul(p+4, &p, 0);
364 else if(cistrncmp(p, "mem=", 4) == 0)
365 isa->mem = strtoul(p+4, &p, 0);
366 else if(cistrncmp(p, "size=", 5) == 0)
367 isa->size = strtoul(p+5, &p, 0);
368 else if(cistrncmp(p, "freq=", 5) == 0)
369 isa->freq = strtoul(p+5, &p, 0);
375 * the new kernel is already loaded at address `code'
376 * of size `size' and entry point `entry'.
379 reboot(void *entry, void *code, ulong size)
381 void (*f)(ulong, ulong, ulong);
383 print("starting reboot...");
388 * should be the only processor running now
391 print("reboot entry %#lux code %#lux size %ld\n",
392 PADDR(entry), PADDR(code), size);
395 /* turn off buffered serial console */
400 /* shutdown devices */
403 /* call off the dog */
409 /* setup reboot trampoline function */
410 f = (void*)REBOOTADDR;
411 memmove(f, rebootcode, sizeof(rebootcode));
415 /* off we go - never to return */
416 (*f)(PADDR(entry), PADDR(code), size);
418 iprint("loaded kernel returned!\n");
424 * starting place for first process
430 char buf[2*KNAMELEN];
437 * These are o.k. because rootinit is null.
438 * Then early kproc's will have a root and dot.
440 up->slash = namec("#/", Atodir, 0, 0);
441 pathclose(up->slash->path);
442 up->slash->path = newpath("/");
443 up->dot = cclone(up->slash);
445 dmatest(); /* needs `up' set, so can't do it earlier */
447 i8250console(); /* might be redundant, but harmless */
449 panic("init0: nil serialoq");
453 snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
454 ksetenv("terminal", buf, 0);
455 ksetenv("cputype", "arm", 0);
457 ksetenv("service", "cpu", 0);
459 ksetenv("service", "terminal", 0);
461 /* convert plan9.ini variables to #e and #ec */
462 for(i = 0; i < nconf; i++) {
463 ksetenv(confname[i], confval[i], 0);
464 ksetenv(confname[i], confval[i], 1);
468 kproc("alarm", alarmkproc, 0);
473 bootargs(uintptr base)
480 * Push the boot args onto the stack.
481 * The initial value of the user stack must be such
482 * that the total used is larger than the maximum size
483 * of the argument list checked in syscall.
486 p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
487 memmove(p, oargb, i);
490 * Now push argc and the argv pointers.
491 * This isn't strictly correct as the code jumped to by
492 * touser in init9.s calls startboot (port/initcode.c) which
494 * startboot(char *argv0, char **argv)
495 * not the usual (int argc, char* argv[]), but argv0 is
496 * unused so it doesn't matter (at the moment...).
498 av = (char**)(p - (oargc+2)*sizeof(char*));
499 ssize = base + BY2PG - PTR2UINT(av);
500 *av++ = (char*)oargc;
501 for(i = 0; i < oargc; i++)
502 *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
506 * Leave space for the return PC of the
507 * caller of initcode.
509 sp = USTKTOP - ssize - sizeof(void*);
513 * create the first process
523 /* no processes yet */
528 p->egrp = smalloc(sizeof(Egrp));
530 p->fgrp = dupfgrp(nil);
535 kstrdup(&p->text, "*init*");
536 kstrdup(&p->user, eve);
541 p->sched.pc = PTR2UINT(init0);
542 p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
543 p->sched.sp = STACKALIGN(p->sched.sp);
548 * Technically, newpage can't be called here because it
549 * should only be called when in a user context as it may
550 * try to sleep if there are no pages available, but that
551 * shouldn't be the case here.
553 s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
556 pg = newpage(1, 0, USTKTOP-BY2PG);
565 s = newseg(SG_TEXT, UTZERO, 1);
567 pg = newpage(1, 0, UTZERO);
568 memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
570 k = kmap(s->map[0]->pages[0]);
571 memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
577 Conf conf; /* XXX - must go - gag */
579 Confmem omapmem[nelem(conf.mem)] = {
581 * Memory available to Plan 9:
583 { .base = PHYSDRAM, .limit = PHYSDRAM + Minmem, },
585 ulong memsize = Minmem;
592 addr = PHYSDRAM + sz - BY2WD;
594 if (probeaddr(addr) >= 0) {
610 * Copy the physical memory configuration to Conf.mem.
612 if(nelem(omapmem) > nelem(conf.mem)){
613 iprint("memory configuration botch\n");
616 if((p = getconf("*maxmem")) != nil) {
617 memsize = strtoul(p, 0, 0) - PHYSDRAM;
618 if (memsize < 16*MB) /* sanity */
623 * see if all that memory exists; if not, find out how much does.
624 * trapinit must have been called first.
626 if (gotmem(memsize) < 0 && gotmem(256*MB) < 0 && gotmem(128*MB) < 0) {
627 iprint("can't find any memory, assuming %dMB\n", Minmem / MB);
631 omapmem[0].limit = PHYSDRAM + memsize;
632 memmove(conf.mem, omapmem, sizeof(omapmem));
635 pa = PADDR(PGROUND(PTR2UINT(end)));
638 * we assume that the kernel is at the beginning of one of the
639 * contiguous chunks of memory and fits therein.
641 for(i=0; i<nelem(conf.mem); i++){
642 /* take kernel out of allocatable space */
643 if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
644 conf.mem[i].base = pa;
646 conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
647 conf.npage += conf.mem[i].npage;
650 conf.upages = (conf.npage*80)/100;
651 conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
653 /* only one processor */
656 /* set up other configuration parameters */
657 conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
660 if(conf.nproc > 2000)
662 conf.nswap = conf.npage*3;
666 conf.copymode = 0; /* copy on write */
669 * Guess how much is taken by the large permanent
670 * datastructures. Mntcache and Mntrpc are not accounted for
673 kpages = conf.npage - conf.upages;
675 kpages -= conf.upages*sizeof(Page)
676 + conf.nproc*sizeof(Proc)
677 + conf.nimage*sizeof(Image)
679 + conf.nswppo*sizeof(Page*);
680 mainmem->maxsize = kpages;
683 * give terminals lots of image memory, too; the dynamic
684 * allocation will balance the load properly, hopefully.
685 * be careful with 32-bit overflow.
687 imagmem->maxsize = kpages;
693 cmpswap(long *addr, long old, long new)
695 return cas32(addr, old, new);