-
-
Notifications
You must be signed in to change notification settings - Fork 170
/
Copy pathtext.rs
153 lines (141 loc) · 5.44 KB
/
text.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Protocols for converting between UEFI strings and [`DevicePath`]/[`DevicePathNode`].
// Note on return types: the specification of the conversion functions
// is a little unusual in that they return a pointer rather than
// `EFI_STATUS`. A NULL pointer is used to indicate an error, and the
// spec says that will only happen if the input pointer is null (which
// can't happen here since we use references as input, not pointers), or
// if there is insufficient memory. So we treat any NULL output as an
// `OUT_OF_RESOURCES` error.
use crate::data_types::PoolString;
use crate::mem::PoolAllocation;
use crate::proto::device_path::{DevicePath, DevicePathNode};
use crate::proto::unsafe_protocol;
use crate::{CStr16, Result, Status};
use core::ptr::NonNull;
use uefi_raw::protocol::device_path::{DevicePathFromTextProtocol, DevicePathToTextProtocol};
use super::{PoolDevicePath, PoolDevicePathNode};
/// Parameter for [`DevicePathToText`] that alters the output format.
///
/// * `DisplayOnly(false)` produces parseable output.
/// * `DisplayOnly(true)` produces output that _may_ be shorter and not
/// parseable.
///
/// Example of how a node's text representation may be altered by this
/// parameter:
/// * `DisplayOnly(false)`: `Ata(Primary,Master,0x1)`
/// * `DisplayOnly(true)`: `Ata(0x1)`
#[derive(Clone, Copy, Debug)]
pub struct DisplayOnly(pub bool);
/// Parameter for [`DevicePathToText`] that alters the output format.
///
/// * `AllowShortcuts(false)`: node names are based only on the node's type and
/// subtype.
/// * `AllowShortcuts(true)` _may_ alter the node name based on other fields
/// within the node.
///
/// Example of how a node's text representation may be altered by this
/// parameter:
/// * `AllowShortcuts(false)`: `VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)`
/// * `AllowShortcuts(true)`: `VenPcAnsi()`
#[derive(Clone, Copy, Debug)]
pub struct AllowShortcuts(pub bool);
/// Device Path to Text [`Protocol`].
///
/// Protocol for converting a [`DevicePath`] or `DevicePathNode`] to a string.
///
/// [`Protocol`]: uefi::proto::Protocol
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol(DevicePathToTextProtocol::GUID)]
pub struct DevicePathToText(DevicePathToTextProtocol);
impl DevicePathToText {
/// Convert a [`DevicePathNode`] to a [`PoolString`].
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.
///
/// [`OUT_OF_RESOURCES`]: Status::OUT_OF_RESOURCES
pub fn convert_device_node_to_text(
&self,
device_node: &DevicePathNode,
display_only: DisplayOnly,
allow_shortcuts: AllowShortcuts,
) -> Result<PoolString> {
let text = unsafe {
(self.0.convert_device_node_to_text)(
device_node.as_ffi_ptr().cast(),
display_only.0.into(),
allow_shortcuts.0.into(),
)
};
unsafe { PoolString::new(text.cast()) }
}
/// Convert a [`DevicePath`] to a [`PoolString`].
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.
///
/// [`OUT_OF_RESOURCES`]: Status::OUT_OF_RESOURCES
pub fn convert_device_path_to_text(
&self,
device_path: &DevicePath,
display_only: DisplayOnly,
allow_shortcuts: AllowShortcuts,
) -> Result<PoolString> {
let text = unsafe {
(self.0.convert_device_path_to_text)(
device_path.as_ffi_ptr().cast(),
display_only.0.into(),
allow_shortcuts.0.into(),
)
};
unsafe { PoolString::new(text.cast()) }
}
}
/// Device Path from Text [`Protocol`].
///
/// Protocol for converting a string to a [`DevicePath`] or `DevicePathNode`].
///
/// [`Protocol`]: uefi::proto::Protocol
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol("05c99a21-c70f-4ad2-8a5f-35df3343f51e")]
pub struct DevicePathFromText(DevicePathFromTextProtocol);
impl DevicePathFromText {
/// Convert a [`CStr16`] to a [`DevicePathNode`].
///
/// If a non-device-node character is encountered, the rest of the string is ignored.
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.
///
/// [`OUT_OF_RESOURCES`]: Status::OUT_OF_RESOURCES
pub fn convert_text_to_device_node(
&self,
text_device_node: &CStr16,
) -> Result<PoolDevicePathNode> {
unsafe {
let ptr = (self.0.convert_text_to_device_node)(text_device_node.as_ptr().cast());
NonNull::new(ptr.cast_mut())
.map(|p| PoolDevicePathNode(PoolAllocation::new(p.cast())))
.ok_or(Status::OUT_OF_RESOURCES.into())
}
}
/// Convert a [`CStr16`] to a [`DevicePath`].
///
/// If a non-device-node character is encountered, the rest of the string is ignored.
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.
///
/// [`OUT_OF_RESOURCES`]: Status::OUT_OF_RESOURCES
pub fn convert_text_to_device_path(&self, text_device_path: &CStr16) -> Result<PoolDevicePath> {
unsafe {
let ptr = (self.0.convert_text_to_device_path)(text_device_path.as_ptr().cast());
NonNull::new(ptr.cast_mut())
.map(|p| PoolDevicePath(PoolAllocation::new(p.cast())))
.ok_or(Status::OUT_OF_RESOURCES.into())
}
}
}