mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-08-20 17:08:52 +09:00
![Tom Rini](/assets/img/avatar_default.png)
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
403 lines
11 KiB
C
403 lines
11 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 = 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
|
|
* 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;
|
|
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,
|
|
};
|