Files
Acelogic 1510d8c6ce Snapintosh public release
An EL2 monitor/hypervisor and toolchain that boots macOS 27 on the ASUS A16
(Snapdragon X2 Elite), with an Adreno Metal plug-in and IOGPU kext, and
air2ir3, an AIR to Mesa ir3 shader compiler.

MIT, with GPL-2.0 components listed in LICENSE and THIRD_PARTY_NOTICES.md.
No Apple, Qualcomm, ASUS or Microsoft binaries are included.
2026-10-21 21:26:36 -04:00

214 lines
11 KiB
Python
Executable File

#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
from pathlib import Path
from dataclasses import replace
import hashlib
import struct
import sys
import tempfile
import unittest
ROOT=Path(__file__).resolve().parents[1]
sys.path.insert(0,str(ROOT/'probes'))
from ramdisk import load_ramdisk, root_cmdline, load_root_hash, populate_ramdisk_policy, RootHashSpec, ROOT_HASH_NODE
class RAMDiskTests(unittest.TestCase):
def setUp(self):
self.temp=tempfile.TemporaryDirectory()
self.path=Path(self.temp.name)/'geometry-only.apfs'
self.data=bytearray(0x4000)
self.data[32:36]=b'NXSB'
struct.pack_into('<IQ',self.data,36,4096,4)
self.path.write_bytes(self.data)
def tearDown(self):
self.temp.cleanup()
def test_mapping_is_read_only(self):
with load_ramdisk(self.path,0x100000000,0x110000000) as payload:
self.assertEqual(payload[:],self.data)
with self.assertRaises(TypeError):payload[32]=0
def test_refuse_wrappers_and_inconsistent_geometry(self):
for offset,value in [(32,b'IM4P'),(36,struct.pack('<I',16384)),
(40,struct.pack('<Q',5))]:
data=bytearray(self.data);data[offset:offset+len(value)]=value
self.path.write_bytes(data)
with self.assertRaises(ValueError):load_ramdisk(self.path,0x100000000,0x110000000)
for data in [b'',self.data[:-1],self.data+b'\0'*0x4000]:
self.path.write_bytes(data)
with self.assertRaises(ValueError):load_ramdisk(self.path,0x100000000,0x110000000)
def test_placement_and_root_conflicts(self):
for base,end in [(-0x4000,0x10000000),(1,0x10000000),(0,0x8000000),
(0x1000000000,0x1000004000)]:
with self.assertRaises(ValueError):load_ramdisk(self.path,base,end)
for line in ['-v rd=disk0s1','rootdev=md1','rd=md0','boot-uuid=unexpected']:
for mode in ('md0','iokit'):
with self.assertRaises(ValueError):root_cmdline(line,mode)
self.assertEqual(root_cmdline('-v'),'-v rd=md0')
self.assertEqual(root_cmdline('-v','iokit'),'-v')
with self.assertRaises(ValueError):root_cmdline('-v','unknown')
def root_fixture(self):
payload=struct.pack('<4I',2,0,1,32)+bytes(range(192))
path=Path(self.temp.name)/'root-hash.bin'
path.write_bytes(payload)
spec=RootHashSpec(hashlib.sha256(self.data).hexdigest(),
hashlib.sha256(payload).hexdigest(),len(payload),
'test-component','0'*64,'system-volume-auth-blob',
'test-board','test-build')
return path,payload,spec
def test_root_hash_is_bound_to_both_payload_and_media(self):
path,payload,spec=self.root_fixture()
self.assertEqual(load_root_hash(path,self.data,spec),payload)
with self.assertRaises(ValueError):load_root_hash(path,self.data,None)
for raw in (payload[:-1],payload+b'\0',b'X'+payload[1:]):
path.write_bytes(raw)
with self.assertRaises(ValueError):load_root_hash(path,self.data,spec)
path.write_bytes(payload)
modified=bytearray(self.data);modified[-1]^=1
with self.assertRaises(ValueError):load_root_hash(path,modified,spec)
def test_root_hash_requires_media_and_reaches_firmware_unchanged(self):
import xnuboot as xb
from unittest.mock import patch
path,auth,spec=self.root_fixture()
with self.assertRaises(ValueError):
xb.build(xb.DEFAULT_KERNELCACHE,root_hash=path)
with patch.dict(xb.__dict__,xb.__dict__.copy()):
xb.place(0xda000000,guest_span=384<<20)
xb.GUEST_PROFILE=replace(xb.GUEST_PROFILE,root_hash=spec)
built=xb.build(xb.DEFAULT_KERNELCACHE,ramdisk=self.path,root_hash=path)
pa,size=built['ramdisk_range']
try:
dt=xb.DeviceTree(built['chunks'][xb.DEVICETREE_PA])
self.assertEqual(dt.get(ROOT_HASH_NODE,spec.property_name),auth)
self.assertEqual(built['chunks'][pa][:],self.data)
self.assertLessEqual(pa+size,built['alloc_low'])
args=built['chunks'][xb.HANDOFF_PA+0x1000]
self.assertIn(b' rd=md0\0',args[0x6c:0x478])
finally:built['chunks'][pa].close()
def test_loader_reserves_and_publishes_the_same_bytes(self):
import xnuboot as xb
xb.place(0xda000000,guest_span=384<<20)
built=xb.build(xb.DEFAULT_KERNELCACHE,ramdisk=self.path)
pa,size=built['ramdisk_range']
payload=built['chunks'][pa]
try:
self.assertEqual(payload[:],self.data)
dt=xb.DeviceTree(built['chunks'][xb.DEVICETREE_PA])
self.assertEqual(dt.get('/device-tree/chosen/memory-map','RAMDisk'),struct.pack('<QQ',pa,size))
self.assertLessEqual(pa+size,built['alloc_low'])
self.assertEqual(built['tables'].walk(xb.APERTURE_VA+pa-xb.PHYS_BASE),pa)
args=built['chunks'][xb.HANDOFF_PA+0x1000]
self.assertEqual(struct.unpack_from('<Q',args,32)[0],built['alloc_low'])
self.assertIn(b' rd=md0\0',args[0x6c:0x478])
finally:payload.close()
def test_iokit_requires_bound_root_inputs(self):
import xnuboot as xb
from unittest.mock import patch
path,auth,spec=self.root_fixture()
with self.assertRaises(ValueError):
xb.build(xb.DEFAULT_KERNELCACHE,ramdisk_mode='iokit')
with self.assertRaises(ValueError):
xb.build(xb.DEFAULT_KERNELCACHE,ramdisk=self.path,ramdisk_mode='iokit')
with patch.object(xb,'GUEST_PROFILE',replace(xb.GUEST_PROFILE,root_hash=spec)):
with self.assertRaises(ValueError):
xb.build(xb.DEFAULT_KERNELCACHE,ramdisk=self.path,root_hash=path,ramdisk_mode='iokit')
with self.assertRaises(ValueError):
xb.build(xb.DEFAULT_KERNELCACHE,ramdisk=self.path,isc_image=self.path)
def test_iokit_gpt_keeps_root_auth_and_preload_separate(self):
import xnuboot as xb
import bootmedia
from unittest.mock import patch
path,auth,spec=self.root_fixture()
spec=replace(spec,boot_uuid='A9037730-2821-4F3A-90DC-91BA521BB080',
no_protected_data_recipe=xb.GUEST_PROFILE.root_hash.no_protected_data_recipe)
with patch.dict(xb.__dict__,xb.__dict__.copy()):
xb.place(0xda000000,guest_span=384<<20)
xb.GUEST_PROFILE=replace(xb.GUEST_PROFILE,root_hash=spec)
built=xb.build(xb.DEFAULT_KERNELCACHE,ramdisk=self.path,root_hash=path,
ramdisk_mode='iokit',isc_image=self.path)
pa,size=built['ramdisk_range']
root_pa,root_size=built['ramdisk_root_range']
isc_pa,isc_size=built['ramdisk_isc_range']
try:
dt=xb.DeviceTree(built['chunks'][xb.DEVICETREE_PA])
self.assertEqual(dt.get(ROOT_HASH_NODE,spec.property_name),auth)
self.assertEqual(dt.get('/device-tree/chosen','protected-data-access'),bytes(4))
self.assertEqual(dt.get('/device-tree/chosen','boot-ramdmg-extents'),struct.pack('<QQ',pa,size))
self.assertEqual(dt.get('/device-tree/chosen','boot-ramdmg-size'),struct.pack('<Q',size))
self.assertEqual(built['chunks'][root_pa][:],self.data)
self.assertEqual(built['chunks'][isc_pa][:],self.data)
self.assertNotEqual(pa,root_pa)
self.assertEqual(root_size,len(self.data))
self.assertGreater(size,root_size+isc_size)
self.assertLessEqual(pa+size,built['alloc_low'])
image=bytearray(size)
for start,blob in built['chunks'].items():
if pa<=start<pa+size:image[start-pa:start-pa+len(blob)]=blob
layout=bootmedia.inspect(lambda off,n:image[off:off+n],size)
self.assertEqual(layout['root'],(root_pa-pa,root_size))
self.assertEqual(layout['isc'],(isc_pa-pa,isc_size))
finally:
built['chunks'][root_pa].close()
built['chunks'][isc_pa].close()
def test_ramdisk_policy_rejects_changed_firmware_recipe(self):
import xnuboot as xb
spec=xb.GUEST_PROFILE.root_hash
tree=xb.build_devicetree()
self.assertEqual(tree.get('/device-tree/chosen','protected-data-access'),struct.pack('<I',1))
self.assertEqual(tree.get('/device-tree/chosen','sepfw-load-at-boot'),struct.pack('<I',1))
before=tree.serialize()
populate_ramdisk_policy(tree,replace(spec,no_protected_data_recipe=None,no_sep_firmware_recipe=None))
self.assertEqual(tree.serialize(),before)
for recipe in (spec.no_protected_data_recipe,spec.no_sep_firmware_recipe):
for key,value in [('value',b'\0'),('value',struct.pack('<I',1)),
('node_path',b'arm-io\0'),('property_name',b'other\0')]:
tree=xb.build_devicetree()
tree.put(recipe,key,value)
before=tree.serialize()
with self.subTest(recipe=recipe,key=key,value=value), self.assertRaises(ValueError):
populate_ramdisk_policy(tree,spec)
self.assertEqual(tree.serialize(),before)
tree=xb.build_devicetree()
populate_ramdisk_policy(tree,spec)
self.assertEqual(tree.get('/device-tree/chosen','protected-data-access'),bytes(4))
self.assertEqual(tree.get('/device-tree/chosen','sepfw-load-at-boot'),bytes(4))
def test_iokit_uses_physical_extents_and_uuid_without_md0(self):
import xnuboot as xb
from unittest.mock import patch
path,auth,spec=self.root_fixture()
spec=replace(spec,boot_uuid='A9037730-2821-4F3A-90DC-91BA521BB080')
with patch.dict(xb.__dict__,xb.__dict__.copy()):
xb.place(0xda000000,guest_span=384<<20)
xb.GUEST_PROFILE=replace(xb.GUEST_PROFILE,root_hash=spec)
built=xb.build(xb.DEFAULT_KERNELCACHE,ramdisk=self.path,root_hash=path,ramdisk_mode='iokit')
pa,size=built['ramdisk_range']
try:
dt=xb.DeviceTree(built['chunks'][xb.DEVICETREE_PA])
self.assertEqual(built['chunks'][pa][:],self.data)
self.assertLessEqual(pa+size,built['alloc_low'])
self.assertIsNone(dt.get('/device-tree/chosen/memory-map','RAMDisk'))
self.assertEqual(dt.get('/device-tree/chosen','boot-ramdmg-extents'),struct.pack('<QQ',pa,size))
self.assertEqual(dt.get('/device-tree/chosen','boot-ramdmg-size'),struct.pack('<Q',size))
self.assertEqual(dt.get('/device-tree/chosen','boot-uuid'),spec.boot_uuid.encode()+b'\0')
self.assertEqual(dt.get('/device-tree/chosen','apfs-preboot-uuid'),spec.boot_uuid.encode()+b'\0')
self.assertEqual(dt.get(ROOT_HASH_NODE,spec.property_name),auth)
args=built['chunks'][xb.HANDOFF_PA+0x1000]
self.assertNotIn(b'rd=',args[0x6c:0x478])
self.assertNotIn(b'rootdev=',args[0x6c:0x478])
self.assertEqual(built['tables'].walk(xb.APERTURE_VA+pa-xb.PHYS_BASE),pa)
finally:built['chunks'][pa].close()
if __name__=='__main__':unittest.main()