use alloc::vec;
use core::{net::Ipv4Addr, str::FromStr};
use uefi::{
Handle, boot,
proto::network::{IpAddress, pxe::BaseCode},
};
use crate::{
BootResult,
boot::{
loader::{LoadError, get_efi},
secure_boot::shim::shim_load_image,
},
config::Config,
system::{
fs::ONE_GIGABYTE,
helper::{bytes_to_cstr8, locate_protocol, str_to_cstring},
},
};
pub(crate) fn load_boot_option(config: &Config) -> BootResult<Handle> {
let mut base_code = locate_protocol::<BaseCode>()?;
let addr_as_octets = Ipv4Addr::from_str(&config.filename)
.map_err(LoadError::IpParse)?
.octets();
let addr = IpAddress::new_v4(addr_as_octets);
if !base_code.mode().started() {
base_code.start(true)?;
}
let efi = get_efi(config)?;
let filename = str_to_cstring(efi)?; let filename_bytes = filename.as_bytes_with_nul();
let filename_cstr = bytes_to_cstr8(filename_bytes)?;
let size = usize::try_from(base_code.tftp_get_file_size(&addr, filename_cstr)?)
.unwrap_or(ONE_GIGABYTE);
let mut vec = vec![0; size];
base_code.tftp_read_file(&addr, filename_cstr, Some(&mut vec))?;
let src = boot::LoadImageSource::FromBuffer {
buffer: &vec,
file_path: None,
};
shim_load_image(boot::image_handle(), src)
}