utils: implement BIOS boot for Linux

Create a bios.py file to hold all the BIOS specific functions.
Implement the _boot_bios_linux in Python. The new boot process
tries to find the vmlinuz and initrd binaries at the desired
partition. Then it tries to load them with kexec with the proper
Grub boot params.
One step closer to the removal of the boot legacy script.
master
Alejandro Sirgo Rica 2024-03-07 13:27:09 +01:00 committed by lupoDharkael
parent 37600660f3
commit a3ffdf2370
2 changed files with 70 additions and 1 deletions

53
src/utils/bios.py 100644
View File

@ -0,0 +1,53 @@
#
# 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 logging
import os
def get_grub_boot_params(mountpoint, device):
grub_conf = f'{mountpoint}/etc/default/grub'
res = []
with open(grub_conf, 'r') as f:
for line in f:
if line.find('=') == -1:
continue
key, value = line.split('=', 1)
if key == 'GRUB_CMDLINE_LINUX' or key == 'GRUB_CMDLINE_LINUE_DEFAULT':
value = value.replace('\n', '')
value = value.strip('"')
res.append(value)
res.append(f'root={device}')
return " ".join(res)
def get_vmlinuz_path(mountpoint):
linuz_dir = os.path.join(mountpoint, 'boot')
target_file = None
for file in sorted(os.listdir(linuz_dir)):
if file.startswith('vmlinuz-'):
target_file = file
if not target_file:
raise FileNotFoundError('vmlinuz not found in {initrd_dir}')
return os.path.join(linuz_dir, target_file)
def get_initrd_path(mountpoint):
initrd_dir = os.path.join(mountpoint, 'boot')
target_file = None
for file in sorted(os.listdir(initrd_dir)):
if file.startswith('initrd.img-') or file.startswith('initramfs-') and file.endswith('.img'):
target_file = file
if not target_file:
raise FileNotFoundError('initrd not found in {initrd_dir}')
return os.path.join(initrd_dir, target_file)

View File

@ -14,6 +14,7 @@ import subprocess
from src.utils.probe import OSFamily, get_os_family, get_linux_distro_id, os_probe
from src.utils.disk import get_partition_device, get_efi_partition
from src.utils.bios import *
from src.utils.uefi import *
from src.utils.fs import *
@ -27,7 +28,22 @@ def _boot_bios_linux(disk, part, mountpoint):
if not get_linux_distro_id(mountpoint) == 'ubuntu':
raise NotImplementedError(f'{os_probe(mountpoint)} detected, only Ubuntu is supported for legacy BIOS boot')
_boot_bios_legacy(disk, part, mountpoint)
kernel_path = get_vmlinuz_path(mountpoint)
initrd_path = get_initrd_path(mountpoint)
device = get_partition_device(disk, part)
grub_boot_params = get_grub_boot_params(mountpoint, device)
kexec_cmd = f'kexec -l {kernel_path} --append="{grub_boot_params}" --initrd="{initrd_path}"'
kexec_reboot_cmd = 'kexec -e'
logging.info(f'Booting with: {kexec_cmd}')
try:
subprocess.run(shlex.split(kexec_cmd), check=True, text=True)
subprocess.run(shlex.split(kexec_reboot_cmd), check=True, text=True)
except subprocess.CalledProcessError as e:
logging.error(f'Error processing kexec: {e}')
raise e
def _boot_bios_windows(disk, part, mountpoint):
logging.info(f'Booting Windows system')