uboot/lib/efi_selftest/efi_selftest_devicepath.c
<<
>>
Prefs
   1/*
   2 * efi_selftest_devicepath
   3 *
   4 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 *
   8 * This unit test checks the following protocol services:
   9 * DevicePathToText
  10 */
  11
  12#include <efi_selftest.h>
  13
  14static struct efi_boot_services *boottime;
  15
  16static efi_handle_t handle1;
  17static efi_handle_t handle2;
  18static efi_handle_t handle3;
  19
  20struct interface {
  21        void (EFIAPI * inc)(void);
  22} interface;
  23
  24static efi_guid_t guid_device_path = DEVICE_PATH_GUID;
  25
  26static efi_guid_t guid_device_path_to_text_protocol =
  27        EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
  28
  29static efi_guid_t guid_protocol =
  30        EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
  31                 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0x7d);
  32
  33static efi_guid_t guid_vendor1 =
  34        EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
  35                 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xb1);
  36
  37static efi_guid_t guid_vendor2 =
  38        EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
  39                 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xa2);
  40
  41static efi_guid_t guid_vendor3 =
  42        EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
  43                 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xc3);
  44
  45static u8 *dp1;
  46static u8 *dp2;
  47static u8 *dp3;
  48
  49struct efi_device_path_to_text_protocol *device_path_to_text;
  50
  51/*
  52 * Setup unit test.
  53 *
  54 * Create three handles. Install a new protocol on two of them and
  55 * provice device paths.
  56 *
  57 * handle1
  58 *   guid interface
  59 * handle2
  60 *   guid interface
  61 * handle3
  62 *
  63 * @handle:     handle of the loaded image
  64 * @systable:   system table
  65 */
  66static int setup(const efi_handle_t img_handle,
  67                 const struct efi_system_table *systable)
  68{
  69        struct efi_device_path_vendor vendor_node;
  70        struct efi_device_path end_node;
  71        efi_status_t ret;
  72
  73        boottime = systable->boottime;
  74
  75        ret = boottime->locate_protocol(&guid_device_path_to_text_protocol,
  76                                        NULL, (void **)&device_path_to_text);
  77        if (ret != EFI_SUCCESS) {
  78                device_path_to_text = NULL;
  79                efi_st_error(
  80                        "Device path to text protocol is not available.\n");
  81                return EFI_ST_FAILURE;
  82        }
  83
  84        ret = boottime->allocate_pool(EFI_LOADER_DATA,
  85                                      sizeof(struct efi_device_path_vendor) +
  86                                      sizeof(struct efi_device_path),
  87                                      (void **)&dp1);
  88        if (ret != EFI_SUCCESS)
  89                goto out_of_memory;
  90
  91        ret = boottime->allocate_pool(EFI_LOADER_DATA, 2 *
  92                                      sizeof(struct efi_device_path_vendor) +
  93                                      sizeof(struct efi_device_path),
  94                                      (void **)&dp2);
  95        if (ret != EFI_SUCCESS)
  96                goto out_of_memory;
  97
  98        ret = boottime->allocate_pool(EFI_LOADER_DATA, 3 *
  99                                      sizeof(struct efi_device_path_vendor) +
 100                                      sizeof(struct efi_device_path),
 101                                      (void **)&dp3);
 102        if (ret != EFI_SUCCESS)
 103                goto out_of_memory;
 104
 105        vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
 106        vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
 107        vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
 108
 109        boottime->copy_mem(&vendor_node.guid, &guid_vendor1,
 110                           sizeof(efi_guid_t));
 111        boottime->copy_mem(dp1, &vendor_node,
 112                           sizeof(struct efi_device_path_vendor));
 113        boottime->copy_mem(dp2, &vendor_node,
 114                           sizeof(struct efi_device_path_vendor));
 115        boottime->copy_mem(dp3, &vendor_node,
 116                           sizeof(struct efi_device_path_vendor));
 117
 118        boottime->copy_mem(&vendor_node.guid, &guid_vendor2,
 119                           sizeof(efi_guid_t));
 120        boottime->copy_mem(dp2 + sizeof(struct efi_device_path_vendor),
 121                           &vendor_node, sizeof(struct efi_device_path_vendor));
 122        boottime->copy_mem(dp3 + sizeof(struct efi_device_path_vendor),
 123                           &vendor_node, sizeof(struct efi_device_path_vendor));
 124
 125        boottime->copy_mem(&vendor_node.guid, &guid_vendor3,
 126                           sizeof(efi_guid_t));
 127        boottime->copy_mem(dp3 + 2 * sizeof(struct efi_device_path_vendor),
 128                           &vendor_node, sizeof(struct efi_device_path_vendor));
 129
 130        end_node.type = DEVICE_PATH_TYPE_END;
 131        end_node.sub_type = DEVICE_PATH_SUB_TYPE_END;
 132        end_node.length = sizeof(struct efi_device_path);
 133        boottime->copy_mem(dp1 + sizeof(struct efi_device_path_vendor),
 134                           &end_node, sizeof(struct efi_device_path));
 135        boottime->copy_mem(dp2 + 2 * sizeof(struct efi_device_path_vendor),
 136                           &end_node, sizeof(struct efi_device_path));
 137        boottime->copy_mem(dp3 + 3 * sizeof(struct efi_device_path_vendor),
 138                           &end_node, sizeof(struct efi_device_path));
 139
 140        ret = boottime->install_protocol_interface(&handle1,
 141                                                   &guid_device_path,
 142                                                   EFI_NATIVE_INTERFACE,
 143                                                   dp1);
 144        if (ret != EFI_SUCCESS) {
 145                efi_st_error("InstallProtocolInterface failed\n");
 146                return EFI_ST_FAILURE;
 147        }
 148        ret = boottime->install_protocol_interface(&handle1,
 149                                                   &guid_protocol,
 150                                                   EFI_NATIVE_INTERFACE,
 151                                                   &interface);
 152        if (ret != EFI_SUCCESS) {
 153                efi_st_error("InstallProtocolInterface failed\n");
 154                return EFI_ST_FAILURE;
 155        }
 156        ret = boottime->install_protocol_interface(&handle2,
 157                                                   &guid_device_path,
 158                                                   EFI_NATIVE_INTERFACE,
 159                                                   dp2);
 160        if (ret != EFI_SUCCESS) {
 161                efi_st_error("InstallProtocolInterface failed\n");
 162                return EFI_ST_FAILURE;
 163        }
 164        ret = boottime->install_protocol_interface(&handle2,
 165                                                   &guid_protocol,
 166                                                   EFI_NATIVE_INTERFACE,
 167                                                   &interface);
 168        if (ret != EFI_SUCCESS) {
 169                efi_st_error("InstallProtocolInterface failed\n");
 170                return EFI_ST_FAILURE;
 171        }
 172        ret = boottime->install_protocol_interface(&handle3,
 173                                                   &guid_device_path,
 174                                                   EFI_NATIVE_INTERFACE,
 175                                                   dp3);
 176        if (ret != EFI_SUCCESS) {
 177                efi_st_error("InstallProtocolInterface failed\n");
 178                return EFI_ST_FAILURE;
 179        }
 180        return EFI_ST_SUCCESS;
 181
 182out_of_memory:
 183        efi_st_error("Out of memory\n");
 184        return EFI_ST_FAILURE;
 185}
 186
 187/*
 188 * Tear down unit test.
 189 *
 190 */
 191static int teardown(void)
 192{
 193        efi_status_t ret;
 194
 195        ret = boottime->uninstall_protocol_interface(&handle1,
 196                                                     &guid_device_path,
 197                                                     dp1);
 198        if (ret != EFI_SUCCESS)
 199                efi_st_todo("UninstallProtocolInterface failed\n");
 200        ret = boottime->uninstall_protocol_interface(&handle1,
 201                                                     &guid_protocol,
 202                                                     &interface);
 203        if (ret != EFI_SUCCESS)
 204                efi_st_todo("UninstallProtocolInterface failed\n");
 205        ret = boottime->uninstall_protocol_interface(&handle2,
 206                                                     &guid_device_path,
 207                                                     dp2);
 208        if (ret != EFI_SUCCESS)
 209                efi_st_todo("UninstallProtocolInterface failed\n");
 210        ret = boottime->uninstall_protocol_interface(&handle2,
 211                                                     &guid_protocol,
 212                                                     &interface);
 213        if (ret != EFI_SUCCESS)
 214                efi_st_todo("UninstallProtocolInterface failed\n");
 215        ret = boottime->uninstall_protocol_interface(&handle3,
 216                                                     &guid_device_path,
 217                                                     dp3);
 218        if (ret != EFI_SUCCESS)
 219                efi_st_todo("UninstallProtocolInterface failed\n");
 220        if (dp1) {
 221                ret = boottime->free_pool(dp1);
 222                if (ret != EFI_SUCCESS) {
 223                        efi_st_error("FreePool failed\n");
 224                        return EFI_ST_FAILURE;
 225                }
 226        }
 227        if (dp2) {
 228                ret = boottime->free_pool(dp2);
 229                if (ret != EFI_SUCCESS) {
 230                        efi_st_error("FreePool failed\n");
 231                        return EFI_ST_FAILURE;
 232                }
 233        }
 234        if (dp3) {
 235                ret = boottime->free_pool(dp3);
 236                if (ret != EFI_SUCCESS) {
 237                        efi_st_error("FreePool failed\n");
 238                        return EFI_ST_FAILURE;
 239                }
 240        }
 241        return EFI_ST_SUCCESS;
 242}
 243
 244/*
 245 * Execute unit test.
 246 *
 247 */
 248static int execute(void)
 249{
 250        struct efi_device_path *remaining_dp;
 251        void *handle;
 252        /*
 253         * This device path node ends with the letter 't' of 'u-boot'.
 254         * The following '.bin' does not belong to the node but is
 255         * helps to test the correct truncation.
 256         */
 257        struct {
 258                struct efi_device_path dp;
 259                u16 text[12];
 260        } __packed dp_node = {
 261                        { DEVICE_PATH_TYPE_MEDIA_DEVICE,
 262                          DEVICE_PATH_SUB_TYPE_FILE_PATH,
 263                          sizeof(struct efi_device_path) + 12},
 264                        L"u-boot.bin",
 265                };
 266        u16 *string;
 267        efi_status_t ret;
 268        efi_uintn_t i, no_handles;
 269        efi_handle_t *handles;
 270        struct efi_device_path *dp;
 271
 272        /* Display all available device paths */
 273        ret = boottime->locate_handle_buffer(BY_PROTOCOL,
 274                                             &guid_device_path,
 275                                             NULL, &no_handles, &handles);
 276        if (ret != EFI_SUCCESS) {
 277                efi_st_error("Cannot retrieve device path protocols.\n");
 278                return EFI_ST_FAILURE;
 279        }
 280
 281        efi_st_printf("Installed device path protocols:\n");
 282        for (i = 0; i < no_handles; ++i) {
 283                ret = boottime->open_protocol(handles[i], &guid_device_path,
 284                                              (void **)&dp, NULL, NULL,
 285                                              EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 286                if (ret != EFI_SUCCESS) {
 287                        efi_st_error("Cannot open device path protocol.\n");
 288                        return EFI_ST_FAILURE;
 289                }
 290                string = device_path_to_text->convert_device_path_to_text(
 291                                        dp, true, false);
 292                if (!string) {
 293                        efi_st_error("ConvertDevicePathToText failed\n");
 294                        return EFI_ST_FAILURE;
 295                }
 296                efi_st_printf("%ps\n", string);
 297                ret = boottime->free_pool(string);
 298                if (ret != EFI_SUCCESS) {
 299                        efi_st_error("FreePool failed\n");
 300                        return EFI_ST_FAILURE;
 301                }
 302                ret = boottime->close_protocol(handles[i], &guid_device_path,
 303                                               NULL, NULL);
 304                if (ret != EFI_SUCCESS)
 305                        efi_st_todo("Cannot close device path protocol.\n");
 306        }
 307        ret = boottime->free_pool(handles);
 308        if (ret != EFI_SUCCESS) {
 309                efi_st_error("FreePool failed\n");
 310                return EFI_ST_FAILURE;
 311        }
 312        efi_st_printf("\n");
 313
 314        /* Test ConvertDevicePathToText */
 315        string = device_path_to_text->convert_device_path_to_text(
 316                        (struct efi_device_path *)dp2, true, false);
 317        if (!string) {
 318                efi_st_error("ConvertDevicePathToText failed\n");
 319                return EFI_ST_FAILURE;
 320        }
 321        efi_st_printf("dp2: %ps\n", string);
 322        if (efi_st_strcmp_16_8(
 323                string,
 324                "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
 325            ) {
 326                efi_st_error("Incorrect text from ConvertDevicePathToText\n");
 327                return EFI_ST_FAILURE;
 328        }
 329
 330        ret = boottime->free_pool(string);
 331        if (ret != EFI_SUCCESS) {
 332                efi_st_error("FreePool failed\n");
 333                return EFI_ST_FAILURE;
 334        }
 335
 336        /* Test ConvertDeviceNodeToText */
 337        string = device_path_to_text->convert_device_node_to_text(
 338                        (struct efi_device_path *)&dp_node, true, false);
 339        if (!string) {
 340                efi_st_error("ConvertDeviceNodeToText failed\n");
 341                return EFI_ST_FAILURE;
 342        }
 343        efi_st_printf("dp_node: %ps\n", string);
 344        ret = boottime->free_pool(string);
 345        if (ret != EFI_SUCCESS) {
 346                efi_st_error("FreePool failed\n");
 347                return EFI_ST_FAILURE;
 348        }
 349        if (efi_st_strcmp_16_8(string, "u-boot")) {
 350                efi_st_error(
 351                        "Incorrect conversion by ConvertDeviceNodeToText\n");
 352                return EFI_ST_FAILURE;
 353        }
 354
 355        /* Test LocateDevicePath */
 356        remaining_dp = (struct efi_device_path *)dp3;
 357        ret = boottime->locate_device_path(&guid_protocol, &remaining_dp,
 358                                           &handle);
 359        if (ret != EFI_SUCCESS) {
 360                efi_st_error("LocateDevicePath failed\n");
 361                return EFI_ST_FAILURE;
 362        }
 363        if (handle != handle2) {
 364                efi_st_error("LocateDevicePath returned wrong handle\n");
 365                return EFI_ST_FAILURE;
 366        }
 367        string = device_path_to_text->convert_device_path_to_text(remaining_dp,
 368                                                                  true, false);
 369        if (!string) {
 370                efi_st_error("ConvertDevicePathToText failed\n");
 371                return EFI_ST_FAILURE;
 372        }
 373        efi_st_printf("remaining device path: %ps\n", string);
 374        if (efi_st_strcmp_16_8(string,
 375                               "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
 376            ) {
 377                efi_st_error("LocateDevicePath: wrong remaining device path\n");
 378                return EFI_ST_FAILURE;
 379        }
 380
 381        return EFI_ST_SUCCESS;
 382}
 383
 384EFI_UNIT_TEST(devicepath) = {
 385        .name = "device path",
 386        .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
 387        .setup = setup,
 388        .execute = execute,
 389        .teardown = teardown,
 390};
 391