Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
Heinrich Schuchardt | 9ca3071 | 2018-02-18 15:17:53 +0100 | [diff] [blame] | 2 | /* |
| 3 | * efi_selftest_event_groups |
| 4 | * |
| 5 | * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> |
| 6 | * |
Heinrich Schuchardt | 9ca3071 | 2018-02-18 15:17:53 +0100 | [diff] [blame] | 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 | |
| 16 | static struct efi_boot_services *boottime; |
| 17 | static 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 notfication count if parameter |
| 23 | * context is provided. |
| 24 | * |
| 25 | * @event notified event |
| 26 | * @context pointer to the notification count |
| 27 | */ |
| 28 | static 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 | */ |
| 43 | static 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 | */ |
| 59 | static 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 | "Nofification 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 | |
| 134 | EFI_UNIT_TEST(eventgoups) = { |
| 135 | .name = "event groups", |
| 136 | .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, |
| 137 | .setup = setup, |
| 138 | .execute = execute, |
| 139 | }; |