Now it is lab 6 and it is time to compile “something” – kernel of inferno, but we are going to compile without worrying that it would not work (even would not link). We just need inferno kernel which can be compiled okay for R-Pi using a lot of stabs.

Files/Folders structure:

inferno-os/
 |-os/
 |    |-rpi/
 |    |    |-rpi
 |    |    |-mkfile
 |    |    |-load.s
 |    |    |-main.c

mkfile:

 1<../../mkconfig
 2
 3CONF=rpi
 4CONFLIST=rpi
 5loadaddr=0x00008000
 6
 7SYSTARG=$OSTARG
 8OBJTYPE=arm
 9INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin
10
11<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
12
13<| $SHELLNAME ../port/mkdevlist $CONF
14
15OBJ=\
16    load.$O\
17    main.$O\
18    $IP\
19    $DEVS\
20    $ETHERS\
21    $LINKS\
22    $PORT\
23    $MISC\
24    $OTHERS\
25    $CONF.root.$O\
26
27LIBNAMES=${LIBS:%=lib%.a}
28LIBDIRS=$LIBS
29
30CFLAGS=-wFV -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp
31KERNDATE=`{$NDATE}
32
33default:V: i$CONF
34
35i$CONF: $OBJ $CONF.c $CONF.root.h $LIBNAMES
36    $CC $CFLAGS -DKERNDATE=$KERNDATE $CONF.c
37    $LD -l -o $target -R4 -T$loadaddr $OBJ $CONF.$O $LIBFILES
38
39<../port/portmkfile
40
41main.$O:    $ROOT/Inferno/$OBJTYPE/include/ureg.h

rpi:

 1dev
 2    root
 3    cons
 4    env
 5    mnt
 6    pipe
 7    prog
 8    srv
 9    dup
10
11lib
12    interp
13    math
14    kern
15    sec
16
17mod
18    math
19    sys
20
21port
22    alarm
23    alloc
24    allocb
25    chan
26    dev
27    dial
28    dis
29    discall
30    exception
31    exportfs
32    inferno
33    latin1
34    nocache
35    nodynld
36    parse
37    pgrp
38    print
39    proc
40    qio
41    qlock
42    random
43    sysfile
44    taslock
45    xalloc
46
47init
48    bootinit
49
50root
51    /chan   /
52    /dev    /
53    /dis    /
54    /env    /
55    /fd     /
56    /net    /
57    /prog   /
58    /dis/lib
59    /dis/disk

Now if we try to compile with “mk” we will find fast that some header files are required:

# touch dat.h fns.h io.h mem.h
  • fns.h - define signatures of required methods, also should include “../port/portfns.h”
  • dat.h - kernel rpi specific data structures, also should include “../port/portdat.h”
  • io.h - input/output defines and enums
  • mem.h - defines related to our memory model

Also add the section for header files to “mkfile”:

1HFILES=\
2    mem.h\
3    dat.h\
4    fns.h\
5    io.h\

After mutiple times (well, not bazillion times) of change+compile+compare-with-ipaq1110/sa1110 we will reveal that minimal content of these header files is:

io.h:

--EMPTY--

fns.h:

1#define KADDR(p)    ((void *)p)
2#define PADDR(p)    ((ulong)p)
3
4int     waserror();
5void    (*screenputs)(char*, int);
6
7#include "../port/portfns.h"

mem.h:

 1#define KiB     1024u       /*! Kibi 0x0000000000000400 */
 2#define MiB     1048576u    /*! Mebi 0x0000000000100000 */
 3#define GiB     1073741824u /*! Gibi 000000000040000000 */
 4
 5#define KZERO       0                       /*! kernel address space */
 6#define BY2PG       (4*KiB)                 /*! bytes per page */
 7#define BY2V        8                       /*! only used in xalloc.c */
 8#define MACHADDR    (KZERO+0x2000)          /*! Mach structure */
 9#define ROUND(s,sz) (((s)+(sz-1))&~(sz-1))
10
11#define KSTKSIZE    (8*KiB)
12#define KSTACK      KSTKSIZE

dat.h:

 1#define HZ          (100)       /*! clock frequency */
 2#define MS2HZ       (1000/HZ)   /*! millisec per clock tick */
 3#define TK2SEC(t)   ((t)/HZ)    /*! ticks to seconds */
 4#define MS2TK(t)    ((t)/MS2HZ) /*! milliseconds to ticks */
 5
 6#define MACHP(n)    (n == 0 ? (Mach*)(MACHADDR) : (Mach*)0)
 7
 8typedef struct Lock Lock;
 9typedef struct Ureg Ureg;
10typedef struct Label Label;
11typedef struct FPenv FPenv;
12typedef struct Mach Mach;
13typedef struct FPU FPU;
14typedef ulong Instr;
15typedef struct Conf Conf;
16
17struct Lock
18{
19    ulong   key;
20    ulong   sr;
21    ulong   pc;
22    int pri;
23};
24
25struct Label
26{
27    int x;
28};
29
30enum /* FPenv.status */
31{
32    FPINIT,
33    FPACTIVE,
34    FPINACTIVE
35};
36
37struct FPenv
38{
39    int x;
40};
41
42struct  FPU
43{
44    FPenv env;
45};
46
47struct Conf
48{
49    ulong   nmach;      /* processors */
50    ulong   nproc;      /* processes */
51    ulong   npage0;     /* total physical pages of memory */
52    ulong   npage1;     /* total physical pages of memory */
53    ulong   base0;      /* base of bank 0 */
54    ulong   base1;      /* base of bank 1 */
55    ulong   ialloc;     /* max interrupt time allocation in bytes */
56};
57
58#include "../port/portdat.h"
59
60struct Mach
61{
62    int     machno;     /* physical id of processor */
63    ulong   ticks;      /* of the clock since boot time */
64    Proc*   proc;       /* current process on this processor */
65    Label   sched;      /* scheduler wakeup */
66};
67
68extern Mach *m;
69extern Proc *up;

So, with this minimal “set” we already can compile all files of our inferno kernel, but of course we failed on the linking stage because we definitely need an implementation of referenced functions:

(2358)	BL	,waserror+0(SB)
iprint: undefined: splhi
(2495)	BL	,splhi+0(SB)
iprint: undefined: splx
(2502)	BL	,splx+0(SB)
panic: undefined: setpanic
(2514)	BL	,setpanic+0(SB)
panic: undefined: spllo
(2522)	BL	,spllo+0(SB)
panic: undefined: dumpstack
(2523)	BL	,dumpstack+0(SB)
panic: undefined: exit
(2525)	BL	,exit+0(SB)
conswrite: undefined: reboot
(3391)	BL	,reboot+0(SB)
conswrite: undefined: halt
(3394)	BL	,halt+0(SB)
uartreset: undefined: addclock0link
(2106)	BL.NE	,addclock0link+0(SB)
poolimmutable: undefined: getcallerpc
(2207)	BL	,getcallerpc+0(SB)
too many errors

Anyway this is very good start to move to actual implementation of required routines to have our kernel linked and then we can retry our hello world example and move further to have some codes for the initialization stage.

ps: again this minimum set can be used as starting point for another arm boards with tweaking of mem.h for specifying addresses where if kernel is placed, kernel stack, etc.

FILES: