#!/bin/sh # AC Native OS init — DRM direct boot with crash recovery export PATH="/bin:/sbin:/usr/bin:/usr/sbin" mount -t proc proc /proc 2>/dev/null mount -t sysfs sysfs /sys 2>/dev/null mount -t devtmpfs devtmpfs /dev 2>/dev/null mkdir -p /dev/pts /dev/shm /tmp /run /etc mount -t devpts devpts /dev/pts -o ptmxmode=0666 2>/dev/null mount -t tmpfs tmpfs /dev/shm 2>/dev/null mount -t tmpfs tmpfs /tmp 2>/dev/null mount -t tmpfs tmpfs /run 2>/dev/null mount -t efivarfs efivarfs /sys/firmware/efi/efivars 2>/dev/null # zram swap modprobe zram 2>/dev/null || true if [ -e /sys/block/zram0/disksize ] && [ -b /dev/zram0 ]; then echo 1G > /sys/block/zram0/disksize && mkswap /dev/zram0 >/dev/null 2>&1 && swapon /dev/zram0 2>/dev/null fi # Loopback ip link set lo up 2>/dev/null # Restore baked Claude credentials (tmpfs mount hid the originals) if [ -f /claude-creds.json ]; then mkdir -p /tmp/.claude cp /claude-creds.json /tmp/.claude/.credentials.json cp /claude-state.json /tmp/.claude.json 2>/dev/null printf '{"permissions":{"allow":["Bash(*)","Read(*)","Write(*)","Edit(*)","Glob(*)","Grep(*)","WebFetch(*)","WebSearch(*)"]},"autoUpdates":false,"installMethod":"native"}\n' > /tmp/.claude/settings.json fi mkdir -p /tmp/ac [ -f /device-claude.md ] && cp /device-claude.md /tmp/ac/CLAUDE.md 2>/dev/null [ -f /device-score.md ] && cp /device-score.md /tmp/ac/SCORE.md 2>/dev/null # /etc/group and /etc/passwd needed by seatd echo "root:x:0:" > /etc/group echo "root:x:0:root" > /etc/passwd # Wait for GPU (up to 3 seconds) i=0 while [ ! -e /dev/dri/card0 ] && [ ! -e /dev/dri/card1 ] && [ ! -e /dev/fb0 ] && [ $i -lt 300 ]; do usleep 10000 2>/dev/null || sleep 1 i=$((i+1)) done # Performance governor (silently skip if cpufreq not available) if [ -d /sys/devices/system/cpu/cpu0/cpufreq ]; then for g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo performance > "$g" 2>/dev/null done fi export SSL_CERT_FILE="/etc/pki/tls/certs/ca-bundle.crt" export CURL_CA_BUNDLE="/etc/pki/tls/certs/ca-bundle.crt" export SSL_CERT_DIR="/etc/ssl/certs" export HOME="/tmp" # ── Mount USB config/log partition (for config.json, wifi creds, logs) ── # Prefer the writable config partition over the boot partitions. modprobe vfat 2>/dev/null modprobe nls_cp437 2>/dev/null modprobe nls_ascii 2>/dev/null USB_MOUNTED=0 USB_PARTS="/dev/sda1 /dev/sda2 /dev/sda3 /dev/sdb1 /dev/sdb2 /dev/sdb3 /dev/sdc1 /dev/sdc2 /dev/sdc3 /dev/sdd1 /dev/sdd2 /dev/sdd3 /dev/nvme0n1p1 /dev/nvme0n1p2 /dev/nvme0n1p3" mount_usb_partition() { pass="$1" for p in $USB_PARTS; do if [ -b "$p" ]; then mkdir -p /mnt mount -t vfat "$p" /mnt 2>/dev/null || continue if [ "$pass" = "config" ] && [ -f /mnt/config.json ]; then USB_MOUNTED=1 return 0 fi if [ "$pass" = "boot" ] && { [ -f /mnt/EFI/BOOT/BOOTX64.EFI ] || [ -f /mnt/EFI/BOOT/KERNEL.EFI ]; }; then USB_MOUNTED=1 return 0 fi umount /mnt 2>/dev/null fi done return 1 } for attempt in 1 2 3 4 5 6 7 8 9 10; do mount_usb_partition config && break mount_usb_partition boot && break [ "$USB_MOUNTED" = "1" ] && break sleep 1 done # Create samples directory on boot media + mount point for music USB if [ "$USB_MOUNTED" = "1" ]; then mkdir -p /mnt/samples fi mkdir -p /media if [ -x /scripts/usb-midi-gadget.sh ]; then if [ "$USB_MOUNTED" = "1" ] && [ -f /mnt/config.json ] && grep -Eq '"usbMidi"[[:space:]]*:[[:space:]]*true' /mnt/config.json 2>/dev/null; then /scripts/usb-midi-gadget.sh up >/tmp/usb-midi-gadget.log 2>&1 || true else /scripts/usb-midi-gadget.sh down >/tmp/usb-midi-gadget.log 2>&1 || true fi fi # Run ac-native in a loop — if it crashes, restart; if clean exit, shutdown export LD_LIBRARY_PATH="/lib64:/usr/lib64:${LD_LIBRARY_PATH:-}" # Write diagnostics to console AND USB echo "[init] USB_MOUNTED=$USB_MOUNTED" > /dev/tty0 2>/dev/null if [ "$USB_MOUNTED" = "1" ]; then LOG=/mnt/pre-launch.log else # No USB config partition — try writing logs to /tmp LOG=/tmp/pre-launch.log fi echo "=== PRE-LAUNCH ===" > $LOG ls /dev/dri/ >> $LOG 2>&1 echo "binary: $(ls -la /ac-native 2>&1)" >> $LOG echo "build: $(cat /etc/ac-build 2>&1)" >> $LOG echo "usb_mounted: $USB_MOUNTED" >> $LOG echo "gpu:" >> $LOG ls -la /dev/dri/ >> $LOG 2>&1 ls -la /dev/fb* >> $LOG 2>&1 echo "block devs:" >> $LOG ls /dev/sd* /dev/nvme* >> $LOG 2>&1 echo "=== DMESG ===" >> $LOG dmesg >> $LOG 2>&1 echo "=== CPUINFO ===" >> $LOG head -30 /proc/cpuinfo >> $LOG 2>&1 echo "=== CMDLINE ===" >> $LOG cat /proc/cmdline >> $LOG 2>&1 sync echo "[init] GPU: $(ls /dev/dri/ 2>/dev/null || echo NONE) USB=$USB_MOUNTED" > /dev/tty0 2>/dev/null # Start Swank server in background (if SBCL image exists) SWANK_PID=0 if [ -x /ac-swank ]; then LD_LIBRARY_PATH="/lib64:/usr/lib64" /ac-swank --swank-only >/dev/null 2>&1 & SWANK_PID=$! fi # Main loop — ac-native runs as a child process (not PID 1). # First attempt: with SDL3/GPU env vars. # If it crashes (signal), retry without SDL (AC_NO_SDL=1). # If that also crashes, keep retrying without SDL with backoff. CRASH_COUNT=0 SDL_ENABLED=1 while true; do if [ "$SDL_ENABLED" = "1" ]; then echo "[init] launching ac-native (SDL3 GPU enabled)..." > /dev/tty0 2>/dev/null LD_LIBRARY_PATH="/lib64" LIBGL_DRIVERS_PATH="/lib64/dri" GBM_DRIVERS_PATH="/lib64/dri" MESA_LOADER_DRIVER_OVERRIDE=iris \ /ac-native /piece.mjs 2>/tmp/ac-native-stderr.log & else echo "[init] launching ac-native (DRM only)..." > /dev/tty0 2>/dev/null LD_LIBRARY_PATH="/lib64" AC_NO_SDL=1 \ /ac-native /piece.mjs 2>/tmp/ac-native-stderr.log & fi CHILD_PID=$! wait $CHILD_PID EXIT_CODE=$? # Save crash info echo "[init] ac-native (pid $CHILD_PID) exited: code=$EXIT_CODE crash=$CRASH_COUNT sdl=$SDL_ENABLED" > /dev/tty0 2>/dev/null head -5 /tmp/ac-native-stderr.log > /dev/tty0 2>/dev/null # Save crash info to USB if mounted if [ "$USB_MOUNTED" = "1" ]; then echo "exit=$EXIT_CODE crash=$CRASH_COUNT $(date 2>/dev/null)" >> /mnt/ac-crash.log cp /tmp/ac-native-stderr.log /mnt/ac-native-stderr.log 2>/dev/null sync fi if [ "$EXIT_CODE" = "0" ]; then sync # Suppress all kernel output before shutdown echo 0 > /proc/sys/kernel/printk 2>/dev/null printf '\033[?25l\033[2J' > /dev/tty0 2>/dev/null poweroff -f 2>/dev/null echo o > /proc/sysrq-trigger 2>/dev/null sleep 30 break fi if [ "$EXIT_CODE" = "2" ]; then sync echo 0 > /proc/sys/kernel/printk 2>/dev/null printf '\033[?25l\033[2J' > /dev/tty0 2>/dev/null reboot -f 2>/dev/null echo b > /proc/sysrq-trigger 2>/dev/null sleep 30 break fi CRASH_COUNT=$((CRASH_COUNT + 1)) # If crashed with SDL enabled, disable it and retry immediately if [ "$SDL_ENABLED" = "1" ] && [ "$EXIT_CODE" -gt 128 ]; then # Exit > 128 = killed by signal (128 + signal number) SIG=$((EXIT_CODE - 128)) echo "[init] Signal $SIG with SDL — disabling GPU, retrying with DRM..." > /dev/tty0 2>/dev/null SDL_ENABLED=0 if [ "$USB_MOUNTED" = "1" ]; then echo "sdl_crash: signal=$SIG, disabling SDL" >> /mnt/ac-crash.log sync fi sleep 1 continue fi # Flash screen red via framebuffer if [ -c /dev/fb0 ]; then dd if=/dev/zero bs=4096 count=512 2>/dev/null | tr '\0' '\377' > /dev/fb0 2>/dev/null fi sleep 2 done