Files
DroidDeck/tools/qualcomm/fetch_runtime.py
T
K11MCH1 6339d00a7a Stage pinned Qualcomm bridge and constant-index shader compatibility
(cherry picked from commit 03ca7778eff0a1216a57c7e7933297c49ea14532)
(cherry picked from commit ca9f416118)
2026-10-25 23:08:48 +00:00

67 lines
3.0 KiB
Python

"""Stage the checksum-pinned ARM64 glibc bridge, including its corresponding source."""
import argparse
import hashlib
import json
from pathlib import Path
import shutil
import urllib.request
import zipfile
def fetch(cache, lock):
expected = lock['sha256']
cache.mkdir(parents=True, exist_ok=True)
archive = cache / (expected + '.tzst')
def valid(path):
return path.is_file() and path.stat().st_size == lock['size'] and hashlib.sha256(path.read_bytes()).hexdigest() == expected
if not valid(archive):
temporary = archive.with_suffix('.partial')
try:
with urllib.request.urlopen(lock['url'], timeout=120) as source, temporary.open('wb') as target:
shutil.copyfileobj(source, target)
if not valid(temporary):
raise ValueError('Qualcomm bridge archive failed SHA-256 verification')
temporary.replace(archive)
finally:
temporary.unlink(missing_ok=True)
return archive
def stage(output, cache, lock, ndk=None):
archive = fetch(cache, lock)
output.mkdir(parents=True, exist_ok=True)
shutil.copyfile(archive, output / 'runtime.tzst')
gamescope = lock['gamescope']
with zipfile.ZipFile(fetch(cache, gamescope)) as package:
binary = package.read(gamescope['member'])
if hashlib.sha256(binary).hexdigest() != gamescope['member_sha256']:
raise ValueError('Qualcomm Gamescope binary failed SHA-256 verification')
(output / 'gamescope').write_bytes(binary)
if 'wsi' in lock:
with zipfile.ZipFile(fetch(cache, lock['wsi'])) as package:
for entry in lock['wsi']['files']:
target = Path(entry['path'])
if target.is_absolute() or '..' in target.parts:
raise ValueError('Invalid WSI destination')
data = package.read(entry['name'])
if len(data) != entry['size'] or hashlib.sha256(data).hexdigest() != entry['sha256']:
raise ValueError('Qualcomm WSI member failed SHA-256 verification')
destination = output / target
destination.parent.mkdir(parents=True, exist_ok=True)
destination.write_bytes(data)
if 'shaders' in lock:
if ndk is None:
raise ValueError('The Android NDK is required to build Qualcomm shader compatibility')
from build_shaders import build
build(output / 'shaders', fetch(cache, lock['shaders']), lock['shaders'], ndk)
(output / 'runtime.json').write_text(json.dumps(lock, indent=2) + '\n', encoding='utf-8')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--output', type=Path, required=True)
parser.add_argument('--cache', type=Path, required=True)
parser.add_argument('--ndk', type=Path, required=True)
args = parser.parse_args()
stage(args.output, args.cache, json.loads(Path(__file__).with_name('runtime.json').read_text()), args.ndk)