stub: move linux booting into its own function

This commit is contained in:
Julian Stecklina 2023-02-02 15:54:27 +01:00
parent f3ede28eac
commit 8d2ebbc6a7
1 changed files with 41 additions and 17 deletions

View File

@ -11,6 +11,7 @@ mod pe_loader;
mod pe_section; mod pe_section;
mod uefi_helpers; mod uefi_helpers;
use alloc::vec::Vec;
use pe_loader::Image; use pe_loader::Image;
use pe_section::{pe_section, pe_section_as_string}; use pe_section::{pe_section, pe_section_as_string};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
@ -20,7 +21,7 @@ use uefi::{
console::text::Output, console::text::Output,
media::file::{File, FileAttribute, FileMode, RegularFile}, media::file::{File, FileAttribute, FileMode, RegularFile},
}, },
CString16, Result, CStr16, CString16, Result,
}; };
use crate::{ use crate::{
@ -106,6 +107,28 @@ impl EmbeddedConfiguration {
} }
} }
/// Boot the Linux kernel without checking the PE signature.
///
/// We assume that the caller has made sure that the image is safe to
/// be loaded using other means.
fn boot_linux_unchecked(
handle: Handle,
system_table: SystemTable<Boot>,
kernel_data: Vec<u8>,
kernel_cmdline: &CStr16,
initrd_data: Vec<u8>,
) -> uefi::Result<()> {
let kernel =
Image::load(system_table.boot_services(), &kernel_data).expect("Failed to load the kernel");
let mut initrd_loader = InitrdLoader::new(system_table.boot_services(), handle, initrd_data)?;
let status = unsafe { kernel.start(handle, &system_table, kernel_cmdline) };
initrd_loader.uninstall(system_table.boot_services())?;
status.into()
}
#[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();
@ -153,32 +176,33 @@ fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
initrd_data = read_all(&mut initrd_file).expect("Failed to read kernel file into memory"); initrd_data = read_all(&mut initrd_file).expect("Failed to read kernel file into memory");
} }
if Sha256::digest(&kernel_data) != config.kernel_hash { let is_kernel_hash_correct = Sha256::digest(&kernel_data) == config.kernel_hash;
let is_initrd_hash_correct = Sha256::digest(&initrd_data) == config.initrd_hash;
if !is_kernel_hash_correct {
system_table system_table
.stdout() .stdout()
.output_string(cstr16!("Hash mismatch for kernel. Refusing to load!\r\n")) .output_string(cstr16!("Hash mismatch for kernel. Refusing to load!\r\n"))
.unwrap(); .unwrap();
return Status::SECURITY_VIOLATION;
} }
if Sha256::digest(&initrd_data) != config.initrd_hash { if !is_initrd_hash_correct {
system_table system_table
.stdout() .stdout()
.output_string(cstr16!("Hash mismatch for initrd. Refusing to load!\r\n")) .output_string(cstr16!("Hash mismatch for initrd. Refusing to load!\r\n"))
.unwrap(); .unwrap();
return Status::SECURITY_VIOLATION;
} }
let kernel = if is_kernel_hash_correct && is_initrd_hash_correct {
Image::load(system_table.boot_services(), &kernel_data).expect("Failed to load the kernel"); boot_linux_unchecked(
handle,
let mut initrd_loader = InitrdLoader::new(system_table.boot_services(), handle, initrd_data) system_table,
.expect("Failed to load the initrd. It may not be there or it is not signed"); kernel_data,
&config.cmdline,
let status = unsafe { kernel.start(handle, &system_table, &config.cmdline) }; initrd_data,
)
initrd_loader .status()
.uninstall(system_table.boot_services()) } else {
.expect("Failed to uninstall the initrd protocols"); Status::SECURITY_VIOLATION
status }
} }