diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2019-06-07 06:47:01 +0200 |
---|---|---|
committer | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2019-06-10 23:06:19 +0200 |
commit | 7eaa900e56b28350d954eac20b14c3adb6da2570 (patch) | |
tree | b8512f7d4d5e303291ce3e56ba0106c9929f816b /lib | |
parent | dfa306e44271aadc64cca4a070527ad7d64531fc (diff) | |
download | u-boot-7eaa900e56b28350d954eac20b14c3adb6da2570.zip u-boot-7eaa900e56b28350d954eac20b14c3adb6da2570.tar.gz u-boot-7eaa900e56b28350d954eac20b14c3adb6da2570.tar.bz2 |
efi_loader: event signaling in ExitBootServices
ExitBootServices() has to stop timer related activity before calling the
events of the EFI_EVENT_GROUP_EXIT_BOOT_SERVICES event group. But our
current implementation was stopping all other events.
All events have to observe the task priority level.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 42 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_runtime.c | 2 |
4 files changed, 28 insertions, 22 deletions
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 74aa5f9..c146b47 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -27,6 +27,9 @@ LIST_HEAD(efi_obj_list); /* 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); @@ -163,7 +166,6 @@ const char *__efi_nesting_dec(void) /** * 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. @@ -174,12 +176,12 @@ const char *__efi_nesting_dec(void) * 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, @@ -211,7 +213,6 @@ efi_status_t is_valid_tpl(efi_uintn_t tpl) /** * 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 @@ -219,7 +220,7 @@ efi_status_t is_valid_tpl(efi_uintn_t tpl) * * 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; @@ -244,12 +245,12 @@ void efi_signal_event(struct efi_event *event, bool check_tpl) 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); } } @@ -736,7 +737,9 @@ void efi_timer_check(void) 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) { @@ -750,7 +753,7 @@ void efi_timer_check(void) continue; } evt->is_signaled = false; - efi_signal_event(evt, true); + efi_signal_event(evt); } WATCHDOG_RESET(); } @@ -852,7 +855,7 @@ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events, 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 */ @@ -896,7 +899,7 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) 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); } @@ -963,7 +966,7 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) 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); @@ -1071,7 +1074,7 @@ efi_status_t efi_add_protocol(const efi_handle_t handle, 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); } } @@ -1596,7 +1599,7 @@ out: /* 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; } } @@ -1902,13 +1905,13 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, 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) @@ -1919,11 +1922,14 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, 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(); diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 3b7578f..2fc25e1 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -704,7 +704,7 @@ static void efi_cin_check(void) efi_status_t ret; if (key_available) { - efi_signal_event(efi_con_in.wait_for_key, true); + efi_signal_event(efi_con_in.wait_for_key); return; } @@ -718,7 +718,7 @@ static void efi_cin_check(void) /* Queue the wait for key event */ if (key_available) - efi_signal_event(efi_con_in.wait_for_key, true); + efi_signal_event(efi_con_in.wait_for_key); } } } diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 386cf92..8d76851 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -321,7 +321,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, if (evt->group && !guidcmp(evt->group, &efi_guid_event_group_memory_map_change)) { - efi_signal_event(evt, false); + efi_signal_event(evt); break; } } diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 9c50955..432551d 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -130,7 +130,7 @@ static void EFIAPI efi_reset_system_boottime( if (evt->group && !guidcmp(evt->group, &efi_guid_event_group_reset_system)) { - efi_signal_event(evt, false); + efi_signal_event(evt); break; } } |