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
6.9 KiB
PAF · DIAG capture runbook (Route B instrument)
Goal: get the modem's OWN view of RF-init — why it never self-completes, parks offline, and
refuses online (DeviceNotReady 52). Everything so far is QMI reporting a refusal code; DIAG
(QCDM/DM) gives the modem's internal F3 debug messages, radio frames, and NV/EFS state.
This is the byte-for-byte trace every prior frontier (#5/#7/#8) named as the missing piece.
Why DIAG (vs the coredump path)
- F3/DM debug messages = the modem narrating its RF/NAS/MCFG init in its own words. Richer than a remoteproc coredump/SSR reason.
- NV item + EFS read/write over DIAG = Route B's EFS/NV diff (GLM thread #2) at the authoritative
source, and the write path for
mcfg_autoselect_by_uim/ power-up operating mode. - The decisive comparison: run the SAME tool on BOTH OSes against the SAME modem silicon and diff.
Channel facts (confirmed)
- DIAG is exposed on Android via
/dev/diag, created by thediagcharkernel module (root). - Enable frame capture:
DIAG_IOCTL_SWITCH_LOGGING→MEMORY_DEVICE_MODE = 2; checkDIAG_IOCTL_REMOTE_DEVfor the extra device_type byte. - Packet framing:
cmd_code(1B) + payload + CRC16-CCITT(2B) + 0x7e, HDLC escaping (0x7e→0x7d 0x5e,0x7d→0x7d 0x5d). - Message classes:
DIAG_LOG_F(binary log packets / radio frames),DIAG_MSG_F/DIAG_EXT_MSG_F(F3 debug strings — the narration we want). NV/EFS/L1-3 commands supported. - Tool: QCSuper (P1sec, open source) for frame + F3 capture → pcap/GSMTAP. For arbitrary NV item read/write, a raw DIAG client (libqcdm-style framer, or QCSuper's diag layer directly).
- CHECK FIRST:
sdm845-mainline/pmtoolsmay already ship a diag/modem helper — look before reinventing the framer.
Side A — Android (slot B, rooted): the WORKING reference [HIGH VALUE — never captured]
diagchar + /dev/diag are present on the downstream Android kernel. Two ways in:
- USB-DIAG (exposes a serial/COM port):
adb root; adb shell→su→setprop sys.usb.config diag,serial_cdev,rmnet_gsi,adb(XDA-confirmed on Pixel 3). Our ledger saw this HAL-revert to adb-only on this LineageOS build — RETRY it; if it reverts, use local. - Local
/dev/diag(reliable fallback): run the client on-device over adb, not USB-DIAG.
adb root; adb shell ls -l /dev/diag— confirm node exists.- Push/run QCSuper on-device (or proxy /dev/diag over adb). Start F3 + frame capture.
- Trigger a clean offline→online: airplane mode OFF→ON (we already have this at QCRIL-function
granularity in
android-capture-20260620/; DIAG gets it at message/F3 granularity). - Save: F3 stream + radio frames spanning the transition. This is the modem self-onlining at its own RF-init — the thing pmOS never reaches.
- While here, DIAG-read the NV/EFS state the working modem holds:
- power-up operating mode NV
mcfg_autoselect_by_uim- RF-calibration NV / QCN region (Confirm exact NV item indices from the modem's NV table / QCSuper — do NOT guess indices.)
Output → android-capture-YYYYMMDD/diag/.
Side B — pmOS (slot A, mainline): the FAILURE side [verify availability first]
diagchar is a downstream module; mainline SDM845 does NOT ship it. So /dev/diag may be absent.
Determine the transport before assuming symmetry:
ls -l /dev/diag*;dmesg | grep -i diag;zcat /proc/config.gz | grep -i diag(or check the built kernel config) ; look for a glink/rpmsg channel namedDIAG.- If a DIAG transport exists → run QCSuper, attempt
--dms-set-operating-mode=online, capture the F3 stream of the FAILED RF-init. Diff F3 against Side A around the offline→online point — the first divergence is the answer. - If NO DIAG transport on mainline → fall back to GLM thread #1: remoteproc coredump/SSR reason +
tqftpserv/rmtfsrequest trace during the failed online. Diff that against Side A's DIAG F3. (Retry-safe: online attempts do NOT poison the modem — the old "one-shot per boot" rule is disproven. A QMISet Operating Mode = RESET (4)cleanly reinitializes it without reboot. Retry freely. See HANDOFF.md CORRECTIONS.)
What we're diffing for
KEY: a static NV/QCN diff between the two OSes will be NULL. modemst1/2 + fsg/fsc + persist are on UNSLOTTED partitions → the modem reads BYTE-IDENTICAL persisted EFS/NV/cal on both Android and pmOS (ledger L83: Android-primed EFS → still fails). The modem has no separate flash; its NV lives in that shared EFS. So a QPST QCN backup / NV-item dump will read the same bytes on both sides — it will NOT reveal the delta. The difference is necessarily RUNTIME behavior, which is exactly why the F3 stream (not a static snapshot) is the instrument:
- The F3 line(s) where Android's modem advances RF-init past the point pmOS's stalls.
- Whether the working modem boots into LPM and flips LPM→online, vs pmOS sitting in
offline(mode 3) — and what in the F3 stream gates that state. - Whether the working modem's online even TOUCHES NV/PDC (frontier #4 says steady-state Android is verify-only) — if it doesn't, the gate is pure firmware-state/timing the AP can't feed.
(NV reads in Side A step 5 are still worth doing ONCE — to confirm the shared-EFS assumption and record the working values — but expect them equal to pmOS. Don't build a Route B fix around a static NV diff until F3 shows the modem actually consuming that item at init.)
Tools reality (we're on Arch, not Windows)
- QPST / QXDM are Windows-only proprietary. QPST = QCN backup/restore; QXDM = deep F3 logging. Given the shared-EFS point above, QPST's QCN backup buys little here.
- QCSuper (Linux, open) is the path for F3 + frame capture. For raw NV item read/write, a
libqcdm-style framer or QCSuper's diag layer. Check
pmtoolsfirst.
SIDE note — glink rpmsg teardown is broken upstream (applies to CHANNEL open/close, NOT online)
Dynamically opening/closing glink rpmsg channels is documented as broken on the upstreaming list
(the wwan_remove_port/rpmsg_wwan_ctrl 614s hung_task seen on op6t). This is a real risk when
creating/tearing down a glink channel (e.g. opening a raw DIAG rpmsg endpoint). It is NOT the
"one failed online poisons the modem" rule that used to be here — that rule is disproven: a plain
--dms-set-operating-mode=online is an ordinary QMI message on the existing IPCRTR transport, it
does not open a glink channel, and it is retry-safe (RESET reinitializes). Keep the caution for
raw glink channel-open probes only. An AT read of the modem's own reason (+CEER, +CFUN?) has
no free path anyway: QMI service 8 is AT-forwarding, not AT-execution (see qrtr_tools_reference
2026-07-02), and a raw glink AT port is exactly the channel-open that this note warns about.
Refs
- QCSuper: https://github.com/P1sec/QCSuper (docs/The Diag protocol.md)
- pmtools (check for existing diag helper): https://gitlab.com/sdm845-mainline/pmtools