6.2 KiB
PAF · Platform — hardware, boot, storage, recovery (Arch era)
Load-bearing device facts. Add a line when something costs more than 2
minutes to relearn. pmOS-era snapshot preserved at
evidence/platform-pmos-era.md — its Alpine/ash and pmOS-slot notes no
longer apply.
Reaching the phone
- USB (primary):
ssh -F /dev/null -i ~/.ssh/ani -o BatchMode=yes casey@172.16.42.1(NCM gadget, phone serves DHCP; laptop autoconfigures). - WiFi: DHCP on the LAN, drifts — check the router or
nmclion-device via USB first. - User
casey, passwordless-sudo NO — sudo password147147(echo 147147 | sudo -S <cmd>). Never stream sudo-gated output through further pipes over SSH (silent truncation, repeatedly) — write to a file on the phone, pull it separately. - Shell is bash on Arch (systemd, GNU coreutils, pacman). The pmOS-era busybox/ash caveats are dead.
- Serial fallback: ACM gadget → laptop-side
ttyACM0; getty enabled on ttyGS0.
Slots & boot architecture
- Slot A = Arch (ours). Slot B = LineageOS (Android, rooted, on the 4.9
vendor kernel). Slot B is the living downstream reference AND the
fallback OS — never touch
boot_bor Android's partitions. - Boot chain: ABL boots
boot_a(Android bootimg v0, our kernel Image.gz with appended DTB + the pmOS-chain ramdisk — see build.md). Root is found by UUID from the baked cmdline. qbootctl(in the device package since ef21637) marks the slot successful and provides reboot-to-android; closes the A/B retry-lockout that used to eat boots.- Switch to Android:
sudo reboot bootloader→fastboot --set-active=b→fastboot reboot(and back with--set-active=a).
Storage (live table, verified on-device 2026-07-10)
UFS /dev/sda, GPT, 4096-byte sectors (sgdisk needs -a 256; a tool
assuming 512B sectors will misread the table).
| Part | Size | FS | Name | Role |
|---|---|---|---|---|
| sda21 | 42.9G | — | userdata | Android's, FBE-encrypted, NEVER TOUCH (near-formatted once — always verify identity before writing any partition) |
| sda22 | 10.0G | fat32 | shared | Arch↔Android shared data, mounted /shared |
| sda23 | 253M | vfat | Arch_boot | staging/aux boot filesystem |
| sda24 | 66.2G | ext4 | Arch_root | the Arch rootfs, UUID=a094e031-ea89-4847-a299-082a0ae8c9ab |
persist lives on a different UFS LUN (sdf2) — physically immune to sda
operations; mounted ro,nofail. Backup in ../blobs/ +
~/pixel3-backup/persist.img.
- Boot-image A/B slots (
boot_a/boot_b, 67MB each, partitions 11/12) are separate from the rootfs partitions above —fastboot flash boot_ais the only flash operation this project performs.
Recovery
- TWRP:
fastboot boot ~/Downloads/twrp-3.7.1_12-0-blueline.img(boot, not flash). Used for repartition-class work; a live pmOS/Arch root can't modify its own mounted partitions. - Known-good fallback kernel image (stmfts touch, pre-SWIRE display):
../staging/deploy-139aa/boot-139aa7748181-pmoschain.img→ flash to boot_a. Its module tree is on the phone. - Full stock partition clone (2026-06-18) at
~/pixel3-backup/; LOS boot image at~/Downloads/lineage-22.2-20260629-boot.img. - Last resort: slot B is a complete, working Android.
Hardware map (what's proven on this exact unit)
- SoC sdm845, 4G RAM. Panel: LG SW43408 (DSC command-mode, 1080x2160) — settled from per-unit persist calibration data; the Samsung s6e3ha8/sec_ts DTBO fragments are the OTHER hardware variant, not ours.
- Touch: ST FTS @ 0x49 on i2c-2 (888000 geni SE, GPI-DMA-only); reset tlmm 99 (active-low RESETB), IRQ tlmm 125, AP/SLPI bus switch tlmm 136.
- OLED bias: PMI8998 LAB/IBB under SWIRE (DDIC hardware) control — see display.md.
- WiFi wcn3990 (ath10k_snoc), BT (hci_uart/btqca), modem MPSS (see modem.md), sensors behind SLPI DSP (see slpi.md), audio WCD9340 over SLIMbus (working HiFi speaker, microphone and two-way calls; see audio.md).
- Power button = pm8941_pwrkey → input event; volume keys GPIO.
Charging (pmi8998, qcom_smbx)
Two supplies: pmi8998-charger (the charger) and qcom-battery (fuel
gauge). The charger IC does full CC/CV — trickle, pre, fast, full-on,
taper — and BATTERY_CHARGER_STATUS_1 bits 0:2 report which stage it is
in. Mainline read that register only to derive status, collapsing all
five states into "Charging" and discarding the detail.
Since f08dc70b3 the driver exposes them:
| attribute | register | notes |
|---|---|---|
charge_type |
BATTERY_CHARGER_STATUS_1 (0x06) |
read-only; Trickle/Fast/Standard |
constant_charge_current_max |
FAST_CHARGE_CURRENT_CFG (0x61) |
25000µA/step, 8-bit |
voltage_max |
FLOAT_VOLTAGE_CFG (0x70) |
raw=(uV-3487500)/7500+1; 4.4V → 122 |
charge_control_end_threshold |
same as above | percentage form, 0-100 |
Lowering the float voltage is what caps the charge. The cell is held
at whatever CV target is programmed, so 4.1V parks it near 80% and buys
calendar life. Writes are bounded twice — by the DT cell rating
(voltage-max-design-microvolt = <4400000> in
sdm845-google-blueline.dts) and by what the 8-bit fields can encode, so
neither an overcharge nor a silent masked-off write is possible.
These registers are volatile — every setting is lost on reboot. Use
/etc/blueline-charge-limit + blueline-charge-limit.service to persist
one. Front end is blueline-charge status|limit|current.
Not exposed by this driver: charge_full/charge_now (fuel gauge, see
qcom-battery) and any charge scheduling — downstream's google_charger
ran a taper state machine with DT tunables (google,chg-itaper,
chg-soctaper); mainline has no equivalent and this patch does not add one.
Hard lessons (each cost real time — do not relearn)
- Verify partition identity before any write (
parted -s /dev/sda printblkid); an unlabeled lsblk row is not free space. The sda21 near-miss is the standing warning.
/tmpon the phone is tmpfs — never park artifacts there.fastboot boot <img>has a ~60s hardware watchdog — flash, don't test-boot, anything that takes long to come up.- Trust the user's direct visual report of the glass over any remote telemetry — registers can say "on" while the panel shows black.