[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v8] Preserve the EFI System Resource Table for dom0


  • To: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx>
  • From: Luca Fancellu <Luca.Fancellu@xxxxxxx>
  • Date: Wed, 6 Jul 2022 10:32:37 +0000
  • Accept-language: en-GB, en-US
  • Arc-authentication-results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 63.35.35.123) smtp.rcpttodomain=lists.xenproject.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=arm.com] dkim=[1,1,header.d=arm.com] dmarc=[1,1,header.from=arm.com])
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none
  • Arc-message-signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=a99kn8cDTGVaet3F/2ejtPnP0eRvnXZXSgpfklhkZ9k=; b=jibxyfhpnuAcbIoB1DJS1MAj63LA/RzWIOa8ZaczSsDZa/M7CfllKggr/jpHS1UUN96m1KtQWh0x2Gra5XtLeMLDMMTZcDQ2DbH1Ohm5QZb3gSzIg61Mgw6mCKPal+9DdSNIWAfVht7ZMxkixXQwnH1QgNWJJTkteR7Q6/PRrRbEI95eQv/sAss/WVULIIZu9U/5TuXnpUB1waa9J8Jd3W28k0RJ0Jgfqb1mvZ5odDCtVMUz0qFObKEcH3fJMRdPTQ49gzS7w3QIrBns1Lxvb/VPDEhuAnIMmhgML7ORn4pvzzjIWpuXcFU5mAemFYyyiIBPFnuq8T2Te9dsIKF2EA==
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=a99kn8cDTGVaet3F/2ejtPnP0eRvnXZXSgpfklhkZ9k=; b=aGqL3N9vs5byiWUzMwyqdbTz2XKvBr0qQGr/OXyY+sOdY2kMqytu3oKoerzHY3ovqSr2+9JWSpPTHVK39dFB6oxgxKGxExXAoV7gp7aHTgWu5pM2AB3u8ccpLLt3czXwcyj+clauca5iFeTKlAqChSaGSjSXI0Y/jnCtL2Epmq5okHGWhPOBeol9+sGbiME1mtdhPc4PhBJN8351bcEYpq/QklGL/ddPfEznVSBHURHQLoXm+N86oGti3IwEwWhKxtoUX6LK2xQObta7MF3pfoJyrOI39Yk7GAcp/ubMvsWVuw6dI/enELzDhOQABryDUT5ZGjs/ifvSuz68Eu4FXA==
  • Arc-seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass; b=Vov7YWrvge1ETXiSwZk0RNJ4SfJuAFC2onFT6BBlYdpGf0EIHHRQjpfYe+Lob+x/aFh0HqH/soaW3zK1lcs/DqQQIpswI7HWQ+9Dhe6+BLbyQiwWrzm+ArLtAeWMrdIzeXrcgkNQjhQi7kAo2+HQk4Xw7axxw0h+zNo9/YBW2d/3r/gLZjjxkrFjUW8sMDpa8nbNH6vHMnDJPJTOfcEOhQjlDpwZKMgf63fo+uXrFMDBHDduRafZ3CXh5utN3wf8NN49ZqH2OBb+evHtcqLEkg+/u1JXBqnqj7KKjjDw3HOS+OSYzAqMTxMkz6xloHnREHP7GcoWqh9fPJPOkpmAOA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LXbH3E4JfecQSzpTM843Ntt2Lz5qk8S0YdD3cfFjIrgY0oET0RuYQYTOigBUL1ylElppQ97qlP03XxlEYNWbKX0fERFpPxD19+XoTt2cMXfgzo7XyWEKPIZBCCvVPHFOd64P+FuxFRQGGxvVmXETCbEC5qU8NeIh232dxLRaBm6b4674PJupdMsg86dB2JPIOkCjp26+FdeTOf570d+KZe1yahlOfXlYozsrgrnx6Jr13nPjvsAgtXPdsydBKl/rF5RY91nWFzBk72TJQ191rqmum4oDSH36n4L0h6aU26OEsMm5R3d+53t5VF6OhY1aglV92pQzZ3agnr0GzsoEbA==
  • Authentication-results-original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com;
  • Cc: Xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Julien Grall <julien@xxxxxxx>
  • Delivery-date: Wed, 06 Jul 2022 10:33:03 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Nodisclaimer: true
  • Original-authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com;
  • Thread-index: AQHYh/bQ1tgd5TeBbEyn28hq3tAw6K1xN30A
  • Thread-topic: [PATCH v8] Preserve the EFI System Resource Table for dom0

+ CC Julien Grall

> On 24 Jun 2022, at 19:17, Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx> 
> wrote:
> 
> The EFI System Resource Table (ESRT) is necessary for fwupd to identify
> firmware updates to install.  According to the UEFI specification §23.4,
> the ESRT shall be stored in memory of type EfiBootServicesData.  However,
> memory of type EfiBootServicesData is considered general-purpose memory
> by Xen, so the ESRT needs to be moved somewhere where Xen will not
> overwrite it.  Copy the ESRT to memory of type EfiRuntimeServicesData,
> which Xen will not reuse.  dom0 can use the ESRT if (and only if) it is
> in memory of type EfiRuntimeServicesData.
> 
> Earlier versions of this patch reserved the memory in which the ESRT was
> located.  This created awkward alignment problems, and required either
> splitting the E820 table or wasting memory.  It also would have required
> a new platform op for dom0 to use to indicate if the ESRT is reserved.
> By copying the ESRT into EfiRuntimeServicesData memory, the E820 table
> does not need to be modified, and dom0 can just check the type of the
> memory region containing the ESRT.  The copy is only done if the ESRT is
> not already in EfiRuntimeServicesData memory, avoiding memory leaks on
> repeated kexec.
> 
> See https://lore.kernel.org/xen-devel/20200818184018.GN1679@mail-itl/T/
> for details.
> 
> Signed-off-by: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx>
> ---
> xen/common/efi/boot.c | 134 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 134 insertions(+)
> 
> diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
> index a25e1d29f1..f6f34aa816 100644
> --- a/xen/common/efi/boot.c
> +++ b/xen/common/efi/boot.c
> @@ -39,6 +39,26 @@
>   { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 
> 0x23} }
> #define APPLE_PROPERTIES_PROTOCOL_GUID \
>   { 0x91bd12fe, 0xf6c3, 0x44fb, { 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 
> 0xe0} }
> +#define EFI_SYSTEM_RESOURCE_TABLE_GUID    \
> +  { 0xb122a263, 0x3661, 0x4f68, {0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 
> 0x80} }
> +#define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION 1
> +
> +typedef struct {
> +    EFI_GUID FwClass;
> +    UINT32 FwType;
> +    UINT32 FwVersion;
> +    UINT32 LowestSupportedFwVersion;
> +    UINT32 CapsuleFlags;
> +    UINT32 LastAttemptVersion;
> +    UINT32 LastAttemptStatus;
> +} EFI_SYSTEM_RESOURCE_ENTRY;
> +
> +typedef struct {
> +    UINT32 FwResourceCount;
> +    UINT32 FwResourceCountMax;
> +    UINT64 FwResourceVersion;
> +    EFI_SYSTEM_RESOURCE_ENTRY Entries[];
> +} EFI_SYSTEM_RESOURCE_TABLE;
> 
> typedef EFI_STATUS
> (/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
> @@ -567,6 +587,41 @@ static int __init efi_check_dt_boot(const 
> EFI_LOADED_IMAGE *loaded_image)
> }
> #endif
> 
> +static UINTN __initdata esrt = EFI_INVALID_TABLE_ADDR;
> +
> +static size_t __init get_esrt_size(const EFI_MEMORY_DESCRIPTOR *desc)
> +{
> +    size_t available_len, len;
> +    const UINTN physical_start = desc->PhysicalStart;

Hi,

From my tests on an arm64 machine so far I can tell that desc is NULL here,
for this reason we have the problem.

I’ll have a further look on the cause of this, but if you are faster than me 
you are
welcome to give your opinion on that.

Cheers,
Luca

> +    const EFI_SYSTEM_RESOURCE_TABLE *esrt_ptr;
> +
> +    len = desc->NumberOfPages << EFI_PAGE_SHIFT;
> +    if ( esrt == EFI_INVALID_TABLE_ADDR )
> +        return 0;
> +    if ( physical_start > esrt || esrt - physical_start >= len )
> +        return 0;
> +    /*
> +     * The specification requires EfiBootServicesData, but accept
> +     * EfiRuntimeServicesData, which is a more logical choice.
> +     */
> +    if ( (desc->Type != EfiRuntimeServicesData) &&
> +         (desc->Type != EfiBootServicesData) )
> +        return 0;
> +    available_len = len - (esrt - physical_start);
> +    if ( available_len <= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries) )
> +        return 0;
> +    available_len -= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries);
> +    esrt_ptr = (const EFI_SYSTEM_RESOURCE_TABLE *)esrt;
> +    if ( (esrt_ptr->FwResourceVersion !=
> +          EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION) ||
> +         !esrt_ptr->FwResourceCount )
> +        return 0;
> +    if ( esrt_ptr->FwResourceCount > available_len / 
> sizeof(esrt_ptr->Entries[0]) )
> +        return 0;
> +
> +    return esrt_ptr->FwResourceCount * sizeof(esrt_ptr->Entries[0]);
> +}
> +
> /*
>  * Include architecture specific implementation here, which references the
>  * static globals defined above.
> @@ -845,6 +900,8 @@ static UINTN __init 
> efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
>     return gop_mode;
> }
> 
> +static EFI_GUID __initdata esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
> +
> static void __init efi_tables(void)
> {
>     unsigned int i;
> @@ -868,6 +925,8 @@ static void __init efi_tables(void)
>             efi.smbios = (unsigned long)efi_ct[i].VendorTable;
>         if ( match_guid(&smbios3_guid, &efi_ct[i].VendorGuid) )
>             efi.smbios3 = (unsigned long)efi_ct[i].VendorTable;
> +        if ( match_guid(&esrt_guid, &efi_ct[i].VendorGuid) )
> +            esrt = (UINTN)efi_ct[i].VendorTable;
>     }
> 
> #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
> @@ -1051,6 +1110,70 @@ static void __init 
> efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop
> #define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
>                                  (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
> 
> +static void __init efi_relocate_esrt(EFI_SYSTEM_TABLE *SystemTable)
> +{
> +    EFI_STATUS status;
> +    UINTN info_size = 0, map_key, mdesc_size;
> +    void *memory_map = NULL;
> +    UINT32 ver;
> +    unsigned int i;
> +
> +    for ( ; ; ) {
> +        status = efi_bs->GetMemoryMap(&info_size, memory_map, &map_key,
> +                                      &mdesc_size, &ver);
> +        if ( status == EFI_SUCCESS && memory_map != NULL )
> +            break;
> +        if ( status == EFI_BUFFER_TOO_SMALL || memory_map == NULL )
> +        {
> +            info_size += 8 * efi_mdesc_size;
> +            if ( memory_map != NULL )
> +                efi_bs->FreePool(memory_map);
> +            memory_map = NULL;
> +            status = efi_bs->AllocatePool(EfiLoaderData, info_size, 
> &memory_map);
> +            if ( status == EFI_SUCCESS )
> +                continue;
> +            PrintErr(L"Cannot allocate memory to relocate ESRT\r\n");
> +        }
> +        else
> +            PrintErr(L"Cannot obtain memory map to relocate ESRT\r\n");
> +        return;
> +    }
> +
> +    /* Try to obtain the ESRT.  Errors are not fatal. */
> +    for ( i = 0; i < info_size; i += efi_mdesc_size )
> +    {
> +        /*
> +         * ESRT needs to be moved to memory of type EfiRuntimeServicesData
> +         * so that the memory it is in will not be used for other purposes.
> +         */
> +        void *new_esrt = NULL;
> +        size_t esrt_size = get_esrt_size(efi_memmap + i);
> +
> +        if ( !esrt_size )
> +            continue;
> +        if ( ((EFI_MEMORY_DESCRIPTOR *)(efi_memmap + i))->Type ==
> +             EfiRuntimeServicesData )
> +            break; /* ESRT already safe from reuse */
> +        status = efi_bs->AllocatePool(EfiRuntimeServicesData, esrt_size,
> +                                      &new_esrt);
> +        if ( status == EFI_SUCCESS && new_esrt )
> +        {
> +            memcpy(new_esrt, (void *)esrt, esrt_size);
> +            status = efi_bs->InstallConfigurationTable(&esrt_guid, new_esrt);
> +            if ( status != EFI_SUCCESS )
> +            {
> +                PrintErr(L"Cannot install new ESRT\r\n");
> +                efi_bs->FreePool(new_esrt);
> +            }
> +        }
> +        else
> +            PrintErr(L"Cannot allocate memory for ESRT\r\n");
> +        break;
> +    }
> +
> +    efi_bs->FreePool(memory_map);
> +}
> +
> static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
> {
>     EFI_STATUS status;
> @@ -1413,6 +1536,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
>     if ( gop )
>         efi_set_gop_mode(gop, gop_mode);
> 
> +    efi_relocate_esrt(SystemTable);
> +
>     efi_exit_boot(ImageHandle, SystemTable);
> 
>     efi_arch_post_exit_boot(); /* Doesn't return. */
> @@ -1753,3 +1878,12 @@ void __init efi_init_memory(void)
>     unmap_domain_page(efi_l4t);
> }
> #endif
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> -- 
> Sincerely,
> Demi Marie Obenour (she/her/hers)
> Invisible Things Lab
> 


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.