On Sat, Jul 27, 2019 at 11:00:03PM +0200, Heinrich Schuchardt wrote:
> Implement the ConvertPointer() runtime service.

I already submitted a similar patch:
https://lists.denx.de/pipermail/u-boot/2019-June/371773.html

Anyhow,

> Signed-off-by: Heinrich Schuchardt <[email protected]>
> ---
>  lib/efi_loader/efi_runtime.c | 75 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 71 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
> index a8f0b5eae3..2286e847a7 100644
> --- a/lib/efi_loader/efi_runtime.c
> +++ b/lib/efi_loader/efi_runtime.c
> @@ -81,6 +81,10 @@ struct elf_rela {
>       long addend;
>  };
> 
> +static __efi_runtime_data struct efi_mem_desc *efi_virtmap;
> +static __efi_runtime_data efi_uintn_t efi_descriptor_count;
> +static __efi_runtime_data efi_uintn_t efi_descriptor_size;
> +
>  /*
>   * EFI runtime code lives in two stages. In the first stage, U-Boot and an 
> EFI
>   * payload are running concurrently at the same time. In this mode, we can
> @@ -89,7 +93,9 @@ struct elf_rela {
> 
>  efi_status_t efi_init_runtime_supported(void)
>  {
> -     u16 efi_runtime_services_supported = 0;
> +     u16 efi_runtime_services_supported =
> +                             EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP ||

"||" -> "|"

> +                             EFI_RT_SUPPORTED_CONVERT_POINTER;
> 
>       /*
>        * This value must be synced with efi_runtime_detach_list
> @@ -98,8 +104,7 @@ efi_status_t efi_init_runtime_supported(void)
>  #ifdef CONFIG_EFI_HAVE_RUNTIME_RESET
>       efi_runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM;
>  #endif
> -     efi_runtime_services_supported |=
> -                             EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP;
> +
>       return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported",
>                                        &efi_global_variable_guid,
>                                        EFI_VARIABLE_BOOTSERVICE_ACCESS |
> @@ -454,6 +459,58 @@ static __efi_runtime efi_status_t EFIAPI 
> efi_convert_pointer_runtime(
>       return EFI_UNSUPPORTED;
>  }
> 
> +/**
> + * efi_convert_pointer_runtime() - convert from physical to virtual pointer
> + *
> + * This function implements the ConvertPointer() runtime service until
> + * the first call to SetVirtualAddressMap().
> + *
> + * See the Unified Extensible Firmware Interface (UEFI) specification for
> + * details.
> + *
> + * @debug_disposition:       indicates if pointer may be converted to NULL
> + * @address:         pointer to be converted
> + * Return:           status code EFI_UNSUPPORTED
> + */
> +static __efi_runtime efi_status_t EFIAPI efi_convert_pointer(
> +                     efi_uintn_t debug_disposition, void **address)
> +{
> +     efi_physical_addr_t addr = (uintptr_t)*address;
> +     efi_uintn_t i;
> +     efi_status_t ret = EFI_NOT_FOUND;
> +
> +     EFI_ENTRY("%zu %p", debug_disposition, address);
> +
> +     if (!efi_virtmap) {
> +             ret = EFI_UNSUPPORTED;
> +             goto out;
> +     }
> +
> +     if (!address) {
> +             ret = EFI_INVALID_PARAMETER;
> +             goto out;
> +     }
> +
> +     for (i = 0; i < efi_descriptor_count; i++) {
> +             struct efi_mem_desc *map = (void *)efi_virtmap +
> +                                        (efi_descriptor_size * i);
> +
> +             if (addr >= map->physical_start &&
> +                 (addr < map->physical_start
> +                         + (map->num_pages << EFI_PAGE_SHIFT))) {
> +                     *address = (void *)(uintptr_t)
> +                                (addr + map->virtual_start -
> +                                 map->physical_start);
> +
> +                     ret = EFI_SUCCESS;
> +                     break;
> +             }
> +     }
> +
> +out:
> +     return EFI_EXIT(ret);
> +}
> +
>  static __efi_runtime void efi_relocate_runtime_table(ulong offset)
>  {
>       ulong patchoff;
> @@ -480,6 +537,12 @@ static __efi_runtime void 
> efi_relocate_runtime_table(ulong offset)
>        */
>       efi_runtime_services.convert_pointer = &efi_convert_pointer_runtime;
> 
> +     /*
> +      * TODO: Update UEFI variable RuntimeServicesSupported removing flags
> +      * EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP and
> +      * EFI_RT_SUPPORTED_CONVERT_POINTER as required by the UEFI spec 2.8.
> +      */
> +
>       /* Update CRC32 */
>       efi_update_table_header_crc32(&efi_runtime_services.hdr);
>  }
> @@ -584,6 +647,10 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
>       EFI_ENTRY("%zx %zx %x %p", memory_map_size, descriptor_size,
>                 descriptor_version, virtmap);
> 
> +     efi_virtmap = virtmap;
> +     efi_descriptor_size = descriptor_size;
> +     efi_descriptor_count = n;
> +

As I mentioned in the patch above,

!        /* Rebind mmio pointers */
!                for (i = 0; i < n; i++) {
!       ...

This part of code in efi_set_virtual_address_map() is fragile as 
entries in efi_runtime_mmio belong to memory allocated by calloc(),
which means that they are no longer accessible at runtime.

-Takahiro Akashi

>       /*
>        * TODO:
>        * Further down we are cheating. While really we should implement
> @@ -800,7 +867,7 @@ struct efi_runtime_services __efi_runtime_data 
> efi_runtime_services = {
>       .get_wakeup_time = (void *)&efi_unimplemented,
>       .set_wakeup_time = (void *)&efi_unimplemented,
>       .set_virtual_address_map = &efi_set_virtual_address_map,
> -     .convert_pointer = (void *)&efi_unimplemented,
> +     .convert_pointer = efi_convert_pointer,
>       .get_variable = efi_get_variable,
>       .get_next_variable_name = efi_get_next_variable_name,
>       .set_variable = efi_set_variable,
> --
> 2.20.1
> 
_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

Reply via email to