uboot/lib/efi_selftest/efi_selftest_manageprotocols.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * efi_selftest_manageprotocols
   4 *
   5 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
   6 *
   7 * This unit test checks the following protocol services:
   8 * InstallProtocolInterface, UninstallProtocolInterface,
   9 * InstallMultipleProtocolsInterfaces, UninstallMultipleProtocolsInterfaces,
  10 * HandleProtocol, ProtocolsPerHandle,
  11 * LocateHandle, LocateHandleBuffer.
  12 */
  13
  14#include <efi_selftest.h>
  15
  16/*
  17 * The test currently does not actually call the interface function.
  18 * So this is just a dummy structure.
  19 */
  20struct interface {
  21        void (EFIAPI * inc)(void);
  22};
  23
  24static struct efi_boot_services *boottime;
  25static efi_guid_t guid1 =
  26        EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
  27                 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
  28static efi_guid_t guid2 =
  29        EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
  30                 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
  31static efi_guid_t guid3 =
  32        EFI_GUID(0x06d641a3, 0xf4e7, 0xe0c9,
  33                 0xe7, 0x8d, 0x41, 0x2d, 0x72, 0xa6, 0xb1, 0x24);
  34static efi_handle_t handle1;
  35static efi_handle_t handle2;
  36static struct interface interface1;
  37static struct interface interface2;
  38static struct interface interface3;
  39static struct interface interface4;
  40
  41/*
  42 * Find a handle in an array.
  43 *
  44 * @handle:     handle to find
  45 * @count:      number of entries in the array
  46 * @buffer:     array to search
  47 */
  48efi_status_t find_in_buffer(efi_handle_t handle, size_t count,
  49                            efi_handle_t *buffer)
  50{
  51        size_t i;
  52
  53        for (i = 0; i < count; ++i) {
  54                if (buffer[i] == handle)
  55                        return EFI_SUCCESS;
  56        }
  57        return EFI_NOT_FOUND;
  58}
  59
  60/*
  61 * Setup unit test.
  62 *
  63 * Create two handles and install two out of three protocol interfaces on each
  64 * of them:
  65 *
  66 * handle1
  67 *   guid1 interface1
  68 *   guid3 interface3
  69 * handle2
  70 *   guid1 interface4
  71 *   guid2 interface2
  72 *
  73 * @handle:     handle of the loaded image
  74 * @systable:   system table
  75 */
  76static int setup(const efi_handle_t img_handle,
  77                 const struct efi_system_table *systable)
  78{
  79        efi_status_t ret;
  80        efi_handle_t handle;
  81
  82        boottime = systable->boottime;
  83
  84        ret = boottime->install_protocol_interface(&handle1, &guid3,
  85                                                   EFI_NATIVE_INTERFACE,
  86                                                   &interface3);
  87        if (ret != EFI_SUCCESS) {
  88                efi_st_error("InstallProtocolInterface failed\n");
  89                return EFI_ST_FAILURE;
  90        }
  91        if (!handle1) {
  92                efi_st_error("InstallProtocolInterface failed to create handle\n");
  93                return EFI_ST_FAILURE;
  94        }
  95        handle = handle1;
  96        ret = boottime->install_protocol_interface(&handle1, &guid1,
  97                                                   EFI_NATIVE_INTERFACE,
  98                                                   &interface1);
  99        if (ret != EFI_SUCCESS) {
 100                efi_st_error("InstallProtocolInterface failed\n");
 101                return EFI_ST_FAILURE;
 102        }
 103        if (handle != handle1) {
 104                efi_st_error("InstallProtocolInterface failed to use handle\n");
 105                return EFI_ST_FAILURE;
 106        }
 107        ret = boottime->install_multiple_protocol_interfaces(&handle2,
 108                        &guid1, &interface4, &guid2, &interface2, NULL);
 109        if (ret != EFI_SUCCESS) {
 110                efi_st_error("InstallMultipleProtocolInterfaces failed\n");
 111                return EFI_ST_FAILURE;
 112        }
 113        if (!handle2 || handle1 == handle2) {
 114                efi_st_error("InstallMultipleProtocolInterfaces failed to create handle\n");
 115                return EFI_ST_FAILURE;
 116        }
 117
 118        return EFI_ST_SUCCESS;
 119}
 120
 121/*
 122 * Tear down unit test.
 123 *
 124 */
 125static int teardown(void)
 126{
 127        return EFI_ST_SUCCESS;
 128}
 129
 130/*
 131 * Execute unit test.
 132 *
 133 */
 134static int execute(void)
 135{
 136        struct interface *interface;
 137        efi_status_t ret;
 138        efi_handle_t *buffer;
 139        size_t buffer_size;
 140        efi_uintn_t count = 0;
 141        efi_guid_t **prot_buffer;
 142        efi_uintn_t prot_count;
 143
 144        /*
 145         * Test HandleProtocol
 146         */
 147        ret = boottime->handle_protocol(handle1, &guid3, (void **)&interface);
 148        if (ret != EFI_SUCCESS) {
 149                efi_st_error("HandleProtocol failed to retrieve interface\n");
 150                return EFI_ST_FAILURE;
 151        }
 152        if (interface != &interface3) {
 153                efi_st_error("HandleProtocol returned wrong interface\n");
 154                return EFI_ST_FAILURE;
 155        }
 156        ret = boottime->handle_protocol(handle1, &guid2, (void **)&interface);
 157        if (ret == EFI_SUCCESS) {
 158                efi_st_error("HandleProtocol returned not installed interface\n");
 159                return EFI_ST_FAILURE;
 160        }
 161
 162        /*
 163         * Test LocateHandleBuffer with AllHandles
 164         */
 165        ret = boottime->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
 166                                             &count, &buffer);
 167        if (ret != EFI_SUCCESS) {
 168                efi_st_error("LocateHandleBuffer with AllHandles failed\n");
 169                return EFI_ST_FAILURE;
 170        }
 171        buffer_size = count;
 172        ret = find_in_buffer(handle1, count, buffer);
 173        if (ret != EFI_SUCCESS) {
 174                efi_st_error("LocateHandleBuffer failed to locate new handle\n");
 175                return EFI_ST_FAILURE;
 176        }
 177        ret = find_in_buffer(handle2, count, buffer);
 178        if (ret != EFI_SUCCESS) {
 179                efi_st_error("LocateHandleBuffer failed to locate new handle\n");
 180                return EFI_ST_FAILURE;
 181        }
 182        /* Release buffer */
 183        ret = boottime->free_pool(buffer);
 184        if (ret != EFI_SUCCESS) {
 185                efi_st_error("FreePool failed\n");
 186                return EFI_ST_FAILURE;
 187        }
 188
 189        /*
 190         * Test error handling in UninstallMultipleProtocols
 191         *
 192         * These are the installed protocol interfaces on handle 2:
 193         *
 194         *   guid1 interface4
 195         *   guid2 interface2
 196         *
 197         * Try to uninstall more protocols than there are installed. This
 198         * should return an error EFI_INVALID_PARAMETER. All deleted protocols
 199         * should be reinstalled.
 200         */
 201        ret = boottime->uninstall_multiple_protocol_interfaces(
 202                                                handle2,
 203                                                &guid1, &interface4,
 204                                                &guid2, &interface2,
 205                                                &guid3, &interface3,
 206                                                NULL);
 207        if (ret != EFI_INVALID_PARAMETER) {
 208                printf("%lx", ret);
 209                efi_st_error("UninstallMultipleProtocolInterfaces did not catch error\n");
 210                return EFI_ST_FAILURE;
 211        }
 212
 213        /*
 214         * Test LocateHandleBuffer with ByProtocol
 215         *
 216         * These are the handles with a guid1 protocol interface installed:
 217         *
 218         *      handle1, handle2
 219         */
 220        count = buffer_size;
 221        ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
 222                                             &count, &buffer);
 223        if (ret != EFI_SUCCESS) {
 224                efi_st_error("LocateHandleBuffer failed to locate new handles\n");
 225                return EFI_ST_FAILURE;
 226        }
 227        if (count != 2) {
 228                efi_st_error("UninstallMultipleProtocolInterfaces deleted handle\n");
 229                return EFI_ST_FAILURE;
 230        }
 231        ret = find_in_buffer(handle1, count, buffer);
 232        if (ret != EFI_SUCCESS) {
 233                efi_st_error("LocateHandleBuffer failed to locate new handle\n");
 234                return EFI_ST_FAILURE;
 235        }
 236        ret = find_in_buffer(handle2, count, buffer);
 237        if (ret != EFI_SUCCESS) {
 238                efi_st_error("LocateHandleBuffer failed to locate new handle\n");
 239                return EFI_ST_FAILURE;
 240        }
 241        /* Clear the buffer, we are reusing it it the next step. */
 242        boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
 243
 244        /*
 245         * Test LocateHandle with ByProtocol
 246         */
 247        count = buffer_size * sizeof(efi_handle_t);
 248        ret = boottime->locate_handle(BY_PROTOCOL, &guid1, NULL,
 249                                      &count, buffer);
 250        if (ret != EFI_SUCCESS) {
 251                efi_st_error("LocateHandle with ByProtocol failed\n");
 252                return EFI_ST_FAILURE;
 253        }
 254        if (count / sizeof(efi_handle_t) != 2) {
 255                efi_st_error("LocateHandle failed to locate new handles\n");
 256                return EFI_ST_FAILURE;
 257        }
 258        buffer_size = count;
 259        ret = find_in_buffer(handle1, count, buffer);
 260        if (ret != EFI_SUCCESS) {
 261                efi_st_error("LocateHandle failed to locate new handles\n");
 262                return EFI_ST_FAILURE;
 263        }
 264        ret = find_in_buffer(handle2, count, buffer);
 265        if (ret != EFI_SUCCESS) {
 266                efi_st_error("LocateHandle failed to locate new handles\n");
 267                return EFI_ST_FAILURE;
 268        }
 269        /* Release buffer */
 270        ret = boottime->free_pool(buffer);
 271        if (ret != EFI_SUCCESS) {
 272                efi_st_error("FreePool failed\n");
 273                return EFI_ST_FAILURE;
 274        }
 275
 276        /*
 277         * Test LocateProtocol
 278         */
 279        ret = boottime->locate_protocol(&guid1, NULL, (void **)&interface);
 280        if (ret != EFI_SUCCESS) {
 281                efi_st_error("LocateProtocol failed\n");
 282                return EFI_ST_FAILURE;
 283        }
 284        if (interface != &interface1 && interface != &interface4) {
 285                efi_st_error("LocateProtocol failed to locate protocol\n");
 286                return EFI_ST_FAILURE;
 287        }
 288
 289        /*
 290         * Test UninstallMultipleProtocols
 291         */
 292        ret = boottime->uninstall_multiple_protocol_interfaces(
 293                                                handle2,
 294                                                &guid1, &interface4,
 295                                                &guid2, &interface2,
 296                                                NULL);
 297        if (ret != EFI_SUCCESS) {
 298                efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
 299                return EFI_ST_FAILURE;
 300        }
 301        /*
 302         * Check that the protocols are really uninstalled.
 303         */
 304        count = buffer_size;
 305        ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
 306                                             &count, &buffer);
 307        if (ret != EFI_SUCCESS) {
 308                efi_st_error("LocateHandleBuffer failed\n");
 309                return EFI_ST_FAILURE;
 310        }
 311        if (count != 1) {
 312                efi_st_error("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n");
 313                return EFI_ST_FAILURE;
 314        }
 315        ret = find_in_buffer(handle1, count, buffer);
 316        if (ret != EFI_SUCCESS) {
 317                efi_st_error("Failed to locate new handle\n");
 318                return EFI_ST_FAILURE;
 319        }
 320        boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
 321
 322        /*
 323         * Test ProtocolsPerHandle
 324         */
 325        ret = boottime->protocols_per_handle(handle1,
 326                                             &prot_buffer, &prot_count);
 327        if (ret != EFI_SUCCESS) {
 328                efi_st_error("Failed to get protocols per handle\n");
 329                return EFI_ST_FAILURE;
 330        }
 331        if (prot_count != 2) {
 332                efi_st_error("Failed to get protocols per handle\n");
 333                return EFI_ST_FAILURE;
 334        }
 335        if (memcmp(prot_buffer[0], &guid1, 16) &&
 336            memcmp(prot_buffer[1], &guid1, 16)) {
 337                efi_st_error("Failed to get protocols per handle\n");
 338                return EFI_ST_FAILURE;
 339        }
 340        if (memcmp(prot_buffer[0], &guid3, 16) &&
 341            memcmp(prot_buffer[1], &guid3, 16)) {
 342                efi_st_error("Failed to get protocols per handle\n");
 343                return EFI_ST_FAILURE;
 344        }
 345        /* Release buffer */
 346        ret = boottime->free_pool(prot_buffer);
 347        if (ret != EFI_SUCCESS) {
 348                efi_st_error("FreePool failed\n");
 349                return EFI_ST_FAILURE;
 350        }
 351
 352        /*
 353         * Uninstall remaining protocols
 354         */
 355        ret = boottime->uninstall_protocol_interface(handle1, &guid1,
 356                                                     &interface1);
 357        if (ret != EFI_SUCCESS) {
 358                efi_st_error("UninstallProtocolInterface failed\n");
 359                return EFI_ST_FAILURE;
 360        }
 361        ret = boottime->handle_protocol(handle1, &guid1, (void **)&interface);
 362        if (ret == EFI_SUCCESS) {
 363                efi_st_error("UninstallProtocolInterface failed\n");
 364                return EFI_ST_FAILURE;
 365        }
 366        ret = boottime->uninstall_protocol_interface(handle1, &guid3,
 367                                                     &interface3);
 368        if (ret != EFI_SUCCESS) {
 369                efi_st_error("UninstallProtocolInterface failed\n");
 370                return EFI_ST_FAILURE;
 371        }
 372
 373        return EFI_ST_SUCCESS;
 374}
 375
 376EFI_UNIT_TEST(protserv) = {
 377        .name = "manage protocols",
 378        .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
 379        .setup = setup,
 380        .execute = execute,
 381        .teardown = teardown,
 382};
 383