Release Vulpes OS 2.7-preview.24
This commit is contained in:
parent
49572b6b45
commit
97ef99f827
135 changed files with 7717 additions and 2524 deletions
|
|
@ -18,6 +18,7 @@ from cryptography.hazmat.primitives import serialization
|
|||
from ramdisk_reference import read_newc, select_helpers
|
||||
from storage_layout import mount_table
|
||||
from shared_ui import compress_archive
|
||||
from kernel_cmdline import vulpes_cmdline
|
||||
from tundra import ROOT, cpio, checked_source, digest, save, linker
|
||||
|
||||
|
||||
|
|
@ -33,7 +34,9 @@ def main():
|
|||
parser.add_argument('--layout',type=Path,required=True)
|
||||
parser.add_argument('--device-workspace', type=Path,
|
||||
help='Private per-phone workspace; never use the development inventory')
|
||||
parser.add_argument('--native',action='store_true',help='Switch to the staged native root with a ten-minute watchdog')
|
||||
parser.add_argument('--native',action='store_true',help='Switch to the staged native root with a timed watchdog')
|
||||
parser.add_argument('--watchdog-seconds', type=int, default=600,
|
||||
help='RAM trial auto-reboot deadline (60–3600 seconds; default: 600)')
|
||||
parser.add_argument('--system-image',type=Path,help='system.json for a self-contained image staged at /tundra/images/<sha256>.ext4')
|
||||
parser.add_argument('--differential-ui', action='store_true', help='Bundle only UI files differing from the verified immutable system image')
|
||||
parser.add_argument('--hold-hal',action='store_true',help='Boot basic.target first so HAL startup can be traced over USB')
|
||||
|
|
@ -45,6 +48,8 @@ def main():
|
|||
parser.add_argument('--state', type=Path, help='Prepared Tundra data-image manifest; enables persistent writes in that file')
|
||||
parser.add_argument('--no-deadline', action='store_true', help='Keep the persistent development boot running; requires --state')
|
||||
args=parser.parse_args()
|
||||
if not 60 <= args.watchdog_seconds <= 3600:
|
||||
parser.error('--watchdog-seconds must be between 60 and 3600')
|
||||
if args.hold_hal and not args.native:parser.error('--hold-hal requires --native')
|
||||
if args.system_image and not args.native:parser.error('--system-image requires --native')
|
||||
if args.differential_ui and not args.system_image:parser.error('--differential-ui requires --system-image')
|
||||
|
|
@ -79,6 +84,9 @@ def main():
|
|||
else:
|
||||
plan,_=load_boot().checked_plan()
|
||||
storage_table = mount_table(layout)
|
||||
if state and storage_table is None and not (
|
||||
layout.get('schema') == 2 and layout.get('storage') == 'raw-userdata-ext4'):
|
||||
raise ValueError('Persistent trials require inventoried ext4 userdata')
|
||||
out=args.output.resolve();out.mkdir(parents=True,exist_ok=False)
|
||||
source=Path(plan['backupDirectory'])/'boot_a.img'
|
||||
packager=checked_source('aosp-mkbootimg')
|
||||
|
|
@ -86,6 +94,8 @@ def main():
|
|||
result=subprocess.check_output(['python3',str(packager/'unpack_bootimg.py'),'--boot_img',str(source),'--out',str(unpack),'--format=mkbootimg'],text=True)
|
||||
options=shlex.split(result);fields=dict(zip(options[::2],options[1::2]))
|
||||
if fields['--header_version']!='0':raise ValueError('Expected header v0')
|
||||
source_cmdline=fields['--cmdline']
|
||||
fields['--cmdline'],removed_kernel_parameters=vulpes_cmdline(source_cmdline)
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
helpers=select_helpers(read_newc((unpack/'ramdisk').read_bytes()),Path(temp),
|
||||
extra=('sbin/blkid','sbin/e2fsck') if state else ())
|
||||
|
|
@ -113,15 +123,23 @@ def main():
|
|||
(out/'known_hosts').write_text('[10.15.19.82]:2222 '+hostpublic+'\n[127.0.0.1]:2222 '+hostpublic+'\n')
|
||||
init=(ROOT/'boot/rescue-init.sh').read_bytes().replace(b'# No LVM activation',
|
||||
('EXPECTED_STORAGE_HASH='+shlex.quote(layout['firstMiBSha256'])+'\n# No LVM activation').encode())
|
||||
init=init.replace(b"'0 104448000 linear /dev/mmcblk0p72 329728'",
|
||||
shlex.quote(storage_table).encode())
|
||||
sources=[Path(__file__),ROOT/'boot/rescue-init.sh',ROOT/'tools/ramdisk_reference.py',
|
||||
if storage_table is None:
|
||||
uuid_hex=layout['filesystemUuid'].replace('-','')
|
||||
init=init.replace(b'# No LVM activation',
|
||||
('RAW_USERDATA_EXT4=1\nEXPECTED_STORAGE_UUID_HEX='+uuid_hex+
|
||||
'\n# No LVM activation').encode())
|
||||
else:
|
||||
init=init.replace(b"'0 104448000 linear /dev/mmcblk0p72 329728'",
|
||||
shlex.quote(storage_table).encode())
|
||||
sources=[Path(__file__),ROOT/'boot/rescue-init.sh',ROOT/'tools/kernel_cmdline.py',ROOT/'tools/ramdisk_reference.py',
|
||||
ROOT/'tools/storage_layout.py']
|
||||
if args.device_workspace:
|
||||
sources += [ROOT/'tools/sargo_workspace.py', ROOT/'tools/boot_backup.py']
|
||||
if state:
|
||||
# Keep the existing layout intact; only /tundra/data/<UUID>.ext4 is used
|
||||
# for Tundra state. Opening its containing filesystem RW is necessary.
|
||||
if storage_table is None:
|
||||
init=init.replace(b'RAW_USERDATA_EXT4=1',b'RAW_USERDATA_EXT4=1\nTUNDRA_USERDATA_RW=1')
|
||||
init=init.replace(b'--readonly --table', b'--table')
|
||||
init=init.replace(b'-o ro,noload /dev/mapper/tundra-installed-ro', b'-o rw /dev/mapper/tundra-installed-ro')
|
||||
init=init.replace(b'# Temporary RAM-only boot. Installed data is never mounted writable.', b'# Private persistent boot. Only the dedicated Tundra data file receives system writes.')
|
||||
|
|
@ -130,7 +148,7 @@ def main():
|
|||
shared_ui = {}
|
||||
if args.native:
|
||||
binary=out/'watchdog'
|
||||
subprocess.run(['clang','--target=aarch64-linux-gnu','--ld-path='+str(linker()),'-Os','-ffreestanding','-fno-builtin','-fno-stack-protector','-fno-pie','-fno-unwind-tables','-fno-asynchronous-unwind-tables','-Wall','-Wextra','-Werror','-nostdlib','-static','-Wl,--build-id=none','-Wl,-e,_start',str(ROOT/'boot/watchdog.c'),'-o',str(binary)],check=True)
|
||||
subprocess.run(['clang','--target=aarch64-linux-gnu','--ld-path='+str(linker()),'-Os','-ffreestanding','-fno-builtin','-fno-stack-protector','-fno-pie','-fno-unwind-tables','-fno-asynchronous-unwind-tables','-Wall','-Wextra','-Werror','-nostdlib','-static','-Wl,--build-id=none','-Wl,-e,_start','-DTUNDRA_WATCHDOG_SECONDS='+str(args.watchdog_seconds),str(ROOT/'boot/watchdog.c'),'-o',str(binary)],check=True)
|
||||
init=init.replace(b"(sleep 480; echo 'Tundra trial deadline reached'; reboot -f) &",b'/sbin/tundra-watchdog &')
|
||||
if args.no_deadline:
|
||||
init=init.replace(b'/sbin/tundra-watchdog &', b'# Persistent development boot: no timed reboot.')
|
||||
|
|
@ -174,6 +192,8 @@ def main():
|
|||
archive.add(config_dir, arcname=directory, filter=owned)
|
||||
files['native-config.tar']=(0o600,compress_archive(buffer.getvalue()))
|
||||
sources += list(sorted((ROOT/'runtime').glob('*.py')))
|
||||
if args.runtime_config:
|
||||
sources.append(ROOT/'tools/inspect-hardware.py')
|
||||
files['sbin/tundra-watchdog']=(0o755,binary.read_bytes())
|
||||
native_init=(ROOT/'boot/native-root.sh').read_bytes().replace(b'# BUILD_TIME_FLOOR', ('BUILD_EPOCH='+str(built_at)).encode())
|
||||
if args.runtime_config:
|
||||
|
|
@ -181,7 +201,8 @@ def main():
|
|||
if system:
|
||||
sha = system['imageSha256']
|
||||
native_init = native_init.replace(b'# A kernel fallback',
|
||||
('SYSTEM_IMAGE=/installed/tundra/images/'+sha+'.ext4\nSYSTEM_IMAGE_SHA='+sha+'\n# A kernel fallback').encode())
|
||||
('SYSTEM_IMAGE=/installed/tundra/images/'+sha+'.ext4\nSYSTEM_IMAGE_SHA='+sha+
|
||||
'\nSYSTEM_IMAGE_BYTES='+str(system['bytes'])+'\n# A kernel fallback').encode())
|
||||
# Bundle UI changes with the boot trial rather than retransferring
|
||||
# the entire immutable system image for each CSS/JS adjustment.
|
||||
from shared_ui import build_payload, differential_payload
|
||||
|
|
@ -240,9 +261,10 @@ def main():
|
|||
shutil.copy2(path,target)
|
||||
save(out/'build.json',{'scope':'Private persistent Sargo development boot; unqualified' if state else ('Private temporary native-root trial; unqualified' if args.native else 'Private temporary SSH boot; installed root read-only; no graphical session'),
|
||||
'builtAtUnix':built_at,'runtimeConfigOverlay':args.runtime_config,'networkTrial':args.network,'hardwareTrial':args.hardware,'interactiveDiagnostics':args.diagnostics,'image':image.name,'imageSha256':digest(image),'sourceBootSha256':digest(source),
|
||||
'removedKernelParameters':removed_kernel_parameters,
|
||||
'serialSha256':plan['serialSha256'],'kernelSha256':kernel_hash,
|
||||
'deviceWorkspaceSha256':plan.get('workspaceSha256'),
|
||||
'ramdiskSha256':digest(ramdisk),'roundtripPassed':True,'flashReady':False,'localDebugger':args.local_debugger,'watchdogSeconds':None if args.no_deadline else (600 if args.native else 480),'persistentState':state,'storageWrites':bool(state),'nativeRootRequested':args.native,'halHeldForDiagnostics':args.hold_hal,
|
||||
'ramdiskSha256':digest(ramdisk),'roundtripPassed':True,'flashReady':False,'localDebugger':args.local_debugger,'watchdogSeconds':None if args.no_deadline else (args.watchdog_seconds if args.native else 480),'persistentState':state,'storageWrites':bool(state),'nativeRootRequested':args.native,'halHeldForDiagnostics':args.hold_hal,
|
||||
'layout':layout,'layoutSha256':digest(args.layout),'systemImage':system,'sharedUiHashes':shared_ui,'sourceSnapshot':True,'sources':{str(p.relative_to(ROOT)):digest(p) for p in sources},
|
||||
'helpers':{n:__import__('hashlib').sha256(b).hexdigest() for n,b in helpers.items()},
|
||||
'sharedUiFilesAlreadyInSystem':omitted_ui if args.differential_ui else 0,
|
||||
|
|
|
|||
Loading…
Reference in a new issue