On 17.01.18 20:16, Heinrich Schuchardt wrote:
> This patch lets the implementation of ExitBootServices conform to
> the UEFI standard.
> 
> The timer events must be disabled before calling the notification
> functions of the exit boot services events.
> 
> The boot services must be disabled in the system table.
> 
> The handles in the system table should be defined as efi_handle_t.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de>
> ---
> v2
>       new patch
> ---
>  include/efi_api.h             |  6 +++---
>  lib/efi_loader/efi_boottime.c | 36 +++++++++++++++++++++++++++++++-----
>  2 files changed, 34 insertions(+), 8 deletions(-)
> 
> diff --git a/include/efi_api.h b/include/efi_api.h
> index 0bc244444d..4252d11398 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -247,11 +247,11 @@ struct efi_system_table {
>       struct efi_table_hdr hdr;
>       unsigned long fw_vendor;   /* physical addr of wchar_t vendor string */
>       u32 fw_revision;
> -     unsigned long con_in_handle;
> +     efi_handle_t con_in_handle;
>       struct efi_simple_input_interface *con_in;
> -     unsigned long con_out_handle;
> +     efi_handle_t con_out_handle;
>       struct efi_simple_text_output_protocol *con_out;
> -     unsigned long stderr_handle;
> +     efi_handle_t stderr_handle;
>       struct efi_simple_text_output_protocol *std_err;
>       struct efi_runtime_services *runtime;
>       struct efi_boot_services *boottime;
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 4b3b63e39a..2c5499e0c8 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -1645,12 +1645,16 @@ static void efi_exit_caches(void)
>  }
>  
>  /*
> - * Stop boot services.
> + * Stop all boot services.
>   *
>   * This function implements the ExitBootServices service.
>   * See the Unified Extensible Firmware Interface (UEFI) specification
>   * for details.
>   *
> + * All timer events are disabled.
> + * For exit boot services events the notification function is called.
> + * The boot services are disabled in the system table.
> + *
>   * @image_handle     handle of the loaded image
>   * @map_key          key of the memory map
>   * @return           status code
> @@ -1662,16 +1666,24 @@ static efi_status_t EFIAPI 
> efi_exit_boot_services(efi_handle_t image_handle,
>  
>       EFI_ENTRY("%p, %ld", image_handle, map_key);
>  
> +     /* 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);
> +
>       /* Notify that ExitBootServices is invoked. */
>       for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
>               if (efi_events[i].type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
>                       continue;
> -             efi_signal_event(&efi_events[i]);
> +             if (!efi_events[i].notify_function)
> +                     continue;
> +             EFI_CALL_VOID(efi_events[i].notify_function(
> +                             &efi_events[i], efi_events[i].notify_context));

This basically just bypasses the event->notify_tpl check. Can't you add
an enum parameter to efi_signal_event to indicate EFI_SIGNAL_CHECK_TPL
vs EFI_SIGNAL_NOCHECK and only do the TPL check in there if
EFI_SIGNAL_CHECK_TPL is set?


Alex

>       }
> -     /* Make sure that notification functions are not called anymore */
> -     efi_tpl = TPL_HIGH_LEVEL;
>  
> -     /* XXX Should persist EFI variables here */
> +     /* TODO Should persist EFI variables here */
>  
>       board_quiesce_devices();
>  
> @@ -1681,6 +1693,20 @@ static efi_status_t EFIAPI 
> efi_exit_boot_services(efi_handle_t image_handle,
>       /* This stops all lingering devices */
>       bootm_disable_interrupts();
>  
> +     /* Disable boottime services */
> +     systab.con_in_handle = NULL;
> +     systab.con_in = NULL;
> +     systab.con_out_handle = NULL;
> +     systab.con_out = NULL;
> +     systab.stderr_handle = NULL;
> +     systab.std_err = NULL;
> +     systab.boottime = NULL;
> +
> +     /* Recalculate CRC32 */
> +     systab.hdr.crc32 = 0;
> +     systab.hdr.crc32 = crc32(0, (const unsigned char *)&systab,
> +                              sizeof(struct efi_system_table));
> +
>       /* Give the payload some time to boot */
>       efi_set_watchdog(0);
>       WATCHDOG_RESET();
> 
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to