123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- /*
- * efi_selftest_devicepath
- *
- * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * This unit test checks the following protocol services:
- * DevicePathToText
- */
- #include <efi_selftest.h>
- static struct efi_boot_services *boottime;
- static efi_handle_t handle1;
- static efi_handle_t handle2;
- static efi_handle_t handle3;
- struct interface {
- void (EFIAPI * inc)(void);
- } interface;
- static efi_guid_t guid_device_path = DEVICE_PATH_GUID;
- static efi_guid_t guid_device_path_to_text_protocol =
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
- static efi_guid_t guid_protocol =
- EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
- 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0x7d);
- static efi_guid_t guid_vendor1 =
- EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
- 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xb1);
- static efi_guid_t guid_vendor2 =
- EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
- 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xa2);
- static efi_guid_t guid_vendor3 =
- EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
- 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xc3);
- static u8 *dp1;
- static u8 *dp2;
- static u8 *dp3;
- struct efi_device_path_to_text_protocol *device_path_to_text;
- /*
- * Setup unit test.
- *
- * Create three handles. Install a new protocol on two of them and
- * provice device paths.
- *
- * handle1
- * guid interface
- * handle2
- * guid interface
- * handle3
- *
- * @handle: handle of the loaded image
- * @systable: system table
- */
- static int setup(const efi_handle_t img_handle,
- const struct efi_system_table *systable)
- {
- struct efi_device_path_vendor vendor_node;
- struct efi_device_path end_node;
- efi_status_t ret;
- boottime = systable->boottime;
- ret = boottime->locate_protocol(&guid_device_path_to_text_protocol,
- NULL, (void **)&device_path_to_text);
- if (ret != EFI_SUCCESS) {
- device_path_to_text = NULL;
- efi_st_error(
- "Device path to text protocol is not available.\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->allocate_pool(EFI_LOADER_DATA,
- sizeof(struct efi_device_path_vendor) +
- sizeof(struct efi_device_path),
- (void **)&dp1);
- if (ret != EFI_SUCCESS)
- goto out_of_memory;
- ret = boottime->allocate_pool(EFI_LOADER_DATA, 2 *
- sizeof(struct efi_device_path_vendor) +
- sizeof(struct efi_device_path),
- (void **)&dp2);
- if (ret != EFI_SUCCESS)
- goto out_of_memory;
- ret = boottime->allocate_pool(EFI_LOADER_DATA, 3 *
- sizeof(struct efi_device_path_vendor) +
- sizeof(struct efi_device_path),
- (void **)&dp3);
- if (ret != EFI_SUCCESS)
- goto out_of_memory;
- vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
- vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
- vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
- boottime->copy_mem(&vendor_node.guid, &guid_vendor1,
- sizeof(efi_guid_t));
- boottime->copy_mem(dp1, &vendor_node,
- sizeof(struct efi_device_path_vendor));
- boottime->copy_mem(dp2, &vendor_node,
- sizeof(struct efi_device_path_vendor));
- boottime->copy_mem(dp3, &vendor_node,
- sizeof(struct efi_device_path_vendor));
- boottime->copy_mem(&vendor_node.guid, &guid_vendor2,
- sizeof(efi_guid_t));
- boottime->copy_mem(dp2 + sizeof(struct efi_device_path_vendor),
- &vendor_node, sizeof(struct efi_device_path_vendor));
- boottime->copy_mem(dp3 + sizeof(struct efi_device_path_vendor),
- &vendor_node, sizeof(struct efi_device_path_vendor));
- boottime->copy_mem(&vendor_node.guid, &guid_vendor3,
- sizeof(efi_guid_t));
- boottime->copy_mem(dp3 + 2 * sizeof(struct efi_device_path_vendor),
- &vendor_node, sizeof(struct efi_device_path_vendor));
- end_node.type = DEVICE_PATH_TYPE_END;
- end_node.sub_type = DEVICE_PATH_SUB_TYPE_END;
- end_node.length = sizeof(struct efi_device_path);
- boottime->copy_mem(dp1 + sizeof(struct efi_device_path_vendor),
- &end_node, sizeof(struct efi_device_path));
- boottime->copy_mem(dp2 + 2 * sizeof(struct efi_device_path_vendor),
- &end_node, sizeof(struct efi_device_path));
- boottime->copy_mem(dp3 + 3 * sizeof(struct efi_device_path_vendor),
- &end_node, sizeof(struct efi_device_path));
- ret = boottime->install_protocol_interface(&handle1,
- &guid_device_path,
- EFI_NATIVE_INTERFACE,
- dp1);
- if (ret != EFI_SUCCESS) {
- efi_st_error("InstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->install_protocol_interface(&handle1,
- &guid_protocol,
- EFI_NATIVE_INTERFACE,
- &interface);
- if (ret != EFI_SUCCESS) {
- efi_st_error("InstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->install_protocol_interface(&handle2,
- &guid_device_path,
- EFI_NATIVE_INTERFACE,
- dp2);
- if (ret != EFI_SUCCESS) {
- efi_st_error("InstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->install_protocol_interface(&handle2,
- &guid_protocol,
- EFI_NATIVE_INTERFACE,
- &interface);
- if (ret != EFI_SUCCESS) {
- efi_st_error("InstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->install_protocol_interface(&handle3,
- &guid_device_path,
- EFI_NATIVE_INTERFACE,
- dp3);
- if (ret != EFI_SUCCESS) {
- efi_st_error("InstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- return EFI_ST_SUCCESS;
- out_of_memory:
- efi_st_error("Out of memory\n");
- return EFI_ST_FAILURE;
- }
- /*
- * Tear down unit test.
- *
- */
- static int teardown(void)
- {
- efi_status_t ret;
- ret = boottime->uninstall_protocol_interface(handle1,
- &guid_device_path,
- dp1);
- if (ret != EFI_SUCCESS) {
- efi_st_error("UninstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->uninstall_protocol_interface(handle1,
- &guid_protocol,
- &interface);
- if (ret != EFI_SUCCESS) {
- efi_st_error("UninstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->uninstall_protocol_interface(handle2,
- &guid_device_path,
- dp2);
- if (ret != EFI_SUCCESS) {
- efi_st_error("UninstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->uninstall_protocol_interface(handle2,
- &guid_protocol,
- &interface);
- if (ret != EFI_SUCCESS) {
- efi_st_error("UninstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->uninstall_protocol_interface(handle3,
- &guid_device_path,
- dp3);
- if (ret != EFI_SUCCESS) {
- efi_st_error("UninstallProtocolInterface failed\n");
- return EFI_ST_FAILURE;
- }
- if (dp1) {
- ret = boottime->free_pool(dp1);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- }
- if (dp2) {
- ret = boottime->free_pool(dp2);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- }
- if (dp3) {
- ret = boottime->free_pool(dp3);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- }
- return EFI_ST_SUCCESS;
- }
- /*
- * Execute unit test.
- *
- */
- static int execute(void)
- {
- struct efi_device_path *remaining_dp;
- void *handle;
- /*
- * This device path node ends with the letter 't' of 'u-boot'.
- * The following '.bin' does not belong to the node but is
- * helps to test the correct truncation.
- */
- struct {
- struct efi_device_path dp;
- u16 text[12];
- } __packed dp_node = {
- { DEVICE_PATH_TYPE_MEDIA_DEVICE,
- DEVICE_PATH_SUB_TYPE_FILE_PATH,
- sizeof(struct efi_device_path) + 12},
- L"u-boot.bin",
- };
- u16 *string;
- efi_status_t ret;
- efi_uintn_t i, no_handles;
- efi_handle_t *handles;
- struct efi_device_path *dp;
- /* Display all available device paths */
- ret = boottime->locate_handle_buffer(BY_PROTOCOL,
- &guid_device_path,
- NULL, &no_handles, &handles);
- if (ret != EFI_SUCCESS) {
- efi_st_error("Cannot retrieve device path protocols.\n");
- return EFI_ST_FAILURE;
- }
- efi_st_printf("Installed device path protocols:\n");
- for (i = 0; i < no_handles; ++i) {
- ret = boottime->open_protocol(handles[i], &guid_device_path,
- (void **)&dp, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- efi_st_error("Cannot open device path protocol.\n");
- return EFI_ST_FAILURE;
- }
- string = device_path_to_text->convert_device_path_to_text(
- dp, true, false);
- if (!string) {
- efi_st_error("ConvertDevicePathToText failed\n");
- return EFI_ST_FAILURE;
- }
- efi_st_printf("%ps\n", string);
- ret = boottime->free_pool(string);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- /*
- * CloseProtocol cannot be called without agent handle.
- * There is no need to close the device path protocol.
- */
- }
- ret = boottime->free_pool(handles);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- /* Test ConvertDevicePathToText */
- string = device_path_to_text->convert_device_path_to_text(
- (struct efi_device_path *)dp2, true, false);
- if (!string) {
- efi_st_error("ConvertDevicePathToText failed\n");
- return EFI_ST_FAILURE;
- }
- if (efi_st_strcmp_16_8(
- string,
- "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
- ) {
- efi_st_printf("dp2: %ps\n", string);
- efi_st_error("Incorrect text from ConvertDevicePathToText\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->free_pool(string);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- /* Test ConvertDeviceNodeToText */
- string = device_path_to_text->convert_device_node_to_text(
- (struct efi_device_path *)&dp_node, true, false);
- if (!string) {
- efi_st_error("ConvertDeviceNodeToText failed\n");
- return EFI_ST_FAILURE;
- }
- if (efi_st_strcmp_16_8(string, "u-boot")) {
- efi_st_printf("dp_node: %ps\n", string);
- efi_st_error(
- "Incorrect conversion by ConvertDeviceNodeToText\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->free_pool(string);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- /* Test LocateDevicePath */
- remaining_dp = (struct efi_device_path *)dp3;
- ret = boottime->locate_device_path(&guid_protocol, &remaining_dp,
- &handle);
- if (ret != EFI_SUCCESS) {
- efi_st_error("LocateDevicePath failed\n");
- return EFI_ST_FAILURE;
- }
- if (handle != handle2) {
- efi_st_error("LocateDevicePath returned wrong handle\n");
- return EFI_ST_FAILURE;
- }
- string = device_path_to_text->convert_device_path_to_text(remaining_dp,
- true, false);
- if (!string) {
- efi_st_error("ConvertDevicePathToText failed\n");
- return EFI_ST_FAILURE;
- }
- if (efi_st_strcmp_16_8(string,
- "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
- ) {
- efi_st_printf("remaining device path: %ps\n", string);
- efi_st_error("LocateDevicePath: wrong remaining device path\n");
- return EFI_ST_FAILURE;
- }
- ret = boottime->free_pool(string);
- if (ret != EFI_SUCCESS) {
- efi_st_error("FreePool failed\n");
- return EFI_ST_FAILURE;
- }
- return EFI_ST_SUCCESS;
- }
- EFI_UNIT_TEST(devicepath) = {
- .name = "device path",
- .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
- .setup = setup,
- .execute = execute,
- .teardown = teardown,
- };
|