Skip to content

Commit ad3bd8f

Browse files
authored
Merge pull request #10 from csssuf/device-path
Add DevicePath functions/utilities
2 parents 39e6213 + b5e6ca6 commit ad3bd8f

File tree

4 files changed

+271
-23
lines changed

4 files changed

+271
-23
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ pub use event::*;
3030

3131
pub use task::*;
3232

33+
pub use void::CVoid;
34+

src/protocol/device_path.rs

Lines changed: 221 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
use core::mem;
1616

17+
use base::Status;
1718
use console::SimpleTextOutput;
1819
use guid::Guid;
1920
use protocol::Protocol;
2021
use void::CVoid;
22+
use util::{utf16_ptr_to_str, str_to_utf16_ptr};
2123

2224
#[repr(u8)]
2325
pub enum DevicePathTypes {
@@ -29,24 +31,141 @@ pub enum DevicePathTypes {
2931
End = 0x7F
3032
}
3133

34+
impl Into<u8> for DevicePathTypes {
35+
fn into(self) -> u8 {
36+
self as u8
37+
}
38+
}
39+
40+
#[repr(u8)]
41+
pub enum HardwareSubTypes {
42+
PCI = 0x01,
43+
PCCARD = 0x02,
44+
MemoryMapped = 0x03,
45+
Vendor = 0x04,
46+
Controller = 0x05,
47+
BMC = 0x06
48+
}
49+
50+
impl Into<u8> for HardwareSubTypes {
51+
fn into(self) -> u8 {
52+
self as u8
53+
}
54+
}
55+
56+
#[repr(u8)]
57+
pub enum ACPISubTypes {
58+
ACPIDevicePath = 0x01,
59+
ExpandedACPIDevicePath = 0x02,
60+
_ADR = 0x03
61+
}
62+
63+
impl Into<u8> for ACPISubTypes {
64+
fn into(self) -> u8 {
65+
self as u8
66+
}
67+
}
68+
69+
#[allow(non_camel_case_types)]
70+
#[repr(u8)]
71+
pub enum MessagingSubTypes {
72+
ATAPI = 0x01,
73+
SCSI = 0x02,
74+
FibreChannel = 0x03,
75+
// The EFI specification calls this type "1394", but that won't work as an enum variant for
76+
// Rust.
77+
FireWire = 0x4,
78+
USB = 0x5,
79+
I2O = 0x6,
80+
Infiniband = 0x9,
81+
Vendor = 0xA,
82+
MACAddress = 0xB,
83+
IPv4 = 0xC,
84+
IPv6 = 0xD,
85+
UART = 0xE,
86+
USBClass = 0xF,
87+
USBWWID = 0x10,
88+
DeviceLogicalUnit = 0x11,
89+
SATA = 0x12,
90+
iSCSI = 0x13,
91+
Vlan = 0x14,
92+
FibreChannelEx = 0x15,
93+
SASEx = 0x16,
94+
NVMExpressNamespace = 0x17,
95+
URI = 0x18,
96+
UFS = 0x19,
97+
SD = 0x1A,
98+
Bluetooth = 0x1B,
99+
WiFi = 0x1C,
100+
eMMC = 0x1D
101+
}
102+
103+
impl Into<u8> for MessagingSubTypes {
104+
fn into(self) -> u8 {
105+
self as u8
106+
}
107+
}
108+
109+
#[repr(u8)]
110+
pub enum MediaSubTypes {
111+
HardDrive = 0x1,
112+
CDROM = 0x2,
113+
Vendor = 0x3,
114+
FilePath = 0x4,
115+
MediaProtocol = 0x5,
116+
PIWGFirmwareFile = 0x6,
117+
PIWGFirmwareVolume = 0x7,
118+
RelativeOffsetRange = 0x8,
119+
RAMDisk = 0x9
120+
}
121+
122+
impl Into<u8> for MediaSubTypes {
123+
fn into(self) -> u8 {
124+
self as u8
125+
}
126+
}
127+
128+
#[repr(u8)]
129+
pub enum BIOSSubTypes {
130+
BIOSBootSpecification = 0x1
131+
}
132+
133+
impl Into<u8> for BIOSSubTypes {
134+
fn into(self) -> u8 {
135+
self as u8
136+
}
137+
}
138+
32139
#[repr(u8)]
33140
pub enum EndPathSubTypes {
34141
EndInstance = 0x01,
35142
EndEntirePath = 0xFF
36143
}
37144

145+
impl Into<u8> for EndPathSubTypes {
146+
fn into(self) -> u8 {
147+
self as u8
148+
}
149+
}
150+
38151
/// GUID for UEFI protocol for device paths
39152
pub static EFI_DEVICE_PATH_PROTOCOL_GUID: Guid = Guid(0x09576E91, 0x6D3F, 0x11D2, [0x8E,0x39,0x00,0xA0,0xC9,0x69,0x72,0x3B]);
40153

41154
/// GUID for UEFI protocol for converting a DevicePath to text
42155
pub static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID: Guid = Guid(0x8B843E20, 0x8132, 0x4852, [0x90,0xCC,0x55,0x1A,0x4E,0x4A,0x7F,0x1C]);
43156

157+
/// GUID for UEFI protocol for converting text to a DevicePath
158+
pub static EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID: Guid = Guid(0x5C99A21, 0xC70F, 0x4AD2, [0x8A,0x5F,0x35,0xDF,0x33,0x43,0xF5,0x1E]);
159+
160+
/// GUID for UEFI protocol for device path utilities
161+
pub static EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID: Guid = Guid(0x379BE4E, 0xD706, 0x437D, [0xB0,0x37,0xED,0xB8,0x2F,0xB7,0x72,0xA4]);
162+
44163
#[derive(Debug)]
45164
#[repr(C)]
46165
pub struct DevicePathProtocol {
47-
type_: u8,
48-
sub_type: u8,
49-
length: [u8; 2],
166+
pub type_: u8,
167+
pub sub_type: u8,
168+
pub length: [u8; 2],
50169
}
51170

52171
impl Protocol for DevicePathProtocol {
@@ -77,40 +196,119 @@ impl Protocol for DevicePathToTextProtocol {
77196
}
78197

79198
impl DevicePathToTextProtocol {
80-
pub fn device_path_node_to_text(&self, device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) -> *const u16 {
81-
unsafe {
82-
(self.device_path_node_to_text)(device_node, display_only as u8, allow_shortcuts as u8)
83-
}
199+
pub fn device_path_node_to_text(&self, device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) -> Result<&str, Status> {
200+
let chars: *const u16 = unsafe { (self.device_path_node_to_text)(device_node, display_only as u8, allow_shortcuts as u8) };
201+
let out = utf16_ptr_to_str(chars);
202+
::get_system_table().boot_services().free_pool(chars);
203+
out
84204
}
85205

86-
pub fn device_path_to_text(&self, device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) -> *const u16 {
87-
unsafe {
88-
(self.device_path_to_text)(device_node, display_only as u8, allow_shortcuts as u8)
89-
}
206+
pub fn device_path_to_text(&self, device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) -> Result<&str, Status> {
207+
let chars: *const u16 = unsafe { (self.device_path_to_text)(device_node, display_only as u8, allow_shortcuts as u8) };
208+
let out = utf16_ptr_to_str(chars);
209+
::get_system_table().boot_services().free_pool(chars);
210+
out
90211
}
91212

92-
pub fn print_device_path_node(device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) {
213+
pub fn print_device_path_node(device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) -> Result<(), Status> {
93214
let system_table = ::get_system_table();
94215
let boot_services = system_table.boot_services();
95216

96-
let this: &'static DevicePathToTextProtocol = boot_services.locate_protocol(0 as *const CVoid).unwrap();
97-
98-
let ptr = this.device_path_node_to_text(device_node, display_only, allow_shortcuts);
99-
100-
system_table.console().write_raw(ptr);
101-
system_table.boot_services().free_pool(ptr);
217+
boot_services
218+
.locate_protocol::<DevicePathToTextProtocol>(0 as *const CVoid)
219+
.and_then(|this| {
220+
this.device_path_node_to_text(device_node, display_only, allow_shortcuts)
221+
.map(|result| {
222+
system_table.console().write(result);
223+
()
224+
})
225+
})
102226
}
103227

104-
pub fn print_device_path(device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) {
228+
pub fn print_device_path(device_node: *const DevicePathProtocol, display_only: bool, allow_shortcuts: bool) -> Result<(), Status> {
105229
let system_table = ::get_system_table();
106230
let boot_services = system_table.boot_services();
107231

108-
let this: &'static DevicePathToTextProtocol = boot_services.locate_protocol(0 as *const CVoid).unwrap();
232+
boot_services
233+
.locate_protocol::<DevicePathToTextProtocol>(0 as *const CVoid)
234+
.and_then(|this| {
235+
this.device_path_to_text(device_node, display_only, allow_shortcuts)
236+
.map(|result| {
237+
system_table.console().write(result);
238+
()
239+
})
240+
})
241+
}
242+
}
243+
244+
#[repr(C)]
245+
pub struct DevicePathFromTextProtocol {
246+
text_to_device_path_node: unsafe extern "win64" fn(text: *const u16) -> *const DevicePathProtocol,
247+
text_to_device_path: unsafe extern "win64" fn(text: *const u16) -> *const DevicePathProtocol,
248+
}
249+
250+
impl Protocol for DevicePathFromTextProtocol {
251+
fn guid() -> &'static Guid {
252+
&EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID
253+
}
254+
}
255+
256+
impl DevicePathFromTextProtocol {
257+
pub fn text_to_device_path_node(&self, path: &str) -> Result<&DevicePathProtocol, Status> {
258+
str_to_utf16_ptr(path)
259+
.map(|utf16_str| {
260+
let out = unsafe { &*((self.text_to_device_path_node)(utf16_str)) };
261+
::get_system_table().boot_services().free_pool(utf16_str);
262+
out
263+
})
264+
}
109265

110-
let ptr = this.device_path_to_text(device_node, display_only, allow_shortcuts);
266+
pub fn text_to_device_path(&self, path: &str) -> Result<&DevicePathProtocol, Status> {
267+
str_to_utf16_ptr(path)
268+
.map(|utf16_str| {
269+
let out = unsafe { &*((self.text_to_device_path)(utf16_str)) };
270+
::get_system_table().boot_services().free_pool(utf16_str);
271+
out
272+
})
273+
}
274+
}
111275

112-
system_table.console().write_raw(ptr);
113-
system_table.boot_services().free_pool(ptr);
276+
#[repr(C)]
277+
pub struct DevicePathUtilitiesProtocol {
278+
get_device_path_size: *const CVoid,
279+
duplicate_device_path: *const CVoid,
280+
append_device_path: unsafe extern "win64" fn(src1: *const DevicePathProtocol, src2: *const DevicePathProtocol) -> *const DevicePathProtocol,
281+
append_device_node: *const CVoid,
282+
append_device_path_instance: *const CVoid,
283+
get_next_device_path_instance: *const CVoid,
284+
is_device_path_multi_instance: *const CVoid,
285+
create_device_node: unsafe extern "win64" fn(node_type: u8, node_subtype: u8, node_length: u16) -> *const DevicePathProtocol
286+
}
287+
288+
impl Protocol for DevicePathUtilitiesProtocol {
289+
fn guid() -> &'static Guid {
290+
&EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID
114291
}
115292
}
116293

294+
impl DevicePathUtilitiesProtocol {
295+
pub fn append_device_path(&self, src1: *const DevicePathProtocol, src2: *const DevicePathProtocol) -> Result<*const DevicePathProtocol, Status> {
296+
unsafe {
297+
let out = (self.append_device_path)(src1, src2);
298+
if out == 0 as *const DevicePathProtocol {
299+
return Err(Status::InvalidParameter);
300+
}
301+
Ok(out)
302+
}
303+
}
304+
305+
pub fn create_device_node<T: Into<u8>, U: Into<u8>>(&self, node_type: T, node_subtype: U, node_length: u16) -> Result<*const DevicePathProtocol, Status> {
306+
unsafe {
307+
let out = (self.create_device_node)(node_type.into(), node_subtype.into(), node_length);
308+
if out == 0 as *const DevicePathProtocol {
309+
return Err(Status::InvalidParameter);
310+
}
311+
Ok(out)
312+
}
313+
}
314+
}

src/util/device_path.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2017 CoreOS, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use base::Status;
16+
use protocol::{DevicePathProtocol, DevicePathUtilitiesProtocol, DevicePathTypes, MediaSubTypes};
17+
use void::CVoid;
18+
use util::*;
19+
20+
pub fn create_file_device_node(filename: &str) -> Result<&DevicePathProtocol, Status> {
21+
str_to_utf16_ptr(filename).and_then(|filename_ptr| {
22+
let filename_len = utf16_strlen(filename_ptr);
23+
let node_size_bytes = 4 + (filename_len + 1) * 2;
24+
25+
::get_system_table()
26+
.boot_services()
27+
.locate_protocol::<DevicePathUtilitiesProtocol>(0 as *const CVoid)
28+
.and_then(|utilities| {
29+
utilities.create_device_node(DevicePathTypes::Media, MediaSubTypes::FilePath, node_size_bytes as u16)
30+
.map(|node_ptr| {
31+
let node_filename_ptr: *mut u16 = unsafe { (node_ptr as *const u8).offset(4) as *mut u16 };
32+
33+
for i in 0..filename_len as isize{
34+
unsafe {
35+
*node_filename_ptr.offset(i) = *filename_ptr.offset(i);
36+
}
37+
}
38+
unsafe { *node_filename_ptr.offset(filename_len as isize) = 0 };
39+
40+
unsafe { &*node_ptr }
41+
})
42+
})
43+
})
44+
}

src/util/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14+
15+
mod device_path;
16+
pub use self::device_path::*;
17+
1418
use core::slice;
1519
use core::str;
1620

0 commit comments

Comments
 (0)