arch-image-builder/builder/build/mkinitcpio.py

112 lines
3.0 KiB
Python
Raw Permalink Normal View History

import os
from logging import getLogger
from tempfile import NamedTemporaryFile
from builder.build.filesystem import chroot_run
from builder.lib.context import ArchBuilderContext
from builder.lib.config import ArchBuilderConfigError
from builder.lib.utils import open_config
log = getLogger(__name__)
def add_values(ctx: ArchBuilderContext, key: str, arr: list[str]):
vals = ctx.get(key, [])
vt = type(vals)
if vt is list: arr.extend(vals)
elif vt is str: arr.extend(vals.split())
else: raise ArchBuilderConfigError(f"bad values for {key}")
def gen_config(ctx: ArchBuilderContext):
"""
Generate mkinitcpio.conf
"""
modules: list[str] = []
binaries: list[str] = []
files: list[str] = []
hooks: list[str] = []
# add default hooks
hooks.append("base")
hooks.append("systemd")
hooks.append("autodetect")
# add microcode if x86_64 (amd-ucode, intel-ucode)
if ctx.cur_arch in ["x86_64", "i386"]:
hooks.append("microcode")
hooks.append("modconf")
# do not add keymap by default
if ctx.get("mkinitcpio.hooks.keymap", False):
hooks.extend(["kms", "keymap", "consolefont"])
hooks.extend(["keyboard", "block", "filesystems", "fsck"])
# add others values
add_values(ctx, "mkinitcpio.modules", modules)
add_values(ctx, "mkinitcpio.binaries", binaries)
add_values(ctx, "mkinitcpio.files", files)
# write mkinitcpio.conf to rootfs
root = ctx.get_rootfs()
cfg = os.path.join(root, "etc/mkinitcpio.conf")
with open_config(cfg) as f:
f.write("MODULES=(%s)\n" % (" ".join(modules)))
f.write("BINARIES=(%s)\n" % (" ".join(binaries)))
f.write("FILES=(%s)\n" % (" ".join(files)))
f.write("HOOKS=(%s)\n" % (" ".join(hooks)))
# TODO: add more options
def recreate_initrd(ctx: ArchBuilderContext, path: str):
"""
Really run mkinitcpio
"""
chroot_run(ctx, ["mkinitcpio", "-p", path])
# do not check return value of mkinitcpio
def recreate_initrd_no_autodetect(ctx: ArchBuilderContext, path: str):
"""
Create a full initramfs without autodetect
In build stage, mkinitcpio can not find out needs modules, it will cause unbootable.
"""
tmp = os.path.join(ctx.get_rootfs(), "tmp")
with NamedTemporaryFile("w", dir=tmp) as temp:
# copy original preset
with open(path, "r") as f:
temp.write(f.read())
# skip autodetect
temp.write("\ndefault_options=\"-S autodetect\"\n")
temp.flush()
# run mkinitcpio (with path in rootfs)
path = os.path.join("/tmp", os.path.basename(temp.name))
recreate_initrd(ctx, path)
def recreate_initrds(ctx: ArchBuilderContext):
"""
Regenerate all initramfs
"""
root = ctx.get_rootfs()
no_autodetect = ctx.get("mkinitcpio.no_autodetect", True)
folder = os.path.join(root, "etc/mkinitcpio.d")
# scan all initramfs preset and regenerate them
for preset in os.listdir(folder):
if not preset.endswith(".preset"): continue
path = os.path.join(folder, preset)
if not no_autodetect: recreate_initrd(ctx, path)
else: recreate_initrd_no_autodetect(ctx, path)
def proc_mkinitcpio(ctx: ArchBuilderContext):
"""
Process mkinitcpio options
"""
gen_config(ctx)
recreate_initrds(ctx)