From c4b6b8ea6930123632a711cfdd0a0e1802ee8ade Mon Sep 17 00:00:00 2001 From: davidmonterocrespo24 Date: Sat, 16 May 2026 08:04:57 +0200 Subject: [PATCH] =?UTF-8?q?fix(pi3):=20bypass=20systemd=20with=20velxio-in?= =?UTF-8?q?it=20=E2=80=94=20~10s=20to=20root=20shell?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pi 3 simulator boot through Pi OS systemd graph was unworkable inside QEMU's raspi3b emulation: * The PL011 UART at 0x3f201000 enumerates as ttyAMA1 (not ttyAMA0 — the mini-UART at 0x3f215040 takes ttyAMA0 and fails to probe under QEMU). After ~9 s of kernel time the boot effectively went silent on the serial: earlycon was disabled by the normal console init and the IRQ-driven serial driver loses TX under QEMU's emulation. * Even with `keep_bootcon`, systemd dependency graph took 2-3 min to walk inside emulation (network waits, tmpfiles, journald, hostname/machine-id randomness). Masking 9 boot-blocking units helped but didn't fix the silent-after-9s problem. Solution: skip systemd. The SD image is now baked with `/usr/local/sbin/velxio-init` (a 30-line bash script) and the kernel cmdline points init= at it. velxio-init mounts /proc /sys /dev /pts /run /tmp, sets hostname, then loops a passwordless `/bin/bash --login /dev/ttyAMA1`. User sees the prompt within ~10 s of clicking Run; Ctrl-D respawns a fresh session. Cmdline additions: - `keep_bootcon` — keep earlycon alive after the regular console registers, so kernel printk continues to reach ttyAMA1. - `console=ttyAMA1,115200` — the correct PL011, not ttyAMA0. - `init=/usr/local/sbin/velxio-init` — bypass systemd entirely. Python, GPIO shim, apt, mount, etc. all work — they don't need systemd as PID 1, just a populated rootfs + mounted pseudo-fs. Manifest version bumped to 2026-04-21+velxio-init. Same byte size, different SHA, so the sidecar-based cache invalidator forces a re-fetch on every velxio backend the next time it starts. --- .../app/services/boot_images/manifest.json | 8 ++-- backend/app/services/qemu_manager.py | 43 ++++++++++++------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/backend/app/services/boot_images/manifest.json b/backend/app/services/boot_images/manifest.json index f51c5593..3515eb71 100644 --- a/backend/app/services/boot_images/manifest.json +++ b/backend/app/services/boot_images/manifest.json @@ -22,13 +22,13 @@ { "name": "raspios-trixie-armhf.img", "asset_id": "raspios-trixie-armhf-zst", - "sha256": "36b0e9358940ff1ffa9a0f2da3e74c75a2ff657e67e3ed6780df3c5c0df3038d", + "sha256": "8963dbfafa2b0e4673499a74cc9fc0dcb8da49d023e6d340301d071abd07bba8", "size_bytes": 5729419264, - "version": "2026-04-21+autologin+fastboot", + "version": "2026-04-21+velxio-init", "compressed": { "encoding": "zstd", - "sha256": "8de2ed5e49031a92d56a15e894a9f430949cd21ce5ebe26353839073853162e0", - "size_bytes": 1488007643 + "sha256": "8e0eca1865c4a32bbe096044e8ea1d9adeb80f3ffe9fe2f45a54881f7020266d", + "size_bytes": 1488007156 } } ] diff --git a/backend/app/services/qemu_manager.py b/backend/app/services/qemu_manager.py index be805166..d0dddfae 100644 --- a/backend/app/services/qemu_manager.py +++ b/backend/app/services/qemu_manager.py @@ -184,23 +184,36 @@ class QemuManager: # ttyAMA1 → GPIO shim protocol '-serial', f'tcp:127.0.0.1:{inst.gpio_port},server,nowait', '-append', - # earlycon=pl011,mmio32,0x3f201000 — without explicit address - # the kernel doesn't initialise the BCM2837 PL011 UART early - # enough for any output to reach ttyAMA0; we get a silent - # boot followed by a "broken simulator" report. The address - # matches the BCM2837 SoC peripheral mapping (Pi 3 base - # 0x3f000000 + PL011 offset 0x201000). + # earlycon=pl011,mmio32,0x3f201000 — the BCM2837 PL011 UART + # MMIO address. earlycon polled-mode is what actually carries + # all of our serial output; QEMU's raspi3b emulation drives + # the PL011 correctly in this mode but the kernel's normal + # interrupt-based serial driver loses TX once systemd hands + # off (confirmed by experiment — output silently stops after + # ~9 s of kernel time without keep_bootcon). # - # No `quiet`: surface kernel boot messages to ttyAMA0 so the - # user sees progress while the 5.4 GiB Pi OS rootfs comes up. - # No `init=/bin/sh`: let systemd run normally; the SD image - # ships with a serial-getty@ttyAMA0 autologin drop-in (baked - # by scripts/configure-pi3-autologin.sh) so the user lands - # at a root shell without credentials. - 'earlycon=pl011,mmio32,0x3f201000 ' - 'console=ttyAMA0,115200 ' + # keep_bootcon — don't disable earlycon when the regular + # console driver registers. Without this, the boot goes + # silent at the same moment systemd takes /dev/console. + # + # console=ttyAMA1,115200 — the PL011 at 0x3f201000 + # enumerates as ttyAMA1 (not ttyAMA0!). The mini-UART at + # 0x3f215040 takes ttyAMA0 and fails to probe under QEMU. + # console= here drives userspace output once the kernel + # hands off; it works in tandem with the kept-alive earlycon + # for full kernel printk coverage. + # + # init=/usr/local/sbin/velxio-init — skip systemd entirely. + # The init script (baked into the SD image by + # scripts/configure-pi3-autologin.sh) mounts the pseudo- + # filesystems systemd would, then loops a passwordless root + # bash on ttyAMA1. User sees the prompt in ~10 s instead of + # 2-3 min of Pi OS systemd graph churning inside emulation. + 'earlycon=pl011,mmio32,0x3f201000 keep_bootcon ' + 'console=ttyAMA1,115200 ' 'root=/dev/mmcblk0p2 rootwait rw ' - 'dwc_otg.lpm_enable=0', + 'dwc_otg.lpm_enable=0 ' + 'init=/usr/local/sbin/velxio-init', ] logger.info('Launching QEMU for %s: %s', inst.client_id, ' '.join(cmd))