Files
Snapintosh/tools/host-el2-mapping.py
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

75 lines
3.4 KiB
Python

# SPDX-License-Identifier: MIT
"""Admit a secondary's shared EL2 regime using actual firmware page tables.
Only the measured non-VHE, 4 KiB, 44-bit A16 EL2 regime is supported. This
does not create or edit tables. Call while the primary regime is stable.
"""
import struct
def validate_regime(memory):
sctlr, tcr, ttbr, mair, hcr = (int(memory[k], 16) for k in ('sctlr', 'tcr', 'ttbr0', 'mair', 'hcr'))
if (sctlr & 0x1005 != 0x1005 or hcr & (1 << 34) or
tcr & 63 != 20 or (tcr >> 14) & 3 or (tcr >> 8) & 63 != 0x35 or
(tcr >> 16) & 7 != 4 or ttbr & ~0x00000ffffffff000 or not ttbr):
raise ValueError('unsupported primary EL2 memory regime')
return sctlr, tcr, ttbr, mair
def verify(read, memory, ranges, ram_ranges):
_, _, root, mair = validate_regime(memory)
tables = set()
def descriptor(table, slot):
if not any(lo <= table and table+4096 <= hi for lo, hi in ram_ranges):
raise ValueError('host table outside declared RAM')
tables.add(table)
return struct.unpack('<Q', read(table+slot*8, 8))[0]
def walk(va):
if not 0 <= va < 1 << 44:
raise ValueError('host VA outside admitted TCR range')
table = root
for level, shift in enumerate((39, 30, 21, 12)):
desc = descriptor(table, (va >> shift) & 511)
form = desc & 3
if (level == 3 and form == 3) or (level in (1, 2) and form == 1):
mask = (1 << shift)-1
if desc & 0x00000ffffffff000 & mask:
raise ValueError('misaligned host block descriptor')
pa = (desc & 0x00000ffffffff000 & ~mask) | (va & mask)
return pa, desc, shift
if form != 3 or level == 3:
raise ValueError('invalid host translation descriptor')
table = desc & 0x00000ffffffff000
raise ValueError('missing host translation')
witnesses = []
for name, base, size, device in ranges:
if size <= 0 or base % 4096:
raise ValueError('invalid mapping request')
for offset in range(0, size, 4096):
va = base+offset
pa, desc, shift = walk(va)
attr = (mair >> (((desc >> 2) & 7)*8)) & 255
if pa != va or not desc & (1 << 10) or desc & (1 << 7):
raise ValueError('host range must be identity mapped, accessed and writable')
if (device and attr != 0) or (not device and
(attr != 255 or (desc >> 8) & 3 != 3)):
raise ValueError('incompatible shared RAM or Device memory attributes')
if name == 'code' and desc & (1 << 54):
raise ValueError('secondary code is not executable')
witnesses.append(dict(name=name, va=hex(va), pa=hex(pa), desc=hex(desc),
leaf_shift=shift, memory_attribute=hex(attr)))
# These table pages are read through the primary's identity map. Check
# that assumption as well; newly encountered intermediate tables follow.
checked = set()
while tables-checked:
table = next(iter(tables-checked))
pa, desc, _ = walk(table)
if (pa != table or ((mair >> (((desc >> 2) & 7)*8)) & 255) != 255
or (desc >> 8) & 3 != 3 or not desc & (1 << 10)):
raise ValueError('host table is not identity-mapped normal WB memory')
checked.add(table)
return dict(mappings=witnesses, table_pages=[hex(p) for p in sorted(tables)])