Watch
1
0
Fork
You've already forked SouveraineOS
0

devices/: a support matrix per body

One row per capability, one column per body, with a strict status vocabulary —
"works" means exercised with evidence named, never that a device node appeared.
blueline points at PAF/ rather than copying it; d10 carries its own state; m1
records what already transfers before anything is measured.

The display pipe is corrected in the same change: ADP binds and scans out and
the panel stays dark, so it is partial, not working.
This commit is contained in:
Fimeg 2026-08-09 22:30:29 -04:00
commit 10685153ea
6 changed files with 346 additions and 8 deletions

View file

@ -3,6 +3,13 @@
**If you are picking up the phone and something is broken, this page is the
whole answer. Do not go reading doctrine first.**
> **Which phone?** There are two, and they are plugged in at the same time.
> This page is **blueline**, the Pixel 3 daily driver, at `172.16.42.1`.
> The **iPhone 7** is at `172.16.43.1`, boots with
> `~/Projects/hoolock/boot.sh`, and its whole state is
> [`devices/d10/`](devices/README.md). Never unplug one to make a command
> convenient. [`devices/`](devices/README.md) is the per-body support matrix.
Doctrine explains *why* the system is shaped the way it is and is worth reading
before you *design* something. It is the wrong thing to open when the screen is
black. This page is for that.

85
devices/README.md Normal file
View file

@ -0,0 +1,85 @@
# Devices — what works, per body
One row per capability, one column per body. This page is the **matrix**; the
deep record for each subsystem stays where it already lives (`PAF/` for
blueline, `docs/tasks/63` for the d10) and is linked, never copied.
Status vocabulary, and it is strict:
| | meaning |
|---|---|
| **works** | exercised on the hardware, with evidence named |
| **partial** | comes up, does something, and a stated piece is missing |
| **built** | code and DT are in place, **never run on the glass** |
| **absent** | no driver, no node, or the silicon has no such thing |
| **—** | not applicable to this body |
A capability is never "works" because a device node appeared. On 2026-08-09 a
registered `input` node with unpowered rails read exactly like working touch for
several hours. **Verify with events, not with dmesg.**
## The bodies
| | [blueline](blueline/) | [d10](d10/) | [m1](m1/) |
|---|---|---|---|
| device | Pixel 3 | iPhone 7 (A1660) | MacBook (Apple Silicon) |
| SoC | SDM845 | Apple T8010 | M1 |
| role | Casey's daily driver | second body | not here yet |
| boot | pacman kernel + extlinux, no flash | checkm8 → m1n1, per boot, host-tethered | — |
| tether | `172.16.42.1` | `172.16.43.1` | — |
| status | daily use | bring-up | planned |
**Both phones are plugged in at once and that is the invariant.** Never unplug
one to make a command convenient.
## The matrix
| capability | blueline | d10 | owner |
|---|---|---|---|
| **storage** | works | works — NVMe over H9P/DART/ANS | `63` |
| **USB gadget** | works — NCM + ACM | works — NCM + ACM | `62` |
| **display out** | works — SW43408, DPU | works via simpledrm; **ADP binds and scans out to a dark panel** | `61`, `63` |
| **GPU / 3D** | works — Adreno 630, freedreno | absent — no render node, llvmpipe only | `63` |
| **backlight** | works | works — DWI *and* a DSI panel backlight | `63` |
| **gamma / LUT** | works — `GAMMA_LUT` 1024, `CTM` present | built — ADP path unexplored | `61` |
| **touch** | works | partial — binds, inits, **no runtime events** | `63` |
| **buttons** | works — power/volume through the state machine | built — 4 keycodes present, unwired | `63` |
| **haptics** | partial — `pmi8998_haptics` drives dial detents | absent — ADT names a node, nothing driven | `45` |
| **wifi** | works | absent — BCM4350 needs a driver, node kept out of DT | `63` |
| **bluetooth** | works | built — node inherited from `t8010-7.dtsi` | — |
| **modem / calls** | works — two-way audio | absent — MDM9645M behind Apple's own PCIe protocol | `49` |
| **SMS / MMS** | works — `netsvcs` APN | absent | — |
| **audio** | works — HiFi speaker, mic, STT | absent — MCA built, never wired | `07`, `39` |
| **camera** | partial — front IMX355 streams; rear IMX363 DT unbuilt | absent | `46` |
| **fingerprint** | partial — TA protocol recovered, no capture | — (no reader) | `44` |
| **battery / charging** | works — upower fork, charge ceiling | built — SN2400 + BQ27540 in DT and kernel | `33` |
| **proximity / light / accel** | works — one reporter, health-tracked | absent — CT821 built, no reporter | `08`, `47` |
| **session authority** | works | works — greetd, real seat0 session | `63` |
| **lock surface** | works | partial — keypad choice fixed, unverified | `02` |
| **suspend** | works — s2idle | built — never exercised | — |
## Where a body's own record lives
- **blueline**`PAF/` is canonical and per-subsystem: `audio.md`, `display.md`,
`modem.md`, `slpi.md`, `touch.md`, `platform.md`, `mms.md`, `edge-sense.md`.
`devices/blueline/` is a pointer, not a second copy.
- **d10**`docs/tasks/63-d10-second-body.md` carries the whole argument;
`hoolock/BOOT-d10.md` carries the boot chain and `hoolock/boot.sh` runs it.
- **m1** — nothing yet. `devices/m1/` states what is already known to transfer.
## The rule this hierarchy exists to enforce
**One common base that adapts, never `souveraine-upower-iphone` and `-pixel3`.**
Per-device packages carry DT and quirks; everything else is shared and learns to
ask. Every row above that differs between columns is either real hardware
difference or a place the base assumed one board — and the second kind is a
defect. Three were found the night the d10 came up:
- `blueline-screen-toggle` — panel blanking shells out to a script named for one
phone, so the d10 structurally cannot sleep.
- `brightnessctl set 10` — an absolute on a 255-step backlight and a 2047-step
one. 4% on one body, 0.5% and visibly black on the other. Fixed in
`souveraine eb0292c`.
- `hyprctl` — the shell still asks it for windows, monitors and layers. Dead
under viewtop on **both** bodies; blueline merely still has the binary lying
around, so it fails silently there and loudly here.

View file

@ -0,0 +1,58 @@
# blueline — Pixel 3 (SDM845)
Casey's daily driver. **A reprovision costs him his live system**, so reaching
for fastboot is a regression, not a fallback. Cold boots are his, at the device;
a warm reboot poisons TZ/remoteproc state.
**This page is a pointer, not a record.** The canonical per-subsystem spine is
[`../../PAF/`](../../PAF/) and it stays that way — one owner, one path.
| subsystem | record |
|---|---|
| audio, calls, mic | [`PAF/audio.md`](../../PAF/audio.md) — read it before touching a mixer |
| display, panel, DPU | [`PAF/display.md`](../../PAF/display.md) |
| modem, bearer | [`PAF/modem.md`](../../PAF/modem.md) |
| MMS | [`PAF/mms.md`](../../PAF/mms.md) |
| sensors, SLPI | [`PAF/slpi.md`](../../PAF/slpi.md) |
| touch | [`PAF/touch.md`](../../PAF/touch.md) |
| grip / squeeze | [`PAF/edge-sense.md`](../../PAF/edge-sense.md) |
| board, boot, kernel | [`PAF/platform.md`](../../PAF/platform.md) |
## Reaching it
```sh
ssh -i ~/.ssh/ani casey@172.16.42.1 # USB tether
ssh -i ~/.ssh/ani casey@10.10.20.234 # home wifi, via VPN
Pixel3Arch/tools/phone-triage.sh [host] # thirty-second triage
```
`10.10.20/24` is reachable **only** through WireGuard and it does not
autoconnect after a reboot. The phone does join foreign networks; pass the
address rather than hunting for a cable.
## Delivery
`pacman -Syu` from the Gitea repo, kernel included. **Do not flash.** The three
paths that reach this device are enumerated in
[`../../START-HERE.md`](../../START-HERE.md) §5, and picking the wrong one is
why things silently never update — `rootfs-overlay/` lands on a flash only, and
this phone does not flash.
## What the d10 proved about this body
Bring-up on a second board found three places the base assumed one phone. All
three are blueline-visible and two were invisible here:
- **`blueline-screen-toggle`** is the DPMS executor by name, and it ships only
in `rootfs-overlay/`. Panel power belongs in viewtop, which owns the CRTC and
runs on both.
- **`brightnessctl set 10`** is an absolute. 10/255 here is a dim panel; 10/2047
on the iPhone is black. Fixed in `souveraine eb0292c` as a percentage.
- **`hyprctl`** is still asked for windows, monitors, layers, animations and
workspaces. It is dead under viewtop on both bodies — blueline merely still
has the binary lying around, so the failure is silent here.
## Open, per the task index
Fingerprint piece 1 (`44`), rear IMX363 (`46`), haptics chip identification
(`45`), auto-brightness actuation (`47`), the colour path (`61`).

125
devices/d10/README.md Normal file
View file

@ -0,0 +1,125 @@
# d10 — iPhone 7 (A1660, iPhone9,1, T8010)
Second body. Bring-up, not daily use. The argument and the evidence live in
[`../../docs/tasks/63-d10-second-body.md`](../../docs/tasks/63-d10-second-body.md);
this page is the per-capability state and the commands.
**Reboot it freely** — Casey, 2026-08-09: *"I'm happy to reboot it… idgaf,
reboot it whenever."* Nothing is flashed and every boot re-runs checkm8.
## Boot
```sh
~/Projects/hoolock/boot.sh # all stages, newest staged kernel
~/Projects/hoolock/boot.sh -l # what is staged
~/Projects/hoolock/boot.sh -k touch # a specific variant
```
DFU is buttons and only buttons: power off, Vol-Down + Power 8s, release Power,
keep Vol-Down ~10s. The script waits for it. Stage 2 **always** ends in a
`SerialException` — the proxy drops when the kernel takes the machine, and
`kboot` refuses the jump if PCIe init failed, so reaching that disconnect is the
success signal.
Cmdline carries `initcall_blacklist=simpledrm_platform_driver_init`. Without it
simpledrm claims the panel first, udev names it the primary GPU, and viewtop
composites through the fenceless framebuffer while ADP holds the same hardware —
two writers, one panel. Disabling `framebuffer0` in the DT does **not** work;
m1n1's `kboot` fills and re-enables `/chosen/framebuffer` itself.
## What runs
| | |
|---|---|
| kernel | `Pauli1Go/HoolockLinux` + local commits; config `hoolock/config-d10-full-16k` |
| pages | **16K**. The 4K config builds and does not boot |
| display | simpledrm by default. ADP binds and scans out but the panel stays dark — see below |
| backlight | two: `20e200080.backlight` (DWI) and `206600000.dsi.0` (panel, over DCS) |
| storage | `nvme0n1p1` ext4; `nvme0n3` is SysCfg, 131072 bytes, read-only |
| link | NCM `usb0` `172.16.43.1/24`; no wifi, no modem, no battery node populated |
| session | greetd → `souveraine-session-viewtop` as `casey`, real `seat0`/tty1 |
## Per-capability
**works** — storage, USB gadget, both backlights, session authority, SSH,
display *through simpledrm*.
**partial**
- **the display pipe.** ADP binds, and everything measurable says it is
working: `[drm] Initialized adp 0.1.0 for 206200000.display-pipe on minor 1`,
connector `card0-DSI-1` **connected + enabled**, CRTC `active=1` with `fb=43`
and the plane at `750x1334+0+0`, viewtop's EGL up on that card. **The panel
is dark anyway.** Both backlights are raised, so it is content and not
brightness. Two candidates, neither tested:
- **the mode timings are invented.** m1n1 programmed Apple's real timings and
ADP re-modesets with porches I made up (`750 758 774 790 / 1334 1338 1346
1354`, 64179 kHz). Nothing in the ADT gave a raster, so they were guessed —
which is the one thing in this whole port that is not derived.
- **`panel-summit` sends no DCS display-on.** It has no `prepare`/`enable` at
all, by design: on a Touch Bar the loader leaves the panel running. It also
never sets `dsi->lanes` / `format` / `mode_flags`, and D10's ADT says
`#lanes = 2`. If `adp-mipi` reprograms the host from those defaults, the
link comes up wrong.
`boot.sh -a` is the ADP-only boot; without it simpledrm stays and the screen
works. **Do not make ADP the default until a pixel is seen.**
- **touch.** `apple_z2` binds on `spi0.0`, firmware loads, `firmware ready IRQ
received`, surface geometry reads back off the part (5850×10405, 13 units/mm),
*"report initialization complete"*, and the gen2 report-enable answers. Then
the IRQ never moves for a finger. It **did** work once — 2407 events, 270
`SYN_REPORT`, 13 balanced down/up, X 53..735, Y 107..1333 — on the first boot
after the rails were fixed, and has not since. Ruled out by test: the driver
changes (the original kernel is equally dead), and the rails (forced power
cycle at probe, no change; a rebind cleanly re-inits). The untested difference
is the display path — that first boot was the last one where simpledrm drove
the panel. Apple's touch controllers sync to display scan;
`t8010-ipad7.dtsi` gives its touchscreen `display-sync-gpios`, and D10's
`disp0` carries `function-lcd_enable`. **Next test is one boot:** the original
`touch` variant *without* the simpledrm blacklist, which restores the exact
conditions of the working run.
- **lock surface.** `touchKeypad` is answered from the environment now
(`SOUVERAINE_TOUCH_KEYPAD=1`, set in `/etc/environment` and the shell unit
drop-in), because `PersistentProperties` only carries the choice through a
reload and the d10 always starts cold. Unverified on glass.
**built, never run** — bluetooth (node inherited), charging (SN2400 + BQ27540 in
DT and kernel), ambient light (CT821 → `TSL2583`), audio (`SND_SOC_APPLE_MCA`),
suspend, buttons (`gpio-keys` reports `KEY_MUTE`/`VOLUMEDOWN`/`VOLUMEUP`/
`KEY_POWER`, and viewtop already classifies the last three — nothing routes them
on this body).
**absent** — GPU (no render node; llvmpipe, `GALLIUM_DRIVER` set in
`/etc/environment` and it must **never** be set on blueline), wifi (BCM4350
needs a driver; the node is deliberately kept out of the DT because declaring it
stalls PCI pwrctrl and takes the host bridge and NVMe down with it), modem,
camera, sensor reporters.
## Traps this body has already cost
1. **`/dev/mem` on live display registers wedged it into recovery, twice.** Do
not probe MMIO to identify a register window. A wrong `reg` in a DT node is
safe by comparison — the driver maps what it is told and fails to probe.
2. **Warm re-exploit is not a cold boot.** Rails, clocks and controller state
survive it. The one boot where touch worked was the one following a true
power-off.
3. **`config_16k` is the bare upstream reference** — no `PCIE_APPLE_H9P`, no
`APPLE_SIO`, no `TOUCHSCREEN_APPLE_Z2`. Building d10 from it produces a
kernel with no storage and no touch. Use `config-d10-full-16k`.
4. **Firmware must be `CONFIG_EXTRA_FIRMWARE`.** The disk-boot blob has no
initramfs, so `apple-sio`'s `request_firmware` loses the race to rootfs: 60 s
`-ETIMEDOUT`, then the SPI bus never probes and touch cannot exist.
5. **`pgrep -f` matches your own ssh command line.** It has killed a session and
produced two false "phone is down" readings in one night.
## Owed
- `casey` still has password `123456`, which is also the lock PIN.
- Buttons are unrouted.
- `sessiond eb0292c` (dim by percent) needs a CI build and `pacman -Syu` to
reach the device; until then the panel dims to black at `set 10` and the idle
policy is widened as a stopgap.
- The kernel work lives as a patch at
`../../PAF/evidence/d10-adp-touch-2026-08-09.patch` because `hoolock/` is not
a repository. It wants a real home.

48
devices/m1/README.md Normal file
View file

@ -0,0 +1,48 @@
# m1 — MacBook (Apple Silicon)
**Not here yet.** This page exists so the first session has somewhere to land
and does not start by inventing a structure. Nothing below is measured.
## What already transfers, and why that is more than it looks
The d10 bring-up put Apple-silicon knowledge in the tree that was not here
before, and the M1 is the platform most of it was written for:
- **m1n1** is Asahi's, and `hoolock/m1n1-pauli` is a fork of it. On the M1 it is
the supported loader rather than a checkm8 payload — so the boot chain gets
*simpler*, not harder, and `hoolock/boot.sh`'s stage split stops needing DFU.
- **ADP**`drivers/gpu/drm/adp/`, Sasha Finkelstein's pre-DCP display pipe —
is upstream *for* `apple,t8103-display-pipe` (M1) and `t8112` (M2). We drove
it on T8010 first, which is the harder direction; the M1 is its home turf.
It only covers the Touch Bar pipe there, though: the M1's main display is
**DCP**, a different and much larger driver.
- **`panel-summit`** is the Touch Bar panel, M1/M2, 134 lines and no init
sequence. It gained a 750×1334 mode for the d10 and keeps its own.
- **apple-dart, apple-mailbox, apple-rtkit, apple-sart, apple-pmgr-pwrstate,
apple-spi, apple-nvme, macsmc** are all in the tree and all bind on M1 —
several already bind on the d10.
- **16K pages** is the Apple norm; the d10 config already carries it and the
ALARM userland was measured 0x10000-aligned, so no distro rebuild was needed.
## What does not transfer
- checkm8. The M1 has no bootrom exploit and does not need one — it boots
untrusted kernels through Apple's own supported path.
- The T8010 PCIe/S3E bring-up sequence, which is board-specific and hard-gated.
- Every d10 board value: GPIOs, DART offsets, the C1F5D touch personality.
## The question to answer first
Souveraine's shape assumes a phone: one screen, one battery, no fallback device.
The M1 is the first body where that is false — external displays, a keyboard, a
trackpad, a lid. Doctrine §13 does not change (the agent owns operation, the
user owns being the user), but `DEVICE-STATE-MACHINE.md`'s state set was written
for a pocket, and `Observed` means something different on a laptop.
Decide that before writing a line of it, and write the decision in
`SESSION-AUTHORITY-DOCTRINE.md` where the rest of the argument lives.
Also unresolved and already named as debt: **SDDM-vs-greetd**. Doctrine §12's
watch list says two greeters is a seam that contradicts the intent, deferred and
not accepted. A third body is when that stops being deferrable — both phones are
on greetd with no greeter, and the laptop should be too.

View file

@ -108,14 +108,29 @@ The be/fe split is not guesswork: ADP binds only `be`/`fe` by name, pokes `be` t
134 lines with no init sequence because the loader lights the panel, which is
exactly our situation; it gained a 750×1334 mode under `apple,d10-panel`.
**Still on simpledrm, and the reason matters.** `status = "disabled"` on
`framebuffer0` in the DT does nothing — m1n1's `kboot` fills and re-enables
`/chosen/framebuffer` itself, so the loader wins. udev then names simpledrm the
primary GPU and `primary_device()` (`kms.rs:447`) hands viewtop `card0`. So the
shell composites through the fenceless framebuffer while ADP holds the same
panel — two drivers, one panel, which reads as tearing *and* lock-ups. The fix
is `initcall_blacklist=simpledrm_platform_driver_init` on the cmdline (now in
`boot.sh`), or `CONFIG_DRM_SIMPLEDRM=n`. **Untested as of this writing.**
**Getting simpledrm out of the way works. The panel is dark anyway.**
`status = "disabled"` on `framebuffer0` in the DT does nothing — m1n1's `kboot`
fills and re-enables `/chosen/framebuffer` itself, so the loader wins. udev then
names simpledrm the primary GPU and `primary_device()` (`kms.rs:447`) hands
viewtop `card0`. `initcall_blacklist=simpledrm_platform_driver_init` on the
cmdline does remove it, and then ADP *is* `card0`: viewtop opens it, EGL comes
up, the CRTC reports `active=1` with `fb=43` and the plane at `750x1334+0+0`,
the connector is `connected` and `enabled`. Both backlights raised. Still black.
So the compositor is producing frames and the panel is not showing them, and the
two candidates are both in the parts that were *guessed* rather than derived:
- **The mode timings are invented.** Every address in this port came off the ADT
or matched T8012. The raster did not — nothing published one, so
`panel-summit`'s d10 mode carries porches I made up. m1n1 already programmed
Apple's real ones; ADP then re-modesets over them.
- **`panel-summit` never sends a DCS display-on**, and never sets `dsi->lanes`,
`format` or `mode_flags`. That is deliberate for a Touch Bar, where the loader
leaves the panel running. D10's ADT says `#lanes = 2`; if `adp-mipi`
reprograms the host from unset defaults the link comes up wrong.
`boot.sh` therefore keeps simpledrm by default and takes `-a` for the ADP-only
boot. **The pipe is not the daily path until a pixel is seen on it.**
Kernel work is committed on archdev as `2e349ddf2` and exported to
`hoolock/d10-port/patch/`. That commit also captured the 141-line `t8010-d10.dts`