PAF becomes saf/device (history kept), STATE.md dissolves into saf/state.md with the dated era archived, the substrate SAF moves up from souveraine, and every agreement points at saf/INDEX.md and nowhere else. one map, nothing to remember
7.7 KiB
PAF · Platform — hardware, boot, storage, recovery
Load-bearing device facts. Add a line when something costs more than 2 minutes to relearn.
Reaching the phone
- WiFi (preferred):
ssh -i ~/.ssh/ani_id_ed25519 casey@10.10.20.220(Samaritan Solutions). Drops on reboot / ~60–90 s to rejoin — poll, don't assume. - USB fallback:
casey@172.16.42.1. Helper:../phone.sh {ssh,vnc,push,pull,run}. - sudo password
147147→echo 147147 | sudo -S <cmd>. Never pipe file content into asudo -S tee(password and content fight over stdin). Write/tmp/xas user, thenecho PW | sudo -S cp /tmp/x /dest. - pmOS is Alpine — shell is ash/busybox, not bash. No
[[ ]], no arrays, nofunction. - Host (Arch) ↔ Android:
adbworks with root (magisk);fastbootfor slot/boot ops.
Slots & boot architecture
- slot A = pmOS, slot B = LineageOS (Android). Verified 2026-06-25 on-device: pmOS
ran with
androidboot.slot_suffix=_a;fastboot getvar current-slot= a; flipping active to b booted Android; Android (slot B) hadsystem_b/sda6 mounted. So pmOS =boot_a(sda11) +system_a(sda5); Android =boot_b(sda12) +system_b(sda6). Older PAF entries saying A=Android/B=pmOS or rootfs in system_b are pre-swap and stale. Switch active slot: from pmOSsudo reboot bootloader(~12 s → fastboot), thenfastboot --set-active={a,b} && fastboot reboot. - pmOS rootfs lives inside
system_a(sda5) as a packed GPT image with 4096-byte sectors (UFS). Two inner partitions:- boot (vfat, ~236 MB) at byte offset 8388608 in sda6 — holds the kernel, initramfs,
linux.efi, and DTBs. The appended DTB in the boot_b partition image IS used by ABL (it is baked into the kernel image in the boot.img). Thedtbs/qcom/copies in the vfat are for a U-Boot/EFI path that is NOT used on this device currently. - root (ext4, ~2.5 GB) at byte offset 255852544.
UUID:
26733d78-aa54-454d-ba43-0fa1eabfb3fd(pmOS_root label) - boot vfat UUID:
2CE8-836F(pmOS_boot label)
- boot (vfat, ~236 MB) at byte offset 8388608 in sda6 — holds the kernel, initramfs,
fastboot flash systemis blocked (needs fastbootd, which won't enumerate on this device). Write the rootfs viaddover ADB from Android, aftersimg2img.- 4K sectors:
sgdiskneeds-a 256for 1 MiB alignment;gdiskreports "GPT not present" if it assumes 512-byte sectors — the image is valid. fastboot boot <img>has a hardware watchdog timeout (~60 s) — the phone reboots itself if the image doesn't complete boot. Alwaysfastboot flash boot_b <img>instead.- /tmp is tmpfs (volatile, wiped on reboot) — never park load-bearing artifacts there.
Boot image parameters (slot A — pmOS)
The canonical pmOS boot image for slot A was /tmp/pmos-boot-b.img (29245440 bytes) — wiped on 2026-06-21 reboot (/tmp is tmpfs). The rescued recovery boot is now at artifacts/tmp-rescue-20260626/recovery-boots/boot_a_restore.img (65M). The filename predated the slot swap; always flash to boot_a, not boot_b.
Rebuild targets /tmp/pmos-debug2.img (debug shell) and /tmp/pmos-nodebug.img (normal boot)
must be regenerated. To rebuild from rescued kernel+ramdisk in artifacts/tmp-rescue-20260626/bootimg-workspace/:
# Normal boot (no debug shell):
mkbootimg --kernel artifacts/tmp-rescue-20260626/bootimg-workspace/kernel --ramdisk artifacts/tmp-rescue-20260626/bootimg-workspace/ramdisk \
--base 0x0 --kernel_offset 0x00008000 --ramdisk_offset 0x01000000 \
--tags_offset 0x00000100 --pagesize 4096 --header_version 0 \
--cmdline "console=tty0 console=ttyMSM0,115200 consoleblank=0 \
pmos_boot_uuid=2CE8-836F pmos_root_uuid=26733d78-aa54-454d-ba43-0fa1eabfb3fd \
pmos_rootfsopts=defaults" \
-o /tmp/pmos-nodebug.img
# Debug shell (drops to telnet:23 before mounting rootfs, adds pmos.debug-shell):
# ... same but append: pmos.debug-shell
Flash to slot A (pmOS) and reboot:
fastboot flash boot_a /tmp/pmos-nodebug.img && fastboot set_active a && fastboot reboot
Emergency debug shell (when pmOS won't boot — flash debug image to boot_a):
fastboot flash boot_a /tmp/pmos-debug2.img && fastboot set_active a && fastboot reboot
# USB gadget comes up as 18d1:d001 at 172.16.42.1 (~8 s after reboot)
# telnet 172.16.42.1 23 → shell with pmos_continue_boot / pmos_logdump
# After diagnosing, re-flash the normal image and reboot.
USB host setup (permanent, already configured 06-19):
/etc/NetworkManager/conf.d/99-pmos-usb.conf— NM ignorescdc_ncm/rndis_host/cdc_ether/etc/udev/rules.d/99-pmos-usb.rules— auto-assigns172.16.42.2/24on interface up
Disk full recovery (happened 06-19 — logs filled rootfs to 100%):
Boot debug image → telnet in → mount_subpartitions → mount /dev/loop0p2 /sysroot →
rm -rf /sysroot/var/log/* → pmos_continue_boot. Frees ~94 MB.
The rootfs will slowly refill — set up log rotation on pmOS (/etc/logrotate.d/ or
journalctl --vacuum-size=10M) once booted.
Recovery: swap the slot-B DTB from rooted Android (no TWRP)
Used 06-19 to un-brick slot B after the SPMI-pmic DTB panic. Reversible; backs up the old DTB.
adb push <good>.dtb /data/local/tmp/recovery.dtb
adb shell 'su -c "
for l in /dev/block/loop*; do losetup -d \$l 2>/dev/null; done
LO=\$(losetup -f); losetup -o 8388608 \$LO /dev/block/by-name/system_b
mkdir -p /data/local/tmp/bmnt; mount -t vfat \$LO /data/local/tmp/bmnt
T=/data/local/tmp/bmnt/dtbs/qcom/sdm845-google-blueline.dtb
cp \$T \$T.broken.bak
cp /data/local/tmp/recovery.dtb \$T
sync; md5sum \$T /data/local/tmp/recovery.dtb
umount /data/local/tmp/bmnt"' # loop auto-detaches on umount
Building a DTB: base = the pristine kernel-package DTB (decompile
linux-postmarketos-qcom-sdm845-*.apk, or /tmp/pmos-packages/blueline.dts). Edit, then
dtc -I dts -O dtb -o out.dtb in.dts. The pristine DTB is 111641 bytes; verify
grep -c 'pmic@4\|pmic@5' is 0 (those panic).
Storage situation
- Root (ext4 inside sda6) is 2.4 GB, ~80 MB free (94 MB logs cleared 06-19), 828 packages.
Nothing significant installs until userdata is resized.
apk cache cleanbuys ~300 MB temporarily. Logs will refill — set up log rotation once booted. - userdata (sda21, 111 GB) is FBE + metadata-encrypted (dm-default-key, AES-256-XTS; key
KeyMint-wrapped in TEE, stored in
/metadatasda20). Cannot shrink offline — no plaintext F2FS superblock outside Android; key can't be re-derived in TWRP. Shrinking = full wipe. Decision (06-18): do not wipe until calls + Linux desktop both justify it. - GPT backup of the outer table:
../gpt-sda-20260618.bak. Nothing on sda was modified.
Hardware lessons (do not relearn)
- Never
misc:vfr = 0, never DPMS off/on in Hyprland — wedges the DSI panel + stmfts touch IC. Recovery:systemctl restart getty@tty1for a clean modeset. Usevfr = true+cursor:no_hardware_cursors = true. Skip earboxer's power-button DPMS binds. - hyprgrass must match the Hyprland version exactly (build against the
hl-x.y.ztag). - Display already correct:
monitor = DSI-1,1080x2160@60,0x0,2.0(scale 2.0 → 540×1080 logical). ~443 PPI panel. - Restarting rmtfs blips ath10k → WiFi can drop; prefer USB during modem work.
- USB-net flaps because NetworkManager grabs
enp0s20f0u6. Fix with pkexec (not sudo):nmcli dev set <if> managed no; ip addr add 172.16.42.2/24 dev <if>; ip link set <if> up.
Backups on the laptop
~/pixel3-backup/ — full Android partition images (gzipped): boot_a (downstream DTB +
kernel), modem_a (FAT16 with mba.mbn + modem.b00..b25), persist (cal: audio/sensors/
rfs/DRM), system_a, vendor_a, vbmeta_a, dtbo_a, userdata (87 GB). EFS snapshot:
../efs-backup-20260618/ (modemst1/2, fsg, fsc).