basic functionality
This commit is contained in:
3
.cargo/config.toml
Normal file
3
.cargo/config.toml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[build]
|
||||||
|
target = "x86_64-unknown-uefi"
|
||||||
|
rustflags = ["-C", "link-args=-base:0x0"]
|
||||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/.vscode/
|
||||||
|
/target/
|
||||||
|
/esp/
|
||||||
|
/virtual/
|
||||||
138
Cargo.lock
generated
Normal file
138
Cargo.lock
generated
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "barnacle"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"uefi",
|
||||||
|
"uefi-services",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit_field"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.51"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ptr_meta"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcada80daa06c42ed5f48c9a043865edea5dc44cbf9ac009fda3b89526e28607"
|
||||||
|
dependencies = [
|
||||||
|
"ptr_meta_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ptr_meta_derive"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucs2"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bad643914094137d475641b6bab89462505316ec2ce70907ad20102d28a79ab8"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uefi"
|
||||||
|
version = "0.19.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f5607fef843201070ed442fa257c7a944fae963fac7d4620612123192eb4d844"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"log",
|
||||||
|
"ptr_meta",
|
||||||
|
"ucs2",
|
||||||
|
"uefi-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uefi-macros"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8099684193f2d99f7f130951f4054a1591ff7da370e2b33d7a71f0434920499"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uefi-services"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f75daa44f951cc1d9dc68d98cabc06ddbccc221d7bd21222271be5d7ac526a9d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"log",
|
||||||
|
"uefi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||||
20
Cargo.toml
Normal file
20
Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "barnacle"
|
||||||
|
version = "0.1.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.17"
|
||||||
|
uefi = "0.19.1"
|
||||||
|
uefi-services = "0.16.0"
|
||||||
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Barnacle : The Rusty Stub Loader
|
||||||
|
|
||||||
|
## Example objcopy command
|
||||||
|
|
||||||
|
cmdline has to be converted to utf-16
|
||||||
|
|
||||||
|
```sh
|
||||||
|
objcopy target/x86_64-unknown-uefi/release/barnacle.efi /boot/efi/arch.efi \
|
||||||
|
--add-section .linux=/boot/vmlinuz-linux --change-section-vma .linux=0x2000000 \
|
||||||
|
--add-section .initrd=/boot/initramfs-linux.img --change-section-vma .initrd=0x3000000 \
|
||||||
|
--add-section .cmdline=<(grep -a '^[^#]' "/etc/kernel/cmdline" | tr -s '\n' ' ' | iconv -t utf-16; printf '\n\0') --change-section-vma .cmdline=0x30000
|
||||||
|
```
|
||||||
89
src/initrd.rs
Normal file
89
src/initrd.rs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
use core::{ffi::c_void, mem::MaybeUninit};
|
||||||
|
|
||||||
|
use uefi::{
|
||||||
|
guid,
|
||||||
|
prelude::BootServices,
|
||||||
|
proto::device_path::{build, DevicePath},
|
||||||
|
Identify, Status,
|
||||||
|
};
|
||||||
|
|
||||||
|
const LOADFILE2_GUID: uefi::Guid = guid!("4006c0c1-fcb3-403e-996d-4a6c8724e06d");
|
||||||
|
const LINUX_INITRD_DEVICE_GUID: uefi::Guid = guid!("5568e427-68fc-4f3d-ac74-ca555231cc68");
|
||||||
|
|
||||||
|
/// Extends the LoadFile2 interface with initrd buffer location and size
|
||||||
|
pub struct Loader {
|
||||||
|
pub _handler: *const c_void,
|
||||||
|
pub buf: *const c_void,
|
||||||
|
pub size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a loader from buffer memory location and size
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Installs the initrd virtual device
|
||||||
|
/// Uses a buffer to build the device path
|
||||||
|
/// Creates a callback to initrd_loadfile2 for the kernel
|
||||||
|
pub fn install_initrd(
|
||||||
|
boot_services: &BootServices,
|
||||||
|
buf: &mut [MaybeUninit<u8>; 256],
|
||||||
|
mut loader: Loader,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
// Define new virtual device
|
||||||
|
let initrd_handle = boot_services
|
||||||
|
.install_protocol_interface(
|
||||||
|
None,
|
||||||
|
&DevicePath::GUID,
|
||||||
|
make_initrd_device_path(buf).as_ffi_ptr() as *mut c_void,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
// Install LoadFile2 protocol and callback
|
||||||
|
boot_services
|
||||||
|
.install_protocol_interface(
|
||||||
|
Some(initrd_handle),
|
||||||
|
&LOADFILE2_GUID,
|
||||||
|
core::ptr::addr_of_mut!(loader) as *mut c_void,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<u8>; 256]) -> &'a DevicePath {
|
||||||
|
&build::DevicePathBuilder::with_buf(buf)
|
||||||
|
.push(&build::media::Vendor {
|
||||||
|
vendor_guid: LINUX_INITRD_DEVICE_GUID,
|
||||||
|
vendor_defined_data: &[],
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.finalize()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// LoadFile2 protocol callback
|
||||||
|
/// Returns expected size if invalid buffer
|
||||||
|
/// Copies data if valid
|
||||||
|
fn initrd_loadfile2(
|
||||||
|
this: *const Loader,
|
||||||
|
_proto: *const c_void,
|
||||||
|
_boot_policy: bool,
|
||||||
|
size: *mut usize,
|
||||||
|
buf: *mut c_void,
|
||||||
|
) -> Status {
|
||||||
|
unsafe {
|
||||||
|
// Invalid buffer or insufficient size
|
||||||
|
if (*this).size > *size || buf == core::ptr::null_mut() {
|
||||||
|
// Update size parameter to specify expected space
|
||||||
|
*size = (*this).size;
|
||||||
|
return Status::BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
core::ptr::copy_nonoverlapping((*this).buf, buf, (*this).size);
|
||||||
|
}
|
||||||
|
Status::SUCCESS
|
||||||
|
}
|
||||||
22
src/lib.rs
Normal file
22
src/lib.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use linux::start_linux;
|
||||||
|
use pe::get_loader_sections;
|
||||||
|
use uefi::table::{Boot, SystemTable};
|
||||||
|
use uefi::{Handle, Status};
|
||||||
|
|
||||||
|
mod initrd;
|
||||||
|
mod linux;
|
||||||
|
mod pe;
|
||||||
|
mod secureboot;
|
||||||
|
mod unicode;
|
||||||
|
|
||||||
|
pub fn bootloader(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
||||||
|
uefi_services::init(&mut system_table).unwrap();
|
||||||
|
let boot_services = system_table.boot_services();
|
||||||
|
let sections = get_loader_sections(boot_services).unwrap();
|
||||||
|
start_linux(image_handle, boot_services, sections).unwrap();
|
||||||
|
|
||||||
|
boot_services.stall(1_000_000_000);
|
||||||
|
Status::SUCCESS
|
||||||
|
}
|
||||||
73
src/linux.rs
Normal file
73
src/linux.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use core::{ffi::c_void, mem::MaybeUninit, ptr::slice_from_raw_parts};
|
||||||
|
|
||||||
|
use uefi::{
|
||||||
|
prelude::BootServices, proto::loaded_image::LoadedImage, table::boot::LoadImageSource, Handle,
|
||||||
|
Result,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
initrd::{install_initrd, make_loader},
|
||||||
|
pe::BootSections,
|
||||||
|
secureboot::install_security_override,
|
||||||
|
unicode::convert_8_to_16,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Sets up linux image and initrd virtual device
|
||||||
|
/// Reads cmdline
|
||||||
|
/// Runs kernel
|
||||||
|
pub fn start_linux(
|
||||||
|
image_handle: Handle,
|
||||||
|
boot_services: &BootServices,
|
||||||
|
sections: BootSections,
|
||||||
|
) -> Result {
|
||||||
|
// Override Secure Boot loader
|
||||||
|
let uninstall = install_security_override(boot_services);
|
||||||
|
|
||||||
|
// Load kernel as image from memory
|
||||||
|
let handle = unsafe {
|
||||||
|
boot_services
|
||||||
|
.load_image(
|
||||||
|
image_handle,
|
||||||
|
LoadImageSource::FromBuffer {
|
||||||
|
buffer: &*slice_from_raw_parts::<u8>(
|
||||||
|
sections.linux.pointer,
|
||||||
|
sections.linux.size as usize,
|
||||||
|
),
|
||||||
|
file_path: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove secure boot override
|
||||||
|
uninstall();
|
||||||
|
|
||||||
|
let mut linux_image = boot_services
|
||||||
|
.open_protocol_exclusive::<LoadedImage>(handle)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Set cmdline for kernel image
|
||||||
|
let (cmdline_utf16, cmdline_utf16_size) = convert_8_to_16(
|
||||||
|
boot_services,
|
||||||
|
sections.cmdline.pointer,
|
||||||
|
sections.cmdline.size as usize,
|
||||||
|
);
|
||||||
|
unsafe { linux_image.set_load_options(cmdline_utf16, cmdline_utf16_size as u32) };
|
||||||
|
|
||||||
|
// Define loader for virtual initrd device
|
||||||
|
// Has to be defined here in order not to be discarded after install_initrd exit
|
||||||
|
let loader = make_loader(
|
||||||
|
sections.initrd.pointer as *const c_void,
|
||||||
|
sections.initrd.size as usize,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Install virtual initrd device
|
||||||
|
// Buffer is used to build the device path
|
||||||
|
let mut buf = [MaybeUninit::<u8>::uninit(); 256];
|
||||||
|
install_initrd(boot_services, &mut buf, loader);
|
||||||
|
|
||||||
|
// Run kernel image
|
||||||
|
boot_services.start_image(handle).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
13
src/main.rs
Normal file
13
src/main.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use barnacle::bootloader;
|
||||||
|
|
||||||
|
use uefi::prelude::entry;
|
||||||
|
use uefi::table::{Boot, SystemTable};
|
||||||
|
use uefi::{Handle, Status};
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main(image_handle: Handle, system_table: SystemTable<Boot>) -> Status {
|
||||||
|
bootloader(image_handle, system_table)
|
||||||
|
}
|
||||||
93
src/pe.rs
Normal file
93
src/pe.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
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];
|
||||||
|
|
||||||
|
pub struct PESection {
|
||||||
|
pub name: [u8; 8],
|
||||||
|
pub size: u32,
|
||||||
|
pub pointer: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TempSections {
|
||||||
|
pub linux: Option<PESection>,
|
||||||
|
pub cmdline: Option<PESection>,
|
||||||
|
pub initrd: Option<PESection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BootSections {
|
||||||
|
pub linux: PESection,
|
||||||
|
pub cmdline: PESection,
|
||||||
|
pub initrd: PESection,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extracts .linux, .initrd, and .cmdline sections from UKI
|
||||||
|
pub fn get_loader_sections(boot_services: &BootServices) -> Result<BootSections> {
|
||||||
|
// Obtain current image (UKI) memory location (and size)
|
||||||
|
let loaded_image =
|
||||||
|
boot_services.open_protocol_exclusive::<LoadedImage>(boot_services.image_handle())?;
|
||||||
|
let (image_ptr, _image_size) = loaded_image.info();
|
||||||
|
|
||||||
|
let mut tmp_sections = TempSections {
|
||||||
|
linux: None,
|
||||||
|
cmdline: None,
|
||||||
|
initrd: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (section_table, section_count) = unsafe {
|
||||||
|
// PE table offset from start at 60 bytes offset, 4 bytes long
|
||||||
|
let pe_offset = *(image_ptr.add(0x3c) as *const u32);
|
||||||
|
let pe_ptr = image_ptr.add(pe_offset as usize).add(4);
|
||||||
|
// Section table is 260 bytes after PE table
|
||||||
|
// Number of sections at 2 bytes offset (in PE), 2 bytes long
|
||||||
|
(pe_ptr.add(0x104), *(pe_ptr.add(2) as *const u16))
|
||||||
|
};
|
||||||
|
for i in 0..section_count {
|
||||||
|
let section = unsafe {
|
||||||
|
// Each row is 40 bytes long
|
||||||
|
let section_row_ptr = section_table.add((i * 40) as usize) as *const u8;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section VMA at 12 bytes offset, 4 bytes long
|
||||||
|
let section_vma = *(section_row_ptr.add(12) as *const u32);
|
||||||
|
|
||||||
|
PESection {
|
||||||
|
name,
|
||||||
|
// Section size at 8 bytes offset, 4 bytes long
|
||||||
|
size: *(section_row_ptr.add(8) as *const u32),
|
||||||
|
pointer: image_ptr.add(section_vma as usize) as *const u8,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All sections are needed, error out if not found
|
||||||
|
if tmp_sections.cmdline.is_none()
|
||||||
|
|| tmp_sections.linux.is_none()
|
||||||
|
|| tmp_sections.initrd.is_none()
|
||||||
|
{
|
||||||
|
return Err(Error::new(Status::INVALID_PARAMETER, ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(BootSections {
|
||||||
|
linux: tmp_sections.linux.unwrap(),
|
||||||
|
cmdline: tmp_sections.cmdline.unwrap(),
|
||||||
|
initrd: tmp_sections.initrd.unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
106
src/secureboot.rs
Normal file
106
src/secureboot.rs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
use core::ffi::c_void;
|
||||||
|
|
||||||
|
use log::info;
|
||||||
|
use uefi::{guid, prelude::BootServices, proto::Protocol, Identify};
|
||||||
|
|
||||||
|
struct SecurityArch {
|
||||||
|
pub handler: *const c_void,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Identify for SecurityArch {
|
||||||
|
const GUID: uefi::Guid = guid!("A46423E3-4617-49F1-B9FF-D1BFA9115839");
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Protocol for SecurityArch {}
|
||||||
|
|
||||||
|
struct Security2Arch {
|
||||||
|
pub handler: *const c_void,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Identify for Security2Arch {
|
||||||
|
const GUID: uefi::Guid = guid!("94ab2f58-1438-4ef1-9152-18941a3a0e68");
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Protocol for Security2Arch {}
|
||||||
|
|
||||||
|
/// Most basic security handler, always returns true
|
||||||
|
fn security_handler() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stores default security handlers to restore them when uninstalling
|
||||||
|
struct DefaultSecurityHandlers {
|
||||||
|
pub security1: Option<*mut *const c_void>,
|
||||||
|
pub security1_handler: Option<*const c_void>,
|
||||||
|
pub security2: Option<*mut *const c_void>,
|
||||||
|
pub security2_handler: Option<*const c_void>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Secure Boot override to load kernel image from memory
|
||||||
|
/// Plagiarized from systemd-stub's "hack"
|
||||||
|
/// Returns an override uninstaller to restore default handlers
|
||||||
|
pub fn install_security_override(boot_services: &BootServices) -> impl Fn() -> () {
|
||||||
|
let mut defaults = DefaultSecurityHandlers {
|
||||||
|
security1: None,
|
||||||
|
security1_handler: None,
|
||||||
|
security2: None,
|
||||||
|
security2_handler: None,
|
||||||
|
};
|
||||||
|
// Obtain SecurityArch protocol and replace handler
|
||||||
|
boot_services
|
||||||
|
.get_handle_for_protocol::<SecurityArch>()
|
||||||
|
.and_then(|h| {
|
||||||
|
boot_services
|
||||||
|
.open_protocol_exclusive::<SecurityArch>(h)
|
||||||
|
.and_then(|mut security| {
|
||||||
|
defaults.security1 = Some(core::ptr::addr_of_mut!(security.handler));
|
||||||
|
defaults.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::<Security2Arch>()
|
||||||
|
.and_then(|h| {
|
||||||
|
boot_services
|
||||||
|
.open_protocol_exclusive::<Security2Arch>(h)
|
||||||
|
.and_then(|mut security| {
|
||||||
|
defaults.security2 = Some(core::ptr::addr_of_mut!(security.handler));
|
||||||
|
defaults.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");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Returns restore function
|
||||||
|
return move || {
|
||||||
|
// Restore default SecurityArch handler
|
||||||
|
defaults.security1.and_then(|s1| {
|
||||||
|
defaults
|
||||||
|
.security1_handler
|
||||||
|
.and_then(|s1h| Some(unsafe { *s1 = s1h }))
|
||||||
|
});
|
||||||
|
|
||||||
|
// Restore default SecurityArch2 handler
|
||||||
|
defaults.security2.and_then(|s2| {
|
||||||
|
defaults
|
||||||
|
.security1_handler
|
||||||
|
.and_then(|s2h| Some(unsafe { *s2 = s2h }))
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
18
src/unicode.rs
Normal file
18
src/unicode.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use uefi::{prelude::BootServices, table::boot::MemoryType};
|
||||||
|
|
||||||
|
/// Converts ascii to basic utf-16
|
||||||
|
pub fn convert_8_to_16(
|
||||||
|
boot_services: &BootServices,
|
||||||
|
text: *const u8,
|
||||||
|
size: usize,
|
||||||
|
) -> (*const u8, usize) {
|
||||||
|
let work_mem = boot_services
|
||||||
|
.allocate_pool(MemoryType::BOOT_SERVICES_DATA, size * 2)
|
||||||
|
.unwrap() as *mut u16;
|
||||||
|
for i in 0..size {
|
||||||
|
unsafe {
|
||||||
|
*work_mem.add(i) = *text.add(i) as u16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(work_mem as *const u8, size * 2)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user