Skip to content

Commit a950682

Browse files
authored
Merge pull request #1527 from nicholasbishop/bishop-improve-dp-tests-2
test-runner: Clean up device path tests
2 parents f10465a + 5d1ed37 commit a950682

File tree

1 file changed

+207
-111
lines changed

1 file changed

+207
-111
lines changed
+207-111
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,219 @@
1-
use alloc::string::ToString;
1+
use alloc::boxed::Box;
22
use alloc::vec::Vec;
3-
use uefi::boot;
4-
use uefi::proto::device_path::text::*;
5-
use uefi::proto::device_path::{DevicePath, LoadedImageDevicePath};
3+
use uefi::proto::device_path::build::{self, DevicePathBuilder};
4+
use uefi::proto::device_path::text::{
5+
AllowShortcuts, DevicePathFromText, DevicePathToText, DisplayOnly,
6+
};
7+
use uefi::proto::device_path::{messaging, DevicePath, DevicePathNode, LoadedImageDevicePath};
68
use uefi::proto::loaded_image::LoadedImage;
79
use uefi::proto::media::disk::DiskIo;
10+
use uefi::{boot, cstr16};
811

912
pub fn test() {
10-
info!("Running device path protocol test");
13+
info!("Running device path tests");
1114

12-
// test 1/2: test low-level API by directly opening all protocols
15+
test_convert_device_path_to_text();
16+
test_device_path_to_string();
17+
18+
test_convert_device_node_to_text();
19+
test_device_path_node_to_string();
20+
21+
test_convert_text_to_device_path();
22+
test_convert_text_to_device_node();
23+
24+
// Get the current executable's device path via the `LoadedImage` protocol.
25+
let loaded_image = boot::open_protocol_exclusive::<LoadedImage>(boot::image_handle()).unwrap();
26+
let device_path =
27+
boot::open_protocol_exclusive::<DevicePath>(loaded_image.device().unwrap()).unwrap();
28+
29+
// Get the `LoadedImageDevicePath`. Verify it start with the same nodes as
30+
// `device_path`.
31+
let loaded_image_device_path =
32+
boot::open_protocol_exclusive::<LoadedImageDevicePath>(boot::image_handle()).unwrap();
33+
for (n1, n2) in device_path
34+
.node_iter()
35+
.zip(loaded_image_device_path.node_iter())
1336
{
14-
let loaded_image = boot::open_protocol_exclusive::<LoadedImage>(boot::image_handle())
15-
.expect("Failed to open LoadedImage protocol");
16-
17-
let device_path =
18-
boot::open_protocol_exclusive::<DevicePath>(loaded_image.device().unwrap())
19-
.expect("Failed to open DevicePath protocol");
20-
21-
let device_path_to_text = boot::open_protocol_exclusive::<DevicePathToText>(
22-
boot::get_handle_for_protocol::<DevicePathToText>()
23-
.expect("Failed to get DevicePathToText handle"),
24-
)
25-
.expect("Failed to open DevicePathToText protocol");
26-
27-
let device_path_from_text = boot::open_protocol_exclusive::<DevicePathFromText>(
28-
boot::get_handle_for_protocol::<DevicePathFromText>()
29-
.expect("Failed to get DevicePathFromText handle"),
30-
)
31-
.expect("Failed to open DevicePathFromText protocol");
32-
33-
// Test round-trip conversion from path to text and back.
34-
let device_path_string = device_path_to_text
35-
.convert_device_path_to_text(&device_path, DisplayOnly(false), AllowShortcuts(false))
36-
.unwrap();
37-
assert_eq!(
38-
*device_path_from_text
39-
.convert_text_to_device_path(&device_path_string)
40-
.unwrap(),
41-
*device_path
42-
);
43-
44-
for path in device_path.node_iter() {
45-
info!(
46-
"path: type={:?}, subtype={:?}, length={}",
47-
path.device_type(),
48-
path.sub_type(),
49-
path.length(),
50-
);
51-
52-
let text = device_path_to_text
53-
.convert_device_node_to_text(path, DisplayOnly(true), AllowShortcuts(false))
54-
.expect("Failed to convert device path to text");
55-
let text = &*text;
56-
info!("path name: {text}");
57-
58-
let convert = device_path_from_text
59-
.convert_text_to_device_node(text)
60-
.expect("Failed to convert text to device path");
61-
assert_eq!(*path, *convert);
62-
}
63-
64-
// Get the `LoadedImageDevicePath`. Verify it start with the same nodes as
65-
// `device_path`.
66-
let loaded_image_device_path =
67-
boot::open_protocol_exclusive::<LoadedImageDevicePath>(boot::image_handle())
68-
.expect("Failed to open LoadedImageDevicePath protocol");
69-
70-
for (n1, n2) in device_path
71-
.node_iter()
72-
.zip(loaded_image_device_path.node_iter())
73-
{
74-
assert_eq!(n1, n2);
75-
}
76-
77-
// Test `locate_device_path`.
78-
let mut dp = &*device_path;
79-
boot::locate_device_path::<DiskIo>(&mut dp).unwrap();
37+
assert_eq!(n1, n2);
8038
}
8139

82-
// test 2/2: test high-level to-string api
83-
{
84-
let loaded_image_device_path =
85-
boot::open_protocol_exclusive::<LoadedImageDevicePath>(boot::image_handle())
86-
.expect("Failed to open LoadedImageDevicePath protocol");
87-
let device_path: &DevicePath = &loaded_image_device_path;
88-
89-
let path_components = device_path
90-
.node_iter()
91-
.map(|node| node.to_string(DisplayOnly(false), AllowShortcuts(false)))
92-
.map(|str| str.unwrap().to_string())
93-
.collect::<Vec<_>>();
94-
95-
let expected_device_path_str_components = &[
96-
"PciRoot(0x0)",
97-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
98-
"Pci(0x1F,0x2)",
99-
#[cfg(target_arch = "aarch64")]
100-
"Pci(0x4,0x0)",
101-
// Sata device only used on x86.
102-
// See xtask utility.
103-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
104-
"Sata(0x0,0xFFFF,0x0)",
105-
"HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)",
106-
"\\efi\\boot\\test_runner.efi",
107-
];
108-
let expected_device_path_str = expected_device_path_str_components.join("/");
109-
110-
assert_eq!(
111-
path_components.as_slice(),
112-
expected_device_path_str_components
113-
);
114-
115-
// Test that to_string works for device_paths
116-
let path = device_path
117-
.to_string(DisplayOnly(false), AllowShortcuts(false))
40+
// Test finding a handle by device path.
41+
let mut dp = &*device_path;
42+
boot::locate_device_path::<DiskIo>(&mut dp).unwrap();
43+
}
44+
45+
fn create_test_device_path() -> Box<DevicePath> {
46+
let mut v = Vec::new();
47+
DevicePathBuilder::with_vec(&mut v)
48+
// Add an ATAPI node because edk2 displays it differently depending on
49+
// the value of `DisplayOnly`.
50+
.push(&build::messaging::Atapi {
51+
primary_secondary: messaging::PrimarySecondary::PRIMARY,
52+
master_slave: messaging::MasterSlave::MASTER,
53+
logical_unit_number: 1,
54+
})
55+
.unwrap()
56+
// Add a messaging::vendor node because edk2 displays it differently
57+
// depending on the value of `AllowShortcuts`.
58+
.push(&build::messaging::Vendor {
59+
vendor_guid: messaging::Vendor::PC_ANSI,
60+
vendor_defined_data: &[],
61+
})
62+
.unwrap()
63+
.finalize()
64+
.unwrap()
65+
.to_boxed()
66+
}
67+
68+
/// Test `DevicePathToText::convert_device_path_to_text`.
69+
fn test_convert_device_path_to_text() {
70+
let path = create_test_device_path();
71+
72+
let proto = boot::open_protocol_exclusive::<DevicePathToText>(
73+
boot::get_handle_for_protocol::<DevicePathToText>().unwrap(),
74+
)
75+
.unwrap();
76+
77+
let to_text = |display_only, allow_shortcuts| {
78+
proto
79+
.convert_device_path_to_text(&path, display_only, allow_shortcuts)
11880
.unwrap()
119-
.to_string();
81+
};
82+
83+
assert_eq!(
84+
&*to_text(DisplayOnly(true), AllowShortcuts(true)),
85+
cstr16!("Ata(0x1)/VenPcAnsi()")
86+
);
87+
assert_eq!(
88+
&*to_text(DisplayOnly(true), AllowShortcuts(false)),
89+
cstr16!("Ata(0x1)/VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)")
90+
);
91+
assert_eq!(
92+
&*to_text(DisplayOnly(false), AllowShortcuts(true)),
93+
cstr16!("Ata(Primary,Master,0x1)/VenPcAnsi()")
94+
);
95+
assert_eq!(
96+
&*to_text(DisplayOnly(false), AllowShortcuts(false)),
97+
cstr16!("Ata(Primary,Master,0x1)/VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)")
98+
);
99+
}
120100

121-
assert_eq!(path, expected_device_path_str);
122-
}
101+
/// Test `DevicePath::to_string`.
102+
fn test_device_path_to_string() {
103+
let path = create_test_device_path();
104+
105+
let to_text =
106+
|display_only, allow_shortcuts| path.to_string(display_only, allow_shortcuts).unwrap();
107+
108+
assert_eq!(
109+
&*to_text(DisplayOnly(true), AllowShortcuts(true)),
110+
cstr16!("Ata(0x1)/VenPcAnsi()")
111+
);
112+
assert_eq!(
113+
&*to_text(DisplayOnly(true), AllowShortcuts(false)),
114+
cstr16!("Ata(0x1)/VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)")
115+
);
116+
assert_eq!(
117+
&*to_text(DisplayOnly(false), AllowShortcuts(true)),
118+
cstr16!("Ata(Primary,Master,0x1)/VenPcAnsi()")
119+
);
120+
assert_eq!(
121+
&*to_text(DisplayOnly(false), AllowShortcuts(false)),
122+
cstr16!("Ata(Primary,Master,0x1)/VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)")
123+
);
124+
}
125+
126+
/// Test `DevicePathToText::convert_device_node_to_text`.
127+
fn test_convert_device_node_to_text() {
128+
let path = create_test_device_path();
129+
let nodes: Vec<_> = path.node_iter().collect();
130+
131+
let proto = boot::open_protocol_exclusive::<DevicePathToText>(
132+
boot::get_handle_for_protocol::<DevicePathToText>().unwrap(),
133+
)
134+
.unwrap();
135+
136+
let to_text = |node, display_only, allow_shortcuts| {
137+
proto
138+
.convert_device_node_to_text(node, display_only, allow_shortcuts)
139+
.unwrap()
140+
};
141+
142+
assert_eq!(
143+
&*to_text(nodes[0], DisplayOnly(true), AllowShortcuts(true)),
144+
cstr16!("Ata(0x1)")
145+
);
146+
assert_eq!(
147+
&*to_text(nodes[0], DisplayOnly(false), AllowShortcuts(true)),
148+
cstr16!("Ata(Primary,Master,0x1)")
149+
);
150+
assert_eq!(
151+
&*to_text(nodes[1], DisplayOnly(false), AllowShortcuts(true)),
152+
cstr16!("VenPcAnsi()")
153+
);
154+
assert_eq!(
155+
&*to_text(nodes[1], DisplayOnly(false), AllowShortcuts(false)),
156+
cstr16!("VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)")
157+
);
158+
}
159+
160+
/// Test `DevicePathNode::to_string`.
161+
fn test_device_path_node_to_string() {
162+
let path = create_test_device_path();
163+
let nodes: Vec<_> = path.node_iter().collect();
164+
165+
let to_text = |node: &DevicePathNode, display_only, allow_shortcuts| {
166+
node.to_string(display_only, allow_shortcuts).unwrap()
167+
};
168+
169+
assert_eq!(
170+
&*to_text(nodes[0], DisplayOnly(true), AllowShortcuts(true)),
171+
cstr16!("Ata(0x1)")
172+
);
173+
assert_eq!(
174+
&*to_text(nodes[0], DisplayOnly(false), AllowShortcuts(true)),
175+
cstr16!("Ata(Primary,Master,0x1)")
176+
);
177+
assert_eq!(
178+
&*to_text(nodes[1], DisplayOnly(false), AllowShortcuts(true)),
179+
cstr16!("VenPcAnsi()")
180+
);
181+
assert_eq!(
182+
&*to_text(nodes[1], DisplayOnly(false), AllowShortcuts(false)),
183+
cstr16!("VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)")
184+
);
185+
}
186+
187+
/// Test `DevicePathFromText::convert_text_to_device_path`.
188+
fn test_convert_text_to_device_path() {
189+
let text = cstr16!("Ata(Primary,Master,0x1)/VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)");
190+
let expected_path = create_test_device_path();
191+
192+
let proto = boot::open_protocol_exclusive::<DevicePathFromText>(
193+
boot::get_handle_for_protocol::<DevicePathFromText>().unwrap(),
194+
)
195+
.unwrap();
196+
197+
assert_eq!(
198+
&*proto.convert_text_to_device_path(text).unwrap(),
199+
&*expected_path
200+
);
201+
}
202+
203+
/// Test `DevicePathFromText::convert_text_to_device_node`.
204+
fn test_convert_text_to_device_node() {
205+
let path = create_test_device_path();
206+
let expected_node = path.node_iter().next().unwrap();
207+
208+
let proto = boot::open_protocol_exclusive::<DevicePathFromText>(
209+
boot::get_handle_for_protocol::<DevicePathFromText>().unwrap(),
210+
)
211+
.unwrap();
212+
213+
assert_eq!(
214+
&*proto
215+
.convert_text_to_device_node(cstr16!("Ata(Primary,Master,0x1)"))
216+
.unwrap(),
217+
expected_node,
218+
);
123219
}

0 commit comments

Comments
 (0)