Xiaomi Redmi K40S (munch, 22021211RC)
Redmi K40S (munch) bring-up derived from UniXNU-alioth: SM8250-AC, GOP framebuffer, FocalTech SE4 touch, UFS root. Hardware results are inherited from alioth and not yet measured on a K40S.
Source record: porting.toml, 84b36d92355baf017d1a513c0432bb0f9ad36557.
This page is generated from the device record.
| Area | Status |
|---|---|
| Configuration | planned |
| Firmware and boot | planned |
| CPU and interrupts | implemented |
| Memory and DMA | planned |
| Storage and root | device-verified |
| Display | implemented |
| Input | implemented |
| GPU | implemented |
| Network | implemented |
| Audio | planned |
| Power | planned |
| Image assembly | planned |
| Diagnostics | device-verified |
Configuration
planned
Components: ArmDTPlatform, ArmCpu, SoftwareAES, XnuPrelink, DarwinBoot, AppleKeyStoreState.
Hardware and dependencies
- Identify the configuration hardware, resources and existing component interfaces for this board.
Configuration
- Record the board.toml fields, DTS properties and defconfig values used for configuration.
Procedure
- Follow the configuration stage in the porting guide and record the actual commands.
Development findings
- Collect the first configuration observation, its cause when established, and the resulting implementation decision.
Completion criteria
- All source pins resolve; every selected component has a record; status shows the intended overrides and patch order.
Current limits
- Hardware inputs and implementation are pending for this example board.
Next action
- Inventory the required configuration inputs before implementation.
Evidence
Collect evidence using the next action.
Firmware and boot
planned
Hardware and dependencies
- Identify the firmware and boot hardware, resources and existing component interfaces for this board.
Configuration
- Record the board.toml fields, DTS properties and defconfig values used for firmware and boot.
Procedure
- Follow the firmware and boot stage in the porting guide and record the actual commands.
Development findings
- Collect the first firmware and boot observation, its cause when established, and the resulting implementation decision.
Completion criteria
- Firmware image builds, enters UniXNU, publishes the framebuffer and preserves the documented memory reservations.
Current limits
- Hardware inputs and implementation are pending for this example board.
Next action
- Inventory the required firmware and boot inputs before implementation.
Evidence
Collect evidence using the next action.
CPU and interrupts
implemented
Hardware and dependencies
- kona: four Cortex-A55 (cpu0-3) and four Cortex-A77 (cpu4-7), MPIDR core number in Affinity1 so phys ids are 0x000-0x700. Interrupts and timers come from the ArmCpu component; secondary start is PSCI CPU_ON over smc.
Configuration
- board.toml: sheng-smp=1 starts secondary CPUs, armcpu-spi-ipi=1 routes IPIs through software-pended SPIs, armcpu-self-ipi=1 makes each core signal itself so XNU enables its IPI (a component argument, not one of the documented boot arguments), armcpu-diagnostics=1 reports the bring-up. dts: unixnu,cluster-type E on cpu0-3 and P on cpu4-7.
Procedure
- Apply both SoC patches (native-smp-secondary, native-smp-type-clusters) through the SoC repository's patch series, then build kernel, payload and boot image and boot over USB. Verify in the build tree that MAX_CPUS is 8 in the BCM2837 block, MAX_CPU_CLUSTERS is 2 and __ARM_AMP__ survives the later #undef.
Development findings
- Without native-smp-secondary.patch the reset vector masks MPIDR with 0xFF, which is Aff0 and is zero for every kona core, so every secondary core picked the boot CPU's cpu_data and reset handler. The boot either panicked with Invalid kernel stack pointer or hard-locked with interrupts off in early initialisation.
- unixnu,cluster-type must never ship without native-smp-type-clusters.patch. With MAX_CPU_CLUSTERS still 1 the topology parser takes phys_cluster_id = (cluster_type == P), which is 1, and writes cluster_phys_to_logical[1] past the end of a one-element stack array. Release builds do not assert: the kernel dies before the console comes up. scripts/check-smp-topology.py refuses that combination.
- Both patches are private to UniXNU-pipa, not present in UniXNU/UniXNU. They live in the SM8250 SoC repository because the topology they describe is a property of the SoC, which is why the pins differ from the SM8550 device's.
Completion criteria
- Every enabled CPU reaches its entry checkpoint and timer/IPI handling works on each enabled CPU.
Current limits
- Secondary CPUs have not been brought up on hardware yet. The two patches are applied only in the build feed checkout, not yet committed to FFT-infra/UniXNU-sm8250-common, so a fetch or tree refresh loses them.
- unixnu,cluster-type is still declared in the board DTS rather than the SoC DTSI.
Next action
- Boot the image carrying both patches and read SMP run count, armcpu_smp_step, psci_rc and the boot time.
Evidence
Memory and DMA
planned
Hardware and dependencies
- Identify the memory and dma hardware, resources and existing component interfaces for this board.
Configuration
- Record the board.toml fields, DTS properties and defconfig values used for memory and dma.
Procedure
- Follow the memory and dma stage in the porting guide and record the actual commands.
Development findings
- Collect the first memory and dma observation, its cause when established, and the resulting implementation decision.
Completion criteria
- All handoff regions are accounted for and each enabled DMA engine accesses its allocated range with the documented cache policy.
Current limits
- Hardware inputs and implementation are pending for this example board.
Next action
- Inventory the required memory and dma inputs before implementation.
Evidence
Collect evidence using the next action.
Storage and root
device-verified
Components: ShengUfs, VerifiedRoot, VirtioMmioBlock, RamBlock.
Hardware and dependencies
- UFS 3.1 host on SM8250, bound through ShengUfs, plus the two authenticated volume windows (OS and SystemOS) inside userdata.
- The Data seed is a raw APFS container: scripts/prepare-owner-data-fixture.py requires NXSB at 0x20, so the ADT reserves RAMDisk rather than PackedRAMDisk.
Configuration
- CONFIG_XNU_NATIVE_UFS=y, CONFIG_XNU_VERIFIED_ROOT_PROBE=y, CONFIG_XNU_OWNER_ROOT_AUDIT=y, CONFIG_XNU_OWNER_ROOT_TRUST=y.
- CONFIG_XNU_NATIVE_RAM_BLOCK=y and CONFIG_XNU_OWNER_DATA_MOUNT=y; the Data mount must go through the RamBlock IOKit device, not /dev/md0.
Procedure
- ./unixnu build payload --data-ramdisk <seed>, then bootimg, then fastboot flash boot_b.
- The panel reports UFS read progress and the RAMDisk capacity; the USB console carries exit records.
Development findings
- UFS reads run through ShengUfs and the panel reports verified blocks; the root is published only with an owner-signed policy, so CONFIG_XNU_VERIFIED_ROOT_PROBE must stay on or IOFindBSDRoot times out ten times and panics.
- The Data mount fails with ENOENT through /dev/md0 (measured 2026-10-26, panic screen offline scratch Data mount failed: 2); publishing the seed through RamBlock as a real IOMedia is the path that mounts.
- The Data volume is 32 MiB and holds the original private/var excluding staged_system_apps (39 files, 611715 bytes). Measured 2026-10-27: 20000 directories fit in 5.8 MiB, so capacity and inodes are not the limit for the services that fail.
- cryptexd aborts with mkdirat [28: No space left on device] while that volume reports 31 MiB free, so the ENOSPC names a different mount than /private/var.
Completion criteria
- The configured OS volume mounts and launchd starts; the Data volume mounts read-write as apfs and is accepted by native_owner_data_prepare.
- Persistence within the allocated Data region is not yet demonstrated across a reboot.
Current limits
- The write that fails with ENOSPC is not yet identified: the mkdir probe that prints its path is built but has not run on hardware.
- The Data seed cannot simply be enlarged: boot_a and boot_b are 192 MiB and the payload is a FAT volume, so a seed larger than that does not fit.
Next action
- Run the mkdir probe build and read the path it prints, then decide whether the failing write is on /private/var or elsewhere.
Evidence
device: The kernel reports cryptexd aborting with mkdirat ENOSPC while the Data volume reports 31 MiB free, which places the failing write on a mount other than /private/var. Command:read /dev/tty.usbmodem<N> at 115200 8N1 and collect EXITLOG records. Revision:24d127c47217eb580dbe3f3a94c32ad25cbaae00.
Display
implemented
Components: GopFramebuffer.
Hardware and dependencies
- The panel is 1080x2400 and the loader hands over a framebuffer at 0x9c000000 with 4320-byte rows and 32 bpp, so the display path starts from that memory rather than from a GPU.
- IOMobileFramebufferLegacy is prelinked and exports nothing, so the board archive binds each name to its original absolute address.
Configuration
- CONFIG_XNU_NATIVE_LEGACY_DISPLAY=y; offline-component-load-probes.patch calls both display entry points, so the archive must resolve them or the link fails.
- build-xnu-4k-baseline.sh force-loads libNativeLegacyDisplay.late.a and re-proves every address against this kernel on each run.
Procedure
- Boot the image and read the diagnostic page rows for DISPLAY stage, CLIENT and SWAP; the USB console carries the exit records.
- A photograph of the panel is the frame evidence until a swap is submitted.
Development findings
- Measured 2026-10-27 on boot-usb34: the lock screen is stable, SWAP calls=7 ok=7 rej=0, and backboardd creates its resources with kret=0. Earlier builds never submitted a frame at all.
- The panel is driven directly by the kernel's own renderer, which is why the boot-progress page and the colour bands are visible before any userspace renderer runs.
Completion criteria
- A known frame appears with correct geometry and colors, then userland presentation and backlight controls work.
Current limits
- No wallpaper: the lock screen draws its date and time over a black field, so composition reaches the text layer only. gpu offered=0 confirms the GPU stack takes no part.
Next action
- Get backboardd to start before investigating frame submission: with no render server there is no client that could call Swap.
Evidence
device: DISPLAY stage=10 with CLIENT calls=4 class=IOMobileFramebufferUserClient, and SWAP calls=0: a client connects but no frame is submitted. Command:read the diagnostic page and the USB console after booting the image. Revision:24d127c47217eb580dbe3f3a94c32ad25cbaae00.
Input
implemented
Components: QcomGeniSpi, ShengHidInput, ShengNovatekTouch.
Hardware and dependencies
- FocalTech FT5652 on GENI SE4 (QUPv3 wrapper 0), per munch-sm8250.dtsi: spi-max-frequency 6000000, interrupts <39 0x2008>, reset GPIO 33, irq GPIO 39, vdd L10C, vcc_i2c L1C, display-coords 0 0 8640 19200, max-touch-number 10.
Configuration
- board.toml: native-touch=1 starts kits/munch-touch, sheng-touch-hid=1 enables the publication path in ShengHidInput, native-touch-diag=1 is a measurement-only round and must be removed for release images. SPI clock is the device tree's 6 MHz; the source is TCXO 19.2 MHz on DFS level 0.
Procedure
- Build with component ShengHidInput selected and the board display recipe, which invokes build-sheng-hid-input.py and archives NativeHidInput.late.o plus hid-original-bindings.o into the force-loaded libNativeLegacyDisplay.late.a. Then build payload and boot image, verify the payload carries the built kernel, and boot over USB.
Development findings
- The part answers register reads (ID 0x5652) and returns a CRC-correct all-0xFF buffer while it has no report; an earlier version of FocalTouchProtocol.c treated that buffer as a successful empty frame, which is why every image reported frames=valid with contacts=0.
- Frame reads gated on GPIO 39 going low produced real contacts: at t=100 s two contacts, low count 284, raw 0002805f4598; the part's interrupt counter 0x8F rose from 01 to e0 and its work counter 0x91 advances 60 per second, so the sensor, the SPI link, the CRC and the interrupt line are all working.
- The HID publisher was never in the kernel: ShengHidInput compiles NativeHidInput.cpp but nothing archived it, and an object with no inbound reference is dropped from a plain archive. Selected as a component and archived by the display recipe, as UniXNU-sheng does, it links.
Completion criteria
- Touches map to the display, simultaneous contacts keep stable IDs, release events arrive, and buttons produce expected HID reports.
Current limits
- No HID report has reached the OS yet: native_touch_hid_reports stays 0 while contacts arrive, so the remaining work is the publication path, not the sensor.
- Buttons are not implemented on this board.
Next action
- Boot the image that carries the archived HID objects and confirm native_touch_hid_reports rises and the UI responds to a swipe.
Evidence
GPU
implemented
Components: Adreno650.
Hardware and dependencies
- Adreno 650 on SM8250-AC; chip id 0x06050002; blocks GPU 0x3d00000, GMU 0x3d6a000, GPUCC 0x3d90000, SMMU 0x3da0000.
- Firmware already embedded in package/GpuFirmwareA650.c: gmu 41548 B, sqe 31632 B, zap.mdt 6860 B + zap.b02 1676 B, concatenated for the probe's single zap image.
- The pipa fork's A650 driver (reference/repo/Adreno650) is the same generation as this board; the upstream Adreno740 is not.
Configuration
- board.toml passes pipa-gpu=<mode>; CONFIG_XNU_NATIVE_ADRENO=y links the archive, which must be produced at build/adreno740/libAdreno740.a because build-xnu-4k-baseline.sh hard-codes that name and ignores CONFIG_XNU_NATIVE_ADRENO_ARCHIVE.
- CONFIG_XNU_NATIVE_ADRENO_ARCHIVE uses the {tree} token so the path is absolute and satisfies both the checkout-rooted check in scripts/unixnu/kernel.py and the tree-rooted check in the shell script.
- Mode 12 (the Metal accelerator) is compiled out with PIPA_GPU_ACCELERATOR=0: the accelerator is an IOAccelerator subclass and this kernel has no IOAccelerator class (IOAcceleratorFamily2 is absent).
Procedure
- Build with --local-module driver:Adreno650=<checkout>, ADRENO650_DRIVER, ADRENO650_KITS and ADRENO650_PACKAGE set; the kits and the driver are not in the generated tree because Adreno650 is not in UniXNU's catalogue.
- Boot with pipa-gpu=<n> and read the GPUROW lines on the console; native_gpu_rows is not rendered by this board's page.
Development findings
- Mode 1 (read only) runs: GPU m1 gcc=ok cc=ok smmu=skip gpu=skip io=0.
- Mode 6 powers the GPU: GPU m6 gcc=ok cc=ok smmu=ok io=0 cx1 clocks1 — the CX domain comes out of collapse and the SMMU/GMU clocks run.
- Mode 7 stops at the GMU context's Attach step: status e00002ca, routes 0, programme phase 5 with 13 writes issued and no global fault.
- Two writes to the SMMU, each with a value different from the one present, are accepted and do not take effect: SMR slot 5 0x8000007f reads back 0, sCR0 0x0026040e reads back 0x00260406. Reads through the same mapping are correct (IDR0 0x4c017e06) and GPUCC writes through an identically constructed window do take effect. The readable, silently unwritable register file is what a resource owned above EL1 looks like.
Completion criteria
- GPU submissions complete, mapping/fence handling is correct, a known image renders, and the selected Metal client presents it.
Current limits
- The GMU context cannot be built because this SMMU accepts no writes from EL1; every later step depends on it.
- Metal is unreachable for the same reason plus the missing IOAccelerator class, so the wallpaper overlay and poster rendering stay on the CPU path.
Next action
- Decide the route past the SMMU's EL1 write refusal: an EL2-side channel, a presentation path that needs no SMMU programming, or accepting CPU presentation on this board.
Evidence
device: Mode 1 reads and mode 6 powers the CX domain with the SMMU and GMU clocks running: gcc=ok cc=ok smmu=ok cx1 clocks1. Command:sh scripts/run-sheng-unattended.sh <boot.img> 180, then read GPUROW lines from the console capture of that run. Revision:002ccaa75267bcc70ea1ba97dfefea14c6f7211d.device: Writes to SMR slot 5 (0x8000007f) and sCR0 (0x0026040e) both read back the pre-existing value while IDR0 reads 0x4c017e06 through the same window. Command:boot a pipa-gpu=7 image and read the GPUROW14 line from the console capture. Revision:e240b0e810988bf1012b2aa37bd3ae4fd6d84e67.
Network
implemented
Hardware and dependencies
- QCA6390 at 17cb:1101 behind qcom,pcie@1c00000; parf 0x01c00000+0x3000, phy 0x01c06000+0x1000, dm_core 0x60000000+0xf1d, ELBI 0x60000f20+0xa8, IATU 0x60001000+0x1000, conf 0x60100000+0x100000.
- package/munch_pcie.c is the 723-line bring-up measured on this phone in the ios-sweet series.
Configuration
- board.toml passes pcie=<steps>; pcie_skip=<mask> skips a step, and pcie_skip=32 skips the PHY sequence.
- The file was wrapped in #if defined(ARM64_BOARD_CONFIG_SWEET) and compiled to an empty object under this board; the guard now accepts BCM2837 as well.
- The kernel's C record carries -Werror and the driver leaves struct fields implicit, so the recipe passes -Wno-missing-field-initializers; sweet_log_flush is shimmed because that log belongs to the ios-sweet tree.
- printf does not reach this board's console, so the driver's line() tees to qcom_usb_debug_write and the rows appear as PCIE <step>: <text>.
Procedure
- Build with the archive entry and call munch_pcie_init() from the late display probe; a run is pcie=<n> on the kernel command line.
Development findings
- Step 1 reads gcc pcie_0_gdscr = 0x22f001: PWR_ON clear, SW_COLLAPSE set, the controller fully off — the same value the ios-sweet series recorded.
- Step 2 powers it: writing 0x22f000 reads back 0xf822f000 within a millisecond.
- Step 3 finds the halt registers already zero; step 2's power-up cleared them.
- Step 4 reports phy_status 0x68 with bit 6 set before any PHY write, so the bootloader left the PHY initialised and the sequence can be skipped.
- Step 9 with pcie_skip=32 reaches the PARF: parf_mhi_clock_reset_ctrl 0x3 written to 0x13, parf_axi_mstr_wr_addr_halt_v2 unchanged at 0x80000014, both matching the reference.
Completion criteria
- Scanning, association, address configuration and sustained receive/transmit traffic pass with the selected firmware.
Current limits
- Step 10 (DBI, configuration space, link training) has never run here or in the reference: it needs the pipe clock the skipped PHY step would produce, and accessing DBI without it is expected to hang the bus.
- No link has ever trained (parf_ltssm 0) and no endpoint has been enumerated; MHI, QMI and ath11k do not exist in this tree, and the local reference Ath12kWifi is ath12k, a different driver for a different part.
Next action
- Establish the pipe clock without the PHY sequence that hangs this phone, then run step 10 and read the configuration space for 17cb:1101.
Evidence
device: gcc pcie_0_gdscr reads 0x22f001, the value the ios-sweet series recorded for a fully collapsed controller. Command:boot a pcie=1 image and read the PCIE 1 lines from the console capture. Revision:dc3ab04aa4b05d38a1c372fa2ec257b3ae8547ce.device: Writing 0x22f000 reads back 0xf822f000 within a millisecond: the controller has power. Command:boot a pcie=2 image and read the PCIE 2 lines from the console capture. Revision:28be364f4dc9223a006770635dbc0f352d230401.device: With pcie_skip=32 the PARF setup completes and parf_mhi_clock_reset_ctrl 0x3 becomes 0x13, matching the reference. Command:boot a pcie=9 pcie_skip=32 image and read the PCIE 9 lines from the console capture. Revision:eeda5a8139786ca8029044708679c40e7382eb1e.
Audio
planned
Hardware and dependencies
- Identify the audio hardware, resources and existing component interfaces for this board.
Configuration
- Record the board.toml fields, DTS properties and defconfig values used for audio.
Procedure
- Follow the audio stage in the porting guide and record the actual commands.
Development findings
- Collect the first audio observation, its cause when established, and the resulting implementation decision.
Completion criteria
- Each declared route carries the selected audio format through playback or capture and handles start/stop correctly.
Current limits
- Hardware inputs and implementation are pending for this example board.
Next action
- Inventory the required audio inputs before implementation.
Evidence
Collect evidence using the next action.
Power
planned
Hardware and dependencies
- Identify the power hardware, resources and existing component interfaces for this board.
Configuration
- Record the board.toml fields, DTS properties and defconfig values used for power.
Procedure
- Follow the power stage in the porting guide and record the actual commands.
Development findings
- Collect the first power observation, its cause when established, and the resulting implementation decision.
Completion criteria
- Declared power controls and battery readings match observations; each claimed sleep/resume transition restores its dependent peripherals.
Current limits
- Hardware inputs and implementation are pending for this example board.
Next action
- Inventory the required power inputs before implementation.
Evidence
Collect evidence using the next action.
Image assembly
planned
Hardware and dependencies
- Identify the image assembly hardware, resources and existing component interfaces for this board.
Configuration
- Record the board.toml fields, DTS properties and defconfig values used for image assembly.
Procedure
- Follow the image assembly stage in the porting guide and record the actual commands.
Development findings
- Collect the first image assembly observation, its cause when established, and the resulting implementation decision.
Completion criteria
- Kernel and prelink succeed, payload contains all declared inputs, and the boot image matches the bootloader format and size limit.
Current limits
- Hardware inputs and implementation are pending for this example board.
Next action
- Inventory the required image assembly inputs before implementation.
Evidence
Collect evidence using the next action.
Diagnostics
device-verified
Components: QcomXnuUsbDebug.
Hardware and dependencies
- The board's DWC3 controller, its apps SMMU stream, and the boot arguments qcom-usb-debug=1 and qcom-usb-ctl=1 in board.toml.
- The diagnostic page is boot-progress=2 with boot-diag-resume=10, so it returns after scanout stops.
Configuration
- board.toml selects the QcomXnuUsbDebug component and passes qcom-usb-debug=1 and qcom-usb-ctl=1.
- configs/munch_defconfig sets CONFIG_XNU_BOOT_PROGRESS=y and CONFIG_XNU_QCOM_USB_DEBUG=y.
- The apps SMMU is iommu@15000000 with qcom,skip-init; the USB node's iommus = <0x47 0x00 0x00> gives SID 0.
Procedure
- ./unixnu build kernel, then build payload and bootimg, then fastboot flash boot_b.
- Read the console at /dev/tty.usbmodem<N> with a raw 115200 8N1 tty; the dock's SN234567892 node is not the phone.
- Control frames are SXNU1 <16 hex session> <8 hex seq> <VERB> <8 hex crc32>, HELLO first to learn the session.
- One unattended round is scripts/run-sheng-unattended.sh <image> [timeout]: fastboot boot the image, wait for the board's own return, boot the reader from slot a, read and decode into build/sheng-logs/<tag>-<boot id>/, then restore the slot. Fail-closed, and the timeout must exceed sheng-autoreset by 60 s.
Development findings
- The CDC-ACM console refused to start with error=10 core=0 domain=5. QcomUsbDomainInstall calls halted() before scan(), so a PRTCAPDIR of 3 would have returned CoreRunning=4; it returned 5, which proves the controller already reported device mode.
- Firmware leaves an SMR entry for SID 0 pointing at context bank 5 with SCTLR=0xe0 (M=0) and TTBR0=0: the stream is programmed but no table exists under it. scan() now reclaims that slot only when translation is off and there is no table, and still refuses a bank that holds a live mapping.
- With that, the console enumerates as 1209:316d named QcomXnuUsbDebug and the kernel log is readable on the host. It is the only channel that keeps a record after the panel has moved on.
- printf and kprintf both fail to reach the console: a DEVELOPMENT kernel leaves disable_kprintf_output true without -enable_kprintf_spam, and printf's console path did not reach the _cnputs tee either. qcom_usb_debug_write() is the entry point that works.
- Exit records measured over 420 s: 180 xpcproxy exits with status=0 (normal fork and exit), 13 cryptexd SIGABRT with ns=18 code=2 (OS_REASON_LIBSYSTEM_CODE_FAULT), 11 liveactivitiesd SIGTRAP, 2 lsd SIGSEGV. Each process crashes at one fixed PC repeated, so the fault is deterministic rather than a race.
- A software REBOOT via the control channel is acknowledged (state=queued) but does not reach fastboot: the worker calls reboot_kernel(0, NULL), an orderly restart that unmounts every filesystem and returns through UEFI. Entering fastboot needs the ABL IMEM handshake, whose address is not measured here.
- The persistent log writer runs: boot-usb101 recorded 273 rounds over 546 s with zero write errors after the console had already stopped, so the medium is the only record past the link's death.
- Returning to fastboot works with sheng-log=1 and sheng-autoreset=<seconds> together: boot-usb102 rebooted at 153 s and boot-usb103 at 120 s, both landing in the board's own bootloader with the PON spare cell written ('pon: subtype 04 shift 1 spare 00 -> 04 want 04 rc=0 ok pon_rc=0') and IMEM reading the reason back (known=1). PSCI alone cannot do it: SYSTEM_RESET, SYSTEM_RESET2(32) and SYSTEM_RESET2(64) all report NOT_SUPPORTED, so PS_HOLD is the path that works.
- The reader must seek relative to the partition: /dev/block/by-name/userdata starts at LBA 0x2a8000, so the window's last 8192 blocks are skip=59086843, not the absolute LBA 61872123 the header records. Passing the absolute value reads nothing at all and looks like a hung read.
- The console's death is a latch, not a transient: dwc3_poll() returns -1 forever once d->failed is set (Dwc3.c:570/581/584), and nothing in the driver clears it, so the worker's retry path cannot revive the link.
Completion criteria
- The console enumerates and answers HELLO and STATUS on the board; STATUS reports usb=3 er=0.
- Every process exit and crash reaches the host console, which is what the exit-loop investigation needs.
Current limits
- cryptexd's fault is not yet attributed: OWNER_CRYPTEX_FILES is 0 by design because UNION_SYSTEMOS requires it off, so cryptexd's expected paths do not exist. Its crash PC is captured but not symbolicated.
- The MAC exec refusal is intermittent. One boot showed backboardd, imagent, lockdownd, cfprefsd, sharingd and nfcd exiting with status=9 ns=9 code=8; the next showed none of them, so the errno the patch now reports has not been observed yet.
- Symbolication of the crash PCs against the extracted dyld shared cache was attempted and produced implausible image names, so it is not reported as a result.
Next action
- Make the console survive its first error: clear d->failed and re-initialise the controller from the worker, with backoff, and draw the worker's retry and error counters on the diagnostic page so the failure is readable without the link it is about.
- Attribute cryptexd's fault, then decide whether the fix is a stub, a mount change, or accepting the crash.
- Wait for the MAC refusal to reproduce and read the ip_mac_return value it now prints.
Evidence
device: Console enumerated as 1209:316d named QcomXnuUsbDebug; STATUS returned usb=3 er=0 with the worker polling, so the port is live in both directions. Command:read /dev/tty.usbmodem<N> at 115200 8N1 and send SXNU1 ... HELLO / STATUS. Revision:15a15d7cc526262a64531ff56b3a33bdbc46379c.device: 215 exit records captured. 180 xpcproxy status=0 (normal), 13 cryptexd ns=18 code=2, 11 liveactivitiesd sig5, 2 lsd sig11; each process repeats one fixed crash PC, so the faults are deterministic. Command:./unixnu build kernel; ./unixnu bootimg; fastboot flash boot_b; read the CDC-ACM console for 420 s. Revision:15a15d7cc526262a64531ff56b3a33bdbc46379c.