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
24 #define isascii(c) ((uchar)(c) > 0 && (uchar)(c) < 0177)
26 uintptr kseg0 = KZERO;
27 Mach* machaddr[MAXMACH];
30 * Option arguments from the command line.
31 * oargv[0] is the boot file.
32 * Optionsinit() is called from multiboot()
33 * or some other machine-dependent place
37 static char* oargv[20];
38 static char oargb[128];
40 static char oenv[4096];
42 static uintptr sp; /* XXX - must go - user stack of init proc */
47 /* store plan9.ini contents here at least until we stash them in #ec */
48 static char confname[MAXCONF][KNAMELEN];
49 static char confval[MAXCONF][MAXCONFLINE];
53 uchar sandbox[64*1024+BY2PG];
61 for(i = 0; i < nconf; i++)
62 if(cistrcmp(confname[i], name) == 0)
79 addconf(char *name, char *val)
85 if(val == nil || nconf >= MAXCONF)
88 strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
91 strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
107 /* convert to name=value\n format */
116 error("kernel configuration too large");
117 memmove(BOOTARGS, p, n);
123 * assumes that we have loaded our /cfg/pxe/mac file at 0x1000 with
124 * tftp in u-boot. no longer uses malloc, so can be called early.
131 k = (char *)CONFADDR;
135 for(; k && *k != '\0'; k = next) {
136 if (!isascii(*k)) /* sanity check */
138 next = strchr(k, '\n');
142 if (*k == '\0' || *k == '\n' || *k == '#')
146 continue; /* mal-formed line */
158 o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
159 if(getenv("bootargs", o, o - oargb) != nil)
162 oargblen = strlen(oargb);
163 oargc = tokenize(oargb, oargv, nelem(oargv)-1);
168 getenv(char* name, char* buf, int n)
174 if((e = strchr(p, '=')) == nil)
176 for(q = name; p < e; p++){
181 if(p == e && *q == 0){
182 strecpy(buf, buf+n, e+1);
193 typedef struct Spiregs Spiregs;
195 ulong ictl; /* interface ctl */
196 ulong icfg; /* interface config */
197 ulong out; /* data out */
198 ulong in; /* data in */
199 ulong ic; /* interrupt cause */
200 ulong im; /* interrupt mask */
202 ulong dwrcfg; /* direct write config */
203 ulong dwrhdr; /* direct write header */
208 Csnact = 1<<0, /* serial memory activated */
211 Bytelen = 1<<5, /* 2^(this_bit) bytes per transfer */
212 Dirrdcmd= 1<<10, /* flag: fast read */
216 dumpbytes(uchar *bp, long max)
219 for (; max > 0; max--)
220 iprint("%02.2ux ", *bp++);
227 Spiregs *rp = (Spiregs *)soc.spi;
231 rp->icfg |= Dirrdcmd | 3<<8; /* fast reads, 4-byte addresses */
232 rp->icfg &= ~Bytelen; /* one-byte reads */
235 // print("spi flash at %#ux: memory reads enabled\n", PHYSSPIFLASH);
238 void archconsole(void);
241 * entered from l.s with mmu enabled.
243 * we may have to realign the data segment; apparently 5l -H0 -R4096
244 * does not pad the text segment. on the other hand, we may have been
245 * loaded by another kernel.
247 * be careful not to touch the data segment until we know it's aligned.
252 extern char bdata[], edata[], end[], etext[];
253 static ulong vfy = 0xcafebabe;
256 if (vfy != 0xcafebabe)
257 memmove(bdata, etext, edata - bdata);
258 if (vfy != 0xcafebabe) {
260 panic("misaligned data segment");
262 memset(edata, 0, end - edata); /* zero bss */
270 optionsinit("/boot/boot boot");
275 /* want plan9.ini to be able to affect memory sizing in confinit */
276 plan9iniinit(); /* before we step on plan9.ini in low memory */
279 /* xinit would print if it could */
283 * Printinit will cause the first malloc call.
284 * (printinit->qopen->malloc) unless any of the
285 * above (like clockintr) do an irqenable, which
287 * If the system dies here it's probably due
288 * to malloc(->xalloc) not being initialised
289 * correctly, or the data segment is misaligned
290 * (it's amazing how far you can get with
291 * things like that completely broken).
293 * (Should be) boilerplate from here on.
299 uartkirkwoodconsole();
300 /* only now can we print */
301 print("from Bell Labs\n\n");
304 print("sandbox: 64K at physical %#lux, mapped to 0xf10b0000\n",
305 PADDR((uintptr)sandbox & ~(BY2PG-1)));
315 chandevreset(); /* most devices are discovered here */
321 panic("schedinit returned");
329 cputype2name(name, sizeof name);
330 print("cpu%d: %lldMHz ARM %s\n", m->machno, m->cpuhz/1000000, name);
336 memset(m, 0, sizeof(Mach));
338 machaddr[m->machno] = m;
352 shutdown(int ispanic)
358 active.ispanic = ispanic;
359 else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
361 once = active.machs & (1<<m->machno);
362 active.machs &= ~(1<<m->machno);
367 iprint("cpu%d: exiting\n", m->machno);
369 for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
371 if(active.machs == 0 && consactive() == 0)
378 * exit kernel either on a panic or user request
389 * the new kernel is already loaded at address `code'
390 * of size `size' and entry point `entry'.
393 reboot(void *entry, void *code, ulong size)
395 void (*f)(ulong, ulong, ulong);
397 iprint("starting reboot...");
403 * should be the only processor running now
406 print("shutting down...\n");
409 /* turn off buffered serial console */
412 /* shutdown devices */
415 /* call off the dog */
420 /* setup reboot trampoline function */
421 f = (void*)REBOOTADDR;
422 memmove(f, rebootcode, sizeof(rebootcode));
426 print("rebooting...");
427 iprint("entry %#lux code %#lux size %ld\n",
428 PADDR(entry), PADDR(code), size);
429 delay(100); /* wait for uart to quiesce */
431 /* off we go - never to return */
434 (*f)(PADDR(entry), PADDR(code), size);
436 iprint("loaded kernel returned!\n");
442 * starting place for first process
448 char buf[2*KNAMELEN];
456 * These are o.k. because rootinit is null.
457 * Then early kproc's will have a root and dot.
459 up->slash = namec("#/", Atodir, 0, 0);
460 pathclose(up->slash->path);
461 up->slash->path = newpath("/");
462 up->dot = cclone(up->slash);
467 snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
468 ksetenv("terminal", buf, 0);
469 ksetenv("cputype", "arm", 0);
471 ksetenv("service", "cpu", 0);
473 ksetenv("service", "terminal", 0);
475 /* convert plan9.ini variables to #e and #ec */
476 for(i = 0; i < nconf; i++) {
477 ksetenv(confname[i], confval[i], 0);
478 ksetenv(confname[i], confval[i], 1);
482 kproc("alarm", alarmkproc, 0);
488 bootargs(uintptr base)
495 * Push the boot args onto the stack.
496 * The initial value of the user stack must be such
497 * that the total used is larger than the maximum size
498 * of the argument list checked in syscall.
501 p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
502 memmove(p, oargb, i);
505 * Now push argc and the argv pointers.
506 * This isn't strictly correct as the code jumped to by
507 * touser in init9.s calls startboot (port/initcode.c) which
509 * startboot(char *argv0, char **argv)
510 * not the usual (int argc, char* argv[]), but argv0 is
511 * unused so it doesn't matter (at the moment...).
513 av = (char**)(p - (oargc+2)*sizeof(char*));
514 ssize = base + BY2PG - PTR2UINT(av);
515 *av++ = (char*)oargc;
516 for(i = 0; i < oargc; i++)
517 *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
521 * Leave space for the return PC of the
522 * caller of initcode.
524 sp = USTKTOP - ssize - sizeof(void*);
528 * create the first process
538 /* no processes yet */
543 p->egrp = smalloc(sizeof(Egrp));
545 p->fgrp = dupfgrp(nil);
550 kstrdup(&p->text, "*init*");
551 kstrdup(&p->user, eve);
556 p->sched.pc = PTR2UINT(init0);
557 p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
558 p->sched.sp = STACKALIGN(p->sched.sp);
563 * Technically, newpage can't be called here because it
564 * should only be called when in a user context as it may
565 * try to sleep if there are no pages available, but that
566 * shouldn't be the case here.
568 s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
570 pg = newpage(1, 0, USTKTOP-BY2PG);
579 s = newseg(SG_TEXT, UTZERO, 1);
582 pg = newpage(1, 0, UTZERO);
583 memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
585 k = kmap(s->map[0]->pages[0]);
586 memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
592 Conf conf; /* XXX - must go - gag */
594 Confmem sheevamem[] = {
596 * Memory available to Plan 9:
597 * the 8K is reserved for ethernet dma access violations to scribble on.
599 { .base = 0, .limit = 512*MB - 8*1024, },
610 * Copy the physical memory configuration to Conf.mem.
612 if(nelem(sheevamem) > nelem(conf.mem)){
613 iprint("memory configuration botch\n");
616 memmove(conf.mem, sheevamem, sizeof(sheevamem));
619 pa = PADDR(PGROUND(PTR2UINT(end)));
622 * we assume that the kernel is at the beginning of one of the
623 * contiguous chunks of memory and fits therein.
625 for(i=0; i<nelem(conf.mem); i++){
626 /* take kernel out of allocatable space */
627 if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
628 conf.mem[i].base = pa;
630 conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
631 conf.npage += conf.mem[i].npage;
634 conf.upages = (conf.npage*90)/100;
635 conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
637 /* only one processor */
640 /* set up other configuration parameters */
641 conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
644 if(conf.nproc > 2000)
646 conf.nswap = conf.npage*3;
650 conf.copymode = 0; /* copy on write */
653 * Guess how much is taken by the large permanent
654 * datastructures. Mntcache and Mntrpc are not accounted for
657 kpages = conf.npage - conf.upages;
659 kpages -= conf.upages*sizeof(Page)
660 + conf.nproc*sizeof(Proc)
661 + conf.nimage*sizeof(Image)
663 + conf.nswppo*sizeof(Page*);
664 mainmem->maxsize = kpages;
667 * give terminals lots of image memory, too; the dynamic
668 * allocation will balance the load properly, hopefully.
669 * be careful with 32-bit overflow.
671 imagmem->maxsize = kpages;
675 cmpswap(long *addr, long old, long new)
677 return cas32(addr, old, new);