#! /tclkit

proc load_modules {path} {
	catch {
		set fd [open [file join $path load]]
		set modules [split [read $fd] "\n"]
		close $fd
	}

	foreach module $modules {
		if {![file exists $module]} {
			puts stderr "\[module\] File not found: $module"
			continue
		}

		if {[catch {
			system::syscall::insmod $module
		} err]} {
			puts stderr "\[module\] Failed to load $module: $err"
		}
	}
}

proc locate_config_partition {} {
	foreach dev [glob -nocomplain /dev/*] {
		unset -nocomplain devinfo
		catch {
			file stat $dev devinfo
		}

		if {![info exists devinfo(type)]} {
			continue
		}

		if {$devinfo(type) != "blockSpecial"} {
			continue
		}

		unset -nocomplain fd
		catch {
			set fd [open $dev]
			fconfigure $fd -translation binary
		}

		if {![info exists fd]} {
			continue
		}

		set magic [read $fd 32]
		binary scan $magic H* magic

		if {$magic != "1daa459b9772ef5d7d58c814458246c69dbd1d53fa75f396462910250bf7a4b6"} {
			continue
		}

		return $dev
	}

	return ""
}

proc boot {} {
	package require system

	# 1. Load kernel modules
	load_modules /modules

	# 2. Mount devfs
	file mkdir /dev
	system::syscall::mount devfs /dev devfs [list]

	# 3. Locate Config partition
	set dev [locate_config_partition]

	if {$dev == ""} {
		## XXX: Install to tmpfs
		## XXX: Offer to do installation
	} else {
		# 4. Mount config partition
		mount_config_partition $dev /config

		# 5. Load kernel modules
		load_modules /config/modules

		# 5. Mount /system (from fstab) 
		## XXX: TODO
	}

	# 6. Mount /system/config and populate
	system::syscall::mount tmpfs /system/config tmpfs [list]

	# 7. Unmount devfs
	system::syscall::umount /dev
	file rmdir /dev

	# 8. Pass control to later boot init
	system::syscall::execve init /system/apps/appbox-core/default/sbin/init
}

if {[catch {
	boot
} err]} {
	puts stderr "\[boot\] Boot failed: $err"
}

while 1 {
	puts -nonewline "> "
	flush stdout

	gets stdin line
	set ret [catch {
		eval $line
	}]

	if {$ret != ""} {
		puts $ret
	}
}
