u-boot/lib/efi_selftest/efi_selftest_devicepath.c
Heinrich Schuchardt 8d7cf39090 efi_selftest: remove todo in device path test
The installation of UninstallProtocol is functional now.
So we do not expect errors when calling it.

Call UninstallProtocol with correct level of indirection
for parameter handle.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2018-01-22 23:09:13 +01:00

400 lines
11 KiB
C

/*
* 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;
}
efi_st_printf("\n");
/* 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;
}
efi_st_printf("dp2: %ps\n", string);
if (efi_st_strcmp_16_8(
string,
"/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
) {
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;
}
efi_st_printf("dp_node: %ps\n", string);
ret = boottime->free_pool(string);
if (ret != EFI_SUCCESS) {
efi_st_error("FreePool failed\n");
return EFI_ST_FAILURE;
}
if (efi_st_strcmp_16_8(string, "u-boot")) {
efi_st_error(
"Incorrect conversion by ConvertDeviceNodeToText\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;
}
efi_st_printf("remaining device path: %ps\n", string);
if (efi_st_strcmp_16_8(string,
"/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
) {
efi_st_error("LocateDevicePath: wrong remaining device path\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,
};