2021-04-06 00:12:02 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
A helper application used to start bootstrapping process.
|
|
|
|
It has a few modes of operation, you can create initramfs with
|
|
|
|
binary seeds and sources that you can boot into or alternatively
|
|
|
|
you can run bootstap inside chroot.
|
|
|
|
"""
|
|
|
|
|
|
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
2021-12-25 18:19:01 +00:00
|
|
|
# SPDX-FileCopyrightText: 2022 Dor Askayo <dor.askayo@gmail.com>
|
2021-04-06 00:12:02 +01:00
|
|
|
# SPDX-FileCopyrightText: 2021 Andrius Štikonas <andrius@stikonas.eu>
|
2021-04-16 18:35:24 +01:00
|
|
|
# SPDX-FileCopyrightText: 2021 Bastian Bittorf <bb@npl.de>
|
2021-05-18 12:37:34 +01:00
|
|
|
# SPDX-FileCopyrightText: 2021 Melg Eight <public.melg8@gmail.com>
|
2023-01-28 00:11:32 +00:00
|
|
|
# SPDX-FileCopyrightText: 2021-23 fosslinux <fosslinux@aussies.space>
|
2021-04-06 00:12:02 +01:00
|
|
|
|
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
|
|
|
|
from sysa import SysA
|
2021-07-06 01:52:10 +01:00
|
|
|
from sysc import SysC
|
2021-08-05 13:16:19 +01:00
|
|
|
from lib.utils import run
|
2021-10-20 21:11:48 +01:00
|
|
|
from lib.sysgeneral import stage0_arch_map
|
2023-01-28 00:11:32 +00:00
|
|
|
from lib.tmpdir import Tmpdir
|
2021-07-06 01:52:10 +01:00
|
|
|
|
|
|
|
def create_configuration_file(args):
|
|
|
|
"""
|
|
|
|
Creates bootstrap.cfg file which would contain options used to
|
|
|
|
customize bootstrap.
|
|
|
|
"""
|
2021-10-03 02:28:08 +01:00
|
|
|
config_path = os.path.join('sysa', 'bootstrap.cfg')
|
2021-08-05 13:16:19 +01:00
|
|
|
with open(config_path, "w", encoding="utf_8") as config:
|
2023-04-10 06:30:16 +01:00
|
|
|
config.write(f"FORCE_TIMESTAMPS={args.force_timestamps}\n")
|
|
|
|
config.write(f"CHROOT={args.chroot or args.bwrap}\n")
|
|
|
|
config.write(f"CHROOT_ONLY_SYSA={args.bwrap}\n")
|
|
|
|
config.write(f"UPDATE_CHECKSUMS={args.update_checksums}\n")
|
|
|
|
config.write(f"JOBS={args.cores}\n")
|
2023-01-29 10:07:56 +00:00
|
|
|
config.write("DISK=sda1\n")
|
2023-04-03 19:07:24 +01:00
|
|
|
if (args.bare_metal or args.qemu) and not args.kernel:
|
2023-03-31 19:08:50 +01:00
|
|
|
config.write("KERNEL_BOOTSTRAP=True\n")
|
2023-04-03 19:07:24 +01:00
|
|
|
else:
|
|
|
|
config.write("KERNEL_BOOTSTRAP=False\n")
|
2023-04-16 11:14:26 +01:00
|
|
|
config.write(f"BUILD_KERNELS={args.update_checksums or args.build_kernels}\n")
|
2021-04-06 00:12:02 +01:00
|
|
|
|
2022-05-23 06:56:18 +01:00
|
|
|
# pylint: disable=too-many-statements
|
2021-04-06 00:12:02 +01:00
|
|
|
def main():
|
|
|
|
"""
|
|
|
|
A few command line arguments to customize bootstrap.
|
|
|
|
This function also creates SysA object which prepares directory
|
|
|
|
structure with bootstrap seeds and all sources.
|
|
|
|
"""
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("-a", "--arch", help="Bootstrap architecture",
|
|
|
|
default="x86")
|
|
|
|
parser.add_argument("-c", "--chroot", help="Run inside chroot",
|
|
|
|
action="store_true")
|
2021-12-25 18:19:01 +00:00
|
|
|
parser.add_argument("-bw", "--bwrap", help="Run inside a bwrap sandbox",
|
|
|
|
action="store_true")
|
2022-05-23 15:02:33 +01:00
|
|
|
parser.add_argument("-p", "--preserve", help="Do not remove temporary dir",
|
2021-04-06 00:12:02 +01:00
|
|
|
action="store_true")
|
2023-01-28 00:11:32 +00:00
|
|
|
parser.add_argument("-t", "--tmpdir", help="Temporary directory",
|
|
|
|
default="tmp")
|
|
|
|
parser.add_argument("--tmpfs", help="Use a tmpfs on tmpdir",
|
|
|
|
action="store_true")
|
|
|
|
parser.add_argument("--tmpfs-size", help="Size of the tmpfs",
|
|
|
|
default="8G")
|
2023-04-10 06:30:16 +01:00
|
|
|
parser.add_argument("--cores", help="Cores to use for building",
|
|
|
|
default=2)
|
2022-04-07 00:09:45 +01:00
|
|
|
parser.add_argument("--force-timestamps",
|
2021-05-18 12:37:34 +01:00
|
|
|
help="Force all files timestamps to be 0 unix time",
|
|
|
|
action="store_true")
|
2022-04-07 00:09:45 +01:00
|
|
|
parser.add_argument("--update-checksums",
|
|
|
|
help="Update checksum files.",
|
|
|
|
action="store_true")
|
2022-05-22 01:03:21 +01:00
|
|
|
parser.add_argument("--external-sources",
|
2022-05-23 06:56:18 +01:00
|
|
|
help="Download sources externally from live-bootstrap.",
|
|
|
|
action="store_true")
|
2023-04-14 22:16:05 +01:00
|
|
|
parser.add_argument("--build-kernels",
|
|
|
|
help="Also build kernels in chroot and bwrap builds.",
|
|
|
|
action="store_true")
|
2021-10-03 02:28:08 +01:00
|
|
|
parser.add_argument("--no-create-config",
|
|
|
|
help="Do not automatically create config file",
|
|
|
|
action="store_true")
|
2022-05-28 22:59:42 +01:00
|
|
|
parser.add_argument("-r", "--repo",
|
|
|
|
help="Path to prebuilt binary packages.", nargs=None)
|
2022-12-21 03:17:37 +00:00
|
|
|
parser.add_argument("--early-preseed",
|
|
|
|
help="Skip early stages of live-bootstrap.", nargs=None)
|
2021-04-06 00:12:02 +01:00
|
|
|
|
|
|
|
# QEMU arguments
|
2021-10-03 02:28:08 +01:00
|
|
|
parser.add_argument("-q", "--qemu", help="Use QEMU",
|
|
|
|
action="store_true")
|
|
|
|
parser.add_argument("-qc", "--qemu-cmd", help="QEMU command to run",
|
2021-04-06 00:12:02 +01:00
|
|
|
default="qemu-system-x86_64")
|
2021-10-03 02:28:08 +01:00
|
|
|
parser.add_argument("-qr", "--qemu-ram", help="Memory (in megabytes) allocated to QEMU VM",
|
2021-10-09 08:04:00 +01:00
|
|
|
default=4096)
|
2023-04-11 07:36:25 +01:00
|
|
|
parser.add_argument("-qk", "--kernel", help="Custom sysa kernel to use")
|
2021-04-06 00:12:02 +01:00
|
|
|
|
2021-10-03 02:28:08 +01:00
|
|
|
parser.add_argument("-b", "--bare-metal", help="Build images for bare metal",
|
|
|
|
action="store_true")
|
2021-04-06 00:12:02 +01:00
|
|
|
|
|
|
|
args = parser.parse_args()
|
2021-10-03 02:28:08 +01:00
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
# Mode validation
|
2021-10-03 02:28:08 +01:00
|
|
|
def check_types():
|
|
|
|
count = 0
|
|
|
|
if args.qemu:
|
|
|
|
count += 1
|
|
|
|
if args.chroot:
|
|
|
|
count += 1
|
2021-12-25 18:19:01 +00:00
|
|
|
if args.bwrap:
|
|
|
|
count += 1
|
2021-10-03 02:28:08 +01:00
|
|
|
if args.bare_metal:
|
|
|
|
count += 1
|
|
|
|
return count
|
|
|
|
|
|
|
|
if check_types() > 1:
|
2023-01-28 00:11:32 +00:00
|
|
|
raise ValueError("No more than one of qemu, chroot, bwrap, bare metal"
|
2023-01-13 08:28:30 +00:00
|
|
|
"may be used.")
|
2021-10-03 02:28:08 +01:00
|
|
|
if check_types() == 0:
|
2023-01-28 00:11:32 +00:00
|
|
|
raise ValueError("One of qemu, chroot, bwrap, or bare metal must be selected.")
|
2021-04-06 00:12:02 +01:00
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
# Arch validation
|
2021-04-06 00:12:02 +01:00
|
|
|
if args.arch != "x86":
|
|
|
|
raise ValueError("Only x86 is supported at the moment.")
|
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
# Tmp validation
|
|
|
|
if args.bwrap and args.tmpfs:
|
2023-01-28 17:14:20 +00:00
|
|
|
raise ValueError("tmpfs cannot be used with bwrap.")
|
2023-01-28 00:11:32 +00:00
|
|
|
|
2023-04-10 06:30:16 +01:00
|
|
|
# Cores validation
|
|
|
|
if int(args.cores) < 1:
|
|
|
|
raise ValueError("Must use one or more cores.")
|
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
# bootstrap.cfg
|
|
|
|
if args.bare_metal:
|
|
|
|
args.no_create_config = True
|
|
|
|
|
2021-10-03 02:28:08 +01:00
|
|
|
try:
|
|
|
|
os.remove(os.path.join('sysa', 'bootstrap.cfg'))
|
|
|
|
except FileNotFoundError:
|
|
|
|
pass
|
|
|
|
if not args.no_create_config:
|
|
|
|
create_configuration_file(args)
|
|
|
|
else:
|
|
|
|
with open(os.path.join('sysa', 'bootstrap.cfg'), 'a', encoding='UTF-8'):
|
|
|
|
pass
|
2021-04-06 00:12:02 +01:00
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
# tmpdir
|
|
|
|
tmpdir = Tmpdir(path=args.tmpdir, preserve=args.preserve)
|
|
|
|
if args.tmpfs:
|
|
|
|
tmpdir.tmpfs(size=args.tmpfs_size)
|
2021-04-06 00:12:02 +01:00
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
# sys
|
|
|
|
system_c = SysC(arch=args.arch, tmpdir=tmpdir,
|
|
|
|
external_sources=args.external_sources)
|
|
|
|
system_a = SysA(arch=args.arch, early_preseed=args.early_preseed,
|
|
|
|
tmpdir=tmpdir, external_sources=args.external_sources,
|
|
|
|
repo_path=args.repo)
|
2022-09-07 21:37:00 +01:00
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
bootstrap(args, system_a, system_c, tmpdir)
|
2021-04-06 00:12:02 +01:00
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
def bootstrap(args, system_a, system_c, tmpdir):
|
2021-04-06 00:12:02 +01:00
|
|
|
"""Kick off bootstrap process."""
|
2021-09-20 05:31:10 +01:00
|
|
|
print(f"Bootstrapping {args.arch} -- SysA")
|
2021-04-06 00:12:02 +01:00
|
|
|
if args.chroot:
|
2021-04-21 23:54:14 +01:00
|
|
|
find_chroot = """
|
|
|
|
import shutil
|
|
|
|
print(shutil.which('chroot'))
|
|
|
|
"""
|
|
|
|
chroot_binary = run('sudo', 'python3', '-c', find_chroot,
|
|
|
|
capture_output=True).stdout.decode().strip()
|
2021-10-20 21:11:48 +01:00
|
|
|
|
2023-01-28 00:11:32 +00:00
|
|
|
system_c.prepare(create_disk_image=False)
|
|
|
|
system_a.prepare(create_initramfs=False)
|
2022-05-23 12:18:52 +01:00
|
|
|
|
2021-10-20 21:11:48 +01:00
|
|
|
arch = stage0_arch_map.get(args.arch, args.arch)
|
|
|
|
init = os.path.join(os.sep, 'bootstrap-seeds', 'POSIX', arch, 'kaem-optional-seed')
|
2021-07-06 01:52:10 +01:00
|
|
|
run('sudo', 'env', '-i', 'PATH=/bin', chroot_binary, system_a.tmp_dir, init)
|
|
|
|
|
2021-12-25 18:19:01 +00:00
|
|
|
elif args.bwrap:
|
2023-01-28 00:11:32 +00:00
|
|
|
system_c.prepare(create_disk_image=False)
|
|
|
|
system_a.prepare(create_initramfs=False)
|
2021-12-25 18:19:01 +00:00
|
|
|
|
|
|
|
arch = stage0_arch_map.get(args.arch, args.arch)
|
|
|
|
init = os.path.join(os.sep, 'bootstrap-seeds', 'POSIX', arch, 'kaem-optional-seed')
|
|
|
|
run('bwrap', '--unshare-user',
|
|
|
|
'--uid', '0',
|
|
|
|
'--gid', '0',
|
2023-04-13 17:52:37 +01:00
|
|
|
'--unshare-net',
|
2021-12-25 18:19:01 +00:00
|
|
|
'--clearenv',
|
|
|
|
'--setenv', 'PATH', '/usr/bin',
|
|
|
|
'--bind', system_a.tmp_dir, '/',
|
|
|
|
'--dir', '/dev',
|
|
|
|
'--dev-bind', '/dev/null', '/dev/null',
|
|
|
|
'--dev-bind', '/dev/zero', '/dev/zero',
|
|
|
|
'--dev-bind', '/dev/random', '/dev/random',
|
|
|
|
'--dev-bind', '/dev/urandom', '/dev/urandom',
|
|
|
|
init)
|
|
|
|
|
2023-02-06 17:06:11 +00:00
|
|
|
run('bwrap', '--unshare-user',
|
|
|
|
'--uid', '0',
|
|
|
|
'--gid', '0',
|
2023-04-13 17:52:37 +01:00
|
|
|
'--unshare-net' if args.external_sources else None,
|
2023-02-06 17:06:11 +00:00
|
|
|
'--clearenv',
|
|
|
|
'--setenv', 'PATH', '/usr/bin',
|
|
|
|
'--bind', system_a.tmp_dir + "/sysc_image", '/',
|
|
|
|
'--dir', '/dev',
|
|
|
|
'--dev-bind', '/dev/null', '/dev/null',
|
|
|
|
'--dev-bind', '/dev/zero', '/dev/zero',
|
|
|
|
'--dev-bind', '/dev/random', '/dev/random',
|
|
|
|
'--dev-bind', '/dev/urandom', '/dev/urandom',
|
|
|
|
'--tmpfs', '/dev/shm',
|
|
|
|
'--proc', '/proc',
|
|
|
|
'--bind', '/sys', '/sys',
|
|
|
|
'--tmpfs', '/tmp',
|
|
|
|
'/init')
|
|
|
|
|
2021-10-03 02:28:08 +01:00
|
|
|
elif args.bare_metal:
|
2023-03-31 19:08:50 +01:00
|
|
|
if args.kernel:
|
|
|
|
system_c.prepare(create_disk_image=True)
|
|
|
|
system_a.prepare(create_initramfs=True)
|
|
|
|
print("Please:")
|
|
|
|
print(" 1. Take tmp/sysa/initramfs and your kernel, boot using this.")
|
|
|
|
print(" 2. Take tmp/sysc/disk.img and put this on a writable storage medium.")
|
|
|
|
else:
|
|
|
|
system_a.prepare(create_initramfs=True, kernel_bootstrap=True)
|
|
|
|
print("Please:")
|
|
|
|
print(" 1. Take tmp/sysa/sysa.img and write it to a boot drive and then boot it.")
|
2021-10-03 02:28:08 +01:00
|
|
|
|
2021-07-06 01:52:10 +01:00
|
|
|
else:
|
2023-03-31 19:08:50 +01:00
|
|
|
if args.kernel:
|
|
|
|
system_c.prepare(create_disk_image=True)
|
|
|
|
system_a.prepare(create_initramfs=True)
|
|
|
|
|
|
|
|
run(args.qemu_cmd,
|
|
|
|
'-enable-kvm',
|
|
|
|
'-m', str(args.qemu_ram) + 'M',
|
2023-04-10 06:30:16 +01:00
|
|
|
'-smp', str(args.cores),
|
2023-03-31 19:08:50 +01:00
|
|
|
'-no-reboot',
|
|
|
|
'-hda', tmpdir.get_disk("sysc"),
|
|
|
|
'-nic', 'user,ipv6=off,model=e1000',
|
|
|
|
'-kernel', args.kernel,
|
|
|
|
'-initrd', system_a.initramfs_path,
|
|
|
|
'-nographic',
|
|
|
|
'-append', 'console=ttyS0')
|
|
|
|
else:
|
|
|
|
system_a.prepare(create_initramfs=True, kernel_bootstrap=True)
|
|
|
|
run(args.qemu_cmd,
|
|
|
|
'-enable-kvm',
|
|
|
|
'-m', "4G",
|
2023-04-10 06:30:16 +01:00
|
|
|
'-smp', str(args.cores),
|
2023-03-31 19:08:50 +01:00
|
|
|
'-no-reboot',
|
|
|
|
'-drive', 'file=' + os.path.join(system_a.tmp_dir, 'sysa.img') + ',format=raw',
|
|
|
|
'-machine', 'kernel-irqchip=split',
|
|
|
|
'-nic', 'user,ipv6=off,model=e1000',
|
|
|
|
'-nographic')
|
2021-04-06 00:12:02 +01:00
|
|
|
|
2021-04-16 18:35:24 +01:00
|
|
|
if __name__ == "__main__":
|
2021-04-06 00:12:02 +01:00
|
|
|
main()
|