123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * efi_selftest_devicepath_util
- *
- * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
- *
- * 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,
- };
|