A Python 3 driver with defconfig, fetch, tree, build, bootimg, status and clean. Device repositories supply board.toml and configs/*_defconfig; external sources come from feeds.toml and are fetched with shallow, blobless, sparse git checkouts pinned in unixnu.lock. Modules can come from local directories through --local, --local-<kind> and --local-module. The boot image step packs BootShim, the firmware volume and the device tree for a Mu-Silicium checkout given with --uefi.
60 lines
2.6 KiB
Python
60 lines
2.6 KiB
Python
"""XNU kernel: build from the patched Apple source, then prelink against the original kernelcache."""
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from .util import Error, expand, log, run, sha256_file, tool
|
|
|
|
|
|
def xnu_env(ctx):
|
|
"""CONFIG_XNU_* of the defconfig become XNU_* variables of the legacy kernel build script."""
|
|
env = {}
|
|
for key, value in ctx.need_config().items():
|
|
if not key.startswith('XNU_'):
|
|
continue
|
|
if isinstance(value, str):
|
|
value = value.replace('{tree}', str(ctx.tree))
|
|
env[key] = '1' if value is True else '0' if value is False else str(value)
|
|
return env
|
|
|
|
|
|
def build(ctx):
|
|
log('kernel: XNU')
|
|
for name in ('git', 'make', 'clang', 'cmake', 'ninja', 'unifdef'):
|
|
tool(name, 'brew install ' + name)
|
|
script = ctx.tree / 'scripts/build-xnu-4k-baseline.sh'
|
|
if not script.is_file():
|
|
raise Error(f'{script} missing')
|
|
env = dict(os.environ)
|
|
env.update(xnu_env(ctx))
|
|
env['JOBS'] = str(ctx.jobs)
|
|
run(['bash', script], cwd=ctx.tree, env=env, log_file=ctx.logs / 'kernel.log')
|
|
|
|
|
|
def prelink(ctx):
|
|
"""Produce out/<device>/kernel/kernel.macho from the XNU build and the original kernelcache."""
|
|
log('kernel: prelink')
|
|
spec = ctx.board.get('kernel', {}).get('prelink')
|
|
if not spec:
|
|
raise Error('board.toml has no [kernel.prelink]')
|
|
cache = ctx.option('kernelcache', 'UNIXNU_KERNELCACHE') or (expand(ctx.tree / spec['kernelcache']) if spec.get('kernelcache') else None)
|
|
if not cache or not cache.is_file():
|
|
raise Error('the original decompressed kernelcache is an input you provide: --kernelcache FILE or UNIXNU_KERNELCACHE')
|
|
wanted = spec.get('kernelcache_sha256')
|
|
if wanted and sha256_file(cache) != wanted:
|
|
raise Error(f'{cache} does not match the kernelcache this board was qualified against (sha256 {wanted})')
|
|
kernel = ctx.tree / spec['kernel']
|
|
if not kernel.is_file():
|
|
raise Error(f'{kernel} not found; run "unixnu build kernel" first')
|
|
output = ctx.work / 'kernel/kernel.macho'
|
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
command = ['python3', ctx.tree / spec['tool'], '--kernel', kernel, '--prelinked', cache,
|
|
f'--slide={spec["slide"]}', '--output', output]
|
|
for root in spec.get('roots', []):
|
|
command += ['--root', root]
|
|
if spec.get('early_security_init'):
|
|
command += ['--early-security-init', spec['early_security_init']]
|
|
command += spec.get('extra_args', [])
|
|
run(command, cwd=ctx.tree, log_file=ctx.logs / 'prelink.log')
|
|
log(f'kernel: {output} sha256 {sha256_file(output)}')
|
|
return output
|