From 928040c5cf91c896dfbe77b2b7c525121331748f Mon Sep 17 00:00:00 2001 From: Gerg-L Date: Sun, 5 Nov 2023 00:55:34 -0400 Subject: [PATCH] gerg-desktop: go back to grub and enable plymouth --- hosts/gerg-desktop/zfs.nix | 11 +- modules/systemd-boot/default.nix | 412 ------------------- modules/systemd-boot/systemd-boot-builder.py | 341 --------------- 3 files changed, 2 insertions(+), 762 deletions(-) delete mode 100644 modules/systemd-boot/default.nix delete mode 100644 modules/systemd-boot/systemd-boot-builder.py diff --git a/hosts/gerg-desktop/zfs.nix b/hosts/gerg-desktop/zfs.nix index 0dc9285..f0f21c7 100644 --- a/hosts/gerg-desktop/zfs.nix +++ b/hosts/gerg-desktop/zfs.nix @@ -54,20 +54,13 @@ _: ''; }; }; - plymouth.enable = false; loader = { generationsDir.copyKernels = true; #override default - systemd-boot = { - enable = true; - mirroredBoots = [ - "/efi0E" - "/efi22" - ]; - }; + systemd-boot.enable = false; efi.canTouchEfiVariables = false; grub = { - enable = false; + enable = true; copyKernels = true; efiInstallAsRemovable = true; efiSupport = true; diff --git a/modules/systemd-boot/default.nix b/modules/systemd-boot/default.nix deleted file mode 100644 index 7f1921d..0000000 --- a/modules/systemd-boot/default.nix +++ /dev/null @@ -1,412 +0,0 @@ -_: -{ - config, - lib, - pkgs, - modulesPath, - ... -}: -with lib; -let - cfg = config.boot.loader.systemd-boot; - - inherit (config.boot.loader) efi; - - python3 = pkgs.python3.withPackages (ps: [ ps.packaging ]); - - systemdBootBuilder = - mountPoint: - pkgs.substituteAll { - src = ./systemd-boot-builder.py; - - isExecutable = true; - - inherit python3; - - systemd = config.systemd.package; - - nix = config.nix.package.out; - - timeout = - optionalString (config.boot.loader.timeout != null) - config.boot.loader.timeout; - - editor = if cfg.editor then "True" else "False"; - - configurationLimit = - if cfg.configurationLimit == null then 0 else cfg.configurationLimit; - - inherit (cfg) consoleMode graceful; - - inherit (efi) canTouchEfiVariables; - - inherit mountPoint; - - inherit (config.system.nixos) distroName; - - memtest86 = optionalString cfg.memtest86.enable pkgs.memtest86-efi; - - netbootxyz = optionalString cfg.netbootxyz.enable pkgs.netbootxyz-efi; - - copyExtraFiles = pkgs.writeShellScript "copy-extra-files" '' - empty_file=$(${pkgs.coreutils}/bin/mktemp) - - ${concatStrings ( - mapAttrsToList - (n: v: '' - ${pkgs.coreutils}/bin/install -Dp "${v}" "${mountPoint}/"${escapeShellArg n} - ${pkgs.coreutils}/bin/install -D $empty_file "${mountPoint}/efi/nixos/.extra-files/"${ - escapeShellArg n - } - '') - cfg.extraFiles - )} - - ${concatStrings ( - mapAttrsToList - (n: v: '' - ${pkgs.coreutils}/bin/install -Dp "${ - pkgs.writeText n v - }" "${mountPoint}/loader/entries/"${escapeShellArg n} - ${pkgs.coreutils}/bin/install -D $empty_file "${mountPoint}/efi/nixos/.extra-files/loader/entries/"${ - escapeShellArg n - } - '') - cfg.extraEntries - )} - ''; - }; - - checkedSystemdBootBuilder = - mountPoint: - pkgs.runCommand "systemd-boot" - { - nativeBuildInputs = [ - pkgs.mypy - python3 - ]; - } - '' - install -m755 ${systemdBootBuilder mountPoint} $out - mypy \ - --no-implicit-optional \ - --disallow-untyped-calls \ - --disallow-untyped-defs \ - $out - ''; - - finalSystemdBootBuilder = - let - installDirs = - if cfg.mirroredBoots != [ ] then - cfg.mirroredBoots - else - [ efi.efiSysMountPoint ]; - in - pkgs.writeShellScript "install-systemd-boot.sh" ( - lib.concatMapStrings - (x: '' - ${checkedSystemdBootBuilder x} "$@" - '') - installDirs - ) - + cfg.extraInstallCommands; -in -{ - disabledModules = [ - "${modulesPath}/system/boot/loader/systemd-boot/systemd-boot.nix" - ]; - - imports = [ - (mkRenamedOptionModule - [ - "boot" - "loader" - "gummiboot" - "enable" - ] - [ - "boot" - "loader" - "systemd-boot" - "enable" - ] - ) - ]; - - options.boot.loader.systemd-boot = { - enable = mkOption { - default = false; - - type = types.bool; - - description = - lib.mdDoc - "Whether to enable the systemd-boot (formerly gummiboot) EFI boot manager"; - }; - - editor = mkOption { - default = true; - - type = types.bool; - - description = lib.mdDoc '' - Whether to allow editing the kernel command-line before - boot. It is recommended to set this to false, as it allows - gaining root access by passing init=/bin/sh as a kernel - parameter. However, it is enabled by default for backwards - compatibility. - ''; - }; - - configurationLimit = mkOption { - default = null; - example = 120; - type = types.nullOr types.int; - description = lib.mdDoc '' - Maximum number of latest generations in the boot menu. - Useful to prevent boot partition running out of disk space. - - `null` means no limit i.e. all generations - that were not garbage collected yet. - ''; - }; - - extraInstallCommands = mkOption { - default = ""; - example = '' - default_cfg=$(cat /boot/loader/loader.conf | grep default | awk '{print $2}') - init_value=$(cat /boot/loader/entries/$default_cfg | grep init= | awk '{print $2}') - sed -i "s|@INIT@|$init_value|g" /boot/custom/config_with_placeholder.conf - ''; - type = types.lines; - description = lib.mdDoc '' - Additional shell commands inserted in the bootloader installer - script after generating menu entries. It can be used to expand - on extra boot entries that cannot incorporate certain pieces of - information (such as the resulting `init=` kernel parameter). - ''; - }; - - consoleMode = mkOption { - default = "keep"; - - type = types.enum [ - "0" - "1" - "2" - "auto" - "max" - "keep" - ]; - - description = lib.mdDoc '' - The resolution of the console. The following values are valid: - - - `"0"`: Standard UEFI 80x25 mode - - `"1"`: 80x50 mode, not supported by all devices - - `"2"`: The first non-standard mode provided by the device firmware, if any - - `"auto"`: Pick a suitable mode automatically using heuristics - - `"max"`: Pick the highest-numbered available mode - - `"keep"`: Keep the mode selected by firmware (the default) - ''; - }; - - memtest86 = { - enable = mkOption { - default = false; - type = types.bool; - description = lib.mdDoc '' - Make MemTest86 available from the systemd-boot menu. MemTest86 is a - program for testing memory. MemTest86 is an unfree program, so - this requires `allowUnfree` to be set to - `true`. - ''; - }; - - entryFilename = mkOption { - default = "memtest86.conf"; - type = types.str; - description = lib.mdDoc '' - `systemd-boot` orders the menu entries by the config file names, - so if you want something to appear after all the NixOS entries, - it should start with {file}`o` or onwards. - ''; - }; - }; - - netbootxyz = { - enable = mkOption { - default = false; - type = types.bool; - description = lib.mdDoc '' - Make `netboot.xyz` available from the - `systemd-boot` menu. `netboot.xyz` - is a menu system that allows you to boot OS installers and - utilities over the network. - ''; - }; - - entryFilename = mkOption { - default = "o_netbootxyz.conf"; - type = types.str; - description = lib.mdDoc '' - `systemd-boot` orders the menu entries by the config file names, - so if you want something to appear after all the NixOS entries, - it should start with {file}`o` or onwards. - ''; - }; - }; - - extraEntries = mkOption { - type = types.attrsOf types.lines; - default = { }; - example = literalExpression '' - { "memtest86.conf" = ''' - title MemTest86 - efi /efi/memtest86/memtest86.efi - '''; } - ''; - description = lib.mdDoc '' - Any additional entries you want added to the `systemd-boot` menu. - These entries will be copied to {file}`/boot/loader/entries`. - Each attribute name denotes the destination file name, - and the corresponding attribute value is the contents of the entry. - - `systemd-boot` orders the menu entries by the config file names, - so if you want something to appear after all the NixOS entries, - it should start with {file}`o` or onwards. - ''; - }; - - extraFiles = mkOption { - type = types.attrsOf types.path; - default = { }; - example = literalExpression '' - { "efi/memtest86/memtest86.efi" = "''${pkgs.memtest86-efi}/BOOTX64.efi"; } - ''; - description = lib.mdDoc '' - A set of files to be copied to {file}`/boot`. - Each attribute name denotes the destination file name in - {file}`/boot`, while the corresponding - attribute value specifies the source file. - ''; - }; - - graceful = mkOption { - default = false; - - type = types.bool; - - description = lib.mdDoc '' - Invoke `bootctl install` with the `--graceful` option, - which ignores errors when EFI variables cannot be written or when the EFI System Partition - cannot be found. Currently only applies to random seed operations. - - Only enable this option if `systemd-boot` otherwise fails to install, as the - scope or implication of the `--graceful` option may change in the future. - ''; - }; - - mirroredBoots = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - example = '' - [ "/boot1" "/boot2" ] - ''; - description = lib.mdDoc '' - Mirror the boot configuration to multiple locations. - ''; - }; - }; - - config = mkIf cfg.enable { - assertions = - [ - { - assertion = - (config.boot.kernelPackages.kernel.features or { efiBootStub = true; }) - ? efiBootStub; - message = "This kernel does not support the EFI boot stub"; - } - ] - ++ concatMap - (filename: [ - { - assertion = !(hasInfix "/" filename); - message = "boot.loader.systemd-boot.extraEntries.${ - lib.strings.escapeNixIdentifier filename - } is invalid: entries within folders are not supported"; - } - { - assertion = hasSuffix ".conf" filename; - message = "boot.loader.systemd-boot.extraEntries.${ - lib.strings.escapeNixIdentifier filename - } is invalid: entries must have a .conf file extension"; - } - ]) - (builtins.attrNames cfg.extraEntries) - ++ - concatMap - (filename: [ - { - assertion = !(hasPrefix "/" filename); - message = "boot.loader.systemd-boot.extraFiles.${ - lib.strings.escapeNixIdentifier filename - } is invalid: paths must not begin with a slash"; - } - { - assertion = !(hasInfix ".." filename); - message = "boot.loader.systemd-boot.extraFiles.${ - lib.strings.escapeNixIdentifier filename - } is invalid: paths must not reference the parent directory"; - } - { - assertion = !(hasInfix "nixos/.extra-files" (toLower filename)); - message = "boot.loader.systemd-boot.extraFiles.${ - lib.strings.escapeNixIdentifier filename - } is invalid: files cannot be placed in the nixos/.extra-files directory"; - } - ]) - (builtins.attrNames cfg.extraFiles); - - boot.loader.grub.enable = mkDefault false; - - boot.loader.supportsInitrdSecrets = true; - - boot.loader.systemd-boot.extraFiles = mkMerge [ - # TODO: This is hard-coded to use the 64-bit EFI app, but it could probably - # be updated to use the 32-bit EFI app on 32-bit systems. The 32-bit EFI - # app filename is BOOTIA32.efi. - (mkIf cfg.memtest86.enable { - "efi/memtest86/BOOTX64.efi" = "${pkgs.memtest86-efi}/BOOTX64.efi"; - }) - (mkIf cfg.netbootxyz.enable { - "efi/netbootxyz/netboot.xyz.efi" = "${pkgs.netbootxyz-efi}"; - }) - ]; - - boot.loader.systemd-boot.extraEntries = mkMerge [ - (mkIf cfg.memtest86.enable { - "${cfg.memtest86.entryFilename}" = '' - title MemTest86 - efi /efi/memtest86/BOOTX64.efi - ''; - }) - (mkIf cfg.netbootxyz.enable { - "${cfg.netbootxyz.entryFilename}" = '' - title netboot.xyz - efi /efi/netbootxyz/netboot.xyz.efi - ''; - }) - ]; - - system = { - build.installBootLoader = finalSystemdBootBuilder; - - boot.loader.id = "systemd-boot"; - - requiredKernelConfig = with config.lib.kernelConfig; [ (isYes "EFI_STUB") ]; - }; - }; -} diff --git a/modules/systemd-boot/systemd-boot-builder.py b/modules/systemd-boot/systemd-boot-builder.py deleted file mode 100644 index 85a349f..0000000 --- a/modules/systemd-boot/systemd-boot-builder.py +++ /dev/null @@ -1,341 +0,0 @@ -#! @python3@/bin/python3 -B -import argparse -import shutil -import os -import sys -import errno -import subprocess -import glob -import tempfile -import errno -import warnings -import ctypes -libc = ctypes.CDLL("libc.so.6") -import re -import datetime -import glob -import os.path -from typing import NamedTuple, List, Optional -from packaging import version - -class SystemIdentifier(NamedTuple): - profile: Optional[str] - generation: int - specialisation: Optional[str] - - -def copy_if_not_exists(source: str, dest: str) -> None: - if not os.path.exists(dest): - shutil.copyfile(source, dest) - - -def generation_dir(profile: Optional[str], generation: int) -> str: - if profile: - return "/nix/var/nix/profiles/system-profiles/%s-%d-link" % (profile, generation) - else: - return "/nix/var/nix/profiles/system-%d-link" % (generation) - -def system_dir(profile: Optional[str], generation: int, specialisation: Optional[str]) -> str: - d = generation_dir(profile, generation) - if specialisation: - return os.path.join(d, "specialisation", specialisation) - else: - return d - -BOOT_ENTRY = """title {title} -version Generation {generation} {description} -linux {kernel} -initrd {initrd} -options {kernel_params} -""" - -def generation_conf_filename(profile: Optional[str], generation: int, specialisation: Optional[str]) -> str: - pieces = [ - "nixos", - profile or None, - "generation", - str(generation), - f"specialisation-{specialisation}" if specialisation else None, - ] - return "-".join(p for p in pieces if p) + ".conf" - - -def write_loader_conf(profile: Optional[str], generation: int, specialisation: Optional[str]) -> None: - with open("@mountPoint@/loader/loader.conf.tmp", 'w') as f: - if "@timeout@" != "": - f.write("timeout @timeout@\n") - f.write("default %s\n" % generation_conf_filename(profile, generation, specialisation)) - if not @editor@: - f.write("editor 0\n"); - f.write("console-mode @consoleMode@\n"); - os.rename("@mountPoint@/loader/loader.conf.tmp", "@mountPoint@/loader/loader.conf") - - -def profile_path(profile: Optional[str], generation: int, specialisation: Optional[str], name: str) -> str: - return os.path.realpath("%s/%s" % (system_dir(profile, generation, specialisation), name)) - - -def copy_from_profile(profile: Optional[str], generation: int, specialisation: Optional[str], name: str, dry_run: bool = False) -> str: - store_file_path = profile_path(profile, generation, specialisation, name) - suffix = os.path.basename(store_file_path) - store_dir = os.path.basename(os.path.dirname(store_file_path)) - efi_file_path = "/efi/nixos/%s-%s.efi" % (store_dir, suffix) - if not dry_run: - copy_if_not_exists(store_file_path, "@mountPoint@%s" % (efi_file_path)) - return efi_file_path - - -def describe_generation(profile: Optional[str], generation: int, specialisation: Optional[str]) -> str: - try: - with open(profile_path(profile, generation, specialisation, "nixos-version")) as f: - nixos_version = f.read() - except IOError: - nixos_version = "Unknown" - - kernel_dir = os.path.dirname(profile_path(profile, generation, specialisation, "kernel")) - module_dir = glob.glob("%s/lib/modules/*" % kernel_dir)[0] - kernel_version = os.path.basename(module_dir) - - build_time = int(os.path.getctime(system_dir(profile, generation, specialisation))) - build_date = datetime.datetime.fromtimestamp(build_time).strftime('%F') - - description = "@distroName@ {}, Linux Kernel {}, Built on {}".format( - nixos_version, kernel_version, build_date - ) - - return description - - -def write_entry(profile: Optional[str], generation: int, specialisation: Optional[str], - machine_id: str, current: bool) -> None: - kernel = copy_from_profile(profile, generation, specialisation, "kernel") - initrd = copy_from_profile(profile, generation, specialisation, "initrd") - - title = "@distroName@{profile}{specialisation}".format( - profile=" [" + profile + "]" if profile else "", - specialisation=" (%s)" % specialisation if specialisation else "") - - try: - append_initrd_secrets = profile_path(profile, generation, specialisation, "append-initrd-secrets") - subprocess.check_call([append_initrd_secrets, "@mountPoint@%s" % (initrd)]) - except FileNotFoundError: - pass - except subprocess.CalledProcessError: - if current: - print("failed to create initrd secrets!", file=sys.stderr) - sys.exit(1) - else: - print("warning: failed to create initrd secrets " - f'for "{title} - Configuration {generation}", an older generation', file=sys.stderr) - print("note: this is normal after having removed " - "or renamed a file in `boot.initrd.secrets`", file=sys.stderr) - entry_file = "@mountPoint@/loader/entries/%s" % ( - generation_conf_filename(profile, generation, specialisation)) - tmp_path = "%s.tmp" % (entry_file) - kernel_params = "init=%s " % profile_path(profile, generation, specialisation, "init") - - with open(profile_path(profile, generation, specialisation, "kernel-params")) as params_file: - kernel_params = kernel_params + params_file.read() - with open(tmp_path, 'w') as f: - f.write(BOOT_ENTRY.format(title=title, - generation=generation, - kernel=kernel, - initrd=initrd, - kernel_params=kernel_params, - description=describe_generation(profile, generation, specialisation))) - if machine_id is not None: - f.write("machine-id %s\n" % machine_id) - os.rename(tmp_path, entry_file) - - -def mkdir_p(path: str) -> None: - try: - os.makedirs(path) - except OSError as e: - if e.errno != errno.EEXIST or not os.path.isdir(path): - raise - - -def get_generations(profile: Optional[str] = None) -> List[SystemIdentifier]: - gen_list = subprocess.check_output([ - "@nix@/bin/nix-env", - "--list-generations", - "-p", - "/nix/var/nix/profiles/%s" % ("system-profiles/" + profile if profile else "system"), - "--option", "build-users-group", ""], - universal_newlines=True) - gen_lines = gen_list.split('\n') - gen_lines.pop() - - configurationLimit = @configurationLimit@ - configurations = [ - SystemIdentifier( - profile=profile, - generation=int(line.split()[0]), - specialisation=None - ) - for line in gen_lines - ] - return configurations[-configurationLimit:] - - -def get_specialisations(profile: Optional[str], generation: int, _: Optional[str]) -> List[SystemIdentifier]: - specialisations_dir = os.path.join( - system_dir(profile, generation, None), "specialisation") - if not os.path.exists(specialisations_dir): - return [] - return [SystemIdentifier(profile, generation, spec) for spec in os.listdir(specialisations_dir)] - - -def remove_old_entries(gens: List[SystemIdentifier]) -> None: - rex_profile = re.compile("^@mountPoint@/loader/entries/nixos-(.*)-generation-.*\.conf$") - rex_generation = re.compile("^@mountPoint@/loader/entries/nixos.*-generation-([0-9]+)(-specialisation-.*)?\.conf$") - known_paths = [] - for gen in gens: - known_paths.append(copy_from_profile(*gen, "kernel", True)) - known_paths.append(copy_from_profile(*gen, "initrd", True)) - for path in glob.iglob("@mountPoint@/loader/entries/nixos*-generation-[1-9]*.conf"): - if rex_profile.match(path): - prof = rex_profile.sub(r"\1", path) - else: - prof = None - try: - gen_number = int(rex_generation.sub(r"\1", path)) - except ValueError: - continue - if not (prof, gen_number, None) in gens: - os.unlink(path) - for path in glob.iglob("@mountPoint@/efi/nixos/*"): - if not path in known_paths and not os.path.isdir(path): - os.unlink(path) - - -def get_profiles() -> List[str]: - if os.path.isdir("/nix/var/nix/profiles/system-profiles/"): - return [x - for x in os.listdir("/nix/var/nix/profiles/system-profiles/") - if not x.endswith("-link")] - else: - return [] - -def main() -> None: - parser = argparse.ArgumentParser(description='Update @distroName@-related systemd-boot files') - parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help='The default @distroName@ config to boot') - args = parser.parse_args() - - try: - with open("/etc/machine-id") as machine_file: - machine_id = machine_file.readlines()[0] - except IOError as e: - if e.errno != errno.ENOENT: - raise - # Since systemd version 232 a machine ID is required and it might not - # be there on newly installed systems, so let's generate one so that - # bootctl can find it and we can also pass it to write_entry() later. - cmd = ["@systemd@/bin/systemd-machine-id-setup", "--print"] - machine_id = subprocess.run( - cmd, text=True, check=True, stdout=subprocess.PIPE - ).stdout.rstrip() - - if os.getenv("NIXOS_INSTALL_GRUB") == "1": - warnings.warn("NIXOS_INSTALL_GRUB env var deprecated, use NIXOS_INSTALL_BOOTLOADER", DeprecationWarning) - os.environ["NIXOS_INSTALL_BOOTLOADER"] = "1" - - # flags to pass to bootctl install/update - bootctl_flags = [] - - if "@canTouchEfiVariables@" != "1": - bootctl_flags.append("--no-variables") - - if "@graceful@" == "1": - bootctl_flags.append("--graceful") - - if os.getenv("NIXOS_INSTALL_BOOTLOADER") == "1": - # bootctl uses fopen() with modes "wxe" and fails if the file exists. - if os.path.exists("@mountPoint@/loader/loader.conf"): - os.unlink("@mountPoint@/loader/loader.conf") - - subprocess.check_call(["@systemd@/bin/bootctl", "--esp-path=@mountPoint@"] + bootctl_flags + ["install"]) - else: - # Update bootloader to latest if needed - available_out = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2] - installed_out = subprocess.check_output(["@systemd@/bin/bootctl", "--esp-path=@mountPoint@", "status"], universal_newlines=True) - - # See status_binaries() in systemd bootctl.c for code which generates this - installed_match = re.search(r"^\W+File:.*/EFI/(?:BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$", - installed_out, re.IGNORECASE | re.MULTILINE) - - available_match = re.search(r"^\((.*)\)$", available_out) - - if installed_match is None: - raise Exception("could not find any previously installed systemd-boot") - - if available_match is None: - raise Exception("could not determine systemd-boot version") - - installed_version = version.parse(installed_match.group(1)) - available_version = version.parse(available_match.group(1)) - - # systemd 252 has a regression that leaves some machines unbootable, so we skip that update. - # The fix is in 252.2 - # See https://github.com/systemd/systemd/issues/25363 and https://github.com/NixOS/nixpkgs/pull/201558#issuecomment-1348603263 - if installed_version < available_version: - if version.parse('252') <= available_version < version.parse('252.2'): - print("skipping systemd-boot update to %s because of known regression" % available_version) - else: - print("updating systemd-boot from %s to %s" % (installed_version, available_version)) - subprocess.check_call(["@systemd@/bin/bootctl", "--esp-path=@mountPoint@"] + bootctl_flags + ["update"]) - - mkdir_p("@mountPoint@/efi/nixos") - mkdir_p("@mountPoint@/loader/entries") - - gens = get_generations() - for profile in get_profiles(): - gens += get_generations(profile) - remove_old_entries(gens) - for gen in gens: - try: - is_default = os.path.dirname(profile_path(*gen, "init")) == args.default_config - write_entry(*gen, machine_id, current=is_default) - for specialisation in get_specialisations(*gen): - write_entry(*specialisation, machine_id, current=is_default) - if is_default: - write_loader_conf(*gen) - except OSError as e: - # See https://github.com/NixOS/nixpkgs/issues/114552 - if e.errno == errno.EINVAL: - profile = f"profile '{gen.profile}'" if gen.profile else "default profile" - print("ignoring {} in the list of boot entries because of the following error:\n{}".format(profile, e), file=sys.stderr) - else: - raise e - - for root, _, files in os.walk('@mountPoint@/efi/nixos/.extra-files', topdown=False): - relative_root = root.removeprefix("@mountPoint@/efi/nixos/.extra-files").removeprefix("/") - actual_root = os.path.join("@mountPoint@", relative_root) - - for file in files: - actual_file = os.path.join(actual_root, file) - - if os.path.exists(actual_file): - os.unlink(actual_file) - os.unlink(os.path.join(root, file)) - - if not len(os.listdir(actual_root)): - os.rmdir(actual_root) - os.rmdir(root) - - mkdir_p("@mountPoint@/efi/nixos/.extra-files") - - subprocess.check_call("@copyExtraFiles@") - - # Since fat32 provides little recovery facilities after a crash, - # it can leave the system in an unbootable state, when a crash/outage - # happens shortly after an update. To decrease the likelihood of this - # event sync the efi filesystem after each update. - rc = libc.syncfs(os.open("@mountPoint@", os.O_RDONLY)) - if rc != 0: - print("could not sync @mountPoint@: {}".format(os.strerror(rc)), file=sys.stderr) - - -if __name__ == '__main__': - main()