183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
26fc901c5SHeinrich Schuchardt /*
36fc901c5SHeinrich Schuchardt * efi_selftest_event_groups
46fc901c5SHeinrich Schuchardt *
56fc901c5SHeinrich Schuchardt * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
66fc901c5SHeinrich Schuchardt *
76fc901c5SHeinrich Schuchardt * This test checks the notification of group events and the
86fc901c5SHeinrich Schuchardt * following services:
96fc901c5SHeinrich Schuchardt * CreateEventEx, CloseEvent, SignalEvent, CheckEvent.
106fc901c5SHeinrich Schuchardt */
116fc901c5SHeinrich Schuchardt
126fc901c5SHeinrich Schuchardt #include <efi_selftest.h>
136fc901c5SHeinrich Schuchardt
146fc901c5SHeinrich Schuchardt #define GROUP_SIZE 16
156fc901c5SHeinrich Schuchardt
166fc901c5SHeinrich Schuchardt static struct efi_boot_services *boottime;
176fc901c5SHeinrich Schuchardt static efi_guid_t event_group =
186fc901c5SHeinrich Schuchardt EFI_GUID(0x2335905b, 0xc3b9, 0x4221, 0xa3, 0x71,
196fc901c5SHeinrich Schuchardt 0x0e, 0x5b, 0x45, 0xc0, 0x56, 0x91);
206fc901c5SHeinrich Schuchardt
216fc901c5SHeinrich Schuchardt /*
22*d8b2216cSHeinrich Schuchardt * Notification function, increments the notification count if parameter
236fc901c5SHeinrich Schuchardt * context is provided.
246fc901c5SHeinrich Schuchardt *
256fc901c5SHeinrich Schuchardt * @event notified event
266fc901c5SHeinrich Schuchardt * @context pointer to the notification count
276fc901c5SHeinrich Schuchardt */
notify(struct efi_event * event,void * context)286fc901c5SHeinrich Schuchardt static void EFIAPI notify(struct efi_event *event, void *context)
296fc901c5SHeinrich Schuchardt {
306fc901c5SHeinrich Schuchardt unsigned int *count = context;
316fc901c5SHeinrich Schuchardt
326fc901c5SHeinrich Schuchardt if (count)
336fc901c5SHeinrich Schuchardt ++*count;
346fc901c5SHeinrich Schuchardt }
356fc901c5SHeinrich Schuchardt
366fc901c5SHeinrich Schuchardt /*
376fc901c5SHeinrich Schuchardt * Setup unit test.
386fc901c5SHeinrich Schuchardt *
396fc901c5SHeinrich Schuchardt * @handle: handle of the loaded image
406fc901c5SHeinrich Schuchardt * @systable: system table
416fc901c5SHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success
426fc901c5SHeinrich Schuchardt */
setup(const efi_handle_t handle,const struct efi_system_table * systable)436fc901c5SHeinrich Schuchardt static int setup(const efi_handle_t handle,
446fc901c5SHeinrich Schuchardt const struct efi_system_table *systable)
456fc901c5SHeinrich Schuchardt {
466fc901c5SHeinrich Schuchardt boottime = systable->boottime;
476fc901c5SHeinrich Schuchardt
486fc901c5SHeinrich Schuchardt return EFI_ST_SUCCESS;
496fc901c5SHeinrich Schuchardt }
506fc901c5SHeinrich Schuchardt
516fc901c5SHeinrich Schuchardt /*
526fc901c5SHeinrich Schuchardt * Execute unit test.
536fc901c5SHeinrich Schuchardt *
546fc901c5SHeinrich Schuchardt * Create multiple events in an event group. Signal each event once and check
556fc901c5SHeinrich Schuchardt * that all events are notified once in each round.
566fc901c5SHeinrich Schuchardt *
576fc901c5SHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success
586fc901c5SHeinrich Schuchardt */
execute(void)596fc901c5SHeinrich Schuchardt static int execute(void)
606fc901c5SHeinrich Schuchardt {
616fc901c5SHeinrich Schuchardt unsigned int counter[GROUP_SIZE] = {0};
626fc901c5SHeinrich Schuchardt struct efi_event *events[GROUP_SIZE];
636fc901c5SHeinrich Schuchardt size_t i, j;
646fc901c5SHeinrich Schuchardt efi_status_t ret;
656fc901c5SHeinrich Schuchardt
666fc901c5SHeinrich Schuchardt for (i = 0; i < GROUP_SIZE; ++i) {
676fc901c5SHeinrich Schuchardt ret = boottime->create_event_ex(0, TPL_NOTIFY,
686fc901c5SHeinrich Schuchardt notify, (void *)&counter[i],
696fc901c5SHeinrich Schuchardt &event_group, &events[i]);
706fc901c5SHeinrich Schuchardt if (ret != EFI_SUCCESS) {
716fc901c5SHeinrich Schuchardt efi_st_error("Failed to create event\n");
726fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
736fc901c5SHeinrich Schuchardt }
746fc901c5SHeinrich Schuchardt }
756fc901c5SHeinrich Schuchardt
766fc901c5SHeinrich Schuchardt for (i = 0; i < GROUP_SIZE; ++i) {
776fc901c5SHeinrich Schuchardt ret = boottime->signal_event(events[i]);
786fc901c5SHeinrich Schuchardt if (ret != EFI_SUCCESS) {
796fc901c5SHeinrich Schuchardt efi_st_error("Failed to signal event\n");
806fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
816fc901c5SHeinrich Schuchardt }
826fc901c5SHeinrich Schuchardt for (j = 0; j < GROUP_SIZE; ++j) {
836fc901c5SHeinrich Schuchardt if (counter[j] != i) {
846fc901c5SHeinrich Schuchardt efi_st_printf("i %u, j %u, count %u\n",
856fc901c5SHeinrich Schuchardt (unsigned int)i, (unsigned int)j,
866fc901c5SHeinrich Schuchardt (unsigned int)counter[j]);
876fc901c5SHeinrich Schuchardt efi_st_error(
886fc901c5SHeinrich Schuchardt "Notification function was called\n");
896fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
906fc901c5SHeinrich Schuchardt }
916fc901c5SHeinrich Schuchardt /* Clear signaled state */
926fc901c5SHeinrich Schuchardt ret = boottime->check_event(events[j]);
936fc901c5SHeinrich Schuchardt if (ret != EFI_SUCCESS) {
946fc901c5SHeinrich Schuchardt efi_st_error("Event was not signaled\n");
956fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
966fc901c5SHeinrich Schuchardt }
976fc901c5SHeinrich Schuchardt if (counter[j] != i) {
986fc901c5SHeinrich Schuchardt efi_st_printf("i %u, j %u, count %u\n",
996fc901c5SHeinrich Schuchardt (unsigned int)i, (unsigned int)j,
1006fc901c5SHeinrich Schuchardt (unsigned int)counter[j]);
1016fc901c5SHeinrich Schuchardt efi_st_error(
1026fc901c5SHeinrich Schuchardt "Notification function was called\n");
1036fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
1046fc901c5SHeinrich Schuchardt }
1056fc901c5SHeinrich Schuchardt /* Call notification function */
1066fc901c5SHeinrich Schuchardt ret = boottime->check_event(events[j]);
1076fc901c5SHeinrich Schuchardt if (ret != EFI_NOT_READY) {
1086fc901c5SHeinrich Schuchardt efi_st_error(
1096fc901c5SHeinrich Schuchardt "Signaled state not cleared\n");
1106fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
1116fc901c5SHeinrich Schuchardt }
1126fc901c5SHeinrich Schuchardt if (counter[j] != i + 1) {
1136fc901c5SHeinrich Schuchardt efi_st_printf("i %u, j %u, count %u\n",
1146fc901c5SHeinrich Schuchardt (unsigned int)i, (unsigned int)j,
1156fc901c5SHeinrich Schuchardt (unsigned int)counter[j]);
1166fc901c5SHeinrich Schuchardt efi_st_error(
117*d8b2216cSHeinrich Schuchardt "Notification function not called\n");
1186fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
1196fc901c5SHeinrich Schuchardt }
1206fc901c5SHeinrich Schuchardt }
1216fc901c5SHeinrich Schuchardt }
1226fc901c5SHeinrich Schuchardt
1236fc901c5SHeinrich Schuchardt for (i = 0; i < GROUP_SIZE; ++i) {
1246fc901c5SHeinrich Schuchardt ret = boottime->close_event(events[i]);
1256fc901c5SHeinrich Schuchardt if (ret != EFI_SUCCESS) {
1266fc901c5SHeinrich Schuchardt efi_st_error("Failed to close event\n");
1276fc901c5SHeinrich Schuchardt return EFI_ST_FAILURE;
1286fc901c5SHeinrich Schuchardt }
1296fc901c5SHeinrich Schuchardt }
1306fc901c5SHeinrich Schuchardt
1316fc901c5SHeinrich Schuchardt return EFI_ST_SUCCESS;
1326fc901c5SHeinrich Schuchardt }
1336fc901c5SHeinrich Schuchardt
1346fc901c5SHeinrich Schuchardt EFI_UNIT_TEST(eventgoups) = {
1356fc901c5SHeinrich Schuchardt .name = "event groups",
1366fc901c5SHeinrich Schuchardt .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
1376fc901c5SHeinrich Schuchardt .setup = setup,
1386fc901c5SHeinrich Schuchardt .execute = execute,
1396fc901c5SHeinrich Schuchardt };
140