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