#!/dis/sh -n

# boot initialization
#	configure boot devices
#	setup /
# sh -n /dis/init
#	-n to avoid forking the namespace and losing the binds created by disinit.b

load std
mount {mntgen} /n

# checked these to get this working
#	/n/m/home/j/local/plan9/plan9front/sys/src/9/boot/bootrc
#	/n/m/home/j/local/plan9/plan9front/sys/src/9/boot/cpurc
#	/n/m/home/j/local/plan9/plan9front/rc/bin/diskparts
#  parse the bootargs and try to find and start that device
#		this is what 9front does and it is wise to stick with it
#		and, after booting the specified device, use /os/init/$sysname
#			for machine specific booting

# read bootargs (plan9.ini)
#	could be tcp or local disk
#	if local, use the specified disk
#	if tcp,
#		tcp!dhcp
#			dhcp server provides fs=
#			if not, get fs= from plan9.ini
#			use tcp!$fs!styx as root
#		tcp!add address mask gateway
#			get fs= from plan9.ini
#			use tcp!$fs!styx as root
# getting the sysname
#	sys= in plan9.ini
#	for tcp!dhcp
#		get the sys= from dhcp
#	for local disk and tcp!address mask gateway
#		figure out the sysname from /lib/ndb/local
# 			ndb/query ether 50e549e5f938 sys
#
# run /lib/init/$sysname, if it exists
#
# for options to disk/kfs:
#	bootargs=local!any other disk/kfs args /dev/sdG0/fs

#TODO
#	use nvram to connect to the authentication server
#	bother with older kfs?
#	usb disks at /shr/sd*
#	tls, il bootargs
#	if set, use ether0= of plan9.ini

## 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 showlocaldev {
	(diskpart fstype)=$*
	echo $diskpart'	' $fstype
	#if{~ $#bootargs 0 && ~ $fstype fs 9660 dos} {
	#	bootargs=local!$diskpart
	#}
}

fn showlocaldevs{
	for d in /dev/sd* {
		if {ftest -r $d/ctl}{
			(a q)=`{grep inquiry $d/ctl}
			echo $d':' $q
			for i in `{ls -p $d} {
				p=$d/$i
				if{~ $"i ctl raw log led}{
					;
				} {~ $"i plan9 nvram swap}{
					echo $p
				} {~ $"i 9fat}{
					showlocaldev $p dos
				} {~ $"i 9660}{
					showlocaldev $p 9660
				} {~ $"i fs}{
					showlocaldev $p kfs64
				} {~ $cdboot 1 && ~ $"i data}{
					showlocaldev $p 9660
				} {
					echo $p: unrecognized filesystem
				}
			}
		}
	}
	#for d in /shr/sd* {
	#	if(test -d $d) {
	#		echo $d':'
	#		for(p in $d/*.^(iso paq)) if(test -f $p){
	#			t=`{fstype $p}
	#			~ $#t 0 || showlocaldev $p $t
	#		}
	#	}
	#}
}

fn mountlocal{
	device=$*
	if{ ~ $device ''}{
		echo local method needs an argument: device
	} {
		part=`{basename $device}
		if{~ $part 9660}{
			9660srv -9 $device /n/cd
			bind /n/cd/dis /dis
			bind -a /n/cd/ /
		}{~ $cdboot 1 && ~ $part data}{
			9660srv -9 $device /n/cd
			bind /n/cd/dis /dis
			bind -a /n/cd/ /
		}{~ $part dos 9fat}{
			dossrv -f $device
			bind /n/dos/dis /dis
			bind -a /n/dos/ /
		}{~ $part fs}{
			mount -c {disk/kfs64 $device} /n/rootdisk
			bind /n/rootdisk/dis /dis
			bind -c -a /n/rootdisk/ /
		}{
			echo unrecognized partition of $device: $part
		}
	}
}

fn bindether0 {
	<>/net/ipifc/clone {
		x=`{read}
		echo bind ether /net/ether0 > /net/ipifc/^$x^/ctl
	}
}

fn usedhcp {
	# the correct /net/ether0 can be set in plan9.ini
	echo binding /net/ether0
	<>/net/ipifc/clone {
		x=`{read}
		echo bind ether /net/ether0 > /net/ipifc/^$x^/ctl
	}
	ip/dhcp -p /net/ipifc/$x
	for tuple in `{cat /net/ndb}{
		(name value)=${split '=' $tuple}
		if{~ $name sys}{
			echo -n $value > /dev/sysname
			sys=$value
			sysname=$value
		}{~ $name ip}{
			ip=$value
		}{~ $name fs}{
			fs=$value
		}
	}
	echo $sysname
	#cat /dev/sysname
	cat /net/ndb
	#cat /dev/sysname
}

# 9front uses the $bootargs to gather
#	the ether device to bind
#	the ether device ip address
#	fs address
#	port
# 9ferno takes the following shortcuts, for now
#	hardcoded the ether device to be /net/ether0
#	use $bootargs for the ethernet ip address, mask and gateway
#	use $fs for the fs address
#	use $noauth to avoid authentication
#	hardcoded the ports
fn mountfs {
	if{! ~ $"fs ''}{
		if{~ $"noauth 1}{
			mount -A -v -c tcp!$"fs!17001 /n/remote
		}{
			mount -v -c tcp!$"fs!6666 /n/remote
		}
		bind /n/remote/dis /dis
		bind -c -a /n/remote/ /
	}
}

sysname=$sys
#showlocaldevs
echo $bootargs
and {ftest -e '#e/bootargs'} {
	(connectmethod localdevice) = ${split ! $bootargs}

	# if local, start disks
	# if tcp, bind ether0 as ipifc and get on with it

	if { ~ $"connectmethod local }{
		sh -n /dis/diskparts
		mountlocal $localdevice
	} {~ $"connectmethod tcp}{
		if{~ $"localdevice dhcp}{
			usedhcp
			mountfs
		}{
			# check the notes above for details
			echo binding /net/ether0
			<>/net/ipifc/clone {
				x=`{read}
				echo bind ether /net/ether0 > /net/ipifc/^$x^/ctl
				echo $localdevice > /net/ipifc/^$x^/ctl
			}
			mountfs
		}
	} {
		echo unsupported connect method: $connectmethod
	}

	if {~ $"sysname ''}{
		sysname=`{ndb/query ether `{cat '#l0/ether0/addr'} sys}
	}

	# for machine specific initialization
	#	use /lib/init/$sysname
	#	special networking setup, disk setup
	#	avoids putting machine specific stuff in devroot
	and {! ~ $"sysname ''} {
		ftest -f /lib/init/$sysname }{
		sh -n /lib/init/$sysname
	}
}

# if I add /lib/sh/profile to devroot,
#	all the above binds can be moved to $home/namespace
sh -n -l -i #-l # to run the /lib/sh/profile
