Skip to content

Commit cc4cf5f

Browse files
committed
Added read_entry_boxed_in and get_boxed_info_in that use the allocator_api
1 parent 01b27af commit cc4cf5f

File tree

5 files changed

+57
-21
lines changed

5 files changed

+57
-21
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
- Added `Directory::read_entry_boxed` which works similar to `File::get_boxed_info`. This allows
99
easier iteration over the entries in a directory.
1010
- Added an `core::error::Error` implementation for `Error` to ease
11-
integration with error-handling crates.
11+
integration with error-handling crates. (requires the **unstable** feature)
12+
- Added `Directory::read_entry_boxed_in` and `File::get_boxed_info_in` that use the `allocator_api`
13+
feature. (requires the **unstable** feature)
1214

1315
## uefi-macros - [Unreleased]
1416

uefi/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
#![feature(ptr_metadata)]
6363
#![cfg_attr(feature = "alloc", feature(vec_into_raw_parts))]
6464
#![cfg_attr(feature = "unstable", feature(error_in_core))]
65+
#![cfg_attr(feature = "unstable", feature(allocator_api))]
66+
#![cfg_attr(feature = "unstable", feature(slice_ptr_get))]
6567
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
6668
#![no_std]
6769
// Enable some additional warnings and lints.

uefi/src/mem.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,25 @@
22
33
use crate::ResultExt;
44
use crate::{Result, Status};
5-
use ::alloc::{alloc, boxed::Box};
6-
use core::alloc::Layout;
5+
use ::alloc::{alloc::Global, boxed::Box};
6+
use core::alloc::{Allocator, Layout};
77
use core::fmt::Debug;
8-
use core::slice;
8+
use core::ptr::NonNull;
99
use uefi::data_types::Align;
1010
use uefi::Error;
1111

12+
/// Wrapper around [`make_boxed_in`] that uses [`Global`]/the system allocator.
13+
#[allow(unused)]
14+
pub fn make_boxed<
15+
'a,
16+
Data: Align + ?Sized + Debug + 'a,
17+
F: FnMut(&'a mut [u8]) -> Result<&'a mut Data, Option<usize>>,
18+
>(
19+
mut fetch_data_fn: F,
20+
) -> Result<Box<Data>> {
21+
make_boxed_in::<'a, Global, _, _>(Global, fetch_data_fn)
22+
}
23+
1224
/// Helper to return owned versions of certain UEFI data structures on the heap in a [`Box`]. This
1325
/// function is intended to wrap low-level UEFI functions of this crate that
1426
/// - can consume an empty buffer without a panic to get the required buffer size in the errors
@@ -17,11 +29,15 @@ use uefi::Error;
1729
/// buffer size is sufficient, and
1830
/// - return a mutable typed reference that points to the same memory as the input buffer on
1931
/// success.
20-
pub fn make_boxed<
32+
///
33+
/// It takes a custom allocator via the `allocator_api`.
34+
pub fn make_boxed_in<
2135
'a,
36+
A: Allocator,
2237
Data: Align + ?Sized + Debug + 'a,
2338
F: FnMut(&'a mut [u8]) -> Result<&'a mut Data, Option<usize>>,
2439
>(
40+
allocator: A,
2541
mut fetch_data_fn: F,
2642
) -> Result<Box<Data>> {
2743
let required_size = match fetch_data_fn(&mut []).map_err(Error::split) {
@@ -41,25 +57,21 @@ pub fn make_boxed<
4157
.pad_to_align();
4258

4359
// Allocate the buffer.
44-
let heap_buf: *mut u8 = unsafe {
45-
let ptr = alloc::alloc(layout);
46-
if ptr.is_null() {
47-
return Err(Status::OUT_OF_RESOURCES.into());
48-
}
49-
ptr
50-
};
60+
let mut heap_buf: NonNull<[u8]> = allocator
61+
.allocate(layout)
62+
.map_err(|_| <Status as Into<Error>>::into(Status::OUT_OF_RESOURCES))?;
5163

5264
// Read the data into the provided buffer.
5365
let data: Result<&mut Data> = {
54-
let buffer = unsafe { slice::from_raw_parts_mut(heap_buf, required_size) };
55-
fetch_data_fn(buffer).discard_errdata()
66+
let slice = unsafe { heap_buf.as_mut() };
67+
fetch_data_fn(slice).discard_errdata()
5668
};
5769

5870
// If an error occurred, deallocate the memory before returning.
5971
let data: &mut Data = match data {
6072
Ok(data) => data,
6173
Err(err) => {
62-
unsafe { alloc::dealloc(heap_buf, layout) };
74+
unsafe { allocator.deallocate(heap_buf.as_non_null_ptr(), layout) };
6375
return Err(err);
6476
}
6577
};

uefi/src/proto/media/file/dir.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::Result;
44
use core::ffi::c_void;
55

66
#[cfg(feature = "alloc")]
7-
use {crate::mem::make_boxed, alloc::boxed::Box};
7+
use {crate::mem::make_boxed_in, alloc::alloc::Global, alloc::boxed::Box, core::alloc::Allocator};
88

99
/// A `FileHandle` that is also a directory.
1010
///
@@ -61,10 +61,21 @@ impl Directory {
6161
})
6262
}
6363

64+
/// Wrapper around [`Self::read_entry_boxed_in`] that uses the [`Global`] allocator.
65+
#[cfg(feature = "alloc")]
66+
pub fn read_entry_boxed(&mut self) -> Result<Option<Box<FileInfo>>> {
67+
self.read_entry_boxed_in(Global)
68+
}
69+
6470
/// Wrapper around [`Self::read_entry`] that returns an owned copy of the data. It has the same
6571
/// implications and requirements. On failure, the payload of `Err` is `()´.
72+
///
73+
/// It allows to use a custom allocator via the `allocator_api` feature.
6674
#[cfg(feature = "alloc")]
67-
pub fn read_entry_boxed(&mut self) -> Result<Option<Box<FileInfo>>> {
75+
pub fn read_entry_boxed_in<A: Allocator>(
76+
&mut self,
77+
allocator: A,
78+
) -> Result<Option<Box<FileInfo>>> {
6879
let read_entry_res = self.read_entry(&mut []);
6980

7081
// If no more entries are available, return early.
@@ -79,7 +90,7 @@ impl Directory {
7990
maybe_info.expect("Should have more entries")
8091
})
8192
};
82-
let file_info = make_boxed::<FileInfo, _>(fetch_data_fn)?;
93+
let file_info = make_boxed_in::<A, FileInfo, _>(allocator, fetch_data_fn)?;
8394
Ok(Some(file_info))
8495
}
8596

uefi/src/proto/media/file/mod.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use core::fmt::Debug;
1717
use core::mem;
1818
use core::ptr;
1919
#[cfg(feature = "alloc")]
20-
use {alloc::boxed::Box, uefi::mem::make_boxed};
20+
use {alloc::alloc::Global, alloc::boxed::Box, core::alloc::Allocator, uefi::mem::make_boxed_in};
2121

2222
pub use self::info::{FileInfo, FileProtocolInfo, FileSystemInfo, FileSystemVolumeLabel, FromUefi};
2323
pub use self::{dir::Directory, regular::RegularFile};
@@ -162,10 +162,19 @@ pub trait File: Sized {
162162
}
163163

164164
#[cfg(feature = "alloc")]
165-
/// Read the dynamically allocated info for a file.
165+
/// Wrapper around [`Self::get_boxed_info_in`] that uses the [`Global`] allocator.
166166
fn get_boxed_info<Info: FileProtocolInfo + ?Sized + Debug>(&mut self) -> Result<Box<Info>> {
167+
self.get_boxed_info_in(Global)
168+
}
169+
170+
#[cfg(feature = "alloc")]
171+
/// Read the dynamically allocated info for a file.
172+
fn get_boxed_info_in<Info: FileProtocolInfo + ?Sized + Debug, A: Allocator>(
173+
&mut self,
174+
allocator: A,
175+
) -> Result<Box<Info>> {
167176
let fetch_data_fn = |buf| self.get_info::<Info>(buf);
168-
let file_info = make_boxed::<Info, _>(fetch_data_fn)?;
177+
let file_info = make_boxed_in::<A, Info, _>(allocator, fetch_data_fn)?;
169178
Ok(file_info)
170179
}
171180

0 commit comments

Comments
 (0)