diff --git a/src/modules/initcpiocfg/main.py b/src/modules/initcpiocfg/main.py index 4fb0923cd..903ef635f 100644 --- a/src/modules/initcpiocfg/main.py +++ b/src/modules/initcpiocfg/main.py @@ -28,35 +28,84 @@ def pretty_name(): return _("Configuring mkinitcpio.") -def cpuinfo(): +def detect_plymouth(): """ - Return the information in /proc/cpuinfo as a dictionary in the following - format: + Checks existence (runnability) of plymouth in the target system. - cpu_info['proc0']={...} - cpu_info['proc1']={...} + @return True if plymouth exists in the target, False otherwise """ - cpu_info = OrderedDict() - procinfo = OrderedDict() + # Used to only check existence of path /usr/bin/plymouth in target + return target_env_call(["sh", "-c", "which plymouth"]) == 0 - nprocs = 0 - with open('/proc/cpuinfo') as cpuinfo_file: - for line in cpuinfo_file: - if not line.strip(): - # end of one processor - cpu_info["proc{!s}".format(nprocs)] = procinfo - nprocs += 1 - # Reset - procinfo = OrderedDict() - else: - if len(line.split(':')) == 2: - splitted_line = line.split(':')[1].strip() - procinfo[line.split(':')[0].strip()] = splitted_line +class cpuinfo(object): + """ + Object describing the current CPU's characteristics. It may be + be considered a named tuple, there's no behavior here. + + Fields in the object: + - is_intel (if it's definitely an Intel CPU) + - is_amd (if it's definitely an AMD CPU) + - number_of_cores + It is possible for both is_* fields to be False. + """ + def __init__(self): + self.is_intel = False + self.is_amd = False + self.number_of_cores = 0 + + cpu = self._cpuinfo() + self.is_intel = cpu['proc0']['vendor_id'].lower() == "genuineintel" + self.is_amd = cpu['proc0']['vendor_id'].lower() == "authenticamd" + self.number_of_cores = len(cpu) + + @staticmethod + def _cpuinfo(): + """ + Return the information in /proc/cpuinfo as a dictionary in the following + format: + + cpu_info['proc0']={...} + cpu_info['proc1']={...} + """ + cpu_info = OrderedDict() + procinfo = OrderedDict() + + nprocs = 0 + + with open('/proc/cpuinfo') as cpuinfo_file: + for line in cpuinfo_file: + if not line.strip(): + # end of one processor + cpu_info["proc{!s}".format(nprocs)] = procinfo + nprocs += 1 + # Reset + procinfo = OrderedDict() else: - procinfo[line.split(':')[0].strip()] = '' + if len(line.split(':')) == 2: + splitted_line = line.split(':')[1].strip() + procinfo[line.split(':')[0].strip()] = splitted_line + else: + procinfo[line.split(':')[0].strip()] = '' - return cpu_info + return cpu_info + + +def get_host_initcpio(): + """ + Reads the host system mkinitcpio.conf and returns all + the lines from that file, or an empty list if it does + not exist. + """ + hostfile = "/etc/mkinitcpio.conf" + try: + with open(hostfile, "r") as mkinitcpio_file: + mklins = [x.strip() for x in mkinitcpio_file.readlines()] + except FileNotFoundError: + libcalamares.utils.debug("Could not open host file '%s'" % hostfile) + mklins = [] + + return mklins def write_mkinitcpio_lines(hooks, modules, files, root_mount_point): @@ -68,56 +117,40 @@ def write_mkinitcpio_lines(hooks, modules, files, root_mount_point): :param files: :param root_mount_point: """ - hostfile = "/etc/mkinitcpio.conf" - try: - with open(hostfile, "r") as mkinitcpio_file: - mklins = [x.strip() for x in mkinitcpio_file.readlines()] - except FileNotFoundError: - libcalamares.utils.debug("Could not open host file '%s'" % hostfile) - mklins = [] + mklins = get_host_initcpio() - for i in range(len(mklins)): - if mklins[i].startswith("HOOKS"): - joined_hooks = ' '.join(hooks) - mklins[i] = "HOOKS=\"{!s}\"".format(joined_hooks) - elif mklins[i].startswith("MODULES"): - joined_modules = ' '.join(modules) - mklins[i] = "MODULES=\"{!s}\"".format(joined_modules) - elif mklins[i].startswith("FILES"): - joined_files = ' '.join(files) - mklins[i] = "FILES=\"{!s}\"".format(joined_files) - - path = os.path.join(root_mount_point, "etc/mkinitcpio.conf") - - with open(path, "w") as mkinitcpio_file: - mkinitcpio_file.write("\n".join(mklins) + "\n") + target_path = os.path.join(root_mount_point, "etc/mkinitcpio.conf") + with open(target_path, "w") as mkinitcpio_file: + for line in mklins: + # Replace HOOKS, MODULES and FILES lines with what we + # have found via find_initcpio_features() + if line.startswith("HOOKS"): + line = "HOOKS=\"{!s}\"".format(' '.join(hooks)) + elif line.startswith("MODULES"): + line = "MODULES=\"{!s}\"".format(' '.join(modules)) + elif lines.startswith("FILES"): + line = "FILES=\"{!s}\"".format(' '.join(files)) + mkinitcpio_file.write(line + "\n") -def detect_plymouth(): +def find_initcpio_features(partitions, root_mount_point): """ - Checks existence (runnability) of plymouth in the target system. + Returns a tuple (hooks, modules, files) needed to support + the given @p partitions (filesystems types, encryption, etc) + in the target. - @return True if plymouth exists in the target, False otherwise + :param partitions: (from GS) + :param root_mount_point: (from GS) + + :return 3-tuple of lists """ - # Used to only check existence of path /usr/bin/plymouth in target - return target_env_call(["sh", "-c", "which plymouth"]) == 0 - - -def modify_mkinitcpio_conf(partitions, root_mount_point): - """ - Modifies mkinitcpio.conf - - :param partitions: - :param root_mount_point: - """ - cpu = cpuinfo() - swap_uuid = "" - btrfs = "" - lvm2 = "" - hooks = ["base", "udev", "autodetect", "modconf", "block", "keyboard", - "keymap"] + hooks = ["base", "udev", "autodetect", "modconf", "block", "keyboard", "keymap"] modules = [] files = [] + + swap_uuid = "" + uses_btrfs = False + uses_lvm2 = False encrypt_hook = False openswap_hook = False unencrypted_separate_boot = False @@ -137,10 +170,10 @@ def modify_mkinitcpio_conf(partitions, root_mount_point): openswap_hook = True if partition["fs"] == "btrfs": - btrfs = "yes" + uses_btrfs = True if "lvm2" in partition["fs"]: - lvm2 = "yes" + uses_lvm2 = True if partition["mountPoint"] == "/" and "luksMapperName" in partition: encrypt_hook = True @@ -162,7 +195,7 @@ def modify_mkinitcpio_conf(partitions, root_mount_point): ): files.append("/crypto_keyfile.bin") - if lvm2: + if uses_lvm2: hooks.append("lvm2") if swap_uuid != "": @@ -172,15 +205,12 @@ def modify_mkinitcpio_conf(partitions, root_mount_point): else: hooks.extend(["filesystems"]) - if btrfs == "yes" and cpu['proc0']['vendor_id'].lower() != "genuineintel": - modules.append("crc32c") - elif (btrfs == "yes" - and cpu['proc0']['vendor_id'].lower() == "genuineintel"): - modules.append("crc32c-intel") + if uses_btrfs: + modules.append("crc32c-intel" if cpuinfo().is_intel else "crc32c") else: hooks.append("fsck") - write_mkinitcpio_lines(hooks, modules, files, root_mount_point) + return (hooks, modules, files) def run(): @@ -201,6 +231,7 @@ def run(): return (_("Configuration Error"), _("No root mount point is given for
{!s}to use." ).format("initcpiocfg")) - modify_mkinitcpio_conf(partitions, root_mount_point) + hooks, modules, files = find_initcpio_features(partitions, root_mount_point) + write_mkinitcpio_lines(hooks, modules, files, root_mount_point) return None diff --git a/src/modules/initcpiocfg/module.desc b/src/modules/initcpiocfg/module.desc index a4476121b..a64fdf173 100644 --- a/src/modules/initcpiocfg/module.desc +++ b/src/modules/initcpiocfg/module.desc @@ -1,7 +1,13 @@ # SPDX-FileCopyrightText: no # SPDX-License-Identifier: CC0-1.0 +# +# Writes a mkinitcpio.conf into the target system. It copies +# the host system's /etc/mkinitcpio.conf, and replaces any +# HOOKS, MODULES, and FILES lines with calculated values +# based on what the installation (seems to) need. --- type: "job" name: "initcpiocfg" interface: "python" script: "main.py" +noconfig: true