Documentation
On this page

Concepts

Boot-args record

Changing the next boot's arguments from iOS, without reflashing boot.

The boot arguments normally live in the payload inside boot. LK write-protects boot while iOS runs, so iOS cannot change them there. The record is a place outside boot that iOS can write and the shim can read before XNU starts.

Where it is

The first 4 KB block of the last MiB of the root partition (block nblocks - 256, 4 KB blocks), outside the HFS+ volume. The kernel checks the volume’s header before every write and refuses (ENOSPC) when the volume reaches the record’s block.

Layout

672 bytes, little endian (shim/bootrec.h, the same struct in the kernel’s mtk_ufs.c):

OffsetSizeField
08magic VIVABOOT
8u32version, 1
12u32flags, bit 0 = enabled
16u64base_hash: FNV-1a 64 of the payload command line the record was written against
24u64seq, up by one on every write
32u64line_hash: FNV-1a 64 of cmdline
4024reserved
64608cmdline, NUL terminated, printable ASCII (0x20-0x7e), at most 607 characters

When the shim uses it

mapple_bootfile in shim/bootrec.c, before the kernel is copied anywhere:

  • It is off when the payload’s line has mp_bootrec=0. That is how a safe boot ignores it.
  • It looks for the root partition by name in the GPT of the UFS LUN: mp_ufslun (default 2) and mp_ufsroot. On spaced the record is read only when the payload names mp_ufsroot=: userdata is Android’s there.
  • It needs the host as LK leaves it (enabled, link up, device present, request list ready, nothing outstanding). It points the transfer list at its own memory, issues polled READ(10) commands, and gives LK’s list back. There is no write in the file.
  • The record applies only if the magic and version match, the enabled bit is set, line_hash matches the line, and base_hash matches the hash of the payload’s current line. Reflashing boot with another line drops the record by itself.
  • Anything else (no partition, timeout, no record, a record for another payload) gives the payload’s line, as if the record did not exist, and the console says why.

Writing it

From iOS, as root:

  • kern.mapple_nextbootargs reads the next boot’s line (the record’s when it applies, else the payload’s) and, written by root, stores a new one in the record. An empty string, or the payload’s own line, disables the record. The payload is never written. Writes need mp_ufsrw=1 (EROFS otherwise); the block is flushed, read back and compared.
  • kern.mapple_nextbootargs_src says bootrec or payload; kern.mapple_nextbootargs_orig is the payload’s line as first seen.
  • kern.mapple_bootrec is the raw 4 KB block: anyone may read it, root writes it with only the volume check.
  • mapple-link.py bootrec [hex|show] on the Mac edits it over the USB link.

Source: shim/bootrec.h, shim/bootrec.c of mapple_loader at 2aa5786; bsd/dev/mtk_ufs.c and bsd/dev/mapple_sysctl.c of the kernel at 76b737c; tools/mapple-link.py of mapple_build at f7431bb.

Applies to Release 1, MediaTek · Updated 15 November 2026