Skip to content

Commit b1416ad

Browse files
device path: add iter method and test (#264)
1 parent 45c38a1 commit b1416ad

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/proto/device_path.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,51 @@ impl DevicePath {
5555
pub fn length(&self) -> u16 {
5656
self.header.length
5757
}
58+
59+
/// True if this node ends the entire path.
60+
pub fn is_end_entire(&self) -> bool {
61+
self.device_type() == DeviceType::END && self.sub_type() == DeviceSubType::END_ENTIRE
62+
}
63+
64+
/// Get an iterator over the [`DevicePath`] nodes starting at
65+
/// `self`. Iteration ends when a path is reached where
66+
/// [`is_end_entire`][DevicePath::is_end_entire] is true. That ending path
67+
/// is not returned by the iterator.
68+
pub fn iter(&self) -> DevicePathIterator {
69+
DevicePathIterator { path: self }
70+
}
71+
}
72+
73+
/// Iterator over [`DevicePath`] nodes.
74+
///
75+
/// Iteration ends when a path is reached where [`DevicePath::is_end_entire`]
76+
/// is true. That ending path is not returned by the iterator.
77+
///
78+
/// This struct is returned by [`DevicePath::iter`].
79+
pub struct DevicePathIterator<'a> {
80+
path: &'a DevicePath,
81+
}
82+
83+
impl<'a> Iterator for DevicePathIterator<'a> {
84+
type Item = &'a DevicePath;
85+
86+
fn next(&mut self) -> Option<Self::Item> {
87+
let cur = self.path;
88+
89+
if cur.is_end_entire() {
90+
return None;
91+
}
92+
93+
// Advance self.path to the next entry.
94+
let len = cur.header.length;
95+
let byte_ptr = cur as *const DevicePath as *const u8;
96+
unsafe {
97+
let next_path_ptr = byte_ptr.add(len as usize) as *const DevicePath;
98+
self.path = &*next_path_ptr;
99+
}
100+
101+
Some(cur)
102+
}
58103
}
59104

60105
newtype_enum! {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use uefi::prelude::*;
2+
use uefi::proto::device_path::DevicePath;
3+
use uefi::proto::loaded_image::LoadedImage;
4+
use uefi::table::boot::BootServices;
5+
6+
pub fn test(image: Handle, bt: &BootServices) {
7+
info!("Running device path protocol test");
8+
9+
let loaded_image = bt
10+
.handle_protocol::<LoadedImage>(image)
11+
.expect_success("Failed to open LoadedImage protocol");
12+
let loaded_image = unsafe { &*loaded_image.get() };
13+
14+
let device_path = bt
15+
.handle_protocol::<DevicePath>(loaded_image.device())
16+
.expect_success("Failed to open DevicePath protocol");
17+
let device_path = unsafe { &*device_path.get() };
18+
19+
for path in device_path.iter() {
20+
info!(
21+
"path: type={:?}, subtype={:?}, length={}",
22+
path.device_type(),
23+
path.sub_type(),
24+
path.length(),
25+
);
26+
}
27+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub fn test(image: Handle, st: &mut SystemTable<Boot>) {
1313
test_protocols_per_handle(image, bt);
1414

1515
debug::test(bt);
16+
device_path::test(image, bt);
1617
media::test(bt);
1718
pi::test(bt);
1819

@@ -54,6 +55,7 @@ fn test_protocols_per_handle(image: Handle, bt: &BootServices) {
5455

5556
mod console;
5657
mod debug;
58+
mod device_path;
5759
mod media;
5860
mod pi;
5961
#[cfg(any(

0 commit comments

Comments
 (0)