8.9 KiB
Build the kernel
The kernel step builds Apple's XNU source with UniXNU patches, then prelinks the result against the original kernelcache.
Procedure
- Complete host setup and select the device with
./unixnu defconfig <name> -D /path/to/device. - Run
./unixnu fetchand./unixnu status --json. Check the OS revision, archives and patch order. Supply the original kernelcache, firmware and any device-specific ABI candidates from build inputs. - Run
./unixnu build kernel. Read the first failed step's log under the outputlogs/directory if it stops. The final output iskernel/kernel.macho. - Use
./unixnu build prelinkwhen only the prelink inputs changed and the native kernel already exists. Rebuild the kernel for source or archive changes. - Continue with package, firmware and payload.
Source and tree
| Path | Contents |
|---|---|
out/<device>/<os_profile>/<config>/tree/refer/xnu |
Pinned XNU source |
out/<device>/<os_profile>/<config>/tree/.cache/xnu-work |
Working clone with patches applied |
out/<device>/<os_profile>/<config>/tree/build/xnu/ios-obj |
Object files and compile command records |
out/<device>/<os_profile>/<config>/tree/build/xnu/ios-sym |
Symbols |
out/<device>/<os_profile>/<config>/tree/build/xnu/ios-dst |
Install headers |
out/<device>/<os_profile>/<config>/tree/.cache/fakeroot |
Kernel SDK root with restored headers |
out/<device>/<os_profile>/<config>/tree/.cache/firmware |
Device proprietary inputs, linked from the device repository |
out/<device>/<os_profile>/<config>/kernel/kernel.macho |
Prelinked kernel |
Format 2 selects XNU version fields from the OS profile. The source feed supplies the checkout; format 1 uses its version fields directly. A source entry has this form:
[[source]]
name = "xnu"
kind = "refer"
git = "https://github.com/apple-oss-distributions/xnu.git"
ref = "xnu-10063.141.1"
commit = "d8b80295118ef25ac3a784134bcf95cd8e88109f"
darwin = "23.6.0"
version = "10063.141.1"
driverkit_tag = "xnu-10063.121.3"
trustcache_tag = "xnu-8796.101.5"
unixnu build kernel passes these values to scripts/build-xnu-4k-baseline.sh as UNIXNU_XNU_TAG, UNIXNU_XNU_COMMIT, UNIXNU_XNU_DARWIN, UNIXNU_XNU_VERSION, UNIXNU_DRIVERKIT_TAG and UNIXNU_TRUSTCACHE_TAG.
The kernel reference set also pins libpthread at libpthread-519.120.4 and corecrypto-2023 at commit 11fba65. The source providers compile against the XNU compile records.
The build target is:
SDKROOT=iphoneos
ARCH_CONFIGS=ARM64
MACHINE_CONFIGS=BCM2837
KERNEL_CONFIGS=DEVELOPMENT
ARM64_LINK_ADDR=0xfffffff007004000
ARM64_PLKSEG_ADDR=0xfffffff004004000
DEPLOYMENT_TARGET_FLAGS="-miphoneos-version-min=17.0 -DXNU_TARGET_OS_IOS"
BCM2837 is the XNU machine configuration that carries the 4 KiB page layout. The kernel still targets iOS 17 so the prelink ABI matches the iPadOS kernelcache.
Defconfig flags
Each CONFIG_XNU_<NAME> line becomes XNU_<NAME> in the kernel build environment. y becomes 1, n becomes 0, quoted strings are passed as text, and {tree} in a string is replaced by the build tree path.
| Flag | Effect | Archive |
|---|---|---|
XNU_SOURCE_CORECRYPTO14 |
Builds and links the source corecrypto provider | build/corecrypto-2023/libcorecrypto_kernel_noasm-namespaced.a |
XNU_SOURCE_PTHREAD |
Builds and registers the source pthread component | build/libpthread-kernel/libpthread_kernel.a |
XNU_ARM_DT_PLATFORM |
Links the Apple-format device tree platform expert | build/armdt-platform/libArmDTPlatform.a |
XNU_ARMVIRT_PLATFORM |
Links the QEMU virt platform expert | build/armvirt-platform/libArmVirtPlatform.a |
XNU_ARMCPU |
Links the architectural CPU and interrupt provider | build/armcpu/libArmCpu.a |
XNU_NATIVE_UFS |
Links the UFS storage driver | build/sheng-ufs/libShengUfs.a |
XNU_NATIVE_AES |
Links the AES accelerator driver | build/software-aes/libSoftwareAES.a |
XNU_NATIVE_VIRTIO_BLOCK |
Links the VirtIO block driver | XNU_NATIVE_VIRTIO_BLOCK_ARCHIVE or build/virtio-mmio-block/libVirtioMmioBlock.a |
XNU_NATIVE_RAM_BLOCK |
Links the RAM block driver | build/ram-block/libRamBlock.a |
XNU_NATIVE_VIRTIO_CONSOLE |
Links the VirtIO console byte transport | build/virtio-mmio-console/libVirtioMmioConsole.a |
XNU_NATIVE_MOBILE_DISPLAY |
Links the mobile display provider | build/gop-framebuffer/libGopFramebuffer.late.a |
XNU_NATIVE_LEGACY_DISPLAY |
Links the legacy display provider | build/native-legacy-display/libNativeLegacyDisplay.late.a |
XNU_NATIVE_ADRENO |
Links the Adreno GPU driver and kits | build/adreno740/libAdreno740.a |
XNU_NATIVE_OFFLINE_GPU |
Links the offline GPU broker | build/native-offline-gpu/libNativeOfflineGPU.late.a |
XNU_VERIFIED_ROOT_PROBE |
Links the verified root provider | XNU_VERIFIED_ROOT_ARCHIVE or build/verified-root-xnu/libVerifiedRootProbe.a |
XNU_NATIVE_CS_HASH_CACHE |
Derives 4 KiB code signature hashes from verified 16 KiB blocks | none |
XNU_NATIVE_ARCH_TIMER |
Uses the architectural timer entry | none |
XNU_NATIVE_PAN |
Enables ARMv8.1 PAN support | none |
XNU_DT_PANIC_REGION |
Reads the panic region from the device tree | none |
XNU_TRUST_CACHE_RUNTIME |
Initializes the trust cache runtime | none |
XNU_BOOT_PROGRESS |
Adds the boot progress layer | build/boot-progress/libBootProgress.a |
XNU_SOURCE_MOCKFS |
Adds the mockfs test file | build/mockfs-fixture/libmockfs_fixture.a |
[kernel] archives in board.toml lists the archive builders in order. Each entry is a script of the build tree and its arguments. For example:
[kernel]
defconfig = "sheng_defconfig"
archives = [
"build-software-aes-bindings.py",
"build-libpthread-kernel.py",
"build-corecrypto-14.py",
"build-corecrypto-14.py --namespace",
]
unixnu build kernel runs the builders after the compile records exist, then links. Entries run in order, so a builder that consumes another builder's output follows it. An archive that no builder makes must be supplied in the build tree. A configuration opts in with CONFIG_XNU_BUILD_ARCHIVES=y; the bootstrap pass and first-console configurations leave it unset.
The builders read symbol names through scripts/xnu_symbols.py. It uses the recorded checkpoint kernel, or the objects in build/xnu/ios-obj/DEVELOPMENT_ARM64_BCM2837/link.filelist plus the aliases in all-alias.exp. A fresh tree therefore needs one kernel pass for the records, and the archive output cannot collide with a previously linked kernel.
The kernel step prepares the public IOStorageFamily headers under build/storage-abi/include before the archive builders.
build-software-aes-bindings.py and build-adreno740-accelerator.py use the recorded audit results in scripts/data/ when the original hardware evidence is absent. The recorded addresses belong to the kernelcache pinned in board.toml.
Build sequence
unixnu fetchclones XNU, libpthread, corecrypto-2023 and the Apple references.unixnu build kernelapplies the patches and restores the omitted headers.- When the compile records are absent, it runs one XNU pass for them. The pass may stop at the link.
- It runs the
[kernel] archivesbuilders in order. - It builds and links the kernel with the archives, then prelinks it against the original kernelcache.
unixnu build prelinkrepeats only the prelink. It replaces the earlier candidate and its report.
The prelinked kernel is out/<device>/<os_profile>/<config>/kernel/kernel.macho.
The prelink reads [kernel.prelink] from board.toml:
[kernel.prelink]
tool = "kits/XnuPrelink/emit_prelink.py"
kernel = "build/xnu/ios-obj/DEVELOPMENT_ARM64_BCM2837/mach.development.bcm2837.unstripped.noctf"
kernelcache_sha256 = "..."
slide = "-0x1000000"
early_security_init = "com.apple.driver.AppleMobileFileIntegrity=0xfffffff005ab4ae0"
roots = [
"com.apple.driver.AppleARMPlatform",
"com.apple.filesystems.apfs",
]
roots lists the original kernelcache components the native kernel uses. early_security_init maps a component identifier to an address that runs during prelink security initialization.
Adding a kernel flag
- Add
CONFIG_XNU_<NAME>=yto the device defconfig. - Read
XNU_<NAME>inscripts/build-xnu-4k-baseline.sh. - Add the object flags with
EXTRA_MAKE_ARGS+=("<file>.o_CFLAGS_ADD=-DXNU_<NAME>=$VALUE"). - Add the builder script to
[kernel] archives, then add the archive toKERNEL_EXTRA_ARCHIVESandKERNEL_ARCHIVE_DEPENDENCIES. - Add the personality to
iokit/KernelConfigTables.cppthrough a patch.
Prebuilt kernel
unixnu build payload --kernel FILE packs an existing prelinked kernel. This path builds the boot image without rebuilding XNU.
Next steps
- Four-kilobyte pages explains the page size work.
- Patch reference lists every patch.
- Prelink explains the kernelcache binding.