MdeModulePkg/DxeCapsuleLibFmp: clone ESRT for runtime access

The DxeCapsuleLibFmp code accesses the ESRT table to decide whether
a certain capsule is an FMP capsule. Since the UEFI spec mandates
that the ESRT resides in EfiBootServicesData memory, this results
in problems at OS runtime, since the firmware implementation itself
cannot access memory that has not been virtually remapped.

So let's take a private copy of the ESRT at ReadyToBoot, and store
it in EfiRuntimeServicesData memory. The ESRT's size is order 10s
of bytes so the memory footprint is going to be negligigble.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
This commit is contained in:
Ard Biesheuvel 2019-04-20 12:34:54 +02:00
parent 40ffb6dc63
commit 2c0d39ac47
2 changed files with 52 additions and 8 deletions

View File

@ -23,6 +23,7 @@
extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
extern BOOLEAN mIsVirtualAddrConverted;
EFI_EVENT mDxeRuntimeCapsuleLibVirtualAddressChangeEvent = NULL;
EFI_EVENT mDxeRuntimeCapsuleLibReadyToBootEvent = NULL;
/**
Convert EsrtTable physical address to virtual address.
@ -38,8 +39,28 @@ DxeCapsuleLibVirtualAddressChangeEvent (
IN VOID *Context
)
{
UINTN Index;
EFI_CONFIGURATION_TABLE *ConfigEntry;
gRT->ConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mEsrtTable);
mIsVirtualAddrConverted = TRUE;
}
/**
Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT.
@param[in] Event The Event that is being processed.
@param[in] Context The Event Context.
**/
STATIC
VOID
EFIAPI
DxeCapsuleLibReadyToBootEventNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINTN Index;
EFI_CONFIGURATION_TABLE *ConfigEntry;
EFI_SYSTEM_RESOURCE_TABLE *EsrtTable;
//
// Get Esrt table first
@ -59,16 +80,19 @@ DxeCapsuleLibVirtualAddressChangeEvent (
//
// Search Esrt to check given capsule is qualified
//
mEsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *) ConfigEntry->VendorTable;
EsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *) ConfigEntry->VendorTable;
mEsrtTable = AllocateRuntimeCopyPool (
sizeof (EFI_SYSTEM_RESOURCE_TABLE) +
EsrtTable->FwResourceCount * sizeof (EFI_SYSTEM_RESOURCE_ENTRY),
EsrtTable);
ASSERT (mEsrtTable != NULL);
//
// Update protocol pointer to Esrt Table.
// Set FwResourceCountMax to a sane value.
//
gRT->ConvertPointer (0x00, (VOID**) &(mEsrtTable));
mEsrtTable->FwResourceCountMax = mEsrtTable->FwResourceCount;
}
mIsVirtualAddrConverted = TRUE;
}
/**
@ -101,6 +125,19 @@ DxeRuntimeCapsuleLibConstructor (
);
ASSERT_EFI_ERROR (Status);
//
// Register notify function to cache the FMP capsule GUIDs at ReadyToBoot.
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
DxeCapsuleLibReadyToBootEventNotify,
NULL,
&gEfiEventReadyToBootGuid,
&mDxeRuntimeCapsuleLibReadyToBootEvent
);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
@ -127,5 +164,11 @@ DxeRuntimeCapsuleLibDestructor (
Status = gBS->CloseEvent (mDxeRuntimeCapsuleLibVirtualAddressChangeEvent);
ASSERT_EFI_ERROR (Status);
//
// Close the ReadyToBoot event.
//
Status = gBS->CloseEvent (mDxeRuntimeCapsuleLibReadyToBootEvent);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}

View File

@ -66,6 +66,7 @@
gEfiCapsuleReportGuid
gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
gEfiEventReadyToBootGuid ## CONSUMES ## Event
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
[Depex]