mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
efi_selftest: test EFI_DEVICE_PATH_UTILITIES_PROTOCOL
Provide unit tests for the EFI_DEVICE_PATH_UTILITIES_PROTOCOL. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
3acef5da40
commit
e83222bfc3
2 changed files with 287 additions and 0 deletions
|
@ -18,6 +18,7 @@ efi_selftest_bitblt.o \
|
|||
efi_selftest_controllers.o \
|
||||
efi_selftest_console.o \
|
||||
efi_selftest_devicepath.o \
|
||||
efi_selftest_devicepath_util.o \
|
||||
efi_selftest_events.o \
|
||||
efi_selftest_event_groups.o \
|
||||
efi_selftest_exitbootservices.o \
|
||||
|
|
286
lib/efi_selftest/efi_selftest_devicepath_util.c
Normal file
286
lib/efi_selftest/efi_selftest_devicepath_util.c
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* efi_selftest_devicepath_util
|
||||
*
|
||||
* Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* This unit test checks the device path utilities protocol.
|
||||
*/
|
||||
|
||||
#include <efi_selftest.h>
|
||||
|
||||
static struct efi_boot_services *boottime;
|
||||
|
||||
static efi_guid_t guid_device_path_utilities_protocol =
|
||||
EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
|
||||
|
||||
struct efi_device_path_utilities_protocol *dpu;
|
||||
|
||||
/*
|
||||
* Setup unit test.
|
||||
*
|
||||
* Locate the device path utilities protocol.
|
||||
*
|
||||
* @handle: handle of the loaded image
|
||||
* @systable: system table
|
||||
*/
|
||||
static int setup(const efi_handle_t img_handle,
|
||||
const struct efi_system_table *systable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
boottime = systable->boottime;
|
||||
|
||||
ret = boottime->locate_protocol(&guid_device_path_utilities_protocol,
|
||||
NULL, (void **)&dpu);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
dpu = NULL;
|
||||
efi_st_error(
|
||||
"Device path to text protocol is not available.\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a device path consisting of a single media device node followed by an
|
||||
* end node.
|
||||
*
|
||||
* @length: length of the media device node
|
||||
* @dp: device path
|
||||
* @return: status code
|
||||
*/
|
||||
static int create_single_node_device_path(unsigned int length,
|
||||
struct efi_device_path **dp)
|
||||
{
|
||||
struct efi_device_path *node;
|
||||
efi_uintn_t len;
|
||||
int ret;
|
||||
|
||||
node = dpu->create_device_node(DEVICE_PATH_TYPE_MEDIA_DEVICE,
|
||||
DEVICE_PATH_SUB_TYPE_FILE_PATH, length);
|
||||
if (!node) {
|
||||
efi_st_error("CreateDeviceNode failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
*dp = dpu->append_device_node(NULL, node);
|
||||
if (!*dp) {
|
||||
efi_st_error("AppendDeviceNode failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(node);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = dpu->get_device_path_size(*dp);
|
||||
if (len != length + 4) {
|
||||
efi_st_error("Wrong device path length %u, expected %u\n",
|
||||
(unsigned int)len, length);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute unit test.
|
||||
*
|
||||
* In the test device paths are created, copied, and concatenated. The device
|
||||
* path length is used as a measure of success.
|
||||
*/
|
||||
static int execute(void)
|
||||
{
|
||||
struct efi_device_path *dp1;
|
||||
struct efi_device_path *dp2;
|
||||
struct efi_device_path *dp3;
|
||||
|
||||
efi_uintn_t len;
|
||||
int ret;
|
||||
|
||||
/* IsDevicePathMultiInstance(NULL) */
|
||||
if (dpu->is_device_path_multi_instance(NULL)) {
|
||||
efi_st_error("IsDevicePathMultiInstance(NULL) returned true\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* GetDevicePathSize(NULL) */
|
||||
len = dpu->get_device_path_size(NULL);
|
||||
if (len) {
|
||||
efi_st_error("Wrong device path length %u, expected 0\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* DuplicateDevicePath(NULL) */
|
||||
dp1 = dpu->duplicate_device_path(NULL);
|
||||
if (dp1) {
|
||||
efi_st_error("DuplicateDevicePath(NULL) failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* AppendDevicePath(NULL, NULL) */
|
||||
dp1 = dpu->append_device_path(NULL, NULL);
|
||||
if (!dp1) {
|
||||
efi_st_error("AppendDevicePath(NULL, NULL) failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = dpu->get_device_path_size(dp1);
|
||||
if (len != 4) {
|
||||
efi_st_error("Wrong device path length %u, expected 4\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp1);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* CreateDeviceNode */
|
||||
ret = create_single_node_device_path(21, &dp1);
|
||||
if (ret != EFI_ST_SUCCESS)
|
||||
return ret;
|
||||
ret = create_single_node_device_path(17, &dp2);
|
||||
if (ret != EFI_ST_SUCCESS)
|
||||
return ret;
|
||||
/* AppendDevicePath */
|
||||
dp3 = dpu->append_device_path(dp1, dp2);
|
||||
if (!dp3) {
|
||||
efi_st_error("AppendDevicePath failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (dp3 == dp1 || dp3 == dp2) {
|
||||
efi_st_error("AppendDevicePath reused buffer\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = dpu->get_device_path_size(dp3);
|
||||
/* 21 + 17 + 4 */
|
||||
if (len != 42) {
|
||||
efi_st_error("Wrong device path length %u, expected 42\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp2);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* AppendDeviceNode */
|
||||
dp2 = dpu->append_device_node(dp1, dp3);
|
||||
if (!dp2) {
|
||||
efi_st_error("AppendDevicePath failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = dpu->get_device_path_size(dp2);
|
||||
/* 21 + 21 + 4 */
|
||||
if (len != 46) {
|
||||
printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
|
||||
efi_st_error("Wrong device path length %u, expected 46\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp1);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* IsDevicePathMultiInstance */
|
||||
if (dpu->is_device_path_multi_instance(dp2)) {
|
||||
printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
|
||||
efi_st_error("IsDevicePathMultiInstance returned true\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* AppendDevicePathInstance */
|
||||
dp1 = dpu->append_device_path_instance(dp2, dp3);
|
||||
if (!dp1) {
|
||||
efi_st_error("AppendDevicePathInstance failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = dpu->get_device_path_size(dp1);
|
||||
/* 46 + 42 */
|
||||
if (len != 88) {
|
||||
efi_st_error("Wrong device path length %u, expected 88\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* IsDevicePathMultiInstance */
|
||||
if (!dpu->is_device_path_multi_instance(dp1)) {
|
||||
efi_st_error("IsDevicePathMultiInstance returned false\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp2);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp3);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* GetNextDevicePathInstance */
|
||||
dp3 = dp1;
|
||||
dp2 = dpu->get_next_device_path_instance(&dp1, &len);
|
||||
if (!dp2) {
|
||||
efi_st_error("GetNextDevicePathInstance failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (!dp1) {
|
||||
efi_st_error("GetNextDevicePathInstance no 2nd instance\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (len != 46) {
|
||||
efi_st_error("Wrong device path length %u, expected 46\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = dpu->get_device_path_size(dp1);
|
||||
if (len != 42) {
|
||||
efi_st_error("Wrong device path length %u, expected 42\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp2);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
dp2 = dpu->get_next_device_path_instance(&dp1, &len);
|
||||
if (!dp2) {
|
||||
efi_st_error("GetNextDevicePathInstance failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (len != 42) {
|
||||
efi_st_error("Wrong device path length %u, expected 46\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (dp1) {
|
||||
efi_st_error("GetNextDevicePathInstance did not signal end\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp2);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
ret = boottime->free_pool(dp2);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(dp3);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_UNIT_TEST(dputil) = {
|
||||
.name = "device path utilities protocol",
|
||||
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
|
||||
.setup = setup,
|
||||
.execute = execute,
|
||||
};
|
Loading…
Reference in a new issue