uboot/lib/efi_selftest/efi_selftest_exitbootservices.c
<<
>>
Prefs
   1/*
   2 * efi_selftest_exitbootservices
   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 that the notification function of an
   9 * EVT_SIGNAL_EXIT_BOOT_SERVICES event is called exactly once.
  10 */
  11
  12#include <efi_selftest.h>
  13
  14static struct efi_boot_services *boottime;
  15static struct efi_event *event_notify;
  16static unsigned int notification_count;
  17
  18/*
  19 * Notification function, increments the notification count.
  20 *
  21 * @event       notified event
  22 * @context     pointer to the notification count
  23 */
  24static void EFIAPI notify(struct efi_event *event, void *context)
  25{
  26        unsigned int *count = context;
  27
  28        ++*count;
  29}
  30
  31/*
  32 * Setup unit test.
  33 *
  34 * Create an EVT_SIGNAL_EXIT_BOOT_SERVICES event.
  35 *
  36 * @handle:     handle of the loaded image
  37 * @systable:   system table
  38 * @return:     EFI_ST_SUCCESS for success
  39 */
  40static int setup(const efi_handle_t handle,
  41                 const struct efi_system_table *systable)
  42{
  43        efi_status_t ret;
  44
  45        boottime = systable->boottime;
  46
  47        notification_count = 0;
  48        ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES,
  49                                     TPL_CALLBACK, notify,
  50                                     (void *)&notification_count,
  51                                     &event_notify);
  52        if (ret != EFI_SUCCESS) {
  53                efi_st_error("could not create event\n");
  54                return EFI_ST_FAILURE;
  55        }
  56        return EFI_ST_SUCCESS;
  57}
  58
  59/*
  60 * Tear down unit test.
  61 *
  62 * Close the event created in setup.
  63 *
  64 * @return:     EFI_ST_SUCCESS for success
  65 */
  66static int teardown(void)
  67{
  68        efi_status_t ret;
  69
  70        if (event_notify) {
  71                ret = boottime->close_event(event_notify);
  72                event_notify = NULL;
  73                if (ret != EFI_SUCCESS) {
  74                        efi_st_error("could not close event\n");
  75                        return EFI_ST_FAILURE;
  76                }
  77        }
  78        return EFI_ST_SUCCESS;
  79}
  80
  81/*
  82 * Execute unit test.
  83 *
  84 * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES
  85 * event has been called.
  86 *
  87 * Call ExitBootServices again and check that the notification function is
  88 * not called again.
  89 *
  90 * @return:     EFI_ST_SUCCESS for success
  91 */
  92static int execute(void)
  93{
  94        if (notification_count != 1) {
  95                efi_st_error("ExitBootServices was not notified\n");
  96                return EFI_ST_FAILURE;
  97        }
  98        efi_st_exit_boot_services();
  99        if (notification_count != 1) {
 100                efi_st_error("ExitBootServices was notified twice\n");
 101                return EFI_ST_FAILURE;
 102        }
 103        return EFI_ST_SUCCESS;
 104}
 105
 106EFI_UNIT_TEST(exitbootservices) = {
 107        .name = "ExitBootServices",
 108        .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
 109        .setup = setup,
 110        .execute = execute,
 111        .teardown = teardown,
 112};
 113