89 lines
4.5 KiB
Python
Executable File
89 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Exercise UniXNU -> DarwinBoot -> ExitBootServices -> synthetic Mach-O."""
|
|
import argparse
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
from unixnu.package import output_dir
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--memory-size', type=lambda value: int(value, 0), choices=[0x10000000, 0x20000000])
|
|
parser.add_argument('--packed-ramdisk', action='store_true', help='Exercise real packed seed expansion before firmware exit')
|
|
parser.add_argument('--gop', action='store_true', help='Exercise the actual QEMU ramfb UEFI GOP handoff')
|
|
parser.add_argument('--gop-high-resolution', action='store_true', help='Exercise real QEMU ramfb 3048x2032 allocation and mode programming')
|
|
parser.add_argument('--ramfb-geometry-refusal', action='store_true', help='Load the geometry fixture without a GOP and require a clean refusal')
|
|
args = parser.parse_args()
|
|
if args.ramfb_geometry_refusal and (args.gop or args.gop_high_resolution):
|
|
parser.error('The refusal control requires no GOP device')
|
|
if args.gop_high_resolution:
|
|
args.gop = True
|
|
OUTPUT = ROOT / ('build/darwinboot-test' if not args.memory_size else f'build/darwinboot-test-{args.memory_size >> 20}m')
|
|
if args.gop:
|
|
OUTPUT = OUTPUT.with_name(OUTPUT.name + '-gop')
|
|
if args.packed_ramdisk:
|
|
OUTPUT = OUTPUT.with_name(OUTPUT.name + '-packed')
|
|
if args.gop_high_resolution:
|
|
OUTPUT = OUTPUT.with_name(OUTPUT.name + '-3048x2032')
|
|
if args.ramfb_geometry_refusal:
|
|
OUTPUT = OUTPUT.with_name(OUTPUT.name + '-geometry-refusal')
|
|
ESP = OUTPUT / 'esp'
|
|
PAYLOADS = ESP / 'EFI/UniXNU/Payloads'
|
|
|
|
OUTPUT.mkdir(parents=True, exist_ok=True)
|
|
PAYLOADS.mkdir(parents=True, exist_ok=True)
|
|
subprocess.run(['python3', ROOT / 'drivers/DarwinBoot/Test/make-fixtures.py', PAYLOADS,
|
|
*(['--memory-size', str(args.memory_size)] if args.memory_size else []),
|
|
*(['--gop'] if args.gop else []),
|
|
*(['--gop-width', '3048', '--gop-height', '2032'] if args.gop_high_resolution else [])], check=True)
|
|
if args.packed_ramdisk:
|
|
import sys
|
|
sys.path.insert(0, str(ROOT / 'drivers/DarwinBoot/Test'))
|
|
from packed_ramdisk import pack
|
|
raw = PAYLOADS / 'ramdisk.bin'
|
|
raw.write_bytes(raw.read_bytes() + bytes(-raw.stat().st_size % 4096))
|
|
packed = PAYLOADS / 'ramdisk.packed'
|
|
packed.unlink(missing_ok=True)
|
|
pack(raw, packed)
|
|
packed.replace(raw)
|
|
(ESP / 'EFI/BOOT').mkdir(exist_ok=True)
|
|
shutil.copyfile(output_dir(ROOT) / 'UniXNU.efi', ESP / 'EFI/BOOT/BOOTAA64.EFI')
|
|
for name in ('DarwinBoot', 'DarwinBootValidation'):
|
|
shutil.copyfile(ROOT / f'build/DarwinBoot/DEBUG_CLANGPDB/AARCH64/{name}.efi', PAYLOADS / f'{name}.efi')
|
|
(ESP / 'EFI/UniXNU/unixnu.toml').write_text('''version = 1
|
|
[boot]
|
|
timeout = 1
|
|
default = "synthetic"
|
|
[kits]
|
|
autoload = false
|
|
[[driver]]
|
|
path = "Payloads/DarwinBoot.efi"
|
|
[[driver]]
|
|
path = "Payloads/DarwinBootValidation.efi"
|
|
[[entry]]
|
|
id = "synthetic"
|
|
title = "Synthetic Darwin ABI entry"
|
|
type = "xnu"
|
|
path = "Payloads/kernel.macho"
|
|
args = "darwinboot.fixture=1"
|
|
initrd = "Payloads/ramdisk.bin"
|
|
''')
|
|
if args.gop_high_resolution or args.ramfb_geometry_refusal:
|
|
driver = ROOT / 'build/DarwinBoot/DEBUG_CLANGPDB/AARCH64/QemuRamfbGeometry.efi'
|
|
shutil.copyfile(driver, PAYLOADS / driver.name)
|
|
config = ESP / 'EFI/UniXNU/unixnu.toml'
|
|
config.write_text(config.read_text().replace('[[entry]]',
|
|
'[[driver]]\npath = "Payloads/QemuRamfbGeometry.efi"\n[[entry]]', 1))
|
|
subprocess.run(['python3', ROOT / 'unixnu/Scripts/qemu-run.py', ESP,
|
|
'--log', OUTPUT / 'qemu.log', '--cpus', '1', *([] if args.gop else ['--no-gop']), '--timeout', '25',
|
|
'--finish-on-expect',
|
|
'--expect', 'DARWINBOOT: loader v2 installed EL1',
|
|
'--expect', 'DARWINBOOT-VALIDATION: 33 rejected requests; firmware retained PASS',
|
|
'--expect', 'DARWINBOOT-VIDEO-VALIDATION: 8 malformed/unsupported GOP field sets refused PASS',
|
|
'--expect', 'DARWINBOOT: inputs validated; exiting boot services',
|
|
*(['--expect', 'QEMU-RAMFB-GEOMETRY: actual SetMode 3048x2032'] if args.gop_high_resolution else []),
|
|
*(['--expect', 'QEMU-RAMFB-GEOMETRY: REFUSED no GOP'] if args.ramfb_geometry_refusal else []),
|
|
'--expect', ('DARWINBOOT-FIXTURE: actual GOP boot video after ExitBootServices PASS' if args.gop else
|
|
'DARWINBOOT-FIXTURE: boot_args, RAMDisk, TrustCache, zero-fill and MMU-off entry PASS'),
|
|
'--reject', r'DARWINBOOT[^\n]*FAIL', '--reject', 'ASSERT'], check=True)
|