Merge pull request #172849 from waldheinz/systemd-boot-builder-downgrade

nixos/systemd-boot: fix systemd-boot-builder dowgrade to fail

authored by Martin Weinelt and committed by GitHub c48756aa a8ac96cd

+31 -15
+31 -15
nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
··· 204 else: 205 return [] 206 207 208 def main() -> None: 209 parser = argparse.ArgumentParser(description='Update NixOS-related systemd-boot files') ··· 244 subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@"] + flags + ["install"]) 245 else: 246 # Update bootloader to latest if needed 247 - systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2] 248 - sdboot_status = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True) 249 250 # See status_binaries() in systemd bootctl.c for code which generates this 251 - m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$", 252 - sdboot_status, re.IGNORECASE | re.MULTILINE) 253 254 - needs_install = False 255 256 - if m is None: 257 - print("could not find any previously installed systemd-boot, installing.") 258 - # Let systemd-boot attempt an installation if a previous one wasn't found 259 - needs_install = True 260 - else: 261 - sdboot_version = f'({m.group(2)})' 262 - if systemd_version != sdboot_version: 263 - print("updating systemd-boot from %s to %s" % (sdboot_version, systemd_version)) 264 - needs_install = True 265 266 - if needs_install: 267 subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"]) 268 269 mkdir_p("@efiSysMountPoint@/efi/nixos") 270 mkdir_p("@efiSysMountPoint@/loader/entries")
··· 204 else: 205 return [] 206 207 + def should_update(v_from: str, v_to: str) -> bool: 208 + # see https://github.com/systemd/systemd/blob/main/src/boot/bootctl.c compare_product function 209 + 210 + len_from = len(v_from) 211 + len_to = len(v_to) 212 + 213 + if len_from < len_to: 214 + return False 215 + 216 + if len_from > len_to: 217 + return True 218 + 219 + return v_from < v_to 220 + 221 222 def main() -> None: 223 parser = argparse.ArgumentParser(description='Update NixOS-related systemd-boot files') ··· 258 subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@"] + flags + ["install"]) 259 else: 260 # Update bootloader to latest if needed 261 + available_out = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2] 262 + installed_out = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True) 263 264 # See status_binaries() in systemd bootctl.c for code which generates this 265 + installed_match = re.search(r"^\W+File:.*/EFI/(?:BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$", 266 + installed_out, re.IGNORECASE | re.MULTILINE) 267 268 + available_match = re.search(r"^\((.*)\)$", available_out) 269 270 + if installed_match is None: 271 + raise Exception("could not find any previously installed systemd-boot") 272 273 + if available_match is None: 274 + raise Exception("could not determine systemd-boot version") 275 + 276 + installed_version = installed_match.group(1) 277 + available_version = available_match.group(1) 278 + 279 + if should_update(installed_version, available_version): 280 + print("updating systemd-boot from %s to %s" % (installed_version, available_version)) 281 subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"]) 282 + else: 283 + print("leaving systemd-boot %s in place (%s is not newer)" % (installed_version, available_version)) 284 285 mkdir_p("@efiSysMountPoint@/efi/nixos") 286 mkdir_p("@efiSysMountPoint@/loader/entries")