Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

96
tundra/vm/init.py Normal file
View file

@ -0,0 +1,96 @@
#!/usr/bin/python3
"""Guest PID 1. Start the graphical session and retain serial diagnostics."""
import json
import os
from pathlib import Path
import signal
import subprocess
import time
import traceback
if os.getpid() != 1:
raise SystemExit('This init runs only as PID 1 inside the VM.')
os.environ.update(PATH='/usr/bin', HOME='/root', LANG='C.UTF-8', LD_LIBRARY_PATH='/usr/lib/weston:/usr/lib')
children = []
def run(*args):
subprocess.run(args, check=True)
def start(*args, env=None):
p = subprocess.Popen(args, env=env)
children.append(p)
return p
def shutdown(*unused):
print('TUNDRA_SHUTDOWN', flush=True)
for p in reversed(children):
if p.poll() is None: p.terminate()
time.sleep(2)
os.sync()
# Kernel poweroff; this process cannot run on the host due to the PID1 guard.
import ctypes
ctypes.CDLL(None).reboot(0x4321FEDC)
signal.signal(signal.SIGTERM, shutdown)
try:
Path('/dev/shm').mkdir(exist_ok=True)
run('mount','-t','tmpfs','tmpfs','/dev/shm')
Path('/dev/pts').mkdir(exist_ok=True)
run('mount','-t','devpts','devpts','/dev/pts')
for path in ('/run/user/1000','/home/vulpes','/var/log/tundra'):
Path(path).mkdir(parents=True, exist_ok=True)
os.chown(path,1000,1000)
os.chmod('/run/user/1000',0o700)
# Staged files belong to the builder; the guest grants only product state to its user.
for base, dirs, files in os.walk('/opt/vulpes'):
os.chown(base,1000,1000)
for name in files: os.chown(Path(base)/name,1000,1000)
run('ip','link','set','lo','up')
start('/usr/lib/systemd/systemd-udevd','--resolve-names=never')
# Coldplug must wait for the daemon's control socket, otherwise its initial
# events can be lost and libinput sees neither keyboard nor pointer.
for _ in range(100):
ping = subprocess.run(['udevadm','control','--timeout=1','--ping'],
stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
if ping.returncode == 0: break
time.sleep(.1)
else: raise RuntimeError('udevd did not become ready')
run('udevadm','trigger','--action=add')
run('udevadm','settle','--timeout=10')
inputs = []
for device in Path('/dev/input').glob('event*'):
info = subprocess.check_output(['udevadm','info','--query=property',str(device)],text=True)
inputs.append(info)
if not any('ID_INPUT_MOUSE=1' in item for item in inputs):
raise RuntimeError('Virtual pointer missing from udev: '+repr(inputs))
if not any('ID_INPUT_KEYBOARD=1' in item for item in inputs):
raise RuntimeError('Virtual keyboard missing from udev: '+repr(inputs))
print('TUNDRA_INPUT_READY',flush=True)
if 'tundra.usb=1' in Path('/proc/cmdline').read_text():
run('python3','-u','/opt/tundra/usb-test.py')
env = dict(os.environ, SEATD_VTBOUND='0')
start('seatd','-g','video',env=env)
for _ in range(50):
if Path('/run/seatd.sock').exists(): break
time.sleep(.1)
env.update(HOME='/home/vulpes',USER='vulpes',LOGNAME='vulpes',
XDG_RUNTIME_DIR='/run/user/1000',LIBSEAT_BACKEND='seatd',
WAYLAND_DISPLAY='wayland-0',MOZ_ENABLE_WAYLAND='1',GDK_BACKEND='wayland',
XDG_SESSION_TYPE='wayland',LIBGL_ALWAYS_SOFTWARE='1')
print('TUNDRA_GRAPHICAL_START', flush=True)
user = ['setpriv','--reuid=1000','--regid=1000','--groups=44,992']
session = start(*user,'dbus-run-session','--','python3','-u','/opt/tundra/session.py',env=env)
while session.poll() is None: time.sleep(1)
print('TUNDRA_SESSION_EXIT',session.returncode,flush=True)
except Exception:
traceback.print_exc()
print('TUNDRA_BOOT_FAILED',flush=True)
finally:
for name in ('weston.log','gecko.log','server.log','test.json','usb.log','usb-test.json'):
p = Path('/var/log/tundra')/name
if p.exists():
print('TUNDRA_LOG_BEGIN', name, flush=True)
print(p.read_text(errors='replace')[-18000:],flush=True)
print('TUNDRA_LOG_END', name, flush=True)
shutdown()
while True: time.sleep(1)