use core::{ffi::CStr, net::Ipv4Addr};
use alloc::{format, string::ToString};
use uefi::proto::network::pxe::{BaseCode, BootstrapType, DhcpV4Packet};
use crate::{
BootResult,
boot::action::BootAction,
config::{Config, builder::ConfigBuilder, parsers::Parsers},
system::helper::locate_protocol,
};
pub fn get_pxe_offer() -> BootResult<Option<Config>> {
let mut base_code = locate_protocol::<BaseCode>()?;
if !base_code.mode().started() {
base_code.start(false)?;
}
base_code.dhcp(true)?;
let mut initial_layer = 0; base_code.discover(BootstrapType::BOOTSTRAP, &mut initial_layer, false, None)?;
if base_code.mode().pxe_reply_received() {
let reply: &DhcpV4Packet = base_code.mode().pxe_reply().as_ref();
let Ok(file) = CStr::from_bytes_with_nul(&reply.bootp_boot_file) else {
return Ok(None);
};
let file = file.to_string_lossy();
if !file.starts_with("http://") && !file.starts_with("https://") {
let addr = Ipv4Addr::from(reply.bootp_si_addr).to_string();
let title = format!("PXE Boot: {file}");
let config = ConfigBuilder::new(addr, "")
.efi_path(file)
.title(title)
.action(BootAction::BootTftp)
.origin(Parsers::Special)
.build();
return Ok(Some(config));
}
}
Ok(None)
}