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.
103 lines
3.8 KiB
Python
Executable File
103 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: MIT
|
|
"""A BSDIFF40 patch for /usr/bin/bspatch, from block matches (no suffix sort).
|
|
|
|
python3 tools/bsdiff-lite.py OLD NEW PATCH
|
|
|
|
The format is bsdiff 4.3's (header, then bzip2'd control, diff and extra blocks), so any bspatch applies it. Matches
|
|
are found only on 16-byte-aligned 32-byte blocks of OLD and extended both ways, so the patch is small only when NEW
|
|
is mostly OLD's bytes, possibly shifted: a rebuilt binary with an unchanged data payload. The patch is applied with
|
|
/usr/bin/bspatch before it is written, and must reproduce NEW exactly; otherwise nothing is written.
|
|
"""
|
|
import bz2
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
BLOCK, STEP = 32, 16
|
|
|
|
|
|
def offtout(x):
|
|
"""bsdiff's int64: sign-magnitude, little-endian, sign in bit 63."""
|
|
return (abs(x) | (1 << 63 if x < 0 else 0)).to_bytes(8, 'little')
|
|
|
|
|
|
def segments(old, new):
|
|
"""NEW as ('copy', old offset, length) and ('lit', bytes) runs, in order."""
|
|
index = {}
|
|
for i in range(0, len(old) - BLOCK + 1, STEP):
|
|
index.setdefault(old[i:i + BLOCK], i)
|
|
out, lit_start, p = [], 0, 0
|
|
while p + BLOCK <= len(new):
|
|
o = index.get(new[p:p + BLOCK])
|
|
if o is None:
|
|
p += 1
|
|
continue
|
|
start, ostart = p, o
|
|
while start > lit_start and ostart > 0 and new[start - 1] == old[ostart - 1]:
|
|
start, ostart = start - 1, ostart - 1
|
|
end, oend = p + BLOCK, o + BLOCK
|
|
while end < len(new) and oend < len(old) and new[end] == old[oend]:
|
|
end, oend = end + 1, oend + 1
|
|
if start > lit_start:
|
|
out.append(('lit', new[lit_start:start]))
|
|
out.append(('copy', ostart, end - start))
|
|
lit_start = p = end
|
|
if lit_start < len(new):
|
|
out.append(('lit', new[lit_start:]))
|
|
return out
|
|
|
|
|
|
def patch(old, new):
|
|
"""bspatch reads (x, y, z): x bytes of old+diff at oldpos, y bytes of extra, then oldpos += x + z."""
|
|
segs = segments(old, new)
|
|
ctrl, diff, extra = bytearray(), bytearray(), bytearray()
|
|
oldpos = newpos = i = 0
|
|
if segs and segs[0][0] == 'copy' and segs[0][1]:
|
|
ctrl += offtout(0) + offtout(0) + offtout(segs[0][1]) # seek old to the first copy
|
|
oldpos = segs[0][1]
|
|
while i < len(segs):
|
|
x = 0
|
|
if segs[i][0] == 'copy':
|
|
_, at, x = segs[i]
|
|
assert at == oldpos, (at, oldpos)
|
|
diff += bytes((a - b) & 0xFF for a, b in zip(new[newpos:newpos + x], old[at:at + x]))
|
|
newpos, oldpos, i = newpos + x, oldpos + x, i + 1
|
|
y = b''
|
|
if i < len(segs) and segs[i][0] == 'lit':
|
|
y = segs[i][1]
|
|
newpos, i = newpos + len(y), i + 1
|
|
nxt = segs[i][1] if i < len(segs) and segs[i][0] == 'copy' else oldpos
|
|
ctrl += offtout(x) + offtout(len(y)) + offtout(nxt - oldpos)
|
|
extra += y
|
|
oldpos = nxt
|
|
assert newpos == len(new)
|
|
c, d, e = (bz2.compress(bytes(b), 9) for b in (ctrl, diff, extra))
|
|
return b'BSDIFF40' + offtout(len(c)) + offtout(len(d)) + offtout(len(new)) + c + d + e
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 4:
|
|
print(__doc__)
|
|
return 64
|
|
old, new, out = Path(sys.argv[1]).read_bytes(), Path(sys.argv[2]).read_bytes(), Path(sys.argv[3])
|
|
if out.exists():
|
|
print(f'{out} exists')
|
|
return 64
|
|
data = patch(old, new)
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
p, r = Path(tmp) / 'patch', Path(tmp) / 'result'
|
|
p.write_bytes(data)
|
|
subprocess.run(['/usr/bin/bspatch', sys.argv[1], str(r), str(p)], check=True)
|
|
if r.read_bytes() != new:
|
|
print('FAIL: bspatch did not reproduce NEW')
|
|
return 1
|
|
out.write_bytes(data)
|
|
print(f'patch {len(data)} bytes for {len(new)} new bytes; /usr/bin/bspatch reproduces NEW exactly')
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|