1 // SPDX-License-Identifier: GPL-2.0+
3 * efi_selftest_devicepath_util
5 * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
7 * This unit test checks the device path utilities protocol.
10 #include <efi_selftest.h>
12 static struct efi_boot_services *boottime;
14 static efi_guid_t guid_device_path_utilities_protocol =
15 EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
17 struct efi_device_path_utilities_protocol *dpu;
22 * Locate the device path utilities protocol.
24 * @handle: handle of the loaded image
25 * @systable: system table
27 static int setup(const efi_handle_t img_handle,
28 const struct efi_system_table *systable)
32 boottime = systable->boottime;
34 ret = boottime->locate_protocol(&guid_device_path_utilities_protocol,
36 if (ret != EFI_SUCCESS) {
39 "Device path to text protocol is not available.\n");
40 return EFI_ST_FAILURE;
43 return EFI_ST_SUCCESS;
47 * Create a device path consisting of a single media device node followed by an
50 * @length: length of the media device node
52 * @return: status code
54 static int create_single_node_device_path(unsigned int length,
55 struct efi_device_path **dp)
57 struct efi_device_path *node;
61 node = dpu->create_device_node(DEVICE_PATH_TYPE_MEDIA_DEVICE,
62 DEVICE_PATH_SUB_TYPE_FILE_PATH, length);
64 efi_st_error("CreateDeviceNode failed\n");
65 return EFI_ST_FAILURE;
67 *dp = dpu->append_device_node(NULL, node);
69 efi_st_error("AppendDeviceNode failed\n");
70 return EFI_ST_FAILURE;
72 ret = boottime->free_pool(node);
73 if (ret != EFI_ST_SUCCESS) {
74 efi_st_error("FreePool failed\n");
75 return EFI_ST_FAILURE;
77 len = dpu->get_device_path_size(*dp);
78 if (len != length + 4) {
79 efi_st_error("Wrong device path length %u, expected %u\n",
80 (unsigned int)len, length);
81 return EFI_ST_FAILURE;
83 return EFI_ST_SUCCESS;
89 * In the test device paths are created, copied, and concatenated. The device
90 * path length is used as a measure of success.
92 static int execute(void)
94 struct efi_device_path *dp1;
95 struct efi_device_path *dp2;
96 struct efi_device_path *dp3;
101 /* IsDevicePathMultiInstance(NULL) */
102 if (dpu->is_device_path_multi_instance(NULL)) {
103 efi_st_error("IsDevicePathMultiInstance(NULL) returned true\n");
104 return EFI_ST_FAILURE;
106 /* GetDevicePathSize(NULL) */
107 len = dpu->get_device_path_size(NULL);
109 efi_st_error("Wrong device path length %u, expected 0\n",
111 return EFI_ST_FAILURE;
113 /* DuplicateDevicePath(NULL) */
114 dp1 = dpu->duplicate_device_path(NULL);
116 efi_st_error("DuplicateDevicePath(NULL) failed\n");
117 return EFI_ST_FAILURE;
119 /* AppendDevicePath(NULL, NULL) */
120 dp1 = dpu->append_device_path(NULL, NULL);
122 efi_st_error("AppendDevicePath(NULL, NULL) failed\n");
123 return EFI_ST_FAILURE;
125 len = dpu->get_device_path_size(dp1);
127 efi_st_error("Wrong device path length %u, expected 4\n",
129 return EFI_ST_FAILURE;
131 ret = boottime->free_pool(dp1);
132 if (ret != EFI_ST_SUCCESS) {
133 efi_st_error("FreePool failed\n");
134 return EFI_ST_FAILURE;
136 /* CreateDeviceNode */
137 ret = create_single_node_device_path(21, &dp1);
138 if (ret != EFI_ST_SUCCESS)
140 ret = create_single_node_device_path(17, &dp2);
141 if (ret != EFI_ST_SUCCESS)
143 /* AppendDevicePath */
144 dp3 = dpu->append_device_path(dp1, dp2);
146 efi_st_error("AppendDevicePath failed\n");
147 return EFI_ST_FAILURE;
149 if (dp3 == dp1 || dp3 == dp2) {
150 efi_st_error("AppendDevicePath reused buffer\n");
151 return EFI_ST_FAILURE;
153 len = dpu->get_device_path_size(dp3);
156 efi_st_error("Wrong device path length %u, expected 42\n",
158 return EFI_ST_FAILURE;
160 ret = boottime->free_pool(dp2);
161 if (ret != EFI_ST_SUCCESS) {
162 efi_st_error("FreePool failed\n");
163 return EFI_ST_FAILURE;
165 /* AppendDeviceNode */
166 dp2 = dpu->append_device_node(dp1, dp3);
168 efi_st_error("AppendDevicePath failed\n");
169 return EFI_ST_FAILURE;
171 len = dpu->get_device_path_size(dp2);
174 printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
175 efi_st_error("Wrong device path length %u, expected 46\n",
177 return EFI_ST_FAILURE;
179 ret = boottime->free_pool(dp1);
180 if (ret != EFI_ST_SUCCESS) {
181 efi_st_error("FreePool failed\n");
182 return EFI_ST_FAILURE;
184 /* IsDevicePathMultiInstance */
185 if (dpu->is_device_path_multi_instance(dp2)) {
186 printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
187 efi_st_error("IsDevicePathMultiInstance returned true\n");
188 return EFI_ST_FAILURE;
190 /* AppendDevicePathInstance */
191 dp1 = dpu->append_device_path_instance(dp2, dp3);
193 efi_st_error("AppendDevicePathInstance failed\n");
194 return EFI_ST_FAILURE;
196 len = dpu->get_device_path_size(dp1);
199 efi_st_error("Wrong device path length %u, expected 88\n",
201 return EFI_ST_FAILURE;
203 /* IsDevicePathMultiInstance */
204 if (!dpu->is_device_path_multi_instance(dp1)) {
205 efi_st_error("IsDevicePathMultiInstance returned false\n");
206 return EFI_ST_FAILURE;
208 ret = boottime->free_pool(dp2);
209 if (ret != EFI_ST_SUCCESS) {
210 efi_st_error("FreePool failed\n");
211 return EFI_ST_FAILURE;
213 ret = boottime->free_pool(dp3);
214 if (ret != EFI_ST_SUCCESS) {
215 efi_st_error("FreePool failed\n");
216 return EFI_ST_FAILURE;
218 /* GetNextDevicePathInstance */
220 dp2 = dpu->get_next_device_path_instance(&dp1, &len);
222 efi_st_error("GetNextDevicePathInstance failed\n");
223 return EFI_ST_FAILURE;
226 efi_st_error("GetNextDevicePathInstance no 2nd instance\n");
227 return EFI_ST_FAILURE;
230 efi_st_error("Wrong device path length %u, expected 46\n",
232 return EFI_ST_FAILURE;
234 len = dpu->get_device_path_size(dp1);
236 efi_st_error("Wrong device path length %u, expected 42\n",
238 return EFI_ST_FAILURE;
240 ret = boottime->free_pool(dp2);
241 if (ret != EFI_ST_SUCCESS) {
242 efi_st_error("FreePool failed\n");
243 return EFI_ST_FAILURE;
245 dp2 = dpu->get_next_device_path_instance(&dp1, &len);
247 efi_st_error("GetNextDevicePathInstance failed\n");
248 return EFI_ST_FAILURE;
251 efi_st_error("Wrong device path length %u, expected 46\n",
253 return EFI_ST_FAILURE;
256 efi_st_error("GetNextDevicePathInstance did not signal end\n");
257 return EFI_ST_FAILURE;
259 ret = boottime->free_pool(dp2);
260 if (ret != EFI_ST_SUCCESS) {
261 efi_st_error("FreePool failed\n");
262 return EFI_ST_FAILURE;
266 ret = boottime->free_pool(dp2);
267 if (ret != EFI_ST_SUCCESS) {
268 efi_st_error("FreePool failed\n");
269 return EFI_ST_FAILURE;
271 ret = boottime->free_pool(dp3);
272 if (ret != EFI_ST_SUCCESS) {
273 efi_st_error("FreePool failed\n");
274 return EFI_ST_FAILURE;
277 return EFI_ST_SUCCESS;
280 EFI_UNIT_TEST(dputil) = {
281 .name = "device path utilities protocol",
282 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,