init at trunk

File initrd/init-earlyboot/init artifact 7fe435c1cc on branch trunk


#! /tclkit

proc load_modules {path} {
	set modules [list]
	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 devtmpfs [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
	catch {
		file mkdir /system/config
	}
	system::syscall::mount tmpfs /system/config tmpfs [list]

	# 7. Unmount devfs
	system::syscall::umount /dev
	file delete -force /dev

	vfs::cvfs::Unmount /tclkit
	file delete -force /init /root /tclkit /modules

	# 8. Pass control to later boot init
	if {![file exists /system/apps/appbox-core/default/sbin/init]} {
		return -code error "No init found, aborting boot."
	}

	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
	if {[catch {
		set ret [eval $line]
	} err]} {
		set ret $err
	}

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