Userdata image
The userdata image supplies the root file system to XNU. It holds the unchanged OS and Cryptex1,SystemOS disk images from the target IPSW behind a manifest that the kernel reads.
Build
./unixnu build userdata --ipsw /path/to/restore.ipswThe step extracts the IPSW components named in [userdata] windows, reads each disk image with hdiutil, and writes a raw image to out/<board>/userdata/userdata-root.img.
The report userdata-root.json records the window offsets, sizes and hashes, the partition capacity and the flash command.
A dry run checks the IPSW and the partition size without writing the image:
./unixnu build userdata --dry-runPartition
board.toml describes the GPT entry:
[userdata]
first_lba = 0x2f3840
last_lba = 0x3d0abfa
lba_bytes = 4096
windows = [
{ name = "OS", component = "OS" },
{ name = "SystemOS", component = "Cryptex1,SystemOS" },
]first_lba and last_lba come from the GPT entry named userdata on the device. lba_bytes is the logical block size of the partition.
The image size is the sum of the windows, each aligned to 1 MiB, plus the 1 MiB header region. The step rejects an image larger than the partition.
Layout
0x000000 SHNGROOT manifest, 4096 bytes, zero padded to 1 MiB
0x100000 OS window, whole disk image
.... SystemOS window, whole disk imageThe manifest is little endian:
| Offset | Field |
|---|---|
| 0 | SHNGROOT |
| 8 | version, 32-bit, value 1 |
| 12 | window count, 32-bit |
| 16 | image size, 64-bit |
| 24 | window entries, 128 bytes each |
| 4064 | SHA-256 of bytes 0 to 4063 |
Each window entry contains a 32-byte name, a 64-bit offset, a 64-bit size, a 32-bit block size, a 32-bit flags field, a 32-byte SHA-256 and 40 reserved bytes.
Flash
fastboot flash userdata out/<board>/userdata/userdata-root.imgThe driver prints the command in the report. The device repository can provide a wrapper script that checks the image and partition before flashing.
Root selection
The kernel mounts the root volume by UUID:
[payload.adt]
root_match_volume_uuid = "00000000-0000-0000-0000-000000000000"The ADT generator writes a /chosen/root-matching dictionary with IOProviderClass = IOMedia and the UUID. The native block driver publishes the userdata partition, the partition scheme publishes the volumes, and XNU selects the IOMedia with the matching UUID.
Data volume
The writable Data volume comes from the Data ramdisk seed in the payload. The seed is an input to the payload step:
./unixnu build payload --data-ramdisk data.img--skip-setup marks Setup as done in a copy of the seed. The payload report records the seed hash and the resulting image hash. See Skip Setup for the preference changes.
Next steps
- Userdata layout explains the manifest and the disk windows.
- Boot the image covers the first boot.
- Device configuration lists every
[userdata]key.