Extract Linux kernel and initrd filenames from PE binary
This commit is contained in:
parent
788a112050
commit
4dab5f7b8f
|
@ -9,18 +9,20 @@ mod linux_loader;
|
||||||
mod pe_section;
|
mod pe_section;
|
||||||
mod uefi_helpers;
|
mod uefi_helpers;
|
||||||
|
|
||||||
|
use pe_section::pe_section_as_string;
|
||||||
use uefi::{
|
use uefi::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
proto::{
|
proto::{
|
||||||
console::text::Output,
|
console::text::Output,
|
||||||
loaded_image::LoadedImage,
|
loaded_image::LoadedImage,
|
||||||
media::file::{File, FileAttribute, FileMode},
|
media::file::{File, FileAttribute, FileMode, RegularFile},
|
||||||
},
|
},
|
||||||
|
CString16,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
linux_loader::InitrdLoader,
|
linux_loader::InitrdLoader,
|
||||||
uefi_helpers::{booted_image_cmdline, read_all},
|
uefi_helpers::{booted_image_cmdline, booted_image_file, read_all},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn print_logo(output: &mut Output) {
|
fn print_logo(output: &mut Output) {
|
||||||
|
@ -41,27 +43,61 @@ fn print_logo(output: &mut Output) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct EmbeddedConfiguration {
|
||||||
|
kernel_filename: CString16,
|
||||||
|
initrd_filename: CString16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&mut RegularFile> for EmbeddedConfiguration {
|
||||||
|
type Error = uefi::Error;
|
||||||
|
|
||||||
|
fn try_from(file: &mut RegularFile) -> Result<Self, Self::Error> {
|
||||||
|
file.set_position(0)?;
|
||||||
|
let file_data = read_all(file)?;
|
||||||
|
|
||||||
|
let kernel_filename =
|
||||||
|
pe_section_as_string(&file_data, ".kernelp").ok_or(Status::INVALID_PARAMETER)?;
|
||||||
|
let initrd_filename =
|
||||||
|
pe_section_as_string(&file_data, ".initrdp").ok_or(Status::INVALID_PARAMETER)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
kernel_filename: CString16::try_from(kernel_filename.as_str()).unwrap(),
|
||||||
|
initrd_filename: CString16::try_from(initrd_filename.as_str()).unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
||||||
uefi_services::init(&mut system_table).unwrap();
|
uefi_services::init(&mut system_table).unwrap();
|
||||||
|
|
||||||
print_logo(system_table.stdout());
|
print_logo(system_table.stdout());
|
||||||
|
|
||||||
|
let config: EmbeddedConfiguration = {
|
||||||
|
let mut booted_image = booted_image_file(system_table.boot_services()).unwrap();
|
||||||
|
|
||||||
|
(&mut booted_image).try_into().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
let mut file_system = system_table
|
let mut file_system = system_table
|
||||||
.boot_services()
|
.boot_services()
|
||||||
.get_image_file_system(handle)
|
.get_image_file_system(handle)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut root = file_system.open_volume().unwrap();
|
let mut root = file_system.open_volume().unwrap();
|
||||||
|
|
||||||
let mut file = root
|
let mut kernel_file = root
|
||||||
.open(cstr16!("linux.efi"), FileMode::Read, FileAttribute::empty())
|
.open(
|
||||||
|
&config.kernel_filename,
|
||||||
|
FileMode::Read,
|
||||||
|
FileAttribute::empty(),
|
||||||
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_regular_file()
|
.into_regular_file()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let initrd = root
|
let initrd = root
|
||||||
.open(
|
.open(
|
||||||
cstr16!("initrd.efi"),
|
&config.initrd_filename,
|
||||||
FileMode::Read,
|
FileMode::Read,
|
||||||
FileAttribute::empty(),
|
FileAttribute::empty(),
|
||||||
)
|
)
|
||||||
|
@ -75,7 +111,7 @@ fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
||||||
|
|
||||||
let kernel_cmdline = booted_image_cmdline(system_table.boot_services()).unwrap();
|
let kernel_cmdline = booted_image_cmdline(system_table.boot_services()).unwrap();
|
||||||
|
|
||||||
let kernel_data = read_all(&mut file).unwrap();
|
let kernel_data = read_all(&mut kernel_file).unwrap();
|
||||||
let kernel_handle = system_table
|
let kernel_handle = system_table
|
||||||
.boot_services()
|
.boot_services()
|
||||||
.load_image(
|
.load_image(
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use alloc::{borrow::ToOwned, string::String};
|
||||||
|
|
||||||
|
/// Extracts the data of a section of a PE file.
|
||||||
pub fn pe_section<'a>(file_data: &'a [u8], section_name: &str) -> Option<&'a [u8]> {
|
pub fn pe_section<'a>(file_data: &'a [u8], section_name: &str) -> Option<&'a [u8]> {
|
||||||
let pe_binary = goblin::pe::PE::parse(file_data).ok()?;
|
let pe_binary = goblin::pe::PE::parse(file_data).ok()?;
|
||||||
|
|
||||||
|
@ -12,3 +15,9 @@ pub fn pe_section<'a>(file_data: &'a [u8], section_name: &str) -> Option<&'a [u8
|
||||||
Some(&file_data[section_start..section_end])
|
Some(&file_data[section_start..section_end])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extracts the data of a section of a PE file and returns it as a string.
|
||||||
|
pub fn pe_section_as_string<'a>(file_data: &'a [u8], section_name: &str) -> Option<String> {
|
||||||
|
pe_section(file_data, section_name)
|
||||||
|
.and_then(|data| Some(core::str::from_utf8(data).unwrap().to_owned()))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue