//go:build linux // tera-recovery-probe is a deliberately read-only PID 1 used to prove the // recovery boot contract before any partition-writing updater is introduced. package main import ( "bufio" "fmt" "io" "os" "strings" "time" "golang.org/x/sys/unix" "tera-clone/services/tera-api/internal/update/recoveryrequest" ) const ( miscDevice = "/dev/mmcblk0p2" userdataDevice = "/dev/mmcblk0p8" journalPath = "/userdata/update/journal/status.json" ) func main() { mustMount("devtmpfs", "/dev", "devtmpfs", unix.MS_NOSUID, "mode=0755") mustMount("proc", "/proc", "proc", unix.MS_NOSUID|unix.MS_NOEXEC|unix.MS_NODEV, "") mustMount("sysfs", "/sys", "sysfs", unix.MS_NOSUID|unix.MS_NOEXEC|unix.MS_NODEV, "") console, err := os.OpenFile("/dev/ttyS2", os.O_WRONLY, 0) if err != nil { console = os.Stdout } log := func(format string, values ...any) { fmt.Fprintf(console, "[tera-recovery-probe] "+format+"\r\n", values...) } log("START read-only probe; no partition payload writes are implemented") cmdline, err := os.ReadFile("/proc/cmdline") if err != nil || !containsWord(string(cmdline), "tera.recovery=probe") || !containsWord(string(cmdline), "rdinit=/init") { hold(log, "FAIL unexpected recovery kernel command line: %q (%v)", strings.TrimSpace(string(cmdline)), err) return } log("PASS recovery kernel command line: %s", strings.TrimSpace(string(cmdline))) if err := requirePartName("/sys/class/block/mmcblk0p2/uevent", "misc"); err != nil { hold(log, "FAIL misc identity: %v", err) return } if err := requirePartName("/sys/class/block/mmcblk0p8/uevent", "userdata"); err != nil { hold(log, "FAIL userdata identity: %v", err) return } misc, err := os.Open(miscDevice) if err != nil { hold(log, "FAIL open misc read-only: %v", err) return } message, readErr := recoveryrequest.ReadAt(misc) closeErr := misc.Close() if readErr != nil || closeErr != nil { hold(log, "FAIL recovery request: read=%v close=%v", readErr, closeErr) return } log("PASS recovery request operation=%s", message.OperationID) if err := unix.Mount(userdataDevice, "/userdata", "ext4", unix.MS_RDONLY|unix.MS_NODEV|unix.MS_NOSUID|unix.MS_NOEXEC|unix.MS_NOATIME, probeUserdataMountData); err != nil { hold(log, "FAIL mount userdata read-only: %v", err) return } journal, err := readJournalOperation(journalPath) if err != nil || journal.OperationID != message.OperationID || journal.State != "validated" { hold(log, "FAIL journal binding: request=%q journal=%q state=%q error=%v", message.OperationID, journal.OperationID, journal.State, err) return } packagePath := "/userdata/update/validated/" + message.OperationID + ".pkg" packageInfo, err := os.Lstat(packagePath) if err != nil || !packageInfo.Mode().IsRegular() || packageInfo.Mode()&os.ModeSymlink != 0 || packageInfo.Size() <= 0 { hold(log, "FAIL validated package identity: path=%s error=%v", packagePath, err) return } log("PASS journal binding operation=%s state=%s package_bytes=%d", journal.OperationID, journal.State, packageInfo.Size()) log("READY boot selection, ttyS2, misc BCB, GPT identity, and read-only userdata journal are proven") hold(log, "HOLD request intentionally remains set; use the service procedure to restore normal boot") } func mustMount(source, target, filesystem string, flags uintptr, data string) { if err := unix.Mount(source, target, filesystem, flags, data); err != nil { fmt.Fprintf(os.Stderr, "mount %s: %v\n", target, err) for { time.Sleep(time.Hour) } } } func containsWord(value, wanted string) bool { for _, word := range strings.Fields(value) { if word == wanted { return true } } return false } func requirePartName(path, wanted string) error { file, err := os.Open(path) if err != nil { return err } defer file.Close() scanner := bufio.NewScanner(io.LimitReader(file, 4096)) for scanner.Scan() { if scanner.Text() == "PARTNAME="+wanted { return nil } } if err := scanner.Err(); err != nil { return err } return fmt.Errorf("expected PARTNAME=%s", wanted) } func hold(log func(string, ...any), format string, values ...any) { log(format, values...) for { time.Sleep(time.Hour) } }