4.8 KiB
userdata 镜像
userdata 镜像为 XNU 提供根文件系统。它保存目标 IPSW 中未修改的 OS 和 Cryptex1,SystemOS 磁盘镜像,并在前面加一个 manifest。
准备选定的 IPSW 及设备 GPT 数据。Linux 上安装提供 lzfse 的 Linux 工具链。扩大 Data 种子(第 4 步)需要 macOS 的 hdiutil 和 diskutil。AEA 加密的镜像(如 iPadOS 26)需要 macOS 的 aea 和 ipsw 工具。先在构建流程中选定设备并保存本地输入。
1. 核对分区
board.toml 描述 GPT 条目:
[userdata]
first_lba = 0x2f3840
last_lba = 0x3d0abfa
lba_bytes = 4096
first_lba 和 last_lba 来自设备上名为 userdata 的 GPT 条目,lba_bytes 是分区逻辑块大小。
OS 配置列出磁盘镜像:
[userdata]
windows = [
{ name = "OS", component = "OS" },
{ name = "SystemOS", component = "Cryptex1,SystemOS", optional = true },
]
IPSW 没有某个 optional = true 的窗口时跳过它。
镜像大小为各窗口按 1 MiB 对齐后的总和,加上 1 MiB 头部区域。步骤拒绝超过分区容量的镜像。
2. 预检并构建镜像
./unixnu build userdata --ipsw /path/to/restore.ipsw --dry-run
./unixnu build userdata --ipsw /path/to/restore.ipsw
步骤按 [userdata] windows 提取 IPSW 组件,在 macOS 上解密 AEA 镜像,在 macOS 上用 hdiutil、在 Linux 上用 scripts/unixnu/udif.py 读取每个磁盘镜像,写出原始镜像到 out/<device>/<os_profile>/<config>/userdata/userdata-root.img。
报告 userdata-root.json 记录窗口偏移、大小、哈希、分区容量和刷写命令。
先检查 dry-run 的分区容量和窗口布局,确认输入正确后再运行第二条命令。完成后应得到镜像及报告。
3. 设置根卷 UUID
内核按 UUID 挂载根卷:
[payload.adt]
root_match_volume_uuid = "REQUIRED_ROOT_VOLUME_UUID"
从所选 OS 镜像取得 APFS 根卷 UUID。在 macOS 连接镜像后用 diskutil apfs list 检查,确认根卷所属镜像容器并复制其 Volume UUID。修改后重建 payload 和启动镜像。
ADT 生成器写入 /chosen/root-matching,包含 IOProviderClass = IOMedia 和该 UUID。原生块驱动发布 userdata 分区,分区方案发布卷,XNU 选择 UUID 匹配的 IOMedia。
4. 准备 Data 卷
可写 Data 卷来自负载中的 Data ramdisk 种子:
./unixnu build payload --data-ramdisk data.img
sheng 的持久存储布局可使用 macOS 工具调整 seed 大小:
python3 scripts/seed-data-grow.py --gib 8 /path/to/data.dbr /path/to/data-grow.dbr
按目标 Data 分配范围选择大小,预留根卷窗口、存储元数据和日志区域。
工具通过 hdiutil 连接原始镜像,使用 diskutil 调整 APFS,生成新的 packed seed。
接受范围为 3 至 1024 GiB。
--auto 还读取脚本树中的 build/userdata-root/userdata-root.json(或 .img),
并通过 fastboot 查询 userdata 容量。使用前在该位置提供同一目标的报告。
--userdata-bytes BYTES 替代容量查询,--reserve-mib 指定日志保留区,默认 1024 MiB。
卷 UUID 保留,seed 大小变化会改变持久化身份并初始化新的 Data store。 随镜像记录所选大小和根卷报告。其他设备先适配并验证 UFS 指南中的存储分配。
--skip-setup 在种子副本中把 Setup 标记为完成。负载报告记录种子哈希和结果镜像哈希。偏好改动见跳过 Setup。
5. 刷写并启动
刷写 userdata 会覆盖该分区。执行前确认目标设备、分区布局和报告中的镜像路径,并保存需要保留的分区数据。
fastboot devices
fastboot flash userdata out/<device>/<os_profile>/<config>/userdata/userdata-root.img
刷写成功后,按启动镜像启动匹配的 boot image,记录根卷挂载结果。
驱动把命令写入报告。设备仓库可以提供封装脚本,在刷写前检查镜像和分区。
布局
0x000000 SHNGROOT manifest,4096 字节,零填充到 1 MiB
0x100000 OS 窗口,完整磁盘镜像
.... SystemOS 窗口,完整磁盘镜像
manifest 为小端:
| 偏移 | 字段 |
|---|---|
| 0 | SHNGROOT |
| 8 | 版本,32 位,值 1 |
| 12 | 窗口数,32 位 |
| 16 | 镜像大小,64 位 |
| 24 | 窗口条目,每条 128 字节 |
| 4064 | 字节 0 到 4063 的 SHA-256 |
每个窗口条目包含 32 字节名称、64 位偏移、64 位大小、32 位块大小、32 位标志、32 字节 SHA-256 和 40 字节保留。