Release Vulpes OS 2.7-preview.22

This commit is contained in:
OverSu 2026-10-22 20:42:26 +02:00
commit a138f97877
294 changed files with 515786 additions and 187 deletions

View file

@ -0,0 +1,74 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MPL-2.0
"""Build an unsigned private Nokia boot trial. Never flashes or unlocks a phone."""
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
from beatles_boot import unpack_boot, pack_boot, read_cpio, write_cpio, add_file
ROOT=Path(__file__).resolve().parents[2]
ENGINE=ROOT/'tundra/out/beatles/gecko-156.0.1'
def digest(data):return hashlib.sha256(data).hexdigest()
def main():
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--backup',type=Path,default=ROOT/'tundra/out/beatles/backups/20261017')
parser.add_argument('--output',type=Path,required=True)
args=parser.parse_args();out=args.output.resolve()
if out.exists():raise ValueError('Choose a new output directory')
backup=json.loads((args.backup/'backup.json').read_text())
verified=json.loads((args.backup/'verification.json').read_text())
if backup['device']!='beatles' or backup['firmware']!='40.00.17.01':raise ValueError('Unsupported firmware')
for name in ('boot','recovery','aboot','abootbak'):
data=(args.backup/(name+'.img')).read_bytes(); record=backup['partitions'][name]
if len(data)!=record['bytes'] or digest(data)!=record['sha256'] or verified['partitions'][name]['sha256']!=record['sha256']:
raise ValueError('Backup verification failed: '+name)
original=(args.backup/'boot.img').read_bytes();parts=unpack_boot(original)
entries=read_cpio(parts['ramdisk'])
rc=entries['init.b2g.rc']['data']
expected=b'service b2g /system/bin/b2g.sh\n class main\n'
if rc.count(expected)!=1:raise ValueError('Unexpected KaiOS service definition')
entries['init.b2g.rc']['data']=rc.replace(expected,expected+b' disabled\n')
entries['init.rc']['data']+=b'\nimport /init.vulpes.rc\n'
out.mkdir(parents=True,mode=0o700)
sysroot=ENGINE/'sysroot/rootfs'
compiler=[str(ENGINE/'mozbuild/clang/bin/clang'),'--target=arm-linux-gnueabihf',
'--sysroot='+str(sysroot),'--gcc-install-dir='+str(sysroot/'usr/lib/gcc/arm-linux-gnueabihf/12'),
'-fuse-ld=lld','-march=armv7-a','-mfpu=neon','-mfloat-abi=hard','-O2','-Wall','-Wextra','-Werror']
subprocess.run(compiler+['-static',str(ROOT/'tundra/probes/beatles-control-client.c'),'-o',str(out/'control-client')],check=True)
supervisor=out/'vulpes-display'
subprocess.run(compiler+['-static',str(ROOT/'tundra/probes/beatles-display-session.c'),'-o',str(supervisor)],check=True)
add_file(entries,'sbin/vulpes-display',supervisor.read_bytes(),0o755)
for name in ('init.vulpes.rc','vulpes-boot.sh'):
add_file(entries,name,(ROOT/'tundra/devices/beatles/boot'/name).read_bytes(),0o755 if name.endswith('.sh') else 0o644)
ramdisk=write_cpio(entries);image=pack_boot(original,ramdisk)
if len(image)>backup['partitions']['boot']['bytes']:raise ValueError('Boot partition too small')
check=unpack_boot(image)
if check['kernel']!=parts['kernel']:raise ValueError('Kernel changed')
reread=read_cpio(check['ramdisk'])
for name,value in entries.items():
if reread[name]['data']!=value['data']:raise ValueError('Ramdisk data mismatch: '+name)
# Only size/name size may change when serializing; owners and modes must survive.
if any(reread[name]['fields'][i]!=value['fields'][i] for i in (0,1,2,3,4,5,7,8,9,10,12)):
raise ValueError('Ramdisk metadata mismatch: '+name)
name='vulpes-beatles-boot-trial-UNSIGNED.img';(out/name).write_bytes(image)
record={'device':'beatles','firmware':'40.00.17.01','image':name,'sha256':digest(image),
'bytes':len(image),'kernelSha256':digest(parts['kernel']),'originalBootSha256':digest(original),
'controlClientSha256':digest((out/'control-client').read_bytes()),
'gecko':'156.0.1','runtimePath':'/data/local/vulpes-beatles','deadlineSeconds':1800,
'unsigned':True,'bootTested':False,'flashReady':False,'standaloneSystem':False,
'dependencies':['Existing vendor /system and modem partitions','Prepared persistent runtime, not included in boot partition'],
'recovery':'KaiOS fallback if runtime is missing or fails, or after 30 minutes; boot partition restoration not qualified',
'sourceFiles':{str(p.relative_to(ROOT)):digest(p.read_bytes()) for p in [Path(__file__),ROOT/'tundra/tools/beatles_boot.py',ROOT/'tundra/probes/beatles-display-session.c',ROOT/'tundra/probes/beatles-control-client.c',ROOT/'tundra/probes/beatles-lid.h',ROOT/'tundra/probes/beatles-hall.h',ROOT/'tundra/devices/beatles/boot/init.vulpes.rc',ROOT/'tundra/devices/beatles/boot/vulpes-boot.sh']}}
(out/'build.json').write_text(json.dumps(record,indent=2)+'\n')
(out/'SHA256SUMS').write_text(record['sha256']+' '+name+'\n')
print('Built private unsigned boot trial:',out/name)
print('Not boot-tested or flash-qualified; existing vendor system and staged runtime required.')
if __name__=='__main__':main()