uboot/lib/efi_selftest/efi_selftest_event_groups.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * efi_selftest_event_groups
   4 *
   5 * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
   6 *
   7 * This test checks the notification of group events and the
   8 * following services:
   9 * CreateEventEx, CloseEvent, SignalEvent, CheckEvent.
  10 */
  11
  12#include <efi_selftest.h>
  13
  14#define GROUP_SIZE 16
  15
  16static struct efi_boot_services *boottime;
  17static efi_guid_t event_group =
  18        EFI_GUID(0x2335905b, 0xc3b9, 0x4221, 0xa3, 0x71,
  19                 0x0e, 0x5b, 0x45, 0xc0, 0x56, 0x91);
  20
  21/*
  22 * Notification function, increments the notification count if parameter
  23 * context is provided.
  24 *
  25 * @event       notified event
  26 * @context     pointer to the notification count
  27 */
  28static void EFIAPI notify(struct efi_event *event, void *context)
  29{
  30        unsigned int *count = context;
  31
  32        if (count)
  33                ++*count;
  34}
  35
  36/*
  37 * Setup unit test.
  38 *
  39 * @handle:     handle of the loaded image
  40 * @systable:   system table
  41 * @return:     EFI_ST_SUCCESS for success
  42 */
  43static int setup(const efi_handle_t handle,
  44                 const struct efi_system_table *systable)
  45{
  46        boottime = systable->boottime;
  47
  48        return EFI_ST_SUCCESS;
  49}
  50
  51/*
  52 * Execute unit test.
  53 *
  54 * Create multiple events in an event group. Signal each event once and check
  55 * that all events are notified once in each round.
  56 *
  57 * @return:     EFI_ST_SUCCESS for success
  58 */
  59static int execute(void)
  60{
  61        unsigned int counter[GROUP_SIZE] = {0};
  62        struct efi_event *events[GROUP_SIZE];
  63        size_t i, j;
  64        efi_status_t ret;
  65
  66        for (i = 0; i < GROUP_SIZE; ++i) {
  67                ret = boottime->create_event_ex(0, TPL_NOTIFY,
  68                                                notify, (void *)&counter[i],
  69                                                &event_group, &events[i]);
  70                if (ret != EFI_SUCCESS) {
  71                        efi_st_error("Failed to create event\n");
  72                        return EFI_ST_FAILURE;
  73                }
  74        }
  75
  76        for (i = 0; i < GROUP_SIZE; ++i) {
  77                ret = boottime->signal_event(events[i]);
  78                if (ret != EFI_SUCCESS) {
  79                        efi_st_error("Failed to signal event\n");
  80                        return EFI_ST_FAILURE;
  81                }
  82                for (j = 0; j < GROUP_SIZE; ++j) {
  83                        if (counter[j] != i) {
  84                                efi_st_printf("i %u, j %u, count %u\n",
  85                                              (unsigned int)i, (unsigned int)j,
  86                                              (unsigned int)counter[j]);
  87                                efi_st_error(
  88                                        "Notification function was called\n");
  89                                return EFI_ST_FAILURE;
  90                        }
  91                        /* Clear signaled state */
  92                        ret = boottime->check_event(events[j]);
  93                        if (ret != EFI_SUCCESS) {
  94                                efi_st_error("Event was not signaled\n");
  95                                return EFI_ST_FAILURE;
  96                        }
  97                        if (counter[j] != i) {
  98                                efi_st_printf("i %u, j %u, count %u\n",
  99                                              (unsigned int)i, (unsigned int)j,
 100                                              (unsigned int)counter[j]);
 101                                efi_st_error(
 102                                        "Notification function was called\n");
 103                                return EFI_ST_FAILURE;
 104                        }
 105                        /* Call notification function  */
 106                        ret = boottime->check_event(events[j]);
 107                        if (ret != EFI_NOT_READY) {
 108                                efi_st_error(
 109                                        "Signaled state not cleared\n");
 110                                return EFI_ST_FAILURE;
 111                        }
 112                        if (counter[j] != i + 1) {
 113                                efi_st_printf("i %u, j %u, count %u\n",
 114                                              (unsigned int)i, (unsigned int)j,
 115                                              (unsigned int)counter[j]);
 116                                efi_st_error(
 117                                        "Notification function not called\n");
 118                                return EFI_ST_FAILURE;
 119                        }
 120                }
 121        }
 122
 123        for (i = 0; i < GROUP_SIZE; ++i) {
 124                ret = boottime->close_event(events[i]);
 125                if (ret != EFI_SUCCESS) {
 126                        efi_st_error("Failed to close event\n");
 127                        return EFI_ST_FAILURE;
 128                }
 129        }
 130
 131        return EFI_ST_SUCCESS;
 132}
 133
 134EFI_UNIT_TEST(eventgoups) = {
 135        .name = "event groups",
 136        .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
 137        .setup = setup,
 138        .execute = execute,
 139};
 140