From a59b723f4b77515a1d3ece111bd0ee6a72119201 Mon Sep 17 00:00:00 2001 From: Altareos Date: Wed, 2 Jul 2025 00:27:56 +0200 Subject: [PATCH] major cleanup --- Cargo.lock | 17 ++++++++--------- Cargo.toml | 12 +----------- src/initrd.rs | 10 +++++----- src/lib.rs | 9 +++++++-- src/linux.rs | 26 +++++++++++++------------- src/pe.rs | 21 ++++++++++----------- src/secureboot.rs | 47 ++++++++++++++++++----------------------------- 7 files changed, 62 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b7ad08..0517f91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "barnacle" -version = "0.2.0" +version = "0.3.0" dependencies = [ - "log", "uefi", "uefi-services", ] @@ -97,9 +96,9 @@ dependencies = [ [[package]] name = "ucs2" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad643914094137d475641b6bab89462505316ec2ce70907ad20102d28a79ab8" +checksum = "df79298e11f316400c57ec268f3c2c29ac3c4d4777687955cd3d4f3a35ce7eba" dependencies = [ "bit_field", ] @@ -132,9 +131,9 @@ dependencies = [ [[package]] name = "uefi-raw" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864ac69eadd877bfb34e7814be1928122ed0057d9f975169a56ee496aa7bdfd7" +checksum = "efa8716f52e8cab8bcedfd5052388a0f263b69fe5cc2561548dc6a530678333c" dependencies = [ "bitflags", "ptr_meta", @@ -154,9 +153,9 @@ dependencies = [ [[package]] name = "uguid" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef516f0806c5f61da6aa95125d0eb2d91cc95b2df426c06bde8be657282aee5" +checksum = "ab14ea9660d240e7865ce9d54ecdbd1cd9fa5802ae6f4512f093c7907e921533" [[package]] name = "unicode-ident" diff --git a/Cargo.toml b/Cargo.toml index f3ae585..807a212 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,10 @@ [package] name = "barnacle" -version = "0.2.0" +version = "0.3.0" edition = "2021" -[[bin]] -name = "barnacle" -test = false -bench = false - -[lib] -test = false -bench = false - # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -log = "0.4.20" uefi = "0.26.0" uefi-services = "0.23.0" diff --git a/src/initrd.rs b/src/initrd.rs index 8921466..f75324f 100644 --- a/src/initrd.rs +++ b/src/initrd.rs @@ -20,8 +20,8 @@ pub struct Loader { pub fn make_loader(pointer: *const c_void, size: usize) -> Loader { Loader { _handler: initrd_loadfile2 as *const c_void, - buf: pointer as *const c_void, - size: size as usize, + buf: pointer, + size, } } @@ -54,8 +54,8 @@ pub fn install_initrd( } /// Creates a device path for a virtual device with the Linux initrd vendor GUID -pub fn make_initrd_device_path<'a>(buf: &'a mut [MaybeUninit; 256]) -> &'a DevicePath { - &build::DevicePathBuilder::with_buf(buf) +pub fn make_initrd_device_path(buf: &mut [MaybeUninit; 256]) -> &DevicePath { + build::DevicePathBuilder::with_buf(buf) .push(&build::media::Vendor { vendor_guid: LINUX_INITRD_DEVICE_GUID, vendor_defined_data: &[], @@ -77,7 +77,7 @@ fn initrd_loadfile2( ) -> Status { unsafe { // Invalid buffer or insufficient size - if (*this).size > *size || buf == core::ptr::null_mut() { + if (*this).size > *size || buf.is_null() { // Update size parameter to specify expected space *size = (*this).size; return Status::BUFFER_TOO_SMALL; diff --git a/src/lib.rs b/src/lib.rs index c88aa2a..640b5b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,13 @@ mod pe; mod secureboot; mod unicode; -pub fn bootloader(image_handle: Handle, mut system_table: SystemTable) -> Status { - uefi_services::init(&mut system_table).unwrap(); +#[cfg(not(test))] +#[panic_handler] +pub fn panic(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +pub fn bootloader(image_handle: Handle, system_table: SystemTable) -> Status { let boot_services = system_table.boot_services(); let sections = get_loader_sections(boot_services).unwrap(); start_linux(image_handle, boot_services, sections).unwrap(); diff --git a/src/linux.rs b/src/linux.rs index c93a7cf..9c264ce 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -22,22 +22,22 @@ pub fn start_linux( ) -> Result { // Load kernel as image from memory ignoring secure boot // Image is already trusted (signed) by being part of this EFI program - let handle = unsafe { - run_in_security_override(boot_services, || { - boot_services - .load_image( - image_handle, - LoadImageSource::FromBuffer { - buffer: &*slice_from_raw_parts::( + let handle = run_in_security_override(boot_services, || { + boot_services + .load_image( + image_handle, + LoadImageSource::FromBuffer { + buffer: unsafe { + &*slice_from_raw_parts::( sections.linux.pointer, sections.linux.size as usize, - ), - file_path: None, + ) }, - ) - .unwrap() - }) - }; + file_path: None, + }, + ) + .unwrap() + })?; let mut linux_image = boot_services .open_protocol_exclusive::(handle) diff --git a/src/pe.rs b/src/pe.rs index 92fa168..eed2665 100644 --- a/src/pe.rs +++ b/src/pe.rs @@ -2,9 +2,9 @@ use uefi::prelude::BootServices; use uefi::proto::loaded_image::LoadedImage; use uefi::{Error, Result, Status}; -const LINUX_SNAME: [u8; 8] = [0x2e, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0, 0]; -const CMDLINE_SNAME: [u8; 8] = [0x2e, 0x63, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65]; -const INITRD_SNAME: [u8; 8] = [0x2e, 0x69, 0x6e, 0x69, 0x74, 0x72, 0x64, 0]; +const LINUX_SNAME: [u8; 8] = *b".linux\0\0"; +const CMDLINE_SNAME: [u8; 8] = *b".cmdline"; +const INITRD_SNAME: [u8; 8] = *b".initrd\0"; pub struct PESection { pub name: [u8; 8], @@ -52,8 +52,8 @@ pub fn get_loader_sections(boot_services: &BootServices) -> Result // Section name at 0 bytes offset, 8 bytes long let mut name = [0; 8]; - for j in 0..8 { - name[j] = *section_row_ptr.add(j); + for (j, char) in name.iter_mut().enumerate() { + *char = *section_row_ptr.add(j); } // Section VMA at 12 bytes offset, 4 bytes long @@ -68,12 +68,11 @@ pub fn get_loader_sections(boot_services: &BootServices) -> Result }; // Section identification - if section.name == LINUX_SNAME { - tmp_sections.linux = Some(section); - } else if section.name == CMDLINE_SNAME { - tmp_sections.cmdline = Some(section); - } else if section.name == INITRD_SNAME { - tmp_sections.initrd = Some(section); + match section.name { + LINUX_SNAME => tmp_sections.linux = Some(section), + CMDLINE_SNAME => tmp_sections.cmdline = Some(section), + INITRD_SNAME => tmp_sections.initrd = Some(section), + _ => {} } } diff --git a/src/secureboot.rs b/src/secureboot.rs index cc8e4c6..35bc41d 100644 --- a/src/secureboot.rs +++ b/src/secureboot.rs @@ -1,7 +1,6 @@ use core::ffi::c_void; -use log::info; -use uefi::{prelude::BootServices, proto::unsafe_protocol}; +use uefi::{prelude::BootServices, proto::unsafe_protocol, Result}; #[unsafe_protocol("A46423E3-4617-49F1-B9FF-D1BFA9115839")] struct SecurityArch { @@ -22,60 +21,50 @@ fn security_handler() -> bool { /// Runs a function with a blind secure boot validator /// Plagiarized from systemd-stub's "hack" /// There must be a better way -pub fn run_in_security_override R>(boot_services: &BootServices, function: T) -> R { - // Backup storage +pub fn run_in_security_override R>( + boot_services: &BootServices, + function: T, +) -> Result { + // Temporary storage for restoration later let mut df_security1 = None; let mut df_security1_handler = None; let mut df_security2 = None; let mut df_security2_handler = None; + // Obtain SecurityArch protocol and replace handler boot_services .get_handle_for_protocol::() - .and_then(|h| { + .map(|h| { boot_services .open_protocol_exclusive::(h) - .and_then(|mut security| { + .map(|mut security| { df_security1 = Some(core::ptr::addr_of_mut!(security.handler)); df_security1_handler = Some(security.handler); security.handler = security_handler as *const c_void; - Ok(()) }) - .unwrap_or_else(|_| { - info!("security1 unsupported"); - }); - Ok(()) - }) - .unwrap_or_else(|_| { - info!("security1 not found"); - }); + })??; + // Obtain Security2Arch protocol and replace handler boot_services .get_handle_for_protocol::() - .and_then(|h| { + .map(|h| { boot_services .open_protocol_exclusive::(h) - .and_then(|mut security| { + .map(|mut security| { df_security2 = Some(core::ptr::addr_of_mut!(security.handler)); df_security2_handler = Some(security.handler); security.handler = security_handler as *const c_void; - Ok(()) }) - .unwrap_or_else(|_| { - info!("security2 unsupported"); - }); - Ok(()) - }) - .unwrap_or_else(|_| { - info!("security2 not found"); - }); + })??; + // Run the parameter function let x = function(); // Restore default SecurityArch handler - df_security1.and_then(|s1| df_security1_handler.and_then(|s1h| Some(unsafe { *s1 = s1h }))); + df_security1.and_then(|s1| df_security1_handler.map(|s1h| unsafe { *s1 = s1h })); // Restore default SecurityArch2 handler - df_security2.and_then(|s2| df_security2_handler.and_then(|s2h| Some(unsafe { *s2 = s2h }))); + df_security2.and_then(|s2| df_security2_handler.map(|s2h| unsafe { *s2 = s2h })); - x + Ok(x) }