diff --git a/docs/porting/arm64e.md b/docs/porting/arm64e.md index 21777b9..ae8ecc6 100644 --- a/docs/porting/arm64e.md +++ b/docs/porting/arm64e.md @@ -5,16 +5,19 @@ meets every [requirement](#requirements) and appears in [supported devices](#supported-devices). Other devices use the arm64 profile `ipados-17.7.11-21H461` and the regular [porting steps](/porting/steps). -iPadOS 18 and later ship arm64e user space only, so arm64 is the last resort -whose endpoints are iOS 17 and iPadOS 18. An arm64e profile builds XNU with -pointer authentication (PAC) and links the original arm64e kexts of the target -kernelcache. +arm64e needs native PAC hardware: a CPU that implements pointer +authentication and a hypervisor that leaves it usable, as the +[requirements](#requirements) check. A device without it stays on arm64, and +iPadOS 18 is the last version that supports arm64. iPadOS 26 and later are +arm64e only. An arm64e profile builds XNU with pointer authentication (PAC) +and links the original arm64e kexts of the target kernelcache. -For a new port, choose a device whose CPUs meet the requirements below. Prefer -the iOS or iPadOS 27 profile: its drivers, patches and build recipes are the -ones under active development, and every driver and optimization in this -repository is maintained against both 17 and 27, selected by build parameter -alone. +For a new port, choose a device whose CPUs have PAC and prefer the iOS or +iPadOS 27 profile. Its drivers, patches and build recipes are the ones under +active maintenance. Every driver and optimization in this repository must work +for 17 and 27, arm64 and arm64e, with the build target as the only difference: +the `--os` parameter of [the packaging script](/porting/packaging). A change that +works for one target only is not merged. ## Requirements {#requirements} diff --git a/docs/porting/device-repository.md b/docs/porting/device-repository.md index 01fb8dc..70e8164 100644 --- a/docs/porting/device-repository.md +++ b/docs/porting/device-repository.md @@ -19,6 +19,7 @@ UniXNU-/ configs/_defconfig dts/.dts patches/xnu/series + scripts/package.sh proprietary-files.txt package/ local.toml.example diff --git a/docs/porting/packaging.md b/docs/porting/packaging.md index bdd8bae..90c6496 100644 --- a/docs/porting/packaging.md +++ b/docs/porting/packaging.md @@ -1,91 +1,102 @@ # Device packaging script -**Mandatory for every device repository.** A device repository carries one -packaging script that produces its boot image and its payload from a clean -checkout, with no argument and no edit. Other device repositories copy this -page's structure. They fill in configuration values, never the script. +**Mandatory for every device repository.** A device repository carries +`scripts/package.sh`, which produces the boot image and the payload of the +device from a clean checkout in one command. Every device repository holds the +same script text. A board changes `board.toml`, never the script. ## Rules -1. **One command, one result.** `scripts/package.sh` in the device repository - builds both artifacts. A second run on the same sources produces byte - identical outputs. -2. **Configuration comes from TOML.** The script reads `board.toml` and the - referenced `feeds.toml`, profile and local file. It contains no device name, - path, size, kernel argument or version as a literal. A value the script - needs but the TOML does not carry is added to `board.toml` first. -3. **The script is shared, not per device.** Device repositories use the same - script text. Boards differ only in their TOML values. A change to the flow - is made once and adopted by every device repository. +1. **One command.** `scripts/package.sh` runs the fixed steps below and writes + the outputs and a manifest. It stops at the first failing step and names it. +2. **Configuration comes from TOML.** The script and `unixnu release` contain no + device name, path, size, kernel argument or version. The values are read from + `board.toml` (and the profiles and feeds it selects). A value that is missing + is added to `board.toml` first. +3. **The script is fixed.** `templates/package.sh` in the UniXNU repository is the + only source. A device repository copies it unchanged. The one board value it + reads itself is `[package] unixnu`, the path of the UniXNU checkout. 4. **The build target is a parameter.** One branch serves every OS profile. - `--os` selects iOS or iPadOS 17, 26 or 27 for that run. There is no per - target branch, and no second copy of a driver, patch or optimization for a - second target. -5. **Every step is named and checked.** A step that fails stops the run with - its name and the command's output. A step that is skipped says so. + `--os 17|26|27|PROFILE` selects the profile for the run. The values that differ + per profile sit in `board.toml` under `[os_overrides.""]`; there is no + branch and no second copy of a driver, patch or optimization per target. +5. **Sources are pinned.** `deps` fetches only the revisions that `feeds.toml`, + `.gitmodules` and `unixnu.lock` name. -## Structure +## Steps -The script runs these steps in this order. Each one is a function with the -step's name, and each prints a header line before it runs. +`unixnu release` runs these steps in order and prints a `step ` line before each. | Step | Does | Reads | | --- | --- | --- | -| `deps` | Clones or updates UniXNU, the device repository, its modules and the UEFI repository; checks each pinned revision | `feeds.toml`, `.gitmodules`, `unixnu.lock` | -| `preflight` | Runs the board's checks and resolves the profiles | `board.toml`, `--os` | -| `patches` | Lists the resolved patch series in application order, then applies it | `patch_series`, profile series | -| `build` | Builds each stage in dependency order, stopping at the first failure | `components`, `kernel`, `firmware` | -| `pack` | Writes the two artifacts and their manifest | `bootimg`, `payload` | -| `verify` | Checks the artifacts against the manifest and reports sizes | the manifest | +| `deps` | Fetches the module submodules and git sources, writes `unixnu.lock`, extracts the IPSW members the board lists | `feeds.toml`, `.gitmodules`, `[ipsw]` | +| `preflight` | Selects the defconfig of the OS profile and writes the configuration | `[package.defconfig]`, `[kernel]` | +| `patches` | Resolves and lists the patch series in application order | `[kernel] patch_series` | +| `build` | Builds kernel, package, payload and firmware in dependency order | `[components]`, `[kernel]`, `[firmware]`, `[payload]` | +| `pack` | Packs the boot image from the firmware volume, the device tree and the payload | `[bootimg]`, `[device_tree]` | +| `verify` | Writes the manifest and checks the outputs against it | the outputs | ## Interface ```sh -scripts/package.sh [--os 17|26|27|PROFILE] [--device DIR] [--out DIR] [--jobs N] [--no-deps] [--check] +scripts/package.sh [--os 17|26|27|PROFILE] [--no-deps] [--check] [unixnu options] ``` | Option | Meaning | | --- | --- | -| `--os` | OS profile for this run. Defaults to `board.os_profile` | -| `--device` | Device repository. Defaults to the directory holding the script | -| `--out` | Output root. Defaults to `out/` in the UniXNU checkout | -| `--jobs` | Parallel jobs for the compile steps | -| `--no-deps` | Skips `deps`, for a machine whose sources are already fetched and pinned | -| `--check` | Runs `deps`, `preflight`, `patches` and `verify` only, and reports what would change | +| `--os` | OS profile for this run. Defaults to `[board] os_profile` | +| `--no-deps` | Skips the `deps` step, for a machine whose sources are fetched and pinned | +| `--check` | Runs `deps`, `preflight` and `patches`, prints the patch list and stops before any build | -Every option maps onto a `unixnu` argument. The script adds no logic of its own -to a step that `unixnu` already performs. +Any other `unixnu` option (`--uefi`, `--kernelcache`, `--dtb`, `--out`, `-j`) is passed on. +Local inputs that are not in a repository come from `unixnu.local.toml`. -## Required outputs +## board.toml keys -The run writes these files, and the manifest names each one with its size and -SHA-256. +```toml +[package] +unixnu = "../UniXNU" + +[package.defconfig] +"ipados-27.0.1-24A446" = "_ipados27_defconfig" + +[os_overrides."ipados-17.7.11-21H461".kernel] +archives = [ ... ] +remove = [ ... ] +``` + +| Key | Meaning | +| --- | --- | +| `[package] unixnu` | Path of the UniXNU checkout, relative to the device repository | +| `[package.defconfig]` | Defconfig for each OS profile; `release` uses it | +| `[package] boot_partition_bytes` | Optional. `verify` refuses a larger `boot.img` | +| `[os_overrides.""]` | Tables merged over the board for that profile only | +| `remove` in an override | Dotted keys the board sets for other profiles and this one does not | + +## Outputs + +All paths are under `out////`. The manifest records the size and +SHA-256 of each file, the resolved revision of every module, the patch order and the length +of the kernel command line. | Output | Contents | | --- | --- | -| `out////boot.img` | Android boot image: shim, firmware volume, device tree, payload ramdisk | -| `out////payload.img` | The payload volume the boot image carries | -| `out////kernel.macho` | The prelinked kernel the payload boots | -| `out////package.manifest.json` | Build id, OS profile, resolved revisions, patch series, output sizes and hashes | - -The boot image must fit the bootloader's partition and the kernel command line -must stay under 1000 bytes. The script refuses both cases before it writes an -image. +| `boot/boot.img` | Android boot image: shim, firmware volume, device tree, payload ramdisk | +| `payload/payload.img` | The FAT payload volume the boot image carries | +| `kernel/kernel.macho` | The prelinked kernel the payload boots | +| `package.manifest.json` | The manifest | ## Verification -A packaging run counts as complete when `verify` passes: both artifacts exist, -their hashes match the manifest, the kernel command line is within its limit, -and the boot image is not larger than the partition it is booted from. Booting -the artifact is a separate step with its own record. +`verify` fails when an output is missing or differs from the manifest, when the kernel +command line reaches 1000 bytes, or when `boot.img` exceeds `boot_partition_bytes`. +Booting the artifacts is a separate step with its own record. ## Adoption -For a device repository without the script: - -1. Copy `scripts/package.sh` from the reference device repository. -2. Fill `board.toml` until `--check` reports no missing value. -3. Record the outputs in the device's `porting.toml` packaging area. -4. Add the run to the build documentation. +1. Copy `templates/package.sh` to `scripts/package.sh` in the device repository. +2. Add `[package]` and `[package.defconfig]` to `board.toml`, and `[os_overrides]` for each other profile. +3. Run `scripts/package.sh --check --os ` for every profile and fix what it reports. +4. Record the run in the `packaging` area of `porting.toml`. [Build and boot](/building), [Device repository](/porting/device-repository) diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 64e0f80..55192da 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -81,6 +81,14 @@ unixnu clean Removes `tree`, `logs`, `kernel`, `package`, `boot` and `edk2-conf` under the board output. Keeps fetched sources. +### release + +``` +unixnu release [--os VERSION] [--no-deps] [--check] +``` + +Runs the fixed steps `deps`, `preflight`, `patches`, `build`, `pack` and `verify` for the device, then writes `package.manifest.json`. The device repository's `scripts/package.sh` calls it. See [Device packaging script](/porting/packaging). + ## Options | Option | Meaning | diff --git a/docs/zh/porting/arm64e.md b/docs/zh/porting/arm64e.md index 4dbd025..327caf4 100644 --- a/docs/zh/porting/arm64e.md +++ b/docs/zh/porting/arm64e.md @@ -3,11 +3,13 @@ **仅适用于受支持的设备。** 只有满足全部[要求](#requirements)并列入[受支持设备](#supported-devices)的设备才能使用本方法。 其他设备使用 arm64 配置 `ipados-17.7.11-21H461` 和常规[移植步骤](/zh/porting/steps)。 -iPadOS 18 及以后版本只提供 arm64e 用户空间,因此 arm64 是最后的退路,其终点是 iOS 17 和 iPadOS 18。 +arm64e 需要原生 PAC 硬件:CPU 实现指针认证,且虚拟机监控程序不阻止使用,见下面的[要求](#requirements)。 +没有 PAC 的设备继续使用 arm64,iPadOS 18 是最后支持 arm64 的版本;iPadOS 26 及以后只提供 arm64e。 arm64e 配置以指针认证(PAC)编译 XNU,并链接目标 kernelcache 中的原版 arm64e kext。 -新移植应选择满足下列要求的设备。优先使用 iOS 或 iPadOS 27 配置:其驱动、补丁和构建配方 -处于持续维护中,本仓库的每个驱动和优化都同时面向 17 和 27 维护,只靠构建参数选择。 +新移植应选择 CPU 带 PAC 的设备,并优先使用 iOS 或 iPadOS 27 配置:其驱动、补丁和构建配方处于持续维护中。 +本仓库的每个驱动和优化都必须同时适用于 17 和 27、arm64 和 arm64e,唯一的差别是构建目标, +即[打包脚本](/zh/porting/packaging)的 `--os` 参数。只对一个目标有效的改动不予合并。 ## 要求 {#requirements} diff --git a/docs/zh/porting/device-repository.md b/docs/zh/porting/device-repository.md index c355f15..7d6f307 100644 --- a/docs/zh/porting/device-repository.md +++ b/docs/zh/porting/device-repository.md @@ -18,6 +18,7 @@ UniXNU-/ configs/_defconfig dts/.dts patches/xnu/series + scripts/package.sh proprietary-files.txt package/ local.toml.example diff --git a/docs/zh/porting/packaging.md b/docs/zh/porting/packaging.md index 556c8bb..e3f478b 100644 --- a/docs/zh/porting/packaging.md +++ b/docs/zh/porting/packaging.md @@ -1,71 +1,85 @@ # 设备打包脚本 -**每个设备仓库必须遵守。** 设备仓库只带一个打包脚本,从干净检出、不带参数、不需要修改即可产出启动镜像和 payload。 -其他设备仓库照搬本页的结构,只填写配置值,不修改脚本本身。 +**每个设备仓库必须遵守。** 设备仓库带有 `scripts/package.sh`,用一条命令从干净检出产出该设备的启动镜像和 payload。 +所有设备仓库中的脚本文本相同。板级只修改 `board.toml`,不修改脚本。 ## 规则 -1. **一条命令,两项产物。** 设备仓库的 `scripts/package.sh` 同时构建两项产物。同一份源码第二次运行产出的字节完全相同。 -2. **配置来自 TOML。** 脚本读取 `board.toml` 及其引用的 `feeds.toml`、配置文件和本地文件。脚本里不出现设备名、路径、尺寸、内核参数或版本的字面值。脚本需要而 TOML 没有的值,先加进 `board.toml`。 -3. **脚本是共享的,不按设备各写一份。** 各设备仓库使用同一份脚本文本,差异只在 TOML 取值。流程改动只改一次,由所有设备仓库采用。 -4. **构建目标是参数。** 单一分支服务所有 OS 配置。`--os` 为本次运行选择 iOS 或 iPadOS 17、26、27。不存在按目标拆分的分支,也不存在为第二个目标另存一份的驱动、补丁或优化。 -5. **每一步都有名字和检查。** 失败的一步以其名称和命令输出终止本次运行;被跳过的一步要说明原因。 +1. **一条命令。** `scripts/package.sh` 按下列固定步骤运行,写出产物和清单。第一个失败的步骤会终止运行并指出步骤名。 +2. **配置来自 TOML。** 脚本和 `unixnu release` 中不出现设备名、路径、尺寸、内核参数或版本。取值读自 `board.toml`(以及它选择的配置文件和 feeds)。缺少的值先加进 `board.toml`。 +3. **脚本是固定的。** UniXNU 仓库的 `templates/package.sh` 是唯一来源,设备仓库原样复制。脚本自己读取的板级值只有 `[package] unixnu`,即 UniXNU 检出的路径。 +4. **构建目标是参数。** 单一分支服务所有 OS 配置。`--os 17|26|27|PROFILE` 为本次运行选择配置。随配置不同的取值写在 `board.toml` 的 `[os_overrides.""]` 下;不按目标建分支,也不为第二个目标另存驱动、补丁或优化。 +5. **源码已固定。** `deps` 只获取 `feeds.toml`、`.gitmodules` 和 `unixnu.lock` 指定的版本。 -## 结构 +## 步骤 -脚本按下列顺序执行。每一步是一个同名函数,运行前打印一行标题。 +`unixnu release` 按顺序运行下列步骤,每步之前打印一行 `step <名称>`。 | 步骤 | 作用 | 读取 | | --- | --- | --- | -| `deps` | 克隆或更新 UniXNU、设备仓库、其模块和 UEFI 仓库,并校验每个固定版本 | `feeds.toml`、`.gitmodules`、`unixnu.lock` | -| `preflight` | 运行板级检查并解析配置 | `board.toml`、`--os` | -| `patches` | 按应用顺序列出解析后的补丁系列,然后应用 | `patch_series`、各配置的系列 | -| `build` | 按依赖顺序构建各阶段,遇到第一个失败即停止 | `components`、`kernel`、`firmware` | -| `pack` | 写出两项产物及其清单 | `bootimg`、`payload` | -| `verify` | 按清单校验产物并报告尺寸 | 清单 | +| `deps` | 获取模块子模块和 git 源,写 `unixnu.lock`,解出板级列出的 IPSW 成员 | `feeds.toml`、`.gitmodules`、`[ipsw]` | +| `preflight` | 选择该 OS 配置的 defconfig 并写出配置 | `[package.defconfig]`、`[kernel]` | +| `patches` | 解析并按应用顺序列出补丁系列 | `[kernel] patch_series` | +| `build` | 按依赖顺序构建内核、package、payload 和固件 | `[components]`、`[kernel]`、`[firmware]`、`[payload]` | +| `pack` | 由固件卷、设备树和 payload 打包启动镜像 | `[bootimg]`、`[device_tree]` | +| `verify` | 写清单并按清单检查产物 | 产物 | ## 接口 ```sh -scripts/package.sh [--os 17|26|27|PROFILE] [--device DIR] [--out DIR] [--jobs N] [--no-deps] [--check] +scripts/package.sh [--os 17|26|27|PROFILE] [--no-deps] [--check] [unixnu 选项] ``` | 选项 | 含义 | | --- | --- | -| `--os` | 本次运行的 OS 配置,默认取 `board.os_profile` | -| `--device` | 设备仓库,默认为脚本所在目录 | -| `--out` | 输出根目录,默认为 UniXNU 检出中的 `out/` | -| `--jobs` | 编译阶段的并行任务数 | -| `--no-deps` | 跳过 `deps`,用于源码已获取并固定版本的本机 | -| `--check` | 只运行 `deps`、`preflight`、`patches` 和 `verify`,报告将会发生的变化 | +| `--os` | 本次运行的 OS 配置,默认取 `[board] os_profile` | +| `--no-deps` | 跳过 `deps`,用于源码已获取并固定的本机 | +| `--check` | 运行 `deps`、`preflight` 和 `patches`,打印补丁列表后在任何构建之前停止 | -每个选项都对应一个 `unixnu` 参数。`unixnu` 已经完成的步骤,脚本不再添加自己的逻辑。 +其他 `unixnu` 选项(`--uefi`、`--kernelcache`、`--dtb`、`--out`、`-j`)原样传递。不在仓库中的本地输入来自 `unixnu.local.toml`。 -## 必需产物 +## board.toml 键 -本次运行写出下列文件,清单为每个文件记录尺寸和 SHA-256。 +```toml +[package] +unixnu = "../UniXNU" + +[package.defconfig] +"ipados-27.0.1-24A446" = "_ipados27_defconfig" + +[os_overrides."ipados-17.7.11-21H461".kernel] +archives = [ ... ] +remove = [ ... ] +``` + +| 键 | 含义 | +| --- | --- | +| `[package] unixnu` | UniXNU 检出相对设备仓库的路径 | +| `[package.defconfig]` | 各 OS 配置的 defconfig,`release` 使用 | +| `[package] boot_partition_bytes` | 可选。`verify` 拒绝更大的 `boot.img` | +| `[os_overrides.""]` | 仅对该配置合并到板级之上的表 | +| 覆盖中的 `remove` | 板级为其他配置设置、而本配置没有的点分键 | + +## 产物 + +路径都在 `out////` 下。清单记录每个文件的尺寸和 SHA-256、每个模块解析后的版本、补丁顺序和内核命令行长度。 | 产物 | 内容 | | --- | --- | -| `out////boot.img` | Android 启动镜像:shim、固件卷、设备树、payload ramdisk | -| `out////payload.img` | 启动镜像携带的 payload 卷 | -| `out////kernel.macho` | payload 启动的预链接内核 | -| `out////package.manifest.json` | 构建标识、OS 配置、解析后的版本、补丁系列、产物尺寸与哈希 | - -启动镜像必须放得进引导加载程序的分区,内核命令行必须保持在 1000 字节以内。两种情况脚本在写镜像之前就拒绝。 +| `boot/boot.img` | Android 启动镜像:shim、固件卷、设备树、payload ramdisk | +| `payload/payload.img` | 启动镜像携带的 FAT payload 卷 | +| `kernel/kernel.macho` | payload 启动的预链接内核 | +| `package.manifest.json` | 清单 | ## 验证 -一次打包运行以 `verify` 通过为完成:两项产物存在,哈希与清单一致,内核命令行在限制之内,启动镜像不大于它所来自的分区。 -启动该产物是另一步,另行记录。 +产物缺失或与清单不符、内核命令行达到 1000 字节、`boot.img` 超过 `boot_partition_bytes`,`verify` 都会失败。启动这些产物是另一步,另行记录。 ## 采用 -给尚无该脚本的设备仓库: - -1. 从参考设备仓库复制 `scripts/package.sh`。 -2. 填写 `board.toml`,直到 `--check` 不再报告缺失值。 -3. 把产物记录到设备 `porting.toml` 的 packaging 区域。 -4. 把运行方式加入构建文档。 +1. 把 `templates/package.sh` 复制为设备仓库的 `scripts/package.sh`。 +2. 在 `board.toml` 加 `[package]` 和 `[package.defconfig]`,为其他配置加 `[os_overrides]`。 +3. 对每个配置运行 `scripts/package.sh --check --os `,修正报告的问题。 +4. 把运行记录到 `porting.toml` 的 `packaging` 区域。 [构建与启动](/zh/building)、[设备仓库](/zh/porting/device-repository) diff --git a/docs/zh/reference/cli.md b/docs/zh/reference/cli.md index 52d7eb2..4d3b4b9 100644 --- a/docs/zh/reference/cli.md +++ b/docs/zh/reference/cli.md @@ -83,6 +83,14 @@ unixnu clean 删除板级输出下的 `tree`、`logs`、`kernel`、`package`、`boot` 和 `edk2-conf`,保留已拉取源码。 +### release + +``` +unixnu release [--os VERSION] [--no-deps] [--check] +``` + +为设备依次运行固定步骤 `deps`、`preflight`、`patches`、`build`、`pack` 和 `verify`,然后写出 `package.manifest.json`。设备仓库的 `scripts/package.sh` 调用它。见[设备打包脚本](/zh/porting/packaging)。 + ## 选项 | 选项 | 含义 |