[U-Boot] [PATCH v3 2/2] efi_loader: Patch non-runtime code out at ExitBootServices already
Heinrich Schuchardt
xypron.glpk at gmx.de
Wed Jan 30 18:52:42 UTC 2019
On 1/30/19 11:46 AM, Alexander Graf wrote:
> While discussing something compeltely different, Ard pointed out
> that it might be legal to omit calling SetVirtualAddressMap altogether.
>
> There is even a patch on the Linux Kernel Mailing List that implements
> such behavior by now:
>
> https://patchwork.kernel.org/patch/10782393/
>
> While that sounds great, we currently rely on the SetVirtualAddressMap
> call to remove all references to code that would not workoutside of
> boot services.
>
> So let's patch out those bits already on the call to ExitBootServices,
> so that we can successfully run even when an OS chooses to omit
> any call to SetVirtualAddressMap.
>
> Reported-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> Signed-off-by: Alexander Graf <agraf at suse.de>
>
> ---
>
This patch series leads to a Python test error on qemu_arm64_defconfig:
if m != 0:
> raise Exception('Reset failed during the EFI selftest')
E Exception: Reset failed during the EFI selftest
test/py/tests/test_efi_selftest.py:25: Exception
<snip />
The output looks like:
Preparing for reset. Press any key...
U-Boot 2019.01-00458-gada5205aef (Jan 30 2019 - 19:47:02 +0100)
DRAM:
<snip />
Please, adjust test_efi_selftest().
Best regards
Heinrich
> v1 -> v2:
>
> - Add missing icache invalidation
>
> v2 -> v3:
>
> - Add link to upstream Linux patch
> ---
> include/efi_loader.h | 2 ++
> lib/efi_loader/efi_boottime.c | 1 +
> lib/efi_loader/efi_runtime.c | 29 ++++++++++++++++++++---------
> 3 files changed, 23 insertions(+), 9 deletions(-)
>
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index 9dd933dae7..2a40b09693 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -310,6 +310,8 @@ void efi_save_gd(void);
> void efi_restore_gd(void);
> /* Call this to relocate the runtime section to an address space */
> void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
> +/* Call this when we start to live in a runtime only world */
> +void efi_runtime_detach(ulong offset);
> /* Call this to set the current device name */
> void efi_set_bootdev(const char *dev, const char *devnr, const char *path);
> /* Add a new object to the object list. */
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index fc26d6adc1..8cb2979bab 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -1917,6 +1917,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
> bootm_disable_interrupts();
>
> /* Disable boot time services */
> + efi_runtime_detach((ulong)gd->relocaddr);
> systab.con_in_handle = NULL;
> systab.con_in = NULL;
> systab.con_out_handle = NULL;
> diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
> index 636dfdab39..17d22d429e 100644
> --- a/lib/efi_loader/efi_runtime.c
> +++ b/lib/efi_loader/efi_runtime.c
> @@ -276,16 +276,12 @@ struct efi_runtime_detach_list_struct {
> void *patchto;
> };
>
> -static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
> +static struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
> {
> /* do_reset is gone */
> .ptr = &efi_runtime_services.reset_system,
> .patchto = efi_reset_system,
> }, {
> - /* invalidate_*cache_all are gone */
> - .ptr = &efi_runtime_services.set_virtual_address_map,
> - .patchto = &efi_unimplemented,
> - }, {
> /* RTC accessors are gone */
> .ptr = &efi_runtime_services.get_time,
> .patchto = &efi_get_time,
> @@ -328,7 +324,15 @@ static bool efi_runtime_tobedetached(void *p)
> return false;
> }
>
> -static void efi_runtime_detach(ulong offset)
> +/**
> + * efi_runtime_detach() - Remove any dependency on non-runtime sections
> + *
> + * This function patches all remaining code to be self-sufficient inside
> + * runtime sections. Any calls to non-runtime will be removed after this.
> + *
> + * @offset: relocaddr for pre-set_v_a_space, offset to VA after
> + */
> +__efi_runtime void efi_runtime_detach(ulong offset)
> {
> int i;
> ulong patchoff = offset - (ulong)gd->relocaddr;
> @@ -344,6 +348,8 @@ static void efi_runtime_detach(ulong offset)
>
> /* Update CRC32 */
> efi_update_table_header_crc32(&efi_runtime_services.hdr);
> +
> + invalidate_icache_all();
> }
>
> /* Relocate EFI runtime to uboot_reloc_base = offset */
> @@ -430,19 +436,25 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
> * @virtmap: virtual address mapping information
> * Return: status code
> */
> -static efi_status_t EFIAPI efi_set_virtual_address_map(
> +static __efi_runtime efi_status_t EFIAPI efi_set_virtual_address_map(
> unsigned long memory_map_size,
> unsigned long descriptor_size,
> uint32_t descriptor_version,
> struct efi_mem_desc *virtmap)
> {
> + static __efi_runtime_data bool is_patched;
> int n = memory_map_size / descriptor_size;
> int i;
> int rt_code_sections = 0;
>
> + if (is_patched)
> + return EFI_INVALID_PARAMETER;
> +
> EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size,
> descriptor_version, virtmap);
>
> + is_patched = true;
> +
> /*
> * TODO:
> * Further down we are cheating. While really we should implement
> @@ -514,8 +526,7 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
> map->physical_start + gd->relocaddr;
>
> efi_runtime_relocate(new_offset, map);
> - /* Once we're virtual, we can no longer handle
> - complex callbacks */
> + /* We need to repatch callbacks for their new VA */
> efi_runtime_detach(new_offset);
> return EFI_EXIT(EFI_SUCCESS);
> }
>
More information about the U-Boot
mailing list