Minimal Linux environment on a Google Pixel 8 (shiba) with USB serial console.
Replaces the Android init with a custom static binary that boots to a root busybox shell accessible over USB-C serial (USB gadget ACM).
- Mounts essential filesystems (proc, sys, dev, configfs)
- Disables SELinux enforcement (required for USB gadget configfs)
- Loads all 209 vendor kernel modules from
vendor_kernel_boot - Feeds the hardware watchdog (Tensor G3 / Exynos s3c2410_wdt)
- Configures USB gadget ACM serial via configfs
- Creates
/dev/ttyGS0device node (major number from/proc/tty/drivers) - Spawns a busybox root shell on the serial port
- Google Pixel 8 (shiba) with unlocked bootloader
- GrapheneOS bootloader + vendor_boot + vendor_kernel_boot flashed
- AVB verification disabled:
fastboot flash vbmeta --disable-verity --disable-verification vbmeta.img - Stock GrapheneOS
init_bootramdisk extracted asstock_raw.cpio
# Build the overlay
nix build .#initramfs
# Assemble and flash (requires stock ramdisk + avbtool + mkbootimg)
cat stock_raw.cpio result/overlay.cpio > combined.cpio
lz4 -l -9 combined.cpio ramdisk.lz4
mkbootimg --header_version 4 --ramdisk ramdisk.lz4 \
--os_version 16.0.0 --os_patch_level 2026-02 --output init_boot.img
avbtool add_hash_footer --image init_boot.img \
--partition_name init_boot --partition_size 8388608
fastboot flash init_boot init_boot.img
fastboot rebootAfter ~55 seconds, /dev/ttyACM0 appears on the host:
picocom /dev/ttyACM0You get a root shell (uid=0 gid=0) with busybox utilities.
The boot image is an overlay CPIO concatenated after the stock GrapheneOS
init_boot ramdisk. CPIO concatenation means later entries override earlier
ones — our /init and /bin/ replace stock ones. Kernel modules at
/lib/modules/ come from the vendor_kernel_boot partition (not modified).
init_boot.img
├── stock GOS ramdisk (base filesystem layout)
└── our overlay:
├── /init (custom static C binary, PID 1)
└── /bin/
├── busybox (static aarch64 binary)
├── sh -> busybox
├── ls -> busybox
└── ... (40+ command symlinks)
- Watchdog: Tensor G3 has
s3c2410_wdt— must be fed or phone reboots at ~80s - SELinux: Must be disabled for configfs gadget mkdir/symlink/write operations
- Module loading: Multi-pass
finit_module()with kernel cmdline options (e.g.,tcpci_max77759.conf_sbu=0) — matches AOSP Modprobe behavior - ttyGS0:
devtmpfsdoes not auto-create the gadget serial device node; mustmknodusing the dynamically-assigned major from/proc/tty/drivers - USB IDs:
18d1:4ee7(Google Nexus/Pixel charging + debug) - UDC:
11210000.dwc3(Exynos DWC3 USB controller) - Boot time: ~55 seconds from power-on to USB serial available
init.c— Custom init binary source (static C, musl cross-compiled)initramfs.nix— Builds the overlay CPIO (init + busybox)boot-img.nix— Assembles the flashable init_boot.imgmkbootimg.nix— AOSP mkbootimg toolkernel.nix— GrapheneOS prebuilt kernel (reference, not used for init_boot)