uboot/lib/efi_selftest/efi_selftest_register_notify.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * efi_selftest_register_notify
   4 *
   5 * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
   6 *
   7 * This unit test checks the following protocol services:
   8 * InstallProtocolInterface, UninstallProtocolInterface,
   9 * RegisterProtocolNotify, CreateEvent, CloseEvent.
  10 */
  11
  12#include <efi_selftest.h>
  13
  14/*
  15 * The test currently does not actually call the interface function.
  16 * So this is just a dummy structure.
  17 */
  18struct interface {
  19        void (EFIAPI * inc)(void);
  20};
  21
  22struct context {
  23        void *registration_key;
  24        efi_uintn_t notify_count;
  25        efi_uintn_t handle_count;
  26        efi_handle_t *handles;
  27};
  28
  29static struct efi_boot_services *boottime;
  30static efi_guid_t guid1 =
  31        EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
  32                 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
  33static efi_guid_t guid2 =
  34        EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
  35                 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
  36static struct context context;
  37static struct efi_event *event;
  38
  39/*
  40 * Notification function, increments the notification count if parameter
  41 * context is provided.
  42 *
  43 * @event       notified event
  44 * @context     pointer to the notification count
  45 */
  46static void EFIAPI notify(struct efi_event *event, void *context)
  47{
  48        struct context *cp = context;
  49        efi_status_t ret;
  50        efi_uintn_t handle_count;
  51        efi_handle_t *handles;
  52
  53        cp->notify_count++;
  54
  55        for (;;) {
  56                ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
  57                                                     cp->registration_key,
  58                                                     &handle_count, &handles);
  59                if (ret != EFI_SUCCESS)
  60                        break;
  61                cp->handle_count += handle_count;
  62                cp->handles = handles;
  63        }
  64}
  65
  66/*
  67 * Setup unit test.
  68 *
  69 * @handle:     handle of the loaded image
  70 * @systable:   system table
  71 */
  72static int setup(const efi_handle_t img_handle,
  73                 const struct efi_system_table *systable)
  74{
  75        efi_status_t ret;
  76
  77        boottime = systable->boottime;
  78
  79        ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
  80                                     TPL_CALLBACK, notify, &context,
  81                                     &event);
  82        if (ret != EFI_SUCCESS) {
  83                efi_st_error("could not create event\n");
  84                return EFI_ST_FAILURE;
  85        }
  86
  87        ret = boottime->register_protocol_notify(&guid1, event,
  88                                                 &context.registration_key);
  89        if (ret != EFI_SUCCESS) {
  90                efi_st_error("could not register event\n");
  91                return EFI_ST_FAILURE;
  92        }
  93
  94        return EFI_ST_SUCCESS;
  95}
  96
  97/*
  98 * Tear down unit test.
  99 *
 100 */
 101static int teardown(void)
 102{
 103        efi_status_t ret;
 104
 105        if (event) {
 106                ret = boottime->close_event(event);
 107                event = NULL;
 108                if (ret != EFI_SUCCESS) {
 109                        efi_st_error("could not close event\n");
 110                        return EFI_ST_FAILURE;
 111                }
 112        }
 113
 114        return EFI_ST_SUCCESS;
 115}
 116
 117/*
 118 * Execute unit test.
 119 *
 120 */
 121static int execute(void)
 122{
 123        efi_status_t ret;
 124        efi_handle_t handle1 = NULL, handle2 = NULL;
 125        struct interface interface1, interface2;
 126
 127        ret = boottime->install_protocol_interface(&handle1, &guid1,
 128                                                   EFI_NATIVE_INTERFACE,
 129                                                   &interface1);
 130        if (ret != EFI_SUCCESS) {
 131                efi_st_error("could not install interface\n");
 132                return EFI_ST_FAILURE;
 133        }
 134        if (!context.notify_count) {
 135                efi_st_error("install was not notified\n");
 136                return EFI_ST_FAILURE;
 137        }
 138        if (context.notify_count > 1) {
 139                efi_st_error("install was notified too often\n");
 140                return EFI_ST_FAILURE;
 141        }
 142        if (context.handle_count != 1) {
 143                efi_st_error("LocateHandle failed\n");
 144                return EFI_ST_FAILURE;
 145        }
 146        ret = boottime->free_pool(context.handles);
 147        if (ret != EFI_SUCCESS) {
 148                efi_st_error("FreePool failed\n");
 149                return EFI_ST_FAILURE;
 150        }
 151        context.notify_count = 0;
 152        ret = boottime->install_protocol_interface(&handle1, &guid2,
 153                                                   EFI_NATIVE_INTERFACE,
 154                                                   &interface1);
 155        if (ret != EFI_SUCCESS) {
 156                efi_st_error("could not install interface\n");
 157                return EFI_ST_FAILURE;
 158        }
 159        if (context.notify_count) {
 160                efi_st_error("wrong protocol was notified\n");
 161                return EFI_ST_FAILURE;
 162        }
 163        context.notify_count = 0;
 164        ret = boottime->reinstall_protocol_interface(handle1, &guid1,
 165                                                     &interface1, &interface2);
 166        if (ret != EFI_SUCCESS) {
 167                efi_st_error("could not reinstall interface\n");
 168                return EFI_ST_FAILURE;
 169        }
 170        if (!context.notify_count) {
 171                efi_st_error("reinstall was not notified\n");
 172                return EFI_ST_FAILURE;
 173        }
 174        if (context.notify_count > 1) {
 175                efi_st_error("reinstall was notified too often\n");
 176                return EFI_ST_FAILURE;
 177        }
 178        if (context.handle_count != 2) {
 179                efi_st_error("LocateHandle failed\n");
 180                return EFI_ST_FAILURE;
 181        }
 182        ret = boottime->free_pool(context.handles);
 183        if (ret != EFI_SUCCESS) {
 184                efi_st_error("FreePool failed\n");
 185                return EFI_ST_FAILURE;
 186        }
 187        context.notify_count = 0;
 188        ret = boottime->install_protocol_interface(&handle2, &guid1,
 189                                                   EFI_NATIVE_INTERFACE,
 190                                                   &interface1);
 191        if (ret != EFI_SUCCESS) {
 192                efi_st_error("could not install interface\n");
 193                return EFI_ST_FAILURE;
 194        }
 195        if (!context.notify_count) {
 196                efi_st_error("install was not notified\n");
 197                return EFI_ST_FAILURE;
 198        }
 199        if (context.notify_count > 1) {
 200                efi_st_error("install was notified too often\n");
 201                return EFI_ST_FAILURE;
 202        }
 203        if (context.handle_count != 3) {
 204                efi_st_error("LocateHandle failed\n");
 205                return EFI_ST_FAILURE;
 206        }
 207        ret = boottime->free_pool(context.handles);
 208        if (ret != EFI_SUCCESS) {
 209                efi_st_error("FreePool failed\n");
 210                return EFI_ST_FAILURE;
 211        }
 212
 213        ret = boottime->uninstall_multiple_protocol_interfaces
 214                        (handle1, &guid1, &interface2,
 215                         &guid2, &interface1, NULL);
 216        if (ret != EFI_SUCCESS) {
 217                efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
 218                return EFI_ST_FAILURE;
 219        }
 220        ret = boottime->uninstall_multiple_protocol_interfaces
 221                        (handle2, &guid1, &interface1, NULL);
 222        if (ret != EFI_SUCCESS) {
 223                efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
 224                return EFI_ST_FAILURE;
 225        }
 226
 227        return EFI_ST_SUCCESS;
 228}
 229
 230EFI_UNIT_TEST(regprotnot) = {
 231        .name = "register protocol notify",
 232        .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
 233        .setup = setup,
 234        .execute = execute,
 235        .teardown = teardown,
 236};
 237