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 * provide 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_error("UninstallProtocolInterface failed\n");
200 return EFI_ST_FAILURE;
202 ret = boottime->uninstall_protocol_interface(handle1,
205 if (ret != EFI_SUCCESS) {
206 efi_st_error("UninstallProtocolInterface failed\n");
207 return EFI_ST_FAILURE;
209 ret = boottime->uninstall_protocol_interface(handle2,
212 if (ret != EFI_SUCCESS) {
213 efi_st_error("UninstallProtocolInterface failed\n");
214 return EFI_ST_FAILURE;
216 ret = boottime->uninstall_protocol_interface(handle2,
219 if (ret != EFI_SUCCESS) {
220 efi_st_error("UninstallProtocolInterface failed\n");
221 return EFI_ST_FAILURE;
223 ret = boottime->uninstall_protocol_interface(handle3,
226 if (ret != EFI_SUCCESS) {
227 efi_st_error("UninstallProtocolInterface failed\n");
228 return EFI_ST_FAILURE;
231 ret = boottime->free_pool(dp1);
232 if (ret != EFI_SUCCESS) {
233 efi_st_error("FreePool failed\n");
234 return EFI_ST_FAILURE;
238 ret = boottime->free_pool(dp2);
239 if (ret != EFI_SUCCESS) {
240 efi_st_error("FreePool failed\n");
241 return EFI_ST_FAILURE;
245 ret = boottime->free_pool(dp3);
246 if (ret != EFI_SUCCESS) {
247 efi_st_error("FreePool failed\n");
248 return EFI_ST_FAILURE;
251 return EFI_ST_SUCCESS;
258 static int execute(void)
260 struct efi_device_path *remaining_dp;
263 * This device path node ends with the letter 't' of 'u-boot'.
264 * The following '.bin' does not belong to the node but is
265 * helps to test the correct truncation.
268 struct efi_device_path dp;
270 } __packed dp_node = {
271 { DEVICE_PATH_TYPE_MEDIA_DEVICE,
272 DEVICE_PATH_SUB_TYPE_FILE_PATH,
273 sizeof(struct efi_device_path) + 12},
278 efi_uintn_t i, no_handles;
279 efi_handle_t *handles;
280 struct efi_device_path *dp;
282 /* Display all available device paths */
283 ret = boottime->locate_handle_buffer(BY_PROTOCOL,
285 NULL, &no_handles, &handles);
286 if (ret != EFI_SUCCESS) {
287 efi_st_error("Cannot retrieve device path protocols.\n");
288 return EFI_ST_FAILURE;
291 efi_st_printf("Installed device path protocols:\n");
292 for (i = 0; i < no_handles; ++i) {
293 ret = boottime->open_protocol(handles[i], &guid_device_path,
294 (void **)&dp, NULL, NULL,
295 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
296 if (ret != EFI_SUCCESS) {
297 efi_st_error("Cannot open device path protocol.\n");
298 return EFI_ST_FAILURE;
300 string = device_path_to_text->convert_device_path_to_text(
303 efi_st_error("ConvertDevicePathToText failed\n");
304 return EFI_ST_FAILURE;
306 efi_st_printf("%ps\n", string);
307 ret = boottime->free_pool(string);
308 if (ret != EFI_SUCCESS) {
309 efi_st_error("FreePool failed\n");
310 return EFI_ST_FAILURE;
313 * CloseProtocol cannot be called without agent handle.
314 * There is no need to close the device path protocol.
317 ret = boottime->free_pool(handles);
318 if (ret != EFI_SUCCESS) {
319 efi_st_error("FreePool failed\n");
320 return EFI_ST_FAILURE;
323 /* Test ConvertDevicePathToText */
324 string = device_path_to_text->convert_device_path_to_text(
325 (struct efi_device_path *)dp2, true, false);
327 efi_st_error("ConvertDevicePathToText failed\n");
328 return EFI_ST_FAILURE;
330 if (efi_st_strcmp_16_8(
332 "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
334 efi_st_printf("dp2: %ps\n", string);
335 efi_st_error("Incorrect text from ConvertDevicePathToText\n");
336 return EFI_ST_FAILURE;
338 ret = boottime->free_pool(string);
339 if (ret != EFI_SUCCESS) {
340 efi_st_error("FreePool failed\n");
341 return EFI_ST_FAILURE;
344 /* Test ConvertDeviceNodeToText */
345 string = device_path_to_text->convert_device_node_to_text(
346 (struct efi_device_path *)&dp_node, true, false);
348 efi_st_error("ConvertDeviceNodeToText failed\n");
349 return EFI_ST_FAILURE;
351 if (efi_st_strcmp_16_8(string, "u-boot")) {
352 efi_st_printf("dp_node: %ps\n", string);
354 "Incorrect conversion by ConvertDeviceNodeToText\n");
355 return EFI_ST_FAILURE;
357 ret = boottime->free_pool(string);
358 if (ret != EFI_SUCCESS) {
359 efi_st_error("FreePool failed\n");
360 return EFI_ST_FAILURE;
363 /* Test LocateDevicePath */
364 remaining_dp = (struct efi_device_path *)dp3;
365 ret = boottime->locate_device_path(&guid_protocol, &remaining_dp,
367 if (ret != EFI_SUCCESS) {
368 efi_st_error("LocateDevicePath failed\n");
369 return EFI_ST_FAILURE;
371 if (handle != handle2) {
372 efi_st_error("LocateDevicePath returned wrong handle\n");
373 return EFI_ST_FAILURE;
375 string = device_path_to_text->convert_device_path_to_text(remaining_dp,
378 efi_st_error("ConvertDevicePathToText failed\n");
379 return EFI_ST_FAILURE;
381 if (efi_st_strcmp_16_8(string,
382 "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
384 efi_st_printf("remaining device path: %ps\n", string);
385 efi_st_error("LocateDevicePath: wrong remaining device path\n");
386 return EFI_ST_FAILURE;
388 ret = boottime->free_pool(string);
389 if (ret != EFI_SUCCESS) {
390 efi_st_error("FreePool failed\n");
391 return EFI_ST_FAILURE;
394 return EFI_ST_SUCCESS;
397 EFI_UNIT_TEST(devicepath) = {
398 .name = "device path",
399 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
402 .teardown = teardown,