From 92cf7a82cd0697761fa9358b6b1595a511fc334f Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 29 Apr 2023 12:56:37 -0400 Subject: [PATCH] uefi: Add get_variable_boxed This alloc-only method is a more convenient form of `get_variable`. --- CHANGELOG.md | 1 + uefi-test-runner/src/runtime/vars.rs | 7 ++++ uefi/src/table/runtime.rs | 50 +++++++++++++++++++++++----- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46a743e89..86c680359 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - `From<&CStr16>` for `CString16` - `From<&CStr16>` for `String` - `From<&CString16>` for `String` +- Added `RuntimeServices::get_variable_boxed` (requires the `alloc` feature). ### Changed diff --git a/uefi-test-runner/src/runtime/vars.rs b/uefi-test-runner/src/runtime/vars.rs index b947fdedd..15a7a37fb 100644 --- a/uefi-test-runner/src/runtime/vars.rs +++ b/uefi-test-runner/src/runtime/vars.rs @@ -29,6 +29,13 @@ fn test_variables(rt: &RuntimeServices) { assert_eq!(data, test_value); assert_eq!(attrs, test_attrs); + info!("Testing get_variable_boxed"); + let (data, attrs) = rt + .get_variable_boxed(name, &vendor) + .expect("failed to get variable"); + assert_eq!(&*data, test_value); + assert_eq!(attrs, test_attrs); + info!("Testing variable_keys"); let variable_keys = rt.variable_keys().expect("failed to get variable keys"); info!("Found {} variables", variable_keys.len()); diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index f83309567..4a5c1aaae 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -1,20 +1,22 @@ //! UEFI services available at runtime, even after the OS boots. use super::{Header, Revision}; -#[cfg(feature = "alloc")] -use crate::data_types::FromSliceWithNulError; -use crate::result::Error; use crate::table::boot::MemoryDescriptor; -use crate::{guid, CStr16, Char16, Guid, Result, Status, StatusExt}; -#[cfg(feature = "alloc")] -use alloc::{vec, vec::Vec}; +use crate::{guid, CStr16, Char16, Error, Guid, Result, Status, StatusExt}; use bitflags::bitflags; use core::ffi::c_void; use core::fmt::{Debug, Formatter}; -#[cfg(feature = "alloc")] -use core::mem; use core::mem::MaybeUninit; use core::{fmt, ptr}; + +#[cfg(feature = "alloc")] +use { + crate::data_types::FromSliceWithNulError, + alloc::boxed::Box, + alloc::{vec, vec::Vec}, + core::mem, +}; + /// Contains pointers to all of the runtime services. /// /// This table, and the function pointers it contains are valid @@ -159,6 +161,38 @@ impl RuntimeServices { } } + /// Get the contents and attributes of a variable. + #[cfg(feature = "alloc")] + pub fn get_variable_boxed( + &self, + name: &CStr16, + vendor: &VariableVendor, + ) -> Result<(Box<[u8]>, VariableAttributes)> { + let mut attributes = VariableAttributes::empty(); + + let mut data_size = self.get_variable_size(name, vendor)?; + let mut data = Vec::with_capacity(data_size); + + let status = unsafe { + (self.get_variable)( + name.as_ptr(), + &vendor.0, + &mut attributes, + &mut data_size, + data.as_mut_ptr(), + ) + }; + if !status.is_success() { + return Err(Error::from(status)); + } + + unsafe { + data.set_len(data_size); + } + + Ok((data.into_boxed_slice(), attributes)) + } + /// Get the names and vendor GUIDs of all currently-set variables. #[cfg(feature = "alloc")] pub fn variable_keys(&self) -> Result> {