Re: [PATCH v4 2/2] Support ESRT in Xen dom0
From: Ard Biesheuvel
Date: Fri Sep 30 2022 - 12:36:33 EST
On Fri, 30 Sept 2022 at 01:02, Demi Marie Obenour
<demi@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> fwupd requires access to the EFI System Resource Table (ESRT) to
> discover which firmware can be updated by the OS. Currently, Linux does
> not expose the ESRT when running as a Xen dom0. Therefore, it is not
> possible to use fwupd in a Xen dom0, which is a serious problem for e.g.
> Qubes OS.
>
> Before Xen 4.17, this was not fixable due to hypervisor limitations.
> The UEFI specification requires the ESRT to be in EfiBootServicesData
> memory, which Xen will use for whatever purposes it likes. Therefore,
> Linux cannot safely access the ESRT, as Xen may have overwritten it.
>
> Starting with Xen 4.17, Xen checks if the ESRT is in EfiBootServicesData
> or EfiRuntimeServicesData memory. If the ESRT is in EfiBootServicesData
> memory, Xen replaces the ESRT with a copy in memory that it has
> reserved. Such memory is currently of type EFI_RUNTIME_SERVICES_DATA,
> but in the future it will be of type EFI_ACPI_RECLAIM_MEMORY. This
> ensures that the ESRT can safely be accessed by the OS.
>
> When running as a Xen dom0, use the new
> xen_config_table_memory_region_max() function to determine if Xen has
> reserved the ESRT and, if so, find the end of the memory region
> containing it. This allows programs such as fwupd which require the
> ESRT to run under Xen, and so makes fwupd support in Qubes OS possible.
>
> Signed-off-by: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx>
Why do we need this patch? I'd expect esrt_table_exists() to return
false when patch 1/2 is applied.
> ---
> drivers/firmware/efi/esrt.c | 43 ++++++++++++++++++++++++++-----------
> 1 file changed, 30 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
> index 2a2f52b017e736dd995c69e8aeb5fbd7761732e5..a0642bc161b4b1f94f818b8c9f46511fe2424bb2 100644
> --- a/drivers/firmware/efi/esrt.c
> +++ b/drivers/firmware/efi/esrt.c
> @@ -243,27 +243,44 @@ void __init efi_esrt_init(void)
> void *va;
> struct efi_system_resource_table tmpesrt;
> size_t size, max, entry_size, entries_size;
> - efi_memory_desc_t md;
> - int rc;
> phys_addr_t end;
> -
> - if (!efi_enabled(EFI_MEMMAP))
> - return;
> + u32 type;
>
> pr_debug("esrt-init: loading.\n");
> if (!esrt_table_exists())
> return;
>
> - rc = efi_mem_desc_lookup(efi.esrt, &md);
> - if (rc < 0 ||
> - (!(md.attribute & EFI_MEMORY_RUNTIME) &&
> - md.type != EFI_BOOT_SERVICES_DATA &&
> - md.type != EFI_RUNTIME_SERVICES_DATA)) {
> - pr_warn("ESRT header is not in the memory map.\n");
> + if (efi_enabled(EFI_MEMMAP)) {
> + efi_memory_desc_t md;
> +
> + if (efi_mem_desc_lookup(efi.esrt, &md) < 0 ||
> + (!(md.attribute & EFI_MEMORY_RUNTIME) &&
> + md.type != EFI_BOOT_SERVICES_DATA &&
> + md.type != EFI_RUNTIME_SERVICES_DATA)) {
> + pr_warn("ESRT header is not in the memory map.\n");
> + return;
> + }
> +
> + type = md.type;
> + max = efi_mem_desc_end(&md);
> +#ifdef CONFIG_XEN_EFI
> + } else if (efi_enabled(EFI_PARAVIRT)) {
> + max = xen_config_table_memory_region_max(efi.esrt);
> + /*
> + * This might be wrong, but it doesn't matter.
> + * xen_config_table_memory_region_max() checks the type
> + * of the memory region, and if it returns 0, the code
> + * below will fail without looking at the type. Choose
> + * a value that will not cause * subsequent code to try
> + * to reserve the memory containing the ESRT, as either
> + * Xen or the firmware has done so already.
> + */
> + type = EFI_RUNTIME_SERVICES_DATA;
> +#endif
> + } else {
> return;
> }
>
> - max = efi_mem_desc_end(&md);
> if (max < efi.esrt) {
> pr_err("EFI memory descriptor is invalid. (esrt: %p max: %p)\n",
> (void *)efi.esrt, (void *)max);
> @@ -333,7 +350,7 @@ void __init efi_esrt_init(void)
>
> end = esrt_data + size;
> pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end);
> - if (md.type == EFI_BOOT_SERVICES_DATA)
> + if (type == EFI_BOOT_SERVICES_DATA)
> efi_mem_reserve(esrt_data, esrt_data_size);
>
> pr_debug("esrt-init: loaded.\n");
> --
> Sincerely,
> Demi Marie Obenour (she/her/hers)
> Invisible Things Lab
>