Auto merge of #137424 - Ayush1325:uefi-path-node, r=nicholasbishop,cu… · rust-lang/rust@cb50d4d (original) (raw)
`@@ -216,6 +216,60 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R
`
216
216
`Err(io::const_error!(io::ErrorKind::NotFound, "no device path to text protocol found"))
`
217
217
`}
`
218
218
``
``
219
`+
fn device_node_to_text(path: NonNull<device_path::Protocol>) -> io::Result {
`
``
220
`+
fn node_to_text(
`
``
221
`+
protocol: NonNull<device_path_to_text::Protocol>,
`
``
222
`+
path: NonNull<device_path::Protocol>,
`
``
223
`+
) -> io::Result {
`
``
224
`+
let path_ptr: *mut r_efi::efi::Char16 = unsafe {
`
``
225
`+
((*protocol.as_ptr()).convert_device_node_to_text)(
`
``
226
`+
path.as_ptr(),
`
``
227
`+
// DisplayOnly
`
``
228
`+
r_efi::efi::Boolean::FALSE,
`
``
229
`+
// AllowShortcuts
`
``
230
`+
r_efi::efi::Boolean::FALSE,
`
``
231
`+
)
`
``
232
`+
};
`
``
233
+
``
234
`+
let path = os_string_from_raw(path_ptr)
`
``
235
`+
.ok_or(io::const_error!(io::ErrorKind::InvalidData, "Invalid path"))?;
`
``
236
+
``
237
`+
if let Some(boot_services) = crate::os::uefi::env::boot_services() {
`
``
238
`+
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast();
`
``
239
`+
unsafe {
`
``
240
`+
((*boot_services.as_ptr()).free_pool)(path_ptr.cast());
`
``
241
`+
}
`
``
242
`+
}
`
``
243
+
``
244
`+
Ok(path)
`
``
245
`+
}
`
``
246
+
``
247
`+
static LAST_VALID_HANDLE: AtomicPtrcrate::ffi::c_void =
`
``
248
`+
AtomicPtr::new(crate::ptr::null_mut());
`
``
249
+
``
250
`+
if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
`
``
251
`+
if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(
`
``
252
`+
handle,
`
``
253
`+
device_path_to_text::PROTOCOL_GUID,
`
``
254
`+
) {
`
``
255
`+
return node_to_text(protocol, path);
`
``
256
`+
}
`
``
257
`+
}
`
``
258
+
``
259
`+
let device_path_to_text_handles = locate_handles(device_path_to_text::PROTOCOL_GUID)?;
`
``
260
`+
for handle in device_path_to_text_handles {
`
``
261
`+
if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(
`
``
262
`+
handle,
`
``
263
`+
device_path_to_text::PROTOCOL_GUID,
`
``
264
`+
) {
`
``
265
`+
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
`
``
266
`+
return node_to_text(protocol, path);
`
``
267
`+
}
`
``
268
`+
}
`
``
269
+
``
270
`+
Err(io::const_error!(io::ErrorKind::NotFound, "No device path to text protocol found"))
`
``
271
`+
}
`
``
272
+
219
273
`/// Gets RuntimeServices.
`
220
274
`pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>> {
`
221
275
`let system_table: NonNull<r_efi::efi::SystemTable> =
`
`@@ -319,6 +373,11 @@ impl<'a> BorrowedDevicePath<'a> {
`
319
373
`pub(crate) fn to_text(&self) -> io::Result {
`
320
374
`device_path_to_text(self.protocol)
`
321
375
`}
`
``
376
+
``
377
`+
#[expect(dead_code)]
`
``
378
`+
pub(crate) const fn iter(&'a self) -> DevicePathIterator<'a> {
`
``
379
`+
DevicePathIterator::new(DevicePathNode::new(self.protocol))
`
``
380
`+
}
`
322
381
`}
`
323
382
``
324
383
`impl<'a> crate::fmt::Debug for BorrowedDevicePath<'a> {
`
`@@ -330,6 +389,126 @@ impl<'a> crate::fmt::Debug for BorrowedDevicePath<'a> {
`
330
389
`}
`
331
390
`}
`
332
391
``
``
392
`+
pub(crate) struct DevicePathIterator<'a>(Option<DevicePathNode<'a>>);
`
``
393
+
``
394
`+
impl<'a> DevicePathIterator<'a> {
`
``
395
`+
const fn new(node: DevicePathNode<'a>) -> Self {
`
``
396
`+
if node.is_end() { Self(None) } else { Self(Some(node)) }
`
``
397
`+
}
`
``
398
`+
}
`
``
399
+
``
400
`+
impl<'a> Iterator for DevicePathIterator<'a> {
`
``
401
`+
type Item = DevicePathNode<'a>;
`
``
402
+
``
403
`+
fn next(&mut self) -> OptionSelf::Item {
`
``
404
`+
let cur_node = self.0?;
`
``
405
+
``
406
`+
let next_node = unsafe { cur_node.next_node() };
`
``
407
`+
self.0 = if next_node.is_end() { None } else { Some(next_node) };
`
``
408
+
``
409
`+
Some(cur_node)
`
``
410
`+
}
`
``
411
`+
}
`
``
412
+
``
413
`+
#[derive(Copy, Clone)]
`
``
414
`+
pub(crate) struct DevicePathNode<'a> {
`
``
415
`+
protocol: NonNull<r_efi::protocols::device_path::Protocol>,
`
``
416
`+
phantom: PhantomData<&'a r_efi::protocols::device_path::Protocol>,
`
``
417
`+
}
`
``
418
+
``
419
`+
impl<'a> DevicePathNode<'a> {
`
``
420
`+
pub(crate) const fn new(protocol: NonNull<r_efi::protocols::device_path::Protocol>) -> Self {
`
``
421
`+
Self { protocol, phantom: PhantomData }
`
``
422
`+
}
`
``
423
+
``
424
`+
pub(crate) const fn length(&self) -> u16 {
`
``
425
`+
let len = unsafe { (*self.protocol.as_ptr()).length };
`
``
426
`+
u16::from_le_bytes(len)
`
``
427
`+
}
`
``
428
+
``
429
`+
pub(crate) const fn node_type(&self) -> u8 {
`
``
430
`+
unsafe { (*self.protocol.as_ptr()).r#type }
`
``
431
`+
}
`
``
432
+
``
433
`+
pub(crate) const fn sub_type(&self) -> u8 {
`
``
434
`+
unsafe { (*self.protocol.as_ptr()).sub_type }
`
``
435
`+
}
`
``
436
+
``
437
`+
pub(crate) fn data(&self) -> &[u8] {
`
``
438
`+
let length: usize = self.length().into();
`
``
439
+
``
440
`+
// Some nodes do not have any special data
`
``
441
`+
if length > 4 {
`
``
442
`+
let raw_ptr: *const u8 = self.protocol.as_ptr().cast();
`
``
443
`+
let data = unsafe { raw_ptr.add(4) };
`
``
444
`+
unsafe { crate::slice::from_raw_parts(data, length - 4) }
`
``
445
`+
} else {
`
``
446
`+
&[]
`
``
447
`+
}
`
``
448
`+
}
`
``
449
+
``
450
`+
pub(crate) const fn is_end(&self) -> bool {
`
``
451
`+
self.node_type() == r_efi::protocols::device_path::TYPE_END
`
``
452
`+
&& self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_ENTIRE
`
``
453
`+
}
`
``
454
+
``
455
`+
#[expect(dead_code)]
`
``
456
`+
pub(crate) const fn is_end_instance(&self) -> bool {
`
``
457
`+
self.node_type() == r_efi::protocols::device_path::TYPE_END
`
``
458
`+
&& self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_INSTANCE
`
``
459
`+
}
`
``
460
+
``
461
`+
pub(crate) unsafe fn next_node(&self) -> Self {
`
``
462
`+
let node = unsafe {
`
``
463
`+
self.protocol
`
``
464
`+
.cast::()
`
``
465
`+
.add(self.length().into())
`
``
466
`+
.cast::<r_efi::protocols::device_path::Protocol>()
`
``
467
`+
};
`
``
468
`+
Self::new(node)
`
``
469
`+
}
`
``
470
+
``
471
`+
#[expect(dead_code)]
`
``
472
`+
pub(crate) fn to_path(&'a self) -> BorrowedDevicePath<'a> {
`
``
473
`+
BorrowedDevicePath::new(self.protocol)
`
``
474
`+
}
`
``
475
+
``
476
`+
pub(crate) fn to_text(&self) -> io::Result {
`
``
477
`+
device_node_to_text(self.protocol)
`
``
478
`+
}
`
``
479
`+
}
`
``
480
+
``
481
`+
impl<'a> PartialEq for DevicePathNode<'a> {
`
``
482
`+
fn eq(&self, other: &Self) -> bool {
`
``
483
`+
let self_len = self.length();
`
``
484
`+
let other_len = other.length();
`
``
485
+
``
486
`+
self_len == other_len
`
``
487
`+
&& unsafe {
`
``
488
`+
compiler_builtins::mem::memcmp(
`
``
489
`+
self.protocol.as_ptr().cast(),
`
``
490
`+
other.protocol.as_ptr().cast(),
`
``
491
`+
usize::from(self_len),
`
``
492
`+
) == 0
`
``
493
`+
}
`
``
494
`+
}
`
``
495
`+
}
`
``
496
+
``
497
`+
impl<'a> crate::fmt::Debug for DevicePathNode<'a> {
`
``
498
`+
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
`
``
499
`+
match self.to_text() {
`
``
500
`+
Ok(p) => p.fmt(f),
`
``
501
`+
Err(_) => f
`
``
502
`+
.debug_struct("DevicePathNode")
`
``
503
`+
.field("type", &self.node_type())
`
``
504
`+
.field("sub_type", &self.sub_type())
`
``
505
`+
.field("length", &self.length())
`
``
506
`+
.field("specific_device_path_data", &self.data())
`
``
507
`+
.finish(),
`
``
508
`+
}
`
``
509
`+
}
`
``
510
`+
}
`
``
511
+
333
512
`pub(crate) struct OwnedProtocol {
`
334
513
`guid: r_efi::efi::Guid,
`
335
514
`handle: NonNullcrate::ffi::c_void,
`