Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
86 lines
4.6 KiB
Python
86 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: MPL-2.0
|
|
"""Mount the inventoried Sargo HAL read-only, with disposable init/data overlays."""
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
import subprocess
|
|
import hal_policy
|
|
from hal_policy import filter_rc, is_init_script
|
|
|
|
|
|
def run(*args):subprocess.run(args,check=True)
|
|
def directory(p):Path(p).mkdir(parents=True,exist_ok=True)
|
|
def overlay(lower,target,label):
|
|
upper='/run/tundra/'+label+'-upper';work='/run/tundra/'+label+'-work'
|
|
for p in (upper,work,target):directory(p)
|
|
run('mount','-t','overlay','overlay','-o',f'lowerdir={lower},upperdir={upper},workdir={work}',target)
|
|
|
|
|
|
def main():
|
|
if os.getuid()!=0:raise RuntimeError('HAL mounts require root')
|
|
# This service only runs in the temporary boot assembled by rescue-init.
|
|
if 'tundra.rescue=1' not in Path('/proc/cmdline').read_text():raise RuntimeError('Temporary boot flag missing')
|
|
directory('/var/lib/lxc')
|
|
if Path('/run/tundra/hal-ready').is_file():return
|
|
network = Path('/etc/tundra/network-enabled').is_file()
|
|
if network:
|
|
# Never let the experimental modem firmware write the installed NV.
|
|
# rmt_storage opens these paths as files; no block device is exposed.
|
|
destination = Path('/run/tundra/nv-block/bootdevice/by-name')
|
|
destination.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
partitions = {'modemst1': (46,2097152), 'modemst2': (47,2097152),
|
|
'fsg': (12,2097152), 'fsc': (42,131072)}
|
|
for name, (number, size) in partitions.items():
|
|
device = 'mmcblk0p'+str(number)
|
|
sectors = int(Path('/sys/class/block',device,'size').read_text())
|
|
if sectors*512 != size:
|
|
raise RuntimeError('Unexpected NV partition size: '+name)
|
|
with open('/dev/'+device,'rb',buffering=0) as source:
|
|
data = source.read(size)
|
|
if len(data) != size:raise RuntimeError('Incomplete NV read: '+name)
|
|
target = destination/name
|
|
target.write_bytes(data)
|
|
target.chmod(0o600)
|
|
hal_policy.SERVICES = hal_policy.SERVICES | hal_policy.NETWORK_SERVICES
|
|
if Path('/etc/tundra/hardware-enabled').is_file():
|
|
hal_policy.SERVICES = hal_policy.SERVICES | hal_policy.HARDWARE_SERVICES
|
|
for p in ('/run/tundra/android-original','/run/tundra/vendor-original','/dev/__properties__','/dev/socket','/mnt/vendor/persist'):
|
|
directory(p)
|
|
image=Path('/reference/android-rootfs.img')
|
|
with image.open('rb') as f:sha=hashlib.file_digest(f,'sha256').hexdigest()
|
|
if sha!='132d0e18c6a6a111293447e940267f35aa2b14fa00a872ef160b20dc2014d886':raise RuntimeError('Android reference changed')
|
|
run('mount','-t','ext4','-o','loop,ro,noload',str(image),'/run/tundra/android-original')
|
|
run('mount','-t','ext4','-o','ro,noload','/dev/mmcblk0p70','/run/tundra/vendor-original')
|
|
run('mount','-t','ext4','-o','ro,noload','/dev/mmcblk0p48','/mnt/vendor/persist')
|
|
overlay('/run/tundra/android-original','/android','android')
|
|
overlay('/run/tundra/vendor-original','/android/vendor','vendor')
|
|
if network:
|
|
# IPA firmware is not initialized in the minimal HAL. Enabling its WLAN
|
|
# offload dereferences a null ipahal context when the interface comes up.
|
|
config = Path('/android/vendor/firmware/wlan/qca_cld/WCNSS_qcom_cfg.ini')
|
|
text, count = re.subn(r'^gIPAConfig=.*$', 'gIPAConfig=0', config.read_text(), flags=re.M)
|
|
if count != 1:raise RuntimeError('Expected exactly one Sargo WLAN IPA setting')
|
|
config.write_text(text) # vendor overlay upper is tmpfs, never the partition
|
|
directory('/android/vendor/firmware_mnt')
|
|
run('mount','-t','vfat','-o','ro','/dev/mmcblk0p21','/android/vendor/firmware_mnt')
|
|
report={}
|
|
for p in sorted(Path('/android').rglob('*.rc')):
|
|
if not p.is_file() or p.is_symlink() or not is_init_script(p):continue
|
|
text=p.read_text();filtered,record=filter_rc(text);record['sourceSha256']=hashlib.sha256(text.encode()).hexdigest()
|
|
p.write_text(filtered);report[str(p)]=record
|
|
(Path('/run/tundra')/'hal-policy-report.json').write_text(json.dumps(report,indent=2))
|
|
# The container cannot open block devices. Its data and metadata live in RAM.
|
|
for p in ('/android/data','/android/metadata'):
|
|
run('mount','-t','tmpfs','-o','mode=0771','tmpfs',p)
|
|
for p in ('/system','/vendor'):
|
|
path=Path(p)
|
|
if not path.is_symlink():
|
|
if path.exists():path.rmdir()
|
|
path.symlink_to('/android'+p)
|
|
Path('/run/tundra/hal-ready').touch()
|
|
|
|
|
|
if __name__=='__main__':main()
|