-# TODO
-# settime
-# handle rootspec
-# handle rootdir
-# clean rc environment before running init(8)
-# kfs
-# caching
-
-rfork e
-# boot methods
-mlocal = (configlocal connectlocal)
-mtcp = (configtcp connecttcp)
-mtab = (mlocal mtcp)
-config=1
-connect=2
-bootargs=()
-
-. /rc/lib/conf.rc
-. /rc/lib/menu.rc
-. /rc/lib/local.rc
-. /rc/lib/tcp.rc
-
-cputype=`{cat '#e'/cputype}
+#!/bin/rc
+
+# mount points
+mntgen -s slashn /n && chmod 666 /srv/slashn
+mntgen -s slashmnt /mnt && chmod 666 /srv/slashmnt
+mntgen -s mntexport /mnt/exportfs && chmod 666 /srv/mntexport
+
+bind /root /mnt/broot
+unmount /root
+
+bind -q '#d' /fd
+bind -q '#p' /proc
+for(i in S f k æ t b m)
+ bind -qa '#'^$i /dev
+
+# bind in an ip interface
+for(i in I l^(0 1 2 3))
+ bind -qa '#'$i /net
+
+# usualy better than 1970
+cat '#r/rtc' >/dev/time >[2]/dev/null
+
+# reparse variables
+for(i in `{ls -Qp /env}){
+ switch($i){
+ case '*'* 'fn#'* e820 apm0 apid ifs path pid prompt status ?
+ # ignore these
+ case *
+ $i=`{echo $$i}
+ }
+}
+
+fn sigint {
+ status=interrupted
+}
fn fatal {
echo $*
$* || fatal $"*^': '^$status
}
-fn devinit{
- bind -qa '#c' /dev
- bind -qa '#S' /dev
- bind -qa '#f' /dev
- bind -qa '#k' /dev
- bind -qa '#æ' /dev
-}
-
-fn usbinit{
- if(test -e '#u'){
- bind -a '#u' /dev
- usb/usbd
+fn ask {
+ echo -n $1
+ echo -n $2
+ if(! ~ $#3 0){
+ echo -n '['
+ echo -n $3
+ echo -n '] '
}
-}
-
-fn kbmap{
- if(! ~ $#kbmap 0){
- bind -a '#κ' /dev
- cat $kbmap > /dev/kbmap
+ $1=`{dd -bs 64 -count 1 >[2]/dev/null}
+ if(~ $#$1 0)
+ $1=$3
+ if(~ $"$1 '!rc'){
+ rc -i
+ $1=()
}
+ if(~ $#$1 0)
+ ask $*
}
-fn readmethod{
- echo
- echo Storage devices
- for(i in /dev/sd[A-Z][0-9]*){
- echo -n local!^$i' '
- echo `{sed 's/inquiry[ ]+//g; q' $i/ctl}\
- partitions: `{cat $i/ctl | grep part | awk '{print $2}'}
- }
+mt=()
- found=0
- while(~ $found 0){
- timeo=5
- resp=()
- while(~ $#resp 0){
- echo -n 'root is from: '
- resp=`{tread $timeo}
- if(! ~ $status ''){
- bootconf # set configuration from file
- if(! ~ $#nobootprompt 0)
- bootargs=$nobootprompt
- resp=$bootargs
- }
- if(~ $resp !rc)
- rc -i
- timeo=0
- }
-
- method=`{echo $resp | awk -F! '{print $1}'}
- NF=`{echo $resp | awk -F! '{print NF}'}
-
- for(i in `{seq 1 $#mtab}){
- if(~ $mtab($i) m^$method)
- found = $i
+fn main{
+ mp=()
+ while(~ $#mp 0){
+ if(~ $#nobootprompt 0){
+ echo
+ showlocaldevs
+ ask bootargs ' is (tcp, tls, il, local!device)' $"bootargs
}
- if(~ $found 0){
- echo method $method not found
+ if not bootargs=$nobootprompt
+ nobootprompt=()
+ mn=`{echo $bootargs | sed 's,!, ,'}
+ ma=$mn(2-)
+ mn=$mn(1)
+ switch(m$"mn){
+ case $mt
+ mp=m$mn
+ mp=$$mp
}
}
- methodarg = `{echo $resp | sed 's/^[A-Za-z]+!(.*)$/\1/'}
- mp = $$mtab($found)
-}
-
-fn authentication{
+ # authentication agent
if(! test -f /srv/factotum){
- x=(auth/factotum -sfactotum)
- if(~ $cpuflag 1)
- x=($x -kS)
+ x=(/boot/factotum -n -sfactotum)
+ if(~ $service cpu){
+ x=($x -S)
+ if(~ -k $ff)
+ x=($x -k)
+ }
if not
x=($x -u)
- if(! ~ $#authaddr 0)
- x=($x -a $authaddr)
if(! ~ $#debugfactotum 0)
x=($x -p)
must $x
}
-}
-fn swapproc{
- if(test -x '#c'/swap)
- echo -n start > '#c'/swap
-}
+ # config method
+ $mp(1) $ma
+
+ # load keys from secstore if $auth or $secstore is not empty
+ x=secstore
+ if(~ $#$x 0) x=auth
+ if(! ~ $#$x 0 && test -x /bin/auth/secstore && test -f /mnt/factotum/ctl){
+ x=(auth/secstore -G factotum -s^$$x)
+ if(~ $service cpu)
+ $x -n >/mnt/factotum/ctl
+ if(~ $status *readnvram* || ! ~ $service cpu)
+ $x >/mnt/factotum/ctl
+ }
-fn main{
- readmethod
- $mp($config)
-
- switch($method){
- case local
- islocal=1
- case hybrid
- ishybrid=1
+ # connect method
+ $mp(2) $ma
+
+ # insert cfs in the pipeline
+ if(test -x /bin/cfs){
+ if(~ $#bootdisk 1 && ~ $#cfs 0)
+ cfs=$bootdisk/cache
+ if(~ $#cfs 1 && ! ~ $cfs off && test -f $cfs){
+ x=(/bin/cfs -s -f $cfs)
+ if(~ -f $ff)
+ x=($x -r)
+ {$x </srv/boot &} | echo 0 >/srv/cfs
+ rm /srv/boot
+ mv /srv/cfs /srv/boot
+ }
}
- # authentication agent
- authentication
+ # mount and change root in new enviroment and namespace
+ rfork ne
- # connect to the root file system
- $mp($connect)
+ # mount root filesystem
+ if(~ $#rootdir 0)
+ rootdir=/root
+ must mount -c /srv/boot $rootdir
- must mount -c /srv/boot /root
+ # compile init command
+ if(~ $#init 0){
+ init=/$cputype/init
+ if(~ $service cpu)
+ init=($init -c)
+ if not
+ init=($init -t)
+ if(~ -m $ff)
+ init=($init -m)
+ }
- swapproc
+ # remove enviroment variables
+ rm -f '#e/'^$mt '#e/'? '#e/'?? '#e/fn#'*
# remove part of our temporary root
- unmount /$cputype/bin /bin
+ /mnt/broot/$cputype/bin/unmount /$cputype/bin /bin
/mnt/broot/$cputype/bin/unmount /rc/bin /bin
- /mnt/broot/$cputype/bin/unmount /boot /bin
/mnt/broot/$cputype/bin/unmount /
# create the name space, mount the root fs
# remove the remaining temporary root
/mnt/broot/$cputype/bin/unmount /mnt/broot
- rootdir=/root
-
- if(~ $#init 0){
- init=/$cputype/init
- if(~ $cpuflag 1)
- init=($init -c)
- if not
- init=($init -t)
- # TODO handle mflag
- }
exec $init
}
-bind -q '#p' /proc
+# keyboard and serial console
+if(test -x /bin/aux/kbdfs){
+ a=$console(1)
+ if(! ~ $#a 0)
+ a=/dev/eia^$a
+ aux/kbdfs -q -s cons $a
+}
-devinit
-usbinit # set up usb keyboard, mouse, and disk, if any
-kbmap
+# usb devices
+if(test -x /bin/nusbrc && ! test -e /env/nousbrc)
+ nusbrc
-configlocal # add partitions and binds
+# load boot methods
+fn showlocaldevs {}
+fn configlocal {}
+for(i in /rc/lib/*.rc){
+ . $i
+}
-while(){
- @{rfork n; main}
+# add partitions and binds
+configlocal
+
+# boot(8) command line arguments
+ff=()
+aa=()
+while(! ~ $#* 0){
+ if(~ $1 -*){
+ if(~ $1 -u*){
+ if(~ $1 -u){
+ user=$2
+ shift
+ }
+ if not {
+ user=`{echo $1 | sed 's,^-u,,g'}
+ }
+ }
+ if not {
+ if(~ $1 -*f*)
+ ff=($ff -f)
+ if(~ $1 -*k*)
+ ff=($ff -k)
+ if(~ $1 -*m*)
+ ff=($ff -m)
+ }
+ shift
+ }
+ if not {
+ while(! ~ $#* 0){
+ aa=($aa $1)
+ shift
+ }
+ }
}
+if(! ~ $#aa 0 && ~ $#bootargs 0 && ~ $#nobootprompt 0){
+ bootargs=$aa
+ nobootprompt=$aa
+}
+
+while(){
+ @{main}
+
+ # subshell doesnt wait on interrupts
+ while(~ $status interrupted){wait}
+
+ # cleanup so it can be restarted
+ nobootprompt=()
+ rm -f /srv/^(cfs boot cs dns)
+} </dev/cons