68 lines
2.2 KiB
Rust
68 lines
2.2 KiB
Rust
use alloc::vec::Vec;
|
|
use uefi::{prelude::*, CString16, Result};
|
|
|
|
use crate::common::{boot_linux_unchecked, extract_string, get_cmdline, get_secure_boot_status};
|
|
use linux_bootloader::pe_section::pe_section;
|
|
use linux_bootloader::uefi_helpers::booted_image_file;
|
|
|
|
/// Extract bytes from a PE section.
|
|
pub fn extract_bytes(pe_data: &[u8], section: &str) -> Result<Vec<u8>> {
|
|
let bytes: Vec<u8> = pe_section(pe_data, section)
|
|
.ok_or(Status::INVALID_PARAMETER)?
|
|
.try_into()
|
|
.map_err(|_| Status::INVALID_PARAMETER)?;
|
|
|
|
Ok(bytes)
|
|
}
|
|
|
|
/// The configuration that is embedded at build time.
|
|
///
|
|
/// After this stub is built, configuration need to be embedded into the binary by adding PE
|
|
/// sections. This struct represents that information.
|
|
struct EmbeddedConfiguration {
|
|
/// The kernel command-line.
|
|
cmdline: CString16,
|
|
|
|
/// The kernel as raw bytes.
|
|
kernel: Vec<u8>,
|
|
|
|
/// The initrd as raw bytes.
|
|
initrd: Vec<u8>,
|
|
}
|
|
|
|
impl EmbeddedConfiguration {
|
|
fn new(file_data: &[u8]) -> Result<Self> {
|
|
Ok(Self {
|
|
kernel: extract_bytes(file_data, ".linux")?,
|
|
initrd: extract_bytes(file_data, ".initrd")?,
|
|
cmdline: extract_string(file_data, ".cmdline")?,
|
|
})
|
|
}
|
|
}
|
|
|
|
pub fn boot_linux(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
|
uefi_services::init(&mut system_table).unwrap();
|
|
|
|
// SAFETY: We get a slice that represents our currently running
|
|
// image and then parse the PE data structures from it. This is
|
|
// safe, because we don't touch any data in the data sections that
|
|
// might conceivably change while we look at the slice.
|
|
let config = unsafe {
|
|
EmbeddedConfiguration::new(
|
|
booted_image_file(system_table.boot_services())
|
|
.unwrap()
|
|
.as_slice(),
|
|
)
|
|
.expect("Failed to extract configuration from binary.")
|
|
};
|
|
|
|
let secure_boot_enabled = get_secure_boot_status(system_table.runtime_services());
|
|
let cmdline = get_cmdline(
|
|
&config.cmdline,
|
|
system_table.boot_services(),
|
|
secure_boot_enabled,
|
|
);
|
|
|
|
boot_linux_unchecked(handle, system_table, config.kernel, &cmdline, config.initrd).status()
|
|
}
|