]> git.sur5r.net Git - u-boot/blob - lib/efi_selftest/efi_selftest_devicepath.c
efi_selftest: fix typo in efi_selftest_devicepath.c
[u-boot] / lib / efi_selftest / efi_selftest_devicepath.c
1 /*
2  * efi_selftest_devicepath
3  *
4  * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  *
8  * This unit test checks the following protocol services:
9  * DevicePathToText
10  */
11
12 #include <efi_selftest.h>
13
14 static struct efi_boot_services *boottime;
15
16 static efi_handle_t handle1;
17 static efi_handle_t handle2;
18 static efi_handle_t handle3;
19
20 struct interface {
21         void (EFIAPI * inc)(void);
22 } interface;
23
24 static efi_guid_t guid_device_path = DEVICE_PATH_GUID;
25
26 static efi_guid_t guid_device_path_to_text_protocol =
27         EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
28
29 static efi_guid_t guid_protocol =
30         EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
31                  0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0x7d);
32
33 static efi_guid_t guid_vendor1 =
34         EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
35                  0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xb1);
36
37 static efi_guid_t guid_vendor2 =
38         EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
39                  0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xa2);
40
41 static efi_guid_t guid_vendor3 =
42         EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
43                  0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xc3);
44
45 static u8 *dp1;
46 static u8 *dp2;
47 static u8 *dp3;
48
49 struct efi_device_path_to_text_protocol *device_path_to_text;
50
51 /*
52  * Setup unit test.
53  *
54  * Create three handles. Install a new protocol on two of them and
55  * provide device paths.
56  *
57  * handle1
58  *   guid interface
59  * handle2
60  *   guid interface
61  * handle3
62  *
63  * @handle:     handle of the loaded image
64  * @systable:   system table
65  */
66 static int setup(const efi_handle_t img_handle,
67                  const struct efi_system_table *systable)
68 {
69         struct efi_device_path_vendor vendor_node;
70         struct efi_device_path end_node;
71         efi_status_t ret;
72
73         boottime = systable->boottime;
74
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;
79                 efi_st_error(
80                         "Device path to text protocol is not available.\n");
81                 return EFI_ST_FAILURE;
82         }
83
84         ret = boottime->allocate_pool(EFI_LOADER_DATA,
85                                       sizeof(struct efi_device_path_vendor) +
86                                       sizeof(struct efi_device_path),
87                                       (void **)&dp1);
88         if (ret != EFI_SUCCESS)
89                 goto out_of_memory;
90
91         ret = boottime->allocate_pool(EFI_LOADER_DATA, 2 *
92                                       sizeof(struct efi_device_path_vendor) +
93                                       sizeof(struct efi_device_path),
94                                       (void **)&dp2);
95         if (ret != EFI_SUCCESS)
96                 goto out_of_memory;
97
98         ret = boottime->allocate_pool(EFI_LOADER_DATA, 3 *
99                                       sizeof(struct efi_device_path_vendor) +
100                                       sizeof(struct efi_device_path),
101                                       (void **)&dp3);
102         if (ret != EFI_SUCCESS)
103                 goto out_of_memory;
104
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);
108
109         boottime->copy_mem(&vendor_node.guid, &guid_vendor1,
110                            sizeof(efi_guid_t));
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));
117
118         boottime->copy_mem(&vendor_node.guid, &guid_vendor2,
119                            sizeof(efi_guid_t));
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));
124
125         boottime->copy_mem(&vendor_node.guid, &guid_vendor3,
126                            sizeof(efi_guid_t));
127         boottime->copy_mem(dp3 + 2 * sizeof(struct efi_device_path_vendor),
128                            &vendor_node, sizeof(struct efi_device_path_vendor));
129
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));
139
140         ret = boottime->install_protocol_interface(&handle1,
141                                                    &guid_device_path,
142                                                    EFI_NATIVE_INTERFACE,
143                                                    dp1);
144         if (ret != EFI_SUCCESS) {
145                 efi_st_error("InstallProtocolInterface failed\n");
146                 return EFI_ST_FAILURE;
147         }
148         ret = boottime->install_protocol_interface(&handle1,
149                                                    &guid_protocol,
150                                                    EFI_NATIVE_INTERFACE,
151                                                    &interface);
152         if (ret != EFI_SUCCESS) {
153                 efi_st_error("InstallProtocolInterface failed\n");
154                 return EFI_ST_FAILURE;
155         }
156         ret = boottime->install_protocol_interface(&handle2,
157                                                    &guid_device_path,
158                                                    EFI_NATIVE_INTERFACE,
159                                                    dp2);
160         if (ret != EFI_SUCCESS) {
161                 efi_st_error("InstallProtocolInterface failed\n");
162                 return EFI_ST_FAILURE;
163         }
164         ret = boottime->install_protocol_interface(&handle2,
165                                                    &guid_protocol,
166                                                    EFI_NATIVE_INTERFACE,
167                                                    &interface);
168         if (ret != EFI_SUCCESS) {
169                 efi_st_error("InstallProtocolInterface failed\n");
170                 return EFI_ST_FAILURE;
171         }
172         ret = boottime->install_protocol_interface(&handle3,
173                                                    &guid_device_path,
174                                                    EFI_NATIVE_INTERFACE,
175                                                    dp3);
176         if (ret != EFI_SUCCESS) {
177                 efi_st_error("InstallProtocolInterface failed\n");
178                 return EFI_ST_FAILURE;
179         }
180         return EFI_ST_SUCCESS;
181
182 out_of_memory:
183         efi_st_error("Out of memory\n");
184         return EFI_ST_FAILURE;
185 }
186
187 /*
188  * Tear down unit test.
189  *
190  */
191 static int teardown(void)
192 {
193         efi_status_t ret;
194
195         ret = boottime->uninstall_protocol_interface(handle1,
196                                                      &guid_device_path,
197                                                      dp1);
198         if (ret != EFI_SUCCESS) {
199                 efi_st_error("UninstallProtocolInterface failed\n");
200                 return EFI_ST_FAILURE;
201         }
202         ret = boottime->uninstall_protocol_interface(handle1,
203                                                      &guid_protocol,
204                                                      &interface);
205         if (ret != EFI_SUCCESS) {
206                 efi_st_error("UninstallProtocolInterface failed\n");
207                 return EFI_ST_FAILURE;
208         }
209         ret = boottime->uninstall_protocol_interface(handle2,
210                                                      &guid_device_path,
211                                                      dp2);
212         if (ret != EFI_SUCCESS) {
213                 efi_st_error("UninstallProtocolInterface failed\n");
214                 return EFI_ST_FAILURE;
215         }
216         ret = boottime->uninstall_protocol_interface(handle2,
217                                                      &guid_protocol,
218                                                      &interface);
219         if (ret != EFI_SUCCESS) {
220                 efi_st_error("UninstallProtocolInterface failed\n");
221                 return EFI_ST_FAILURE;
222         }
223         ret = boottime->uninstall_protocol_interface(handle3,
224                                                      &guid_device_path,
225                                                      dp3);
226         if (ret != EFI_SUCCESS) {
227                 efi_st_error("UninstallProtocolInterface failed\n");
228                 return EFI_ST_FAILURE;
229         }
230         if (dp1) {
231                 ret = boottime->free_pool(dp1);
232                 if (ret != EFI_SUCCESS) {
233                         efi_st_error("FreePool failed\n");
234                         return EFI_ST_FAILURE;
235                 }
236         }
237         if (dp2) {
238                 ret = boottime->free_pool(dp2);
239                 if (ret != EFI_SUCCESS) {
240                         efi_st_error("FreePool failed\n");
241                         return EFI_ST_FAILURE;
242                 }
243         }
244         if (dp3) {
245                 ret = boottime->free_pool(dp3);
246                 if (ret != EFI_SUCCESS) {
247                         efi_st_error("FreePool failed\n");
248                         return EFI_ST_FAILURE;
249                 }
250         }
251         return EFI_ST_SUCCESS;
252 }
253
254 /*
255  * Execute unit test.
256  *
257  */
258 static int execute(void)
259 {
260         struct efi_device_path *remaining_dp;
261         void *handle;
262         /*
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.
266          */
267         struct {
268                 struct efi_device_path dp;
269                 u16 text[12];
270         } __packed dp_node = {
271                         { DEVICE_PATH_TYPE_MEDIA_DEVICE,
272                           DEVICE_PATH_SUB_TYPE_FILE_PATH,
273                           sizeof(struct efi_device_path) + 12},
274                         L"u-boot.bin",
275                 };
276         u16 *string;
277         efi_status_t ret;
278         efi_uintn_t i, no_handles;
279         efi_handle_t *handles;
280         struct efi_device_path *dp;
281
282         /* Display all available device paths */
283         ret = boottime->locate_handle_buffer(BY_PROTOCOL,
284                                              &guid_device_path,
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;
289         }
290
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;
299                 }
300                 string = device_path_to_text->convert_device_path_to_text(
301                                         dp, true, false);
302                 if (!string) {
303                         efi_st_error("ConvertDevicePathToText failed\n");
304                         return EFI_ST_FAILURE;
305                 }
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;
311                 }
312                 /*
313                  * CloseProtocol cannot be called without agent handle.
314                  * There is no need to close the device path protocol.
315                  */
316         }
317         ret = boottime->free_pool(handles);
318         if (ret != EFI_SUCCESS) {
319                 efi_st_error("FreePool failed\n");
320                 return EFI_ST_FAILURE;
321         }
322
323         /* Test ConvertDevicePathToText */
324         string = device_path_to_text->convert_device_path_to_text(
325                         (struct efi_device_path *)dp2, true, false);
326         if (!string) {
327                 efi_st_error("ConvertDevicePathToText failed\n");
328                 return EFI_ST_FAILURE;
329         }
330         if (efi_st_strcmp_16_8(
331                 string,
332                 "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
333             ) {
334                 efi_st_printf("dp2: %ps\n", string);
335                 efi_st_error("Incorrect text from ConvertDevicePathToText\n");
336                 return EFI_ST_FAILURE;
337         }
338         ret = boottime->free_pool(string);
339         if (ret != EFI_SUCCESS) {
340                 efi_st_error("FreePool failed\n");
341                 return EFI_ST_FAILURE;
342         }
343
344         /* Test ConvertDeviceNodeToText */
345         string = device_path_to_text->convert_device_node_to_text(
346                         (struct efi_device_path *)&dp_node, true, false);
347         if (!string) {
348                 efi_st_error("ConvertDeviceNodeToText failed\n");
349                 return EFI_ST_FAILURE;
350         }
351         if (efi_st_strcmp_16_8(string, "u-boot")) {
352                 efi_st_printf("dp_node: %ps\n", string);
353                 efi_st_error(
354                         "Incorrect conversion by ConvertDeviceNodeToText\n");
355                 return EFI_ST_FAILURE;
356         }
357         ret = boottime->free_pool(string);
358         if (ret != EFI_SUCCESS) {
359                 efi_st_error("FreePool failed\n");
360                 return EFI_ST_FAILURE;
361         }
362
363         /* Test LocateDevicePath */
364         remaining_dp = (struct efi_device_path *)dp3;
365         ret = boottime->locate_device_path(&guid_protocol, &remaining_dp,
366                                            &handle);
367         if (ret != EFI_SUCCESS) {
368                 efi_st_error("LocateDevicePath failed\n");
369                 return EFI_ST_FAILURE;
370         }
371         if (handle != handle2) {
372                 efi_st_error("LocateDevicePath returned wrong handle\n");
373                 return EFI_ST_FAILURE;
374         }
375         string = device_path_to_text->convert_device_path_to_text(remaining_dp,
376                                                                   true, false);
377         if (!string) {
378                 efi_st_error("ConvertDevicePathToText failed\n");
379                 return EFI_ST_FAILURE;
380         }
381         if (efi_st_strcmp_16_8(string,
382                                "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
383             ) {
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;
387         }
388         ret = boottime->free_pool(string);
389         if (ret != EFI_SUCCESS) {
390                 efi_st_error("FreePool failed\n");
391                 return EFI_ST_FAILURE;
392         }
393
394         return EFI_ST_SUCCESS;
395 }
396
397 EFI_UNIT_TEST(devicepath) = {
398         .name = "device path",
399         .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
400         .setup = setup,
401         .execute = execute,
402         .teardown = teardown,
403 };