It is our 15-th Lab and it is the time came to make birth of the process Eve, run Dis virtual machine and our first Limbo program!

First create file archrpi.c where we all R-Pi platform specific code. We need to implement kprocchild() call:

 1static void
 2linkproc(void)
 3{
 4	spllo();
 5	if (waserror())
 6		print("error() underflow: %r\n");
 7	else (*up->kpfun)(up->arg);
 8	pexit("end proc", 1);
 9}
10
11void
12kprocchild(Proc *p, void (*func)(void*), void *arg)
13{
14	p->sched.pc = (ulong)linkproc;
15	p->sched.sp = (ulong)p->kstack+KSTACK-8;
16	p->kpfun = func;
17	p->arg = arg;
18}

As it is ready we just add initializations that are left to main.c:

 1...
 2trapinit();
 3printinit();
 4
 5print("\nARM %ld MHz id %8.8lux\n", (m->cpuhz+500000)/1000000, getcpuid());
 6print("Inferno OS %s Vita Nuova\n\n", VERSION);
 7
 8procinit();
 9links();
10chandevreset();
11
12eve = strdup("inferno");
13
14userinit();
15schedinit();
16
17pl011_puts("to inifinite loop\n\n");
18for (;;);

Where our initialization of first process init0() and run first Dis program:

 1void
 2init0(void)
 3{
 4	Osenv *o;
 5	char buf[2*KNAMELEN];
 6
 7	up->nerrlab = 0;
 8
 9	print("Starting init0()\n");
10	spllo();
11
12	if(waserror())
13		panic("init0 %r");
14
15	/* These are o.k. because rootinit is null.
16	 * Then early kproc's will have a root and dot. */
17
18	o = up->env;
19	o->pgrp->slash = namec("#/", Atodir, 0, 0);
20	cnameclose(o->pgrp->slash->name);
21	o->pgrp->slash->name = newcname("/");
22	o->pgrp->dot = cclone(o->pgrp->slash);
23
24	chandevinit();
25
26	if(!waserror()){
27		ksetenv("cputype", "arm", 0);
28		snprint(buf, sizeof(buf), "arm %s", conffile);
29		ksetenv("terminal", buf, 0);
30		poperror();
31	}
32
33	poperror();
34
35	disinit("/osinit.dis");
36}
37
38void
39userinit(void)
40{
41	Proc *p;
42	Osenv *o;
43
44	p = newproc();
45	o = p->env;
46
47	o->fgrp = newfgrp(nil);
48	o->pgrp = newpgrp();
49	o->egrp = newegrp();
50	kstrdup(&o-;>user, eve);
51
52	strcpy(p->text, "interp");
53
54	p->fpstate = FPINIT;
55
56	/*	Kernel Stack
57		N.B. The -12 for the stack pointer is important.
58		4 bytes for gotolabel's return PC */
59	p->sched.pc = (ulong)init0;
60	p->sched.sp = (ulong)p->kstack+KSTACK-8;
61
62	ready(p);
63}

Now go to folder ../init/ and create simple Limbo program rpiinit.b:

 1implement Init;
 2
 3include "sys.m";
 4    sys:    Sys;
 5
 6Bootpreadlen: con 128;
 7
 8Init: module
 9{
10    init:   fn();
11};
12
13init()
14{
15    sys = load Sys Sys->PATH;
16    sys->print("Hey, this is Hello World from Dis!\n\n");
17}

Now edit platform definition file rpi, section init and section root to use rpiinit.b:

 1...
 2init
 3    rpiinit
 4
 5root
 6    /chan   /
 7    /dev    /
 8    /dis    /
 9    /env    /
10    /fd     /
11    /net    /
12    /prog   /
13    /dis/lib
14    /dis/disk
15    /osinit.dis

Compile, start Raspberry Pi device with expectations and:

Load address: 0x7fe0
Loading: T #T #####################################
done
Bytes transferred = 552620 (86eac hex)
## Starting application at 0x00008000 ...
Entered main() at 00009114 with SP=00002FE8
Clearing Mach:  00002000-00002060
Clearing edata: 00065B08-0006CC30
Conf: top=134217728, npage0=32659, ialloc=26750976, nproc=735

ARM 0 MHz id 410fb767
Inferno OS Fourth Edition (20121207) Vita Nuova

Starting init0()
Initial Dis: "/osinit.dis"
Hey, this is Hello World from Dis!

Wow, Success!

FILES: