/* List of all events */
LIST_HEAD(efi_events);
+/* Flag to disable timer activity in ExitBootServices() */
+static bool timers_enabled = true;
+
/* List of all events registered by RegisterProtocolNotify() */
LIST_HEAD(efi_register_notify_events);
/**
* efi_queue_event() - queue an EFI event
* @event: event to signal
- * @check_tpl: check the TPL level
*
* This function queues the notification function of the event for future
* execution.
* For the SignalEvent service see efi_signal_event_ext.
*
*/
-static void efi_queue_event(struct efi_event *event, bool check_tpl)
+static void efi_queue_event(struct efi_event *event)
{
if (event->notify_function) {
event->is_queued = true;
/* Check TPL */
- if (check_tpl && efi_tpl >= event->notify_tpl)
+ if (efi_tpl >= event->notify_tpl)
return;
event->is_queued = false;
EFI_CALL_VOID(event->notify_function(event,
/**
* efi_signal_event() - signal an EFI event
* @event: event to signal
- * @check_tpl: check the TPL level
*
* This function signals an event. If the event belongs to an event group all
* events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL
*
* For the SignalEvent service see efi_signal_event_ext.
*/
-void efi_signal_event(struct efi_event *event, bool check_tpl)
+void efi_signal_event(struct efi_event *event)
{
if (event->is_signaled)
return;
if (!evt->group || guidcmp(evt->group, event->group))
continue;
if (evt->is_queued)
- efi_queue_event(evt, check_tpl);
+ efi_queue_event(evt);
}
} else {
event->is_signaled = true;
if (event->type & EVT_NOTIFY_SIGNAL)
- efi_queue_event(event, check_tpl);
+ efi_queue_event(event);
}
}
list_for_each_entry(evt, &efi_events, link) {
if (evt->is_queued)
- efi_queue_event(evt, true);
+ efi_queue_event(evt);
+ if (!timers_enabled)
+ continue;
if (!(evt->type & EVT_TIMER) || now < evt->trigger_next)
continue;
switch (evt->trigger_type) {
continue;
}
evt->is_signaled = false;
- efi_signal_event(evt, true);
+ efi_signal_event(evt);
}
WATCHDOG_RESET();
}
if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
return EFI_EXIT(EFI_INVALID_PARAMETER);
if (!event[i]->is_signaled)
- efi_queue_event(event[i], true);
+ efi_queue_event(event[i]);
}
/* Wait for signal */
EFI_ENTRY("%p", event);
if (efi_is_event(event) != EFI_SUCCESS)
return EFI_EXIT(EFI_INVALID_PARAMETER);
- efi_signal_event(event, true);
+ efi_signal_event(event);
return EFI_EXIT(EFI_SUCCESS);
}
event->type & EVT_NOTIFY_SIGNAL)
return EFI_EXIT(EFI_INVALID_PARAMETER);
if (!event->is_signaled)
- efi_queue_event(event, true);
+ efi_queue_event(event);
if (event->is_signaled) {
event->is_signaled = false;
return EFI_EXIT(EFI_SUCCESS);
notif->handle = handle;
list_add_tail(¬if->link, &event->handles);
event->event->is_signaled = false;
- efi_signal_event(event->event, true);
+ efi_signal_event(event->event);
}
}
/* Notify that the configuration table was changed */
list_for_each_entry(evt, &efi_events, link) {
if (evt->group && !guidcmp(evt->group, guid)) {
- efi_signal_event(evt, false);
+ efi_signal_event(evt);
break;
}
}
if (map_key != efi_memory_map_key)
return EFI_INVALID_PARAMETER;
- /* Make sure that notification functions are not called anymore */
- efi_tpl = TPL_HIGH_LEVEL;
-
/* Check if ExitBootServices has already been called */
if (!systab.boottime)
return EFI_EXIT(EFI_SUCCESS);
+ /* Stop all timer related activities */
+ timers_enabled = false;
+
/* Add related events to the event group */
list_for_each_entry(evt, &efi_events, link) {
if (evt->type == EVT_SIGNAL_EXIT_BOOT_SERVICES)
if (evt->group &&
!guidcmp(evt->group,
&efi_guid_event_group_exit_boot_services)) {
- efi_signal_event(evt, false);
+ efi_signal_event(evt);
break;
}
}
+ /* Make sure that notification functions are not called anymore */
+ efi_tpl = TPL_HIGH_LEVEL;
+
/* TODO: Should persist EFI variables here */
board_quiesce_devices();