Monorepo for Aesthetic.Computer
aesthetic.computer
1#!/bin/sh
2# AC Native OS init — DRM direct boot with crash recovery
3
4export PATH="/bin:/sbin:/usr/bin:/usr/sbin"
5
6mount -t proc proc /proc 2>/dev/null
7mount -t sysfs sysfs /sys 2>/dev/null
8mount -t devtmpfs devtmpfs /dev 2>/dev/null
9mkdir -p /dev/pts /dev/shm /tmp /run /etc
10mount -t devpts devpts /dev/pts -o ptmxmode=0666 2>/dev/null
11mount -t tmpfs tmpfs /dev/shm 2>/dev/null
12mount -t tmpfs tmpfs /tmp 2>/dev/null
13mount -t tmpfs tmpfs /run 2>/dev/null
14mount -t efivarfs efivarfs /sys/firmware/efi/efivars 2>/dev/null
15
16# zram swap
17modprobe zram 2>/dev/null || true
18if [ -e /sys/block/zram0/disksize ] && [ -b /dev/zram0 ]; then
19 echo 1G > /sys/block/zram0/disksize &&
20 mkswap /dev/zram0 >/dev/null 2>&1 &&
21 swapon /dev/zram0 2>/dev/null
22fi
23
24# Loopback
25ip link set lo up 2>/dev/null
26
27# Restore baked Claude credentials (tmpfs mount hid the originals)
28if [ -f /claude-creds.json ]; then
29 mkdir -p /tmp/.claude
30 cp /claude-creds.json /tmp/.claude/.credentials.json
31 cp /claude-state.json /tmp/.claude.json 2>/dev/null
32 printf '{"permissions":{"allow":["Bash(*)","Read(*)","Write(*)","Edit(*)","Glob(*)","Grep(*)","WebFetch(*)","WebSearch(*)"]},"autoUpdates":false,"installMethod":"native"}\n' > /tmp/.claude/settings.json
33fi
34mkdir -p /tmp/ac
35[ -f /device-claude.md ] && cp /device-claude.md /tmp/ac/CLAUDE.md 2>/dev/null
36[ -f /device-score.md ] && cp /device-score.md /tmp/ac/SCORE.md 2>/dev/null
37
38# /etc/group and /etc/passwd needed by seatd
39echo "root:x:0:" > /etc/group
40echo "root:x:0:root" > /etc/passwd
41
42# Wait for GPU (up to 3 seconds)
43i=0
44while [ ! -e /dev/dri/card0 ] && [ ! -e /dev/dri/card1 ] && [ ! -e /dev/fb0 ] && [ $i -lt 300 ]; do
45 usleep 10000 2>/dev/null || sleep 1
46 i=$((i+1))
47done
48
49# Performance governor (silently skip if cpufreq not available)
50if [ -d /sys/devices/system/cpu/cpu0/cpufreq ]; then
51 for g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
52 echo performance > "$g" 2>/dev/null
53 done
54fi
55export SSL_CERT_FILE="/etc/pki/tls/certs/ca-bundle.crt"
56export CURL_CA_BUNDLE="/etc/pki/tls/certs/ca-bundle.crt"
57export SSL_CERT_DIR="/etc/ssl/certs"
58export HOME="/tmp"
59
60# ── Mount USB config/log partition (for config.json, wifi creds, logs) ──
61# Prefer the writable config partition over the boot partitions.
62modprobe vfat 2>/dev/null
63modprobe nls_cp437 2>/dev/null
64modprobe nls_ascii 2>/dev/null
65USB_MOUNTED=0
66USB_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"
67
68mount_usb_partition() {
69 pass="$1"
70 for p in $USB_PARTS; do
71 if [ -b "$p" ]; then
72 mkdir -p /mnt
73 mount -t vfat "$p" /mnt 2>/dev/null || continue
74 if [ "$pass" = "config" ] && [ -f /mnt/config.json ]; then
75 USB_MOUNTED=1
76 return 0
77 fi
78 if [ "$pass" = "boot" ] && { [ -f /mnt/EFI/BOOT/BOOTX64.EFI ] || [ -f /mnt/EFI/BOOT/KERNEL.EFI ]; }; then
79 USB_MOUNTED=1
80 return 0
81 fi
82 umount /mnt 2>/dev/null
83 fi
84 done
85 return 1
86}
87
88for attempt in 1 2 3 4 5 6 7 8 9 10; do
89 mount_usb_partition config && break
90 mount_usb_partition boot && break
91 [ "$USB_MOUNTED" = "1" ] && break
92 sleep 1
93done
94
95# Create samples directory on boot media + mount point for music USB
96if [ "$USB_MOUNTED" = "1" ]; then
97 mkdir -p /mnt/samples
98fi
99mkdir -p /media
100
101if [ -x /scripts/usb-midi-gadget.sh ]; then
102 if [ "$USB_MOUNTED" = "1" ] && [ -f /mnt/config.json ] &&
103 grep -Eq '"usbMidi"[[:space:]]*:[[:space:]]*true' /mnt/config.json 2>/dev/null; then
104 /scripts/usb-midi-gadget.sh up >/tmp/usb-midi-gadget.log 2>&1 || true
105 else
106 /scripts/usb-midi-gadget.sh down >/tmp/usb-midi-gadget.log 2>&1 || true
107 fi
108fi
109
110# Run ac-native in a loop — if it crashes, restart; if clean exit, shutdown
111export LD_LIBRARY_PATH="/lib64:/usr/lib64:${LD_LIBRARY_PATH:-}"
112
113# Write diagnostics to console AND USB
114echo "[init] USB_MOUNTED=$USB_MOUNTED" > /dev/tty0 2>/dev/null
115if [ "$USB_MOUNTED" = "1" ]; then
116 LOG=/mnt/pre-launch.log
117else
118 # No USB config partition — try writing logs to /tmp
119 LOG=/tmp/pre-launch.log
120fi
121echo "=== PRE-LAUNCH ===" > $LOG
122ls /dev/dri/ >> $LOG 2>&1
123echo "binary: $(ls -la /ac-native 2>&1)" >> $LOG
124echo "build: $(cat /etc/ac-build 2>&1)" >> $LOG
125echo "usb_mounted: $USB_MOUNTED" >> $LOG
126echo "gpu:" >> $LOG
127ls -la /dev/dri/ >> $LOG 2>&1
128ls -la /dev/fb* >> $LOG 2>&1
129echo "block devs:" >> $LOG
130ls /dev/sd* /dev/nvme* >> $LOG 2>&1
131echo "=== DMESG ===" >> $LOG
132dmesg >> $LOG 2>&1
133echo "=== CPUINFO ===" >> $LOG
134head -30 /proc/cpuinfo >> $LOG 2>&1
135echo "=== CMDLINE ===" >> $LOG
136cat /proc/cmdline >> $LOG 2>&1
137sync
138echo "[init] GPU: $(ls /dev/dri/ 2>/dev/null || echo NONE) USB=$USB_MOUNTED" > /dev/tty0 2>/dev/null
139
140# Start Swank server in background (if SBCL image exists)
141SWANK_PID=0
142if [ -x /ac-swank ]; then
143 LD_LIBRARY_PATH="/lib64:/usr/lib64" /ac-swank --swank-only >/dev/null 2>&1 &
144 SWANK_PID=$!
145fi
146
147# Main loop — ac-native runs as a child process (not PID 1).
148# First attempt: with SDL3/GPU env vars.
149# If it crashes (signal), retry without SDL (AC_NO_SDL=1).
150# If that also crashes, keep retrying without SDL with backoff.
151CRASH_COUNT=0
152SDL_ENABLED=1
153while true; do
154 if [ "$SDL_ENABLED" = "1" ]; then
155 echo "[init] launching ac-native (SDL3 GPU enabled)..." > /dev/tty0 2>/dev/null
156 LD_LIBRARY_PATH="/lib64" LIBGL_DRIVERS_PATH="/lib64/dri" GBM_DRIVERS_PATH="/lib64/dri" MESA_LOADER_DRIVER_OVERRIDE=iris \
157 /ac-native /piece.mjs 2>/tmp/ac-native-stderr.log &
158 else
159 echo "[init] launching ac-native (DRM only)..." > /dev/tty0 2>/dev/null
160 LD_LIBRARY_PATH="/lib64" AC_NO_SDL=1 \
161 /ac-native /piece.mjs 2>/tmp/ac-native-stderr.log &
162 fi
163 CHILD_PID=$!
164 wait $CHILD_PID
165 EXIT_CODE=$?
166 # Save crash info
167 echo "[init] ac-native (pid $CHILD_PID) exited: code=$EXIT_CODE crash=$CRASH_COUNT sdl=$SDL_ENABLED" > /dev/tty0 2>/dev/null
168 head -5 /tmp/ac-native-stderr.log > /dev/tty0 2>/dev/null
169 # Save crash info to USB if mounted
170 if [ "$USB_MOUNTED" = "1" ]; then
171 echo "exit=$EXIT_CODE crash=$CRASH_COUNT $(date 2>/dev/null)" >> /mnt/ac-crash.log
172 cp /tmp/ac-native-stderr.log /mnt/ac-native-stderr.log 2>/dev/null
173 sync
174 fi
175
176 if [ "$EXIT_CODE" = "0" ]; then
177 sync
178 # Suppress all kernel output before shutdown
179 echo 0 > /proc/sys/kernel/printk 2>/dev/null
180 printf '\033[?25l\033[2J' > /dev/tty0 2>/dev/null
181 poweroff -f 2>/dev/null
182 echo o > /proc/sysrq-trigger 2>/dev/null
183 sleep 30
184 break
185 fi
186 if [ "$EXIT_CODE" = "2" ]; then
187 sync
188 echo 0 > /proc/sys/kernel/printk 2>/dev/null
189 printf '\033[?25l\033[2J' > /dev/tty0 2>/dev/null
190 reboot -f 2>/dev/null
191 echo b > /proc/sysrq-trigger 2>/dev/null
192 sleep 30
193 break
194 fi
195
196 CRASH_COUNT=$((CRASH_COUNT + 1))
197
198 # If crashed with SDL enabled, disable it and retry immediately
199 if [ "$SDL_ENABLED" = "1" ] && [ "$EXIT_CODE" -gt 128 ]; then
200 # Exit > 128 = killed by signal (128 + signal number)
201 SIG=$((EXIT_CODE - 128))
202 echo "[init] Signal $SIG with SDL — disabling GPU, retrying with DRM..." > /dev/tty0 2>/dev/null
203 SDL_ENABLED=0
204 if [ "$USB_MOUNTED" = "1" ]; then
205 echo "sdl_crash: signal=$SIG, disabling SDL" >> /mnt/ac-crash.log
206 sync
207 fi
208 sleep 1
209 continue
210 fi
211
212 # Flash screen red via framebuffer
213 if [ -c /dev/fb0 ]; then
214 dd if=/dev/zero bs=4096 count=512 2>/dev/null | tr '\0' '\377' > /dev/fb0 2>/dev/null
215 fi
216
217 sleep 2
218done