Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/saf/device/evidence/platform-pmos-era.md
Fimeg bde961c6f2 saf: one spine — device, state, and work under the index
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
2026-08-18 09:47:30 -04:00

7.7 KiB
Raw Permalink Blame History

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 / ~6090 s to rejoin — poll, don't assume.
  • USB fallback: casey@172.16.42.1. Helper: ../phone.sh {ssh,vnc,push,pull,run}.
  • sudo password 147147echo 147147 | sudo -S <cmd>. Never pipe file content into a sudo -S tee (password and content fight over stdin). Write /tmp/x as user, then echo PW | sudo -S cp /tmp/x /dest.
  • pmOS is Alpine — shell is ash/busybox, not bash. No [[ ]], no arrays, no function.
  • Host (Arch) ↔ Android: adb works with root (magisk); fastboot for 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) had system_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 pmOS sudo reboot bootloader (~12 s → fastboot), then fastboot --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). The dtbs/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)
  • fastboot flash system is blocked (needs fastbootd, which won't enumerate on this device). Write the rootfs via dd over ADB from Android, after simg2img.
  • 4K sectors: sgdisk needs -a 256 for 1 MiB alignment; gdisk reports "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. Always fastboot 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 ignores cdc_ncm/rndis_host/cdc_ether
  • /etc/udev/rules.d/99-pmos-usb.rules — auto-assigns 172.16.42.2/24 on 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 clean buys ~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 /metadata sda20). 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)

  1. Never misc:vfr = 0, never DPMS off/on in Hyprland — wedges the DSI panel + stmfts touch IC. Recovery: systemctl restart getty@tty1 for a clean modeset. Use vfr = true + cursor:no_hardware_cursors = true. Skip earboxer's power-button DPMS binds.
  2. hyprgrass must match the Hyprland version exactly (build against the hl-x.y.z tag).
  3. Display already correct: monitor = DSI-1,1080x2160@60,0x0,2.0 (scale 2.0 → 540×1080 logical). ~443 PPI panel.
  4. Restarting rmtfs blips ath10k → WiFi can drop; prefer USB during modem work.
  5. 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).