m/installer: log to tty0 and ttyS0
Without this we only log to whatever the default system console is.
Change-Id: I64b43f8617f3b8752332209b511ea470848c4481
Reviewed-on: https://review.monogon.dev/c/monogon/+/1381
Tested-by: Jenkins CI
Reviewed-by: Leopold Schabel <leo@monogon.tech>
diff --git a/metropolis/installer/BUILD.bazel b/metropolis/installer/BUILD.bazel
index 6e1f1f0..f3b6d1e 100644
--- a/metropolis/installer/BUILD.bazel
+++ b/metropolis/installer/BUILD.bazel
@@ -5,7 +5,10 @@
go_library(
name = "installer_lib",
- srcs = ["main.go"],
+ srcs = [
+ "log.go",
+ "main.go",
+ ],
importpath = "source.monogon.dev/metropolis/installer",
visibility = ["//visibility:private"],
deps = [
diff --git a/metropolis/installer/log.go b/metropolis/installer/log.go
new file mode 100644
index 0000000..cb7dee6
--- /dev/null
+++ b/metropolis/installer/log.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+var logC = make(chan string)
+
+// logPiper pipes log entries submitted via logf and panicf into whatever
+// consoles are available to the system.
+func logPiper() {
+ var consoles []*os.File
+ for _, p := range []string{"/dev/tty0", "/dev/ttyS0"} {
+ f, err := os.OpenFile(p, os.O_WRONLY, 0)
+ if err != nil {
+ continue
+ }
+ consoles = append(consoles, f)
+ }
+
+ for {
+ s := <-logC
+ for _, c := range consoles {
+ fmt.Fprintf(c, "%s\n", s)
+ }
+ }
+}
+
+// logf logs some format/args into the active consoles.
+func logf(format string, args ...any) {
+ s := fmt.Sprintf(format, args...)
+ logC <- s
+}
+
+// panicf aborts the installation process with a given format/args.
+func panicf(format string, args ...any) {
+ s := fmt.Sprintf(format, args...)
+ // We don't need to print `s` here, as it's gonna get printed by the recovery
+ // code in main.
+ panic(s)
+}
diff --git a/metropolis/installer/main.go b/metropolis/installer/main.go
index 520bc89..7dc1da9 100644
--- a/metropolis/installer/main.go
+++ b/metropolis/installer/main.go
@@ -178,20 +178,13 @@
return nil
}
-// panicf is a replacement for log.panicf that doesn't print the error message
-// before calling panic.
-func panicf(format string, v ...interface{}) {
- s := fmt.Sprintf(format, v...)
- panic(s)
-}
-
func main() {
// Reboot on panic after a delay. The error string will have been printed
// before recover is called.
defer func() {
if r := recover(); r != nil {
- fmt.Println(r)
- fmt.Println("The installation could not be finalized. Please reboot to continue.")
+ logf("Fatal error: %v", r)
+ logf("The installation could not be finalized. Please reboot to continue.")
syscall.Pause()
}
}()
@@ -200,6 +193,12 @@
if err := mountPseudoFS(); err != nil {
panicf("While mounting pseudo-filesystems: %v", err)
}
+
+ go logPiper()
+ logf("Metropolis Installer")
+ logf("Copyright (c) 2023 The Monogon Project Authors")
+ logf("")
+
// Read the installer ESP UUID from efivarfs.
espUuid, err := efivarfs.ReadLoaderDevicePartUUID()
if err != nil {
@@ -292,7 +291,7 @@
// Use osimage to partition the target block device and set up its ESP.
// Create will return an EFI boot entry on success.
- fmt.Printf("Installing to %s\n", tgtBlkdevPath)
+ logf("Installing to %s...", tgtBlkdevPath)
be, err := osimage.Create(&installParams)
if err != nil {
panicf("While installing: %v", err)
@@ -327,6 +326,6 @@
// Reboot.
unix.Sync()
- fmt.Println("Installation completed. Rebooting.")
+ logf("Installation completed. Rebooting.")
unix.Reboot(unix.LINUX_REBOOT_CMD_RESTART)
}