[U-Boot] [PATCH v2 18/18] efi_loader: fix ExitBootServices

Alexander Graf agraf at suse.de
Fri Jan 19 10:56:32 UTC 2018



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.glpk at 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();
> 


More information about the U-Boot mailing list