use alloc::vec::Vec;
use log::error;
use uefi::Handle;
use crate::{
BootResult,
boot::{action::add_special_boot, config::BootConfig, loader::load_boot_option},
config::{Config, scan_configs},
system::drivers::load_drivers,
};
pub mod action;
pub mod bli;
pub mod config;
pub mod devicetree;
pub mod loader;
pub mod secure_boot;
pub struct BootMgr {
pub boot_config: BootConfig,
configs: Vec<Config>,
}
impl BootMgr {
pub fn new() -> BootResult<Self> {
let _ = bli::export_variables();
let boot_config = BootConfig::new()?;
if boot_config.drivers {
load_drivers(&boot_config.driver_path)?; }
let mut configs = scan_configs()?;
add_special_boot(&mut configs, &boot_config);
if let Some(default) = boot_config.default {
let _ = bli::set_default_entry(&configs, default);
}
let _ = bli::set_loader_entries(&configs);
Ok(Self {
boot_config,
configs,
})
}
pub fn load(&mut self, selected: usize) -> BootResult<Handle> {
let config = &self.configs[selected];
match load_boot_option(config) {
Ok(handle) => {
let _ = bli::generate_random_seed();
let _ = bli::record_exit_time();
Ok(handle)
}
Err(e) => {
self.configs[selected].bad = true;
Err(e) }
}
}
#[must_use = "Has no effect if the result is unused"]
pub const fn list(&self) -> &Vec<Config> {
&self.configs
}
#[must_use = "Has no effect if the result is unused"]
pub const fn list_mut(&mut self) -> &mut Vec<Config> {
&mut self.configs
}
pub fn get_config(&mut self, option: usize) -> &mut Config {
&mut self.configs[option]
}
#[must_use = "Has no effect if the result is unused"]
pub fn get_default(&self) -> usize {
if let Some(default) = bli::get_default_entry(&self.configs)
&& default < self.configs.len()
{
default
} else {
0
}
}
pub fn set_default(&self, option: usize) {
if option < self.configs.len()
&& let Err(e) = bli::set_default_entry(&self.configs, option)
{
error!("Failed to set LoaderEntryDefault UEFI variable: {e}");
}
}
pub fn validate(&mut self) {
self.configs.retain(Config::is_good);
}
}