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
,