mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 17:10:11 +00:00
156ccbc3c4
At present we use wide characters for unicode but this is not necessary. Change the code to use the 'u' literal instead. This helps to fix build warnings for sandbox on rpi. Signed-off-by: Simon Glass <sjg@chromium.org> Suggested-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
467 lines
12 KiB
C
467 lines
12 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* efi_selftest_devicepath
|
|
*
|
|
* Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
|
|
*
|
|
* 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 = EFI_DEVICE_PATH_PROTOCOL_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;
|
|
|
|
static struct {
|
|
struct efi_device_path_sd_mmc_path sd1;
|
|
struct efi_device_path sep1;
|
|
struct efi_device_path_sd_mmc_path sd2;
|
|
struct efi_device_path sep2;
|
|
struct efi_device_path_sd_mmc_path sd3;
|
|
struct efi_device_path end;
|
|
} multi_part_dp = {
|
|
{
|
|
{
|
|
DEVICE_PATH_TYPE_MESSAGING_DEVICE,
|
|
DEVICE_PATH_SUB_TYPE_MSG_SD,
|
|
sizeof(struct efi_device_path_sd_mmc_path),
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
DEVICE_PATH_TYPE_END,
|
|
DEVICE_PATH_SUB_TYPE_INSTANCE_END,
|
|
sizeof(struct efi_device_path),
|
|
},
|
|
{
|
|
{
|
|
DEVICE_PATH_TYPE_MESSAGING_DEVICE,
|
|
DEVICE_PATH_SUB_TYPE_MSG_SD,
|
|
sizeof(struct efi_device_path_sd_mmc_path),
|
|
},
|
|
1,
|
|
},
|
|
{
|
|
DEVICE_PATH_TYPE_END,
|
|
DEVICE_PATH_SUB_TYPE_INSTANCE_END,
|
|
sizeof(struct efi_device_path),
|
|
},
|
|
{
|
|
{
|
|
DEVICE_PATH_TYPE_MESSAGING_DEVICE,
|
|
DEVICE_PATH_SUB_TYPE_MSG_SD,
|
|
sizeof(struct efi_device_path_sd_mmc_path),
|
|
},
|
|
2,
|
|
},
|
|
{
|
|
DEVICE_PATH_TYPE_END,
|
|
DEVICE_PATH_SUB_TYPE_END,
|
|
sizeof(struct efi_device_path),
|
|
},
|
|
};
|
|
|
|
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
|
|
* provide 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;
|
|
efi_handle_t 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},
|
|
u"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;
|
|
}
|
|
|
|
string = device_path_to_text->convert_device_path_to_text(
|
|
(struct efi_device_path *)&multi_part_dp, true, false);
|
|
if (efi_st_strcmp_16_8(
|
|
string,
|
|
"/SD(0),/SD(1),/SD(2)")
|
|
) {
|
|
efi_st_printf("multi_part_dp: %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,
|
|
};
|