mirror of
https://github.com/minexew/Shrine.git
synced 2026-05-26 18:10:58 +00:00
142 lines
3.8 KiB
Python
Executable File
142 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
'''
|
|
Build a distribution ISO.
|
|
|
|
Typical usage:
|
|
qemu-img create -f qcow2 ~/disk.img 2G
|
|
./make-dist.py ~/TempleOSCD-v502.ISO Shrine ~/disk.img
|
|
|
|
|
|
The process is mostly automated, though at one point it's necessary
|
|
to press "1" to select the boot drive.
|
|
|
|
This works by binary-patching the TempleOS dist ISO to enter a reduced
|
|
version of MFA immediately upon start-up. (see inject_templeos.py)
|
|
The OS installation script is also modified so no user input is required.
|
|
|
|
After booting into the installed OS, distribution install script is run,
|
|
which will typically include building and exporting a distribution ISO.
|
|
'''
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('install_iso')
|
|
parser.add_argument('distro_dir')
|
|
parser.add_argument('disk_img')
|
|
parser.add_argument('--skip-tos-install', dest='skip_tos_install',
|
|
action='store_true')
|
|
args = parser.parse_args()
|
|
|
|
INSTALL_ISO = args.install_iso
|
|
DISTRO_DIR = args.distro_dir
|
|
DISK_IMG = args.disk_img
|
|
|
|
MEM_SIZE = 512
|
|
MFA_PORT = 7770
|
|
SNAIL_PORT = 7777
|
|
QEMU_START_DELAY = 3
|
|
|
|
SLAVE_HC_Z = 'AutoOSInstall/SlaveOnce.HC.Z'
|
|
|
|
AUTO_INSTALL_PATH = 'AutoOSInstall'
|
|
AUTO_INSTALL_TIMEOUT = 300
|
|
|
|
PATCHED_ISO = 'TempleSlave.iso'
|
|
|
|
QEMU_COMMAND = [
|
|
'qemu-system-x86_64',
|
|
'-hda', DISK_IMG,
|
|
'-machine', 'kernel_irqchip=off',
|
|
'-smp', 'cores=1',
|
|
'-m', str(MEM_SIZE),
|
|
'-rtc', 'base=localtime',
|
|
'-soundhw', 'pcspk',
|
|
'-serial', 'tcp::%d,server' % MFA_PORT]
|
|
|
|
ENABLE_KVM = True
|
|
|
|
if ENABLE_KVM:
|
|
QEMU_COMMAND += ['-enable-kvm', '-cpu', 'host']
|
|
|
|
SELF_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
INJECT_BIN = os.path.join(SELF_DIR, 'inject_templeos.py')
|
|
MFA_BIN = os.path.join(SELF_DIR, 'mfa.py')
|
|
SNAIL_BIN = os.path.join(SELF_DIR, 'snail.py')
|
|
|
|
def wait_for_subprocess(subpr, timeout):
|
|
while timeout >= 0:
|
|
if subpr.poll() is not None:
|
|
return
|
|
|
|
time.sleep(1)
|
|
timeout -= 1
|
|
|
|
raise Exception('Subprocess didn\'t finish in time')
|
|
|
|
def run_qemu_and_mfa(qemu_command, mfa_script, timeout, with_snail=False):
|
|
if with_snail:
|
|
qemu_command = qemu_command + ['-serial', 'null',
|
|
'-serial', 'tcp::%d,server' % SNAIL_PORT]
|
|
|
|
qemu = subprocess.Popen(qemu_command)
|
|
time.sleep(QEMU_START_DELAY)
|
|
|
|
if qemu.poll() is not None:
|
|
raise Exception('QEMU failed to start')
|
|
|
|
snail = None
|
|
|
|
try:
|
|
with open(mfa_script, 'rb') as script:
|
|
mfa = subprocess.Popen([MFA_BIN], stdin=script)
|
|
|
|
if with_snail:
|
|
time.sleep(3)
|
|
snail = subprocess.Popen([SNAIL_BIN])
|
|
|
|
wait_for_subprocess(mfa, timeout)
|
|
|
|
if mfa.returncode != 0:
|
|
raise Exception('MFA script failed')
|
|
finally:
|
|
if snail: snail.kill()
|
|
|
|
qemu.terminate()
|
|
time.sleep(5)
|
|
qemu.kill()
|
|
|
|
wait_for_subprocess(qemu, 10)
|
|
|
|
if not args.skip_tos_install:
|
|
shutil.copy(INSTALL_ISO, PATCHED_ISO)
|
|
subprocess.check_call([INJECT_BIN, PATCHED_ISO, 'Once.HC.Z', SLAVE_HC_Z])
|
|
|
|
run_qemu_and_mfa(QEMU_COMMAND + ['-cdrom', PATCHED_ISO, '-boot', 'd'],
|
|
os.path.join(AUTO_INSTALL_PATH, 'install.script'), AUTO_INSTALL_TIMEOUT)
|
|
|
|
mkdist_script = os.path.join(DISTRO_DIR, 'mkdist.script')
|
|
mkdist_timeout = float(open(os.path.join(DISTRO_DIR, 'mkdist-timeout')).read())
|
|
|
|
print()
|
|
print('=====================================================')
|
|
print(' Ready to install %s. Press Enter to continue.' % DISTRO_DIR)
|
|
print(' As soon as the TempleOS boot menu appears, press 1.')
|
|
|
|
if sys.version_info[0] < 3:
|
|
raw_input()
|
|
else:
|
|
input()
|
|
|
|
run_qemu_and_mfa(QEMU_COMMAND, mkdist_script, mkdist_timeout, with_snail=False)
|
|
|
|
print('Success.')
|