Skip to content

Commit 446d299

Browse files
committed
xxx
1 parent 379d53a commit 446d299

File tree

4 files changed

+107
-76
lines changed

4 files changed

+107
-76
lines changed

uefi-test-runner/src/proto/mod.rs

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,7 @@ use uefi::{Identify, proto};
77
pub fn test() {
88
info!("Testing various protocols");
99

10-
console::test();
11-
12-
find_protocol();
13-
test_protocols_per_handle();
14-
test_test_protocol();
15-
16-
debug::test();
17-
device_path::test();
18-
driver::test();
19-
load::test();
20-
loaded_image::test();
21-
media::test();
22-
network::test();
23-
pci::test();
24-
pi::test();
25-
rng::test();
26-
shell_params::test();
27-
string::test();
28-
usb::test();
29-
misc::test();
30-
31-
// disable the ATA test on aarch64 for now. The aarch64 UEFI Firmware does not yet seem
32-
// to support SATA controllers (and providing an AtaPassThru protocol instance for them).
33-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
34-
ata::test();
35-
scsi::test();
36-
nvme::test();
37-
38-
#[cfg(any(
39-
target_arch = "x86",
40-
target_arch = "x86_64",
41-
target_arch = "arm",
42-
target_arch = "aarch64"
43-
))]
44-
shim::test();
4510
shell::test();
46-
tcg::test();
4711
}
4812

4913
fn find_protocol() {

uefi-test-runner/src/proto/shell.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22

3-
use uefi::boot::ScopedProtocol;
3+
use uefi::boot::{OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol};
4+
use uefi::proto::device_path::DevicePath;
5+
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
46
use uefi::proto::shell::Shell;
57
use uefi::{Error, Status, boot, cstr16};
8+
use uefi_raw::protocol::shell::ShellProtocol;
69

710
/// Test `current_dir()` and `set_current_dir()`
811
pub fn test_current_dir(shell: &ScopedProtocol<Shell>) {

uefi/src/proto/device_path/build.rs

Lines changed: 101 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
//! Utilities for creating new [`DevicePaths`].
44
//!
5-
//! This module contains [`DevicePathBuilder`], as well as submodules
6-
//! containing types for building each type of device path node.
5+
//! This module provides builders to construct device paths, as well as
6+
//! submodules containing types for building each type of device path node.
7+
//!
8+
//! - [`DevicePathBuilder`]
9+
//! - [`OwnedDevicePathBuilder`]
710
//!
811
//! [`DevicePaths`]: DevicePath
912
@@ -15,7 +18,10 @@ use core::fmt::{self, Display, Formatter};
1518
use core::mem::MaybeUninit;
1619

1720
#[cfg(feature = "alloc")]
18-
use alloc::vec::Vec;
21+
use {
22+
alloc::{boxed::Box, vec::Vec},
23+
core::mem,
24+
};
1925

2026
/// A builder for [`DevicePaths`].
2127
///
@@ -74,14 +80,14 @@ use alloc::vec::Vec;
7480
/// ```
7581
#[derive(Debug)]
7682
pub struct DevicePathBuilder<'a> {
77-
storage: BuilderStorage<'a>,
83+
storage: BuilderStorageRef<'a>,
7884
}
7985

8086
impl<'a> DevicePathBuilder<'a> {
8187
/// Create a builder backed by a statically-sized buffer.
8288
pub const fn with_buf(buf: &'a mut [MaybeUninit<u8>]) -> Self {
8389
Self {
84-
storage: BuilderStorage::Buf { buf, offset: 0 },
90+
storage: BuilderStorageRef::Buf { buf, offset: 0 },
8591
}
8692
}
8793

@@ -92,30 +98,30 @@ impl<'a> DevicePathBuilder<'a> {
9298
pub fn with_vec(v: &'a mut Vec<u8>) -> Self {
9399
v.clear();
94100
Self {
95-
storage: BuilderStorage::Vec(v),
101+
storage: BuilderStorageRef::Vec(v),
96102
}
97103
}
98104

99105
/// Add a node to the device path.
100106
///
101107
/// An error will be returned if an [`END_ENTIRE`] node is passed to
102-
/// this function, as that node will be added when `finalize` is
108+
/// this function, as that node will be added when [`Self::finalize`] is
103109
/// called.
104110
///
105111
/// [`END_ENTIRE`]: uefi::proto::device_path::DeviceSubType::END_ENTIRE
106112
pub fn push(mut self, node: &dyn BuildNode) -> Result<Self, BuildError> {
107113
let node_size = usize::from(node.size_in_bytes()?);
108114

109115
match &mut self.storage {
110-
BuilderStorage::Buf { buf, offset } => {
116+
BuilderStorageRef::Buf { buf, offset } => {
111117
node.write_data(
112118
buf.get_mut(*offset..*offset + node_size)
113119
.ok_or(BuildError::BufferTooSmall)?,
114120
);
115121
*offset += node_size;
116122
}
117123
#[cfg(feature = "alloc")]
118-
BuilderStorage::Vec(vec) => {
124+
BuilderStorageRef::Vec(vec) => {
119125
let old_size = vec.len();
120126
vec.reserve(node_size);
121127
let buf = &mut vec.spare_capacity_mut()[..node_size];
@@ -138,20 +144,21 @@ impl<'a> DevicePathBuilder<'a> {
138144
let this = self.push(&end::Entire)?;
139145

140146
let data: &[u8] = match &this.storage {
141-
BuilderStorage::Buf { buf, offset } => unsafe {
147+
BuilderStorageRef::Buf { buf, offset } => unsafe {
142148
maybe_uninit_slice_assume_init_ref(&buf[..*offset])
143149
},
144150
#[cfg(feature = "alloc")]
145-
BuilderStorage::Vec(vec) => vec,
151+
BuilderStorageRef::Vec(vec) => vec,
146152
};
147153

148154
let ptr: *const () = data.as_ptr().cast();
149155
Ok(unsafe { &*ptr_meta::from_raw_parts(ptr, data.len()) })
150156
}
151157
}
152158

159+
/// Reference to the backup storage for [`DevicePathBuilder`]
153160
#[derive(Debug)]
154-
enum BuilderStorage<'a> {
161+
enum BuilderStorageRef<'a> {
155162
Buf {
156163
buf: &'a mut [MaybeUninit<u8>],
157164
offset: usize,
@@ -193,6 +200,58 @@ impl Display for BuildError {
193200

194201
impl core::error::Error for BuildError {}
195202

203+
/// Variant of [`DevicePathBuilder`] to construct a boxed [`DevicePath`].
204+
///
205+
/// Using this builder is equivalent to calling [`DevicePath::to_boxed`] on a
206+
/// device path constructed by the normal builder.
207+
#[derive(Debug)]
208+
#[cfg(feature = "alloc")]
209+
pub struct OwnedDevicePathBuilder {
210+
vec: Vec<u8>,
211+
}
212+
213+
#[cfg(feature = "alloc")]
214+
impl OwnedDevicePathBuilder {
215+
/// Creates a new builder.
216+
pub fn new() -> Self {
217+
let vec = Vec::new();
218+
Self { vec }
219+
}
220+
221+
/// Add a node to the device path.
222+
///
223+
/// An error will be returned if an [`END_ENTIRE`] node is passed to
224+
/// this function, as that node will be added when [`Self::finalize`] is
225+
/// called.
226+
///
227+
/// [`END_ENTIRE`]: uefi::proto::device_path::DeviceSubType::END_ENTIRE
228+
pub fn push(mut self, node: &dyn BuildNode) -> Result<Self, BuildError> {
229+
let node_size = usize::from(node.size_in_bytes()?);
230+
231+
let old_size = self.vec.len();
232+
self.vec.reserve(node_size);
233+
let buf = &mut self.vec.spare_capacity_mut()[..node_size];
234+
node.write_data(buf);
235+
unsafe {
236+
self.vec.set_len(old_size + node_size);
237+
}
238+
Ok(self)
239+
}
240+
241+
/// Add an [`END_ENTIRE`] node and return the resulting [`DevicePath`].
242+
///
243+
/// This method consumes the builder.
244+
///
245+
/// [`END_ENTIRE`]: uefi::proto::device_path::DeviceSubType::END_ENTIRE
246+
pub fn finalize(self) -> Result<Box<DevicePath>, BuildError> {
247+
let this = self.push(&end::Entire)?;
248+
let boxed = this.vec.into_boxed_slice();
249+
// SAFETY: This is safe as a DevicePath has the same layout.
250+
let dvp = unsafe { mem::transmute(boxed) };
251+
Ok(dvp)
252+
}
253+
}
254+
196255
/// Trait for types that can be used to build a node via
197256
/// [`DevicePathBuilder::push`].
198257
///
@@ -246,11 +305,6 @@ mod tests {
246305
use crate::proto::device_path::messaging::{
247306
Ipv4AddressOrigin, IscsiLoginOptions, IscsiProtocol, RestServiceAccessMode, RestServiceType,
248307
};
249-
use core::slice;
250-
251-
const fn path_to_bytes(path: &DevicePath) -> &[u8] {
252-
unsafe { slice::from_raw_parts(path.as_ffi_ptr().cast::<u8>(), size_of_val(path)) }
253-
}
254308

255309
/// Test building an ACPI ADR node.
256310
#[test]
@@ -267,10 +321,8 @@ mod tests {
267321
let node: &crate::proto::device_path::acpi::Adr =
268322
path.node_iter().next().unwrap().try_into().unwrap();
269323
assert_eq!(node.adr().iter().collect::<Vec<_>>(), [1, 2]);
270-
271-
let bytes = path_to_bytes(path);
272324
#[rustfmt::skip]
273-
assert_eq!(bytes, [
325+
assert_eq!(path.as_bytes(), [
274326
// ACPI ADR node
275327
0x02, 0x03, 0x0c, 0x00,
276328
// Values
@@ -308,9 +360,8 @@ mod tests {
308360
assert_eq!(node.uid_str(), b"bc\0");
309361
assert_eq!(node.cid_str(), b"def\0");
310362

311-
let bytes = path_to_bytes(path);
312363
#[rustfmt::skip]
313-
assert_eq!(bytes, [
364+
assert_eq!(path.as_bytes(), [
314365
// ACPI Expanded node
315366
0x02, 0x02, 0x19, 0x00,
316367
// HID
@@ -365,9 +416,8 @@ mod tests {
365416
assert_eq!(node.vendor_guid_and_data().unwrap().0, vendor_guid);
366417
assert_eq!(node.vendor_guid_and_data().unwrap().1, &[1, 2, 3, 4, 5]);
367418

368-
let bytes = path_to_bytes(path);
369419
#[rustfmt::skip]
370-
assert_eq!(bytes, [
420+
assert_eq!(path.as_bytes(), [
371421
// Messaging REST Service node.
372422
0x03, 0x21, 0x06, 0x00,
373423
// Type and access mode
@@ -428,27 +478,37 @@ mod tests {
428478
/// from the UEFI Specification.
429479
#[test]
430480
fn test_fibre_channel_ex_device_path_example() -> Result<(), BuildError> {
431-
// Arbitrarily choose this test to use a statically-sized
432-
// buffer, just to make sure that code path is tested.
433-
let mut buf = [MaybeUninit::uninit(); 256];
434-
let path = DevicePathBuilder::with_buf(&mut buf)
435-
.push(&acpi::Acpi {
481+
let nodes: &[&dyn BuildNode] = &[
482+
&acpi::Acpi {
436483
hid: 0x41d0_0a03,
437484
uid: 0x0000_0000,
438-
})?
439-
.push(&hardware::Pci {
485+
},
486+
&hardware::Pci {
440487
function: 0x00,
441488
device: 0x1f,
442-
})?
443-
.push(&messaging::FibreChannelEx {
489+
},
490+
&messaging::FibreChannelEx {
444491
world_wide_name: [0, 1, 2, 3, 4, 5, 6, 7],
445492
logical_unit_number: [0, 1, 2, 3, 4, 5, 6, 7],
446-
})?
493+
},
494+
];
495+
496+
// Arbitrarily choose this test to use a statically-sized
497+
// buffer, just to make sure that code path is tested.
498+
let mut buf = [MaybeUninit::uninit(); 256];
499+
let path1 = DevicePathBuilder::with_buf(&mut buf)
500+
.push(nodes[0])?
501+
.push(nodes[1])?
502+
.push(nodes[2])?
503+
.finalize()?;
504+
let path2 = OwnedDevicePathBuilder::new()
505+
.push(nodes[0])?
506+
.push(nodes[1])?
507+
.push(nodes[2])?
447508
.finalize()?;
448509

449-
let bytes = path_to_bytes(path);
450510
#[rustfmt::skip]
451-
assert_eq!(bytes, [
511+
const EXPECTED: [u8; 46] = [
452512
// ACPI node
453513
0x02, 0x01, 0x0c, 0x00,
454514
// HID
@@ -477,7 +537,10 @@ mod tests {
477537

478538
// End-entire node
479539
0x7f, 0xff, 0x04, 0x00,
480-
]);
540+
];
541+
542+
assert_eq!(path1.as_bytes(), EXPECTED);
543+
assert_eq!(path2.as_bytes(), EXPECTED);
481544

482545
Ok(())
483546
}
@@ -532,9 +595,8 @@ mod tests {
532595
})?
533596
.finalize()?;
534597

535-
let bytes = path_to_bytes(path);
536598
#[rustfmt::skip]
537-
assert_eq!(bytes, [
599+
assert_eq!(path.as_bytes(), [
538600
// ACPI node
539601
0x02, 0x01, 0x0c, 0x00,
540602
// HID

uefi/src/proto/device_path/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ impl DevicePathInstance {
397397
pub fn to_boxed(&self) -> Box<Self> {
398398
let data = self.data.to_owned();
399399
let data = data.into_boxed_slice();
400+
// SAFETY: This is safe as a DevicePath has the same layout.
400401
unsafe { mem::transmute(data) }
401402
}
402403
}
@@ -587,6 +588,7 @@ impl DevicePath {
587588
pub fn to_boxed(&self) -> Box<Self> {
588589
let data = self.data.to_owned();
589590
let data = data.into_boxed_slice();
591+
// SAFETY: This is safe as a DevicePath has the same layout.
590592
unsafe { mem::transmute(data) }
591593
}
592594

0 commit comments

Comments
 (0)