Skip to content

spi: apple-qspi: admit verified NVRAM writes on the J700 (asahi-bless works) - #626

Closed
RyanTheTide wants to merge 2 commits into
aurora-wipfrom
qspi/j700-nvram-write
Closed

RyanTheTide wants to merge 2 commits into
aurora-wipfrom
qspi/j700-nvram-write

Conversation

@RyanTheTide

Copy link
Copy Markdown
Contributor

asahi-bless could not select a one-time boot volume on the MacBook Neo (J700). Two things stopped it.

  1. The J700 nvram partition starts at 0x24000. Without CONFIG_MTD_SPI_NOR_USE_4K_SECTORS the W25Q16 reports 64 KiB erase blocks, so MTD forced the partition read-only ("doesn't start on an erase/write block boundary").
  2. The T8140 controller path admitted programs and erases inside nvram with no runtime opt-in and no readback. The J613 and J713 already use the stricter read-only, opt-in, verified policy.

Changes

  • spi: apple-qspi: admit verified NVRAM writes on the J700. The J700 now uses the same policy as the J613 and J713:

    • It starts read-only, and root opts in at runtime through read_only.
    • Writes need the J700 board and the controller at 0x385110000.
    • Programs are single-wire, three-byte and stay within one 256-byte page. Erases are aligned 4 KiB sectors.
    • Every mutation has JEDEC and status checks, readback verification, and a fault latch.

    The partition bounds come from the DT (0x24000, size 0x1d0000), so the range checks take them as parameters. iBoot leaves BP0 set on the J700, which protects the top 64 KiB. The driver tolerates those bits as found, never changes them, and lets readback latch read-only if a write lands there. T8140 data reads keep their multi-line pass-through. The KUnit suite and the host harness cover the shared policy at the J700 bounds, the board gate and the BP tolerance.

  • arm64: configs: asahi: use 4 KiB SPI NOR erase sectors. No DT or per-flash setting chooses the erase size, so this config option is the only switch. It is also the upstream default, which the Fedora base turns off. The policy already admits only 4 KiB erases.

Tested on the Neo

The test kernel was 7.3.0-aurora-fleet10nv: fleet10 46b7a93f plus these two commits, booted one-shot with fleet10 as the default.

  • /proc/mtd: nvram erasesize 0x1000, MTD flags 0xc00 (writeable). flash_status reads jedec=ef6515 sr1=04 sr2=02 sr3=20.
  • Dry run on a copy (asahi-bless -d copy --next --set-boot 1 -y): 162 bytes changed, no 0->1 bits.
  • Real write with read_only=N, then back to Y: next=Macintosh HD, persistent=Aurora. The flash read back byte-identical to the dry run. No NVRAM fault and no denied requests in dmesg. p3 count 0, no WARN.
  • After a reboot, macOS 26.6.2 (25G83) booted once and was reachable over ssh. sudo shutdown -r now from macOS came back to Linux fleet10 on its own after 44 s, and asahi-bless reported next=Aurora.
  • Host harness tools/asahi/qspi-nvram-tests.py: all PASS, including the new j700-board, range and bp-ok changed-guard controls. The driver and KUnit objects build with W=1 and no warnings.

Not run: the KUnit suite on hardware (it is built as a module).

Assisted-by: LLM

🤖 Generated with Claude Code

RyanTheTide and others added 2 commits October 30, 2026 18:07
asahi-bless cannot select a one-time boot volume on the MacBook Neo
(J700). The T8140 path admitted programs and erases inside the nvram
partition with no runtime opt-in and no readback, while the J613 and
J713 go through the read-only, opt-in, verified policy. Writes still
never reached the flash, because the partition was read-only in MTD.

Put the J700 on the same policy. The controller starts read-only and
root opts in at runtime through the read_only parameter. A write
needs the J700 board and the controller at 0x385110000. Programs are
single-wire, three-byte, within one 256-byte page; erases are aligned
4 KiB sectors; both must lie inside the nvram partition. Every
mutation checks the JEDEC ID and status first, is verified by
readback, and a fault latches the driver read-only.

The J613/J713 partition is pinned at 0x700000. The J700's comes from
its device tree (0x24000, size 0x1d0000), so the range check now takes
the partition bounds, and a DT window must fit in three-byte
addressing. The J700 flash is a W25Q16JV (JEDEC ef6515). iBoot leaves
BP0 set, which protects the top 64 KiB, so the J700 tolerates the
block-protect bits as found: the driver never changes them, the flash
ignores writes in that range, and readback then latches read-only.
CMP, suspend, WPS, BUSY and WEL are still refused.

T8140 data reads keep their multi-line pass-through. KUnit and the
host harness now cover the shared policy at the J700 bounds, the J700
board gate and the block-protect tolerance.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The J700 nvram partition starts at 0x24000 on its boot NOR. SPI-NOR
picks the largest uniform erase size unless MTD_SPI_NOR_USE_4K_SECTORS
is set, so the flash reports 64 KiB erase blocks and MTD forces the
partition read-only because it does not start on an erase boundary.
asahi-bless then cannot set a boot volume.

There is no device tree or per-flash way to choose the erase size;
this option is the only switch, and it is the upstream default. The
Fedora base config turns it off. Set it again. The Apple NVRAM
partitions are managed in 4 KiB units, and the QSPI NVRAM policy on
the J613, J713 and J700 only admits 4 KiB erases anyway. Other SPI NOR
users only see smaller erase blocks.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RyanTheTide

Copy link
Copy Markdown
Contributor Author

Superseded by #673, which carries the same change with the house trailers and is merged into aurora-wip after the fleet12 hardware run.

🤖 Generated with Claude Code

@RyanTheTide
RyanTheTide deleted the qspi/j700-nvram-write branch October 31, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant