Files
hakurei/cmd/earlyinit/main.go
Ophestra 8b875f865c
All checks were successful
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 2m38s
Test / Hakurei (push) Successful in 3m41s
Test / ShareFS (push) Successful in 3m44s
Test / Sandbox (race detector) (push) Successful in 5m7s
Test / Hakurei (race detector) (push) Successful in 6m10s
Test / Flake checks (push) Successful in 1m20s
cmd/earlyinit: remount root and set firmware path
The default search paths cannot be configured, configuring them here is most sound for now.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-03-14 19:50:04 +09:00

128 lines
2.4 KiB
Go

package main
import (
"log"
"os"
"runtime"
"strings"
. "syscall"
)
func main() {
runtime.LockOSThread()
log.SetFlags(0)
log.SetPrefix("earlyinit: ")
var (
option map[string]string
flags []string
)
if len(os.Args) > 1 {
option = make(map[string]string)
for _, s := range os.Args[1:] {
key, value, ok := strings.Cut(s, "=")
if !ok {
flags = append(flags, s)
continue
}
option[key] = value
}
}
if err := Mount(
"devtmpfs",
"/dev/",
"devtmpfs",
MS_NOSUID|MS_NOEXEC,
"",
); err != nil {
log.Fatalf("cannot mount devtmpfs: %v", err)
}
// The kernel might be unable to set up the console. When that happens,
// printk is called with "Warning: unable to open an initial console."
// and the init runs with no files. The checkfds runtime function
// populates 0-2 by opening /dev/null for them.
//
// This check replaces 1 and 2 with /dev/kmsg to improve the chance
// of output being visible to the user.
if fi, err := os.Stdout.Stat(); err == nil {
if stat, ok := fi.Sys().(*Stat_t); ok {
if stat.Rdev == 0x103 {
var fd int
if fd, err = Open(
"/dev/kmsg",
O_WRONLY|O_CLOEXEC,
0,
); err != nil {
log.Fatalf("cannot open kmsg: %v", err)
}
if err = Dup3(fd, Stdout, 0); err != nil {
log.Fatalf("cannot open stdout: %v", err)
}
if err = Dup3(fd, Stderr, 0); err != nil {
log.Fatalf("cannot open stderr: %v", err)
}
if err = Close(fd); err != nil {
log.Printf("cannot close kmsg: %v", err)
}
}
}
}
// staying in rootfs, these are no longer used
must(os.Remove("/root"))
must(os.Remove("/init"))
must(os.Mkdir("/proc", 0))
mustSyscall("mount proc", Mount(
"proc",
"/proc",
"proc",
MS_NOSUID|MS_NOEXEC|MS_NODEV,
"hidepid=1",
))
must(os.Mkdir("/sys", 0))
mustSyscall("mount sysfs", Mount(
"sysfs",
"/sys",
"sysfs",
0,
"",
))
// after top level has been set up
mustSyscall("remount root", Mount(
"",
"/",
"",
MS_REMOUNT|MS_BIND|
MS_RDONLY|MS_NODEV|MS_NOSUID|MS_NOEXEC,
"",
))
must(os.WriteFile(
"/sys/module/firmware_class/parameters/path",
[]byte("/system/lib/firmware"),
0,
))
}
// mustSyscall calls [log.Fatalln] if err is non-nil.
func mustSyscall(action string, err error) {
if err != nil {
log.Fatalln("cannot "+action+":", err)
}
}
// must calls [log.Fatal] with err if it is non-nil.
func must(err error) {
if err != nil {
log.Fatal(err)
}
}