Skip to content

Commit 22c125c

Browse files
committed
XXX make device paths suck less
1 parent b267dca commit 22c125c

File tree

2 files changed

+112
-0
lines changed
  • uefi/src/proto/device_path
  • uefi-test-runner/src/boot

2 files changed

+112
-0
lines changed

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ fn test_load_image(bt: &BootServices) {
5454
// provide us with the file-path portion of the device path.
5555
let image_device_path: &DevicePath = &image_device_path_protocol;
5656

57+
// XXX TEMPORARy
58+
{
59+
log::debug!(
60+
"{:#?}",
61+
image_device_path
62+
.to_text_by_node(bt)
63+
// CString16 -> Rust String
64+
.unwrap()
65+
.iter()
66+
.map(|(a, b)| (a, b.to_string()))
67+
.collect::<alloc::vec::Vec<_>>()
68+
);
69+
log::debug!("{:#?}", image_device_path.to_text(bt).unwrap()
70+
// CString16 -> Rust String
71+
.iter()
72+
.map(|a| a.to_string())
73+
.collect::<alloc::vec::Vec<_>>());
74+
}
75+
5776
// Get the file-path portion of the device path which is typically behind
5877
// device path node (0x4, 0x4).
5978
// TODO we need an abstraction in the UEFI crate for this.

uefi/src/proto/device_path/mod.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,28 @@ pub mod build;
7777
pub mod text;
7878

7979
mod device_path_gen;
80+
8081
pub use device_path_gen::{
8182
acpi, bios_boot_spec, end, hardware, media, messaging, DevicePathNodeEnum,
8283
};
84+
#[cfg(feature = "alloc")]
85+
use {alloc::vec::Vec, uefi::CString16};
8386

8487
use crate::proto::{unsafe_protocol, ProtocolPointer};
8588
use core::ffi::c_void;
8689
use core::fmt::{self, Debug, Formatter};
8790
use core::mem;
8891
use core::ops::Deref;
8992
use ptr_meta::Pointee;
93+
use uefi::data_types::FromSliceWithNulError;
94+
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
95+
use uefi::CStr16;
96+
97+
use crate::prelude::BootServices;
98+
use crate::proto::device_path::text::DevicePathToText;
99+
use crate::table::boot::{OpenProtocolParams, SearchType};
100+
use crate::table::{Boot, Table};
101+
use uefi::table::boot::OpenProtocolAttributes;
90102

91103
opaque_type! {
92104
/// Opaque type that should be used to represent a pointer to a
@@ -187,6 +199,18 @@ impl DevicePathNode {
187199
pub fn as_enum(&self) -> Result<DevicePathNodeEnum, NodeConversionError> {
188200
DevicePathNodeEnum::try_from(self)
189201
}
202+
203+
/// If the device path node is of type (0x4, 0x4), it returns the underlying
204+
/// data as [`CStr16`].
205+
pub fn data_as_filename(&self) -> Option<Result<&CStr16, FromSliceWithNulError>> {
206+
if self.device_type() == DeviceType::MEDIA
207+
&& self.sub_type() == DeviceSubType::HARDWARE_VENDOR
208+
{
209+
Some(CStr16::from_u8_with_nul(self.data()))
210+
} else {
211+
None
212+
}
213+
}
190214
}
191215

192216
impl Debug for DevicePathNode {
@@ -332,6 +356,75 @@ impl DevicePath {
332356
stop_condition: StopCondition::EndEntireNode,
333357
}
334358
}
359+
360+
#[cfg(feature = "alloc")]
361+
pub fn to_text_by_node(
362+
&self,
363+
bs: &BootServices,
364+
) -> crate::Result<Vec<(&DevicePathNode, CString16)>> {
365+
use uefi::Identify;
366+
let &handle = bs
367+
.locate_handle_buffer(SearchType::ByProtocol(&DevicePathToText::GUID))
368+
.unwrap()
369+
.first()
370+
.unwrap();
371+
372+
let to_text_protocol = unsafe {
373+
bs.open_protocol::<DevicePathToText>(
374+
OpenProtocolParams {
375+
handle,
376+
agent: bs.image_handle(),
377+
controller: None,
378+
},
379+
OpenProtocolAttributes::GetProtocol,
380+
)
381+
}
382+
.unwrap();
383+
384+
Ok(self
385+
.node_iter()
386+
.map(|node| {
387+
let cstr16 = to_text_protocol
388+
.convert_device_node_to_text(
389+
bs,
390+
node,
391+
DisplayOnly(false),
392+
AllowShortcuts(false),
393+
)
394+
.unwrap();
395+
let cstr16 = &*cstr16;
396+
(node, CString16::from(cstr16))
397+
})
398+
.collect())
399+
}
400+
401+
#[cfg(feature = "alloc")]
402+
pub fn to_text(&self, bs: &BootServices) -> crate::Result<CString16> {
403+
use uefi::Identify;
404+
let &handle = bs
405+
.locate_handle_buffer(SearchType::ByProtocol(&DevicePathToText::GUID))
406+
.unwrap()
407+
.first()
408+
.unwrap();
409+
410+
let to_text_protocol = unsafe {
411+
bs.open_protocol::<DevicePathToText>(
412+
OpenProtocolParams {
413+
handle,
414+
agent: bs.image_handle(),
415+
controller: None,
416+
},
417+
OpenProtocolAttributes::GetProtocol,
418+
)
419+
}
420+
.unwrap();
421+
422+
let cstr16 = to_text_protocol
423+
.convert_device_path_to_text(bs, self, DisplayOnly(false), AllowShortcuts(false))
424+
.unwrap();
425+
let cstr16 = &*cstr16;
426+
Ok(CString16::from(cstr16))
427+
}
335428
}
336429

337430
impl Debug for DevicePath {

0 commit comments

Comments
 (0)