diff options
author | Jose M. Guisado <jguisado@soleta.eu> | 2023-08-16 14:25:49 +0200 |
---|---|---|
committer | Alejandro Sirgo Rica <asirgo@soleta.eu> | 2024-03-04 11:33:10 +0100 |
commit | 517c99e542813dadc6cec6f94df681f729b26613 (patch) | |
tree | 37352ba5e7a68c385e7c6578ee8c2995818b32d6 | |
parent | 4129256caf54ab61ff87fdd5c25eb08f1c2b0458 (diff) |
utils: add boot.py
Add utility module related to the process of booting a system from a
client's partition.
The main utility function to boot a clients system is boot_os_at(), from
which firmware (UEFI or BIOS) and os-family specific private functions are invoked.
This initial commit adds UEFI windows boot function.
-rw-r--r-- | src/utils/boot.py | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/utils/boot.py b/src/utils/boot.py new file mode 100644 index 0000000..5a02ec6 --- /dev/null +++ b/src/utils/boot.py @@ -0,0 +1,63 @@ +# +# Copyright (C) 2023 Soleta Networks <info@soleta.eu> +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +import json +import logging +import os +import shlex +import subprocess + +from src.utils.probe import OSFamily, get_os_family +from src.utils.disk import get_partition_device, get_efi_partition +from src.utils.uefi import * +from src.utils.fs import * + + +def _boot_uefi_windows(disk, part, mountpoint): + logging.info(f'Booting windows system') + bootlabel = f'Part-{disk:02d}-{part:02d}' + esp, esp_disk, esp_part_number = get_efi_partition(disk) + esp_mountpoint = esp.replace('dev', 'mnt') + if not mount_mkdir(esp, esp_mountpoint): + raise RuntimeError(f'Unable to mount detected EFI System Partition at {esp} into {esp_mountpoint}') + + loader_paths = [f'{esp_mountpoint}/EFI/{bootlabel}/Boot/bootmgfw.efi', + f'{esp_mountpoint}/EFI/Microsoft/Boot/bootmgfw.efi'] + try: + for efi_app in loader_paths: + if os.path.exists(efi_app): + loader = efi_app[len(esp_mountpoint):] + logging.info(f'Found bootloader at ESP partition: {loader}') + break + else: + raise RuntimeError(f'Unable to locate Windows EFI bootloader bootmgfw.efi') + + efibootmgr_delete_bootentry(bootlabel) + efibootmgr_create_bootentry(esp_disk, esp_part_number, loader, bootlabel) + efibootmgr_bootnext(bootlabel) + finally: + umount(esp_mountpoint) + + +def boot_os_at(disk, part): + if not is_uefi_supported(): + raise NotImplementedError('BIOS booting is not implemented yet') + + device = get_partition_device(disk, part) + mountpoint = device.replace('dev', 'mnt') + if not mount_mkdir(device, mountpoint): + raise RuntimeError(f'Cannot probe OS family. Unable to mount {device} at {esp_mountpoint}.') + + logging.info(f'Booting system at {device}. Probing OS family...') + os_family = get_os_family(mountpoint) + if os_family == OSFamily.WINDOWS: + _boot_uefi_windows(disk, part, mountpoint) + elif os_family == OSFamily.LINUX: + raise NotImplementedError('WIP: Linux UEFI boot not implemented yet.') + else: + raise RuntimeError('Unknown OS family') |