2 * efi_selftest_devicepath
4 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
6 * SPDX-License-Identifier: GPL-2.0+
8 * This unit test checks the following protocol services:
12 #include <efi_selftest.h>
14 static struct efi_boot_services
*boottime
;
16 static efi_handle_t handle1
;
17 static efi_handle_t handle2
;
18 static efi_handle_t handle3
;
21 void (EFIAPI
* inc
)(void);
24 static efi_guid_t guid_device_path
= DEVICE_PATH_GUID
;
26 static efi_guid_t guid_device_path_to_text_protocol
=
27 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID
;
29 static efi_guid_t guid_protocol
=
30 EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
31 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0x7d);
33 static efi_guid_t guid_vendor1
=
34 EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
35 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xb1);
37 static efi_guid_t guid_vendor2
=
38 EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
39 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xa2);
41 static efi_guid_t guid_vendor3
=
42 EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
43 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xc3);
49 struct efi_device_path_to_text_protocol
*device_path_to_text
;
54 * Create three handles. Install a new protocol on two of them and
55 * provice device paths.
63 * @handle: handle of the loaded image
64 * @systable: system table
66 static int setup(const efi_handle_t img_handle
,
67 const struct efi_system_table
*systable
)
69 struct efi_device_path_vendor vendor_node
;
70 struct efi_device_path end_node
;
73 boottime
= systable
->boottime
;
75 ret
= boottime
->locate_protocol(&guid_device_path_to_text_protocol
,
76 NULL
, (void **)&device_path_to_text
);
77 if (ret
!= EFI_SUCCESS
) {
78 device_path_to_text
= NULL
;
80 "Device path to text protocol is not available.\n");
81 return EFI_ST_FAILURE
;
84 ret
= boottime
->allocate_pool(EFI_LOADER_DATA
,
85 sizeof(struct efi_device_path_vendor
) +
86 sizeof(struct efi_device_path
),
88 if (ret
!= EFI_SUCCESS
)
91 ret
= boottime
->allocate_pool(EFI_LOADER_DATA
, 2 *
92 sizeof(struct efi_device_path_vendor
) +
93 sizeof(struct efi_device_path
),
95 if (ret
!= EFI_SUCCESS
)
98 ret
= boottime
->allocate_pool(EFI_LOADER_DATA
, 3 *
99 sizeof(struct efi_device_path_vendor
) +
100 sizeof(struct efi_device_path
),
102 if (ret
!= EFI_SUCCESS
)
105 vendor_node
.dp
.type
= DEVICE_PATH_TYPE_HARDWARE_DEVICE
;
106 vendor_node
.dp
.sub_type
= DEVICE_PATH_SUB_TYPE_VENDOR
;
107 vendor_node
.dp
.length
= sizeof(struct efi_device_path_vendor
);
109 boottime
->copy_mem(&vendor_node
.guid
, &guid_vendor1
,
111 boottime
->copy_mem(dp1
, &vendor_node
,
112 sizeof(struct efi_device_path_vendor
));
113 boottime
->copy_mem(dp2
, &vendor_node
,
114 sizeof(struct efi_device_path_vendor
));
115 boottime
->copy_mem(dp3
, &vendor_node
,
116 sizeof(struct efi_device_path_vendor
));
118 boottime
->copy_mem(&vendor_node
.guid
, &guid_vendor2
,
120 boottime
->copy_mem(dp2
+ sizeof(struct efi_device_path_vendor
),
121 &vendor_node
, sizeof(struct efi_device_path_vendor
));
122 boottime
->copy_mem(dp3
+ sizeof(struct efi_device_path_vendor
),
123 &vendor_node
, sizeof(struct efi_device_path_vendor
));
125 boottime
->copy_mem(&vendor_node
.guid
, &guid_vendor3
,
127 boottime
->copy_mem(dp3
+ 2 * sizeof(struct efi_device_path_vendor
),
128 &vendor_node
, sizeof(struct efi_device_path_vendor
));
130 end_node
.type
= DEVICE_PATH_TYPE_END
;
131 end_node
.sub_type
= DEVICE_PATH_SUB_TYPE_END
;
132 end_node
.length
= sizeof(struct efi_device_path
);
133 boottime
->copy_mem(dp1
+ sizeof(struct efi_device_path_vendor
),
134 &end_node
, sizeof(struct efi_device_path
));
135 boottime
->copy_mem(dp2
+ 2 * sizeof(struct efi_device_path_vendor
),
136 &end_node
, sizeof(struct efi_device_path
));
137 boottime
->copy_mem(dp3
+ 3 * sizeof(struct efi_device_path_vendor
),
138 &end_node
, sizeof(struct efi_device_path
));
140 ret
= boottime
->install_protocol_interface(&handle1
,
142 EFI_NATIVE_INTERFACE
,
144 if (ret
!= EFI_SUCCESS
) {
145 efi_st_error("InstallProtocolInterface failed\n");
146 return EFI_ST_FAILURE
;
148 ret
= boottime
->install_protocol_interface(&handle1
,
150 EFI_NATIVE_INTERFACE
,
152 if (ret
!= EFI_SUCCESS
) {
153 efi_st_error("InstallProtocolInterface failed\n");
154 return EFI_ST_FAILURE
;
156 ret
= boottime
->install_protocol_interface(&handle2
,
158 EFI_NATIVE_INTERFACE
,
160 if (ret
!= EFI_SUCCESS
) {
161 efi_st_error("InstallProtocolInterface failed\n");
162 return EFI_ST_FAILURE
;
164 ret
= boottime
->install_protocol_interface(&handle2
,
166 EFI_NATIVE_INTERFACE
,
168 if (ret
!= EFI_SUCCESS
) {
169 efi_st_error("InstallProtocolInterface failed\n");
170 return EFI_ST_FAILURE
;
172 ret
= boottime
->install_protocol_interface(&handle3
,
174 EFI_NATIVE_INTERFACE
,
176 if (ret
!= EFI_SUCCESS
) {
177 efi_st_error("InstallProtocolInterface failed\n");
178 return EFI_ST_FAILURE
;
180 return EFI_ST_SUCCESS
;
183 efi_st_error("Out of memory\n");
184 return EFI_ST_FAILURE
;
188 * Tear down unit test.
191 static int teardown(void)
195 ret
= boottime
->uninstall_protocol_interface(&handle1
,
198 if (ret
!= EFI_SUCCESS
)
199 efi_st_todo("UninstallProtocolInterface failed\n");
200 ret
= boottime
->uninstall_protocol_interface(&handle1
,
203 if (ret
!= EFI_SUCCESS
)
204 efi_st_todo("UninstallProtocolInterface failed\n");
205 ret
= boottime
->uninstall_protocol_interface(&handle2
,
208 if (ret
!= EFI_SUCCESS
)
209 efi_st_todo("UninstallProtocolInterface failed\n");
210 ret
= boottime
->uninstall_protocol_interface(&handle2
,
213 if (ret
!= EFI_SUCCESS
)
214 efi_st_todo("UninstallProtocolInterface failed\n");
215 ret
= boottime
->uninstall_protocol_interface(&handle3
,
218 if (ret
!= EFI_SUCCESS
)
219 efi_st_todo("UninstallProtocolInterface failed\n");
221 ret
= boottime
->free_pool(dp1
);
222 if (ret
!= EFI_SUCCESS
) {
223 efi_st_error("FreePool failed\n");
224 return EFI_ST_FAILURE
;
228 ret
= boottime
->free_pool(dp2
);
229 if (ret
!= EFI_SUCCESS
) {
230 efi_st_error("FreePool failed\n");
231 return EFI_ST_FAILURE
;
235 ret
= boottime
->free_pool(dp3
);
236 if (ret
!= EFI_SUCCESS
) {
237 efi_st_error("FreePool failed\n");
238 return EFI_ST_FAILURE
;
241 return EFI_ST_SUCCESS
;
248 static int execute(void)
250 struct efi_device_path
*remaining_dp
;
253 * This device path node ends with the letter 't' of 'u-boot'.
254 * The following '.bin' does not belong to the node but is
255 * helps to test the correct truncation.
258 struct efi_device_path dp
;
260 } __packed dp_node
= {
261 { DEVICE_PATH_TYPE_MEDIA_DEVICE
,
262 DEVICE_PATH_SUB_TYPE_FILE_PATH
,
263 sizeof(struct efi_device_path
) + 12},
268 efi_uintn_t i
, no_handles
;
269 efi_handle_t
*handles
;
270 struct efi_device_path
*dp
;
272 /* Display all available device paths */
273 ret
= boottime
->locate_handle_buffer(BY_PROTOCOL
,
275 NULL
, &no_handles
, &handles
);
276 if (ret
!= EFI_SUCCESS
) {
277 efi_st_error("Cannot retrieve device path protocols.\n");
278 return EFI_ST_FAILURE
;
281 efi_st_printf("Installed device path protocols:\n");
282 for (i
= 0; i
< no_handles
; ++i
) {
283 ret
= boottime
->open_protocol(handles
[i
], &guid_device_path
,
284 (void **)&dp
, NULL
, NULL
,
285 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
286 if (ret
!= EFI_SUCCESS
) {
287 efi_st_error("Cannot open device path protocol.\n");
288 return EFI_ST_FAILURE
;
290 string
= device_path_to_text
->convert_device_path_to_text(
293 efi_st_error("ConvertDevicePathToText failed\n");
294 return EFI_ST_FAILURE
;
296 efi_st_printf("%ps\n", string
);
297 ret
= boottime
->free_pool(string
);
298 if (ret
!= EFI_SUCCESS
) {
299 efi_st_error("FreePool failed\n");
300 return EFI_ST_FAILURE
;
302 ret
= boottime
->close_protocol(handles
[i
], &guid_device_path
,
304 if (ret
!= EFI_SUCCESS
)
305 efi_st_todo("Cannot close device path protocol.\n");
307 ret
= boottime
->free_pool(handles
);
308 if (ret
!= EFI_SUCCESS
) {
309 efi_st_error("FreePool failed\n");
310 return EFI_ST_FAILURE
;
314 /* Test ConvertDevicePathToText */
315 string
= device_path_to_text
->convert_device_path_to_text(
316 (struct efi_device_path
*)dp2
, true, false);
318 efi_st_error("ConvertDevicePathToText failed\n");
319 return EFI_ST_FAILURE
;
321 efi_st_printf("dp2: %ps\n", string
);
322 if (efi_st_strcmp_16_8(
324 "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
326 efi_st_error("Incorrect text from ConvertDevicePathToText\n");
327 return EFI_ST_FAILURE
;
330 ret
= boottime
->free_pool(string
);
331 if (ret
!= EFI_SUCCESS
) {
332 efi_st_error("FreePool failed\n");
333 return EFI_ST_FAILURE
;
336 /* Test ConvertDeviceNodeToText */
337 string
= device_path_to_text
->convert_device_node_to_text(
338 (struct efi_device_path
*)&dp_node
, true, false);
340 efi_st_error("ConvertDeviceNodeToText failed\n");
341 return EFI_ST_FAILURE
;
343 efi_st_printf("dp_node: %ps\n", string
);
344 ret
= boottime
->free_pool(string
);
345 if (ret
!= EFI_SUCCESS
) {
346 efi_st_error("FreePool failed\n");
347 return EFI_ST_FAILURE
;
349 if (efi_st_strcmp_16_8(string
, "u-boot")) {
351 "Incorrect conversion by ConvertDeviceNodeToText\n");
352 return EFI_ST_FAILURE
;
355 /* Test LocateDevicePath */
356 remaining_dp
= (struct efi_device_path
*)dp3
;
357 ret
= boottime
->locate_device_path(&guid_protocol
, &remaining_dp
,
359 if (ret
!= EFI_SUCCESS
) {
360 efi_st_error("LocateDevicePath failed\n");
361 return EFI_ST_FAILURE
;
363 if (handle
!= handle2
) {
364 efi_st_error("LocateDevicePath returned wrong handle\n");
365 return EFI_ST_FAILURE
;
367 string
= device_path_to_text
->convert_device_path_to_text(remaining_dp
,
370 efi_st_error("ConvertDevicePathToText failed\n");
371 return EFI_ST_FAILURE
;
373 efi_st_printf("remaining device path: %ps\n", string
);
374 if (efi_st_strcmp_16_8(string
,
375 "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
377 efi_st_error("LocateDevicePath: wrong remaining device path\n");
378 return EFI_ST_FAILURE
;
381 return EFI_ST_SUCCESS
;
384 EFI_UNIT_TEST(devicepath
) = {
385 .name
= "device path",
386 .phase
= EFI_EXECUTE_BEFORE_BOOTTIME_EXIT
,
389 .teardown
= teardown
,