Skip to content

Commit

Permalink
freebsd: Add support for ESRT parsing
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Schaefer <[email protected]>
  • Loading branch information
JohnAZoidberg committed Jul 6, 2024
1 parent e328bb4 commit 0f45402
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ see the [Support Matrices](support-matrices.md).
###### Firmware Information

- [x] Show system information
- [x] ESRT table (UEFI and Linux only) (`--esrt`)
- [x] ESRT table (UEFI, Linux, FreeBSD only) (`--esrt`)
- [x] SMBIOS
- [x] Get firmware version from binary file
- [x] Legacy EC (Intel 13th Gen and earlier) (`--ec-bin`)
Expand Down
91 changes: 70 additions & 21 deletions framework_lib/src/esrt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::guid::Guid;
use core::prelude::v1::derive;
#[cfg(not(feature = "uefi"))]
use guid_macros::guid;
#[cfg(feature = "uefi")]
#[cfg(any(feature = "uefi", target_os = "freebsd"))]
use std::slice;
#[cfg(feature = "uefi")]
use uefi::{guid, Guid};
Expand All @@ -31,6 +31,15 @@ use std::io;
#[cfg(feature = "linux")]
use std::path::Path;

#[cfg(target_os = "freebsd")]
use nix::ioctl_readwrite;
#[cfg(target_os = "freebsd")]
use std::fs::OpenOptions;
#[cfg(target_os = "freebsd")]
use std::os::fd::AsRawFd;
#[cfg(target_os = "freebsd")]
use std::os::unix::fs::OpenOptionsExt;

/// Decode from GUID string version
///
/// # Examples
Expand Down Expand Up @@ -316,7 +325,7 @@ fn esrt_from_sysfs(dir: &Path) -> io::Result<Esrt> {
Ok(esrt_table)
}

#[cfg(all(not(feature = "uefi"), feature = "linux"))]
#[cfg(all(not(feature = "uefi"), feature = "linux", target_os = "linux"))]
pub fn get_esrt() -> Option<Esrt> {
let res = esrt_from_sysfs(Path::new("/sys/firmware/efi/esrt/entries")).ok();
if res.is_none() {
Expand All @@ -332,10 +341,45 @@ pub fn get_esrt() -> Option<Esrt> {
None
}

#[cfg(target_os = "freebsd")]
#[repr(C)]
struct EfiGetTableIoc {
buf: *mut u8,
uuid: [u8; 16],
table_len: usize,
buf_len: usize,
}
#[cfg(target_os = "freebsd")]
ioctl_readwrite!(efi_get_table, b'E', 1, EfiGetTableIoc);

#[cfg(all(not(feature = "uefi"), target_os = "freebsd"))]
pub fn get_esrt() -> Option<Esrt> {
// TODO: Implement
println!("Reading ESRT is not implemented on FreeBSD yet.");
let file = OpenOptions::new()
.read(true)
.write(true)
.custom_flags(libc::O_NONBLOCK)
.open("/dev/efi")
.unwrap();

let mut buf: Vec<u8> = Vec::new();
let mut table = EfiGetTableIoc {
buf: std::ptr::null_mut(),
uuid: SYSTEM_RESOURCE_TABLE_GUID.to_bytes(),
buf_len: 0,
table_len: 0,
};
unsafe {
let fd = file.as_raw_fd();
let _res = efi_get_table(fd, &mut table).unwrap();
buf.resize(table.table_len, 0);
table.buf_len = table.table_len;
table.buf = buf.as_mut_ptr();

let _res = efi_get_table(fd, &mut table).unwrap();
return esrt_from_buf(table.buf);
}
println!("Success");

None
}

Expand All @@ -353,26 +397,31 @@ pub fn get_esrt() -> Option<Esrt> {
let table_guid: Guid = unsafe { std::mem::transmute(table.guid) };
match table_guid {
SYSTEM_RESOURCE_TABLE_GUID => unsafe {
let raw_esrt = &*(table.address as *const _Esrt);
let mut esrt = Esrt {
resource_count: raw_esrt.resource_count,
resource_count_max: raw_esrt.resource_count_max,
resource_version: raw_esrt.resource_version,
entries: vec![],
};

// Make sure it's the version we expect
debug_assert!(esrt.resource_version == ESRT_FIRMWARE_RESOURCE_VERSION);

let src_ptr = std::ptr::addr_of!(raw_esrt.entries) as *const EsrtResourceEntry;
let slice_entries = slice::from_raw_parts(src_ptr, esrt.resource_count as usize);

esrt.entries = slice_entries.to_vec();

return Some(esrt);
return esrt_from_buf(table.address);
},
_ => {}
}
}
None
}

/// Parse the ESRT table buffer
unsafe fn esrt_from_buf(ptr: *const u8) -> Option<Esrt> {
let raw_esrt = &*(ptr as *const _Esrt);
let mut esrt = Esrt {
resource_count: raw_esrt.resource_count,
resource_count_max: raw_esrt.resource_count_max,
resource_version: raw_esrt.resource_version,
entries: vec![],
};

// Make sure it's the version we expect
debug_assert!(esrt.resource_version == ESRT_FIRMWARE_RESOURCE_VERSION);

let src_ptr = core::ptr::addr_of!(raw_esrt.entries) as *const EsrtResourceEntry;
let slice_entries = core::slice::from_raw_parts(src_ptr, esrt.resource_count as usize);

esrt.entries = slice_entries.to_vec();

Some(esrt)
}

0 comments on commit 0f45402

Please sign in to comment.