diff --git a/boot-qemu.py b/boot-qemu.py index 879ed9d..40044e0 100755 --- a/boot-qemu.py +++ b/boot-qemu.py @@ -52,6 +52,7 @@ def __init__(self): self.kernel = None self.kernel_dir = None self.memory = '1G' + self.modules = None self.supports_efi = False # It may be tempting to use self.use_kvm during initialization of # subclasses to set certain properties but the user can explicitly opt @@ -173,7 +174,8 @@ def _prepare_initrd(self): if not self._initrd_arch: raise RuntimeError('No initrd architecture specified?') return utils.prepare_initrd(self._initrd_arch, - gh_json_file=self.gh_json_file) + gh_json_file=self.gh_json_file, + modules=self.modules) def _run_fg(self): # Pretty print and run QEMU command @@ -854,6 +856,12 @@ def parse_arguments(): help= "Value for '-m' QEMU option (default: generally '512m', depends on machine)", ) + parser.add_argument( + '-M', + '--modules', + help= + 'Path to .cpio generated with the Linux kernel\'s "modules-cpio-pkg" target' + ) parser.add_argument( '-s', '--smp', @@ -937,6 +945,16 @@ def parse_arguments(): if args.memory: runner.memory = args.memory + if args.modules: + if not (modules := Path(args.modules).resolve()).exists(): + raise FileNotFoundError( + f"Supplied modules .cpio ('{modules}') does not exist?") + if not args.memory: + utils.yellow( + 'Memory not specified, the default may be too small for modules...' + ) + runner.modules = modules + if args.no_kvm: runner.use_kvm = False diff --git a/utils.py b/utils.py index 6ca0846..b3b9bcf 100755 --- a/utils.py +++ b/utils.py @@ -172,7 +172,10 @@ def green(string): print(f"\n\033[01;32m{string}\033[0m", flush=True) -def prepare_initrd(architecture, rootfs_format='cpio', gh_json_file=None): +def prepare_initrd(architecture, + rootfs_format='cpio', + gh_json_file=None, + modules=None): """ Returns a decompressed initial ramdisk. @@ -228,6 +231,24 @@ def prepare_initrd(architecture, rootfs_format='cpio', gh_json_file=None): (dst := src.with_suffix('')).unlink(missing_ok=True) subprocess.run(['zstd', '-d', src, '-o', dst, '-q'], check=True) + if modules: + # "new" cpio magic bytes + cpio_sig = bytes([0x30, 0x37, 0x30, 0x37, 0x30, 0x31]) + with modules.open('rb') as module_file: + if module_file.read(6) != cpio_sig: + raise RuntimeError( + f"{modules} does not have cpio magic bytes, was it generated with the 'modules-cpio-pkg' target?" + ) + + (new_dst := + dst.parent.joinpath('rootfs-modules.cpio')).unlink(missing_ok=True) + with subprocess.Popen(['cat', dst, modules], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) as proc, new_dst.open( + 'xb') as dst_file: + dst_file.write(proc.stdout.read()) + dst = new_dst + return dst