123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- /** @file
- This file contains the implementation for a Platform Runtime Mechanism (PRM)
- loader driver.
- Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
- Copyright (c) Microsoft Corporation
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "PrmAcpiTable.h"
- #include <Guid/ZeroGuid.h>
- #include <IndustryStandard/Acpi.h>
- #include <Library/BaseLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/DebugLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/PrmContextBufferLib.h>
- #include <Library/PrmModuleDiscoveryLib.h>
- #include <Library/PrmPeCoffLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/UefiLib.h>
- #include <Protocol/AcpiTable.h>
- #include <Protocol/PrmConfig.h>
- #include <PrmContextBuffer.h>
- #include <PrmMmio.h>
- #define _DBGMSGID_ "[PRMLOADER]"
- UINTN mPrmHandlerCount;
- UINTN mPrmModuleCount;
- /**
- Processes a list of PRM context entries to build a PRM ACPI table.
- The ACPI table buffer is allocated and the table structure is built inside this function.
- @param[out] PrmAcpiDescriptionTable A pointer to a pointer to a buffer that is allocated within this function
- and will contain the PRM ACPI table. In case of an error in this function,
- *PrmAcpiDescriptorTable will be NULL.
- @retval EFI_SUCCESS All PRM Modules were processed to construct the PRM ACPI table successfully.
- @retval EFI_INVALID_PARAMETER THe parameter PrmAcpiDescriptionTable is NULL.
- @retval EFI_OUT_OF_RESOURCES Insufficient memory resources to allocate the PRM ACPI table boot services
- memory data buffer.
- **/
- EFI_STATUS
- ProcessPrmModules (
- OUT PRM_ACPI_DESCRIPTION_TABLE **PrmAcpiDescriptionTable
- )
- {
- EFI_IMAGE_EXPORT_DIRECTORY *CurrentImageExportDirectory;
- PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *CurrentExportDescriptorStruct;
- PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiTable;
- PRM_MODULE_IMAGE_CONTEXT *CurrentPrmModuleImageContext;
- CONST CHAR8 *CurrentExportDescriptorHandlerName;
- ACPI_PARAMETER_BUFFER_DESCRIPTOR *CurrentModuleAcpiParamDescriptors;
- PRM_CONTEXT_BUFFER *CurrentContextBuffer;
- PRM_MODULE_CONTEXT_BUFFERS *CurrentModuleContextBuffers;
- PRM_MODULE_INFORMATION_STRUCT *CurrentModuleInfoStruct;
- PRM_HANDLER_INFORMATION_STRUCT *CurrentHandlerInfoStruct;
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS CurrentImageAddress;
- UINTN AcpiParamIndex;
- UINTN HandlerIndex;
- UINT32 PrmAcpiDescriptionTableBufferSize;
- UINT64 HandlerPhysicalAddress;
- DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
- if (PrmAcpiDescriptionTable == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- *PrmAcpiDescriptionTable = NULL;
- //
- // The platform DSC GUID must be set to a non-zero value
- //
- if (CompareGuid (&gEdkiiDscPlatformGuid, &gZeroGuid)) {
- DEBUG ((
- DEBUG_ERROR,
- " %a %a: The Platform GUID in the DSC file must be set to a unique non-zero value.\n",
- _DBGMSGID_,
- __FUNCTION__
- ));
- ASSERT (!CompareGuid (&gEdkiiDscPlatformGuid, &gZeroGuid));
- }
- DEBUG ((DEBUG_INFO, " %a %a: %d total PRM modules to process.\n", _DBGMSGID_, __FUNCTION__, mPrmModuleCount));
- DEBUG ((DEBUG_INFO, " %a %a: %d total PRM handlers to process.\n", _DBGMSGID_, __FUNCTION__, mPrmHandlerCount));
- PrmAcpiDescriptionTableBufferSize = (UINT32)(OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure) +
- (OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) * mPrmModuleCount) +
- (sizeof (PRM_HANDLER_INFORMATION_STRUCT) * mPrmHandlerCount)
- );
- DEBUG ((DEBUG_INFO, " %a %a: Total PRM ACPI table size: 0x%x.\n", _DBGMSGID_, __FUNCTION__, PrmAcpiDescriptionTableBufferSize));
- PrmAcpiTable = AllocateZeroPool ((UINTN)PrmAcpiDescriptionTableBufferSize);
- if (PrmAcpiTable == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- PrmAcpiTable->Header.Signature = PRM_TABLE_SIGNATURE;
- PrmAcpiTable->Header.Length = PrmAcpiDescriptionTableBufferSize;
- PrmAcpiTable->Header.Revision = PRM_TABLE_REVISION;
- PrmAcpiTable->Header.Checksum = 0x0;
- CopyMem (&PrmAcpiTable->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (PrmAcpiTable->Header.OemId));
- PrmAcpiTable->Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
- PrmAcpiTable->Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
- PrmAcpiTable->Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
- PrmAcpiTable->Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
- CopyGuid (&PrmAcpiTable->PrmPlatformGuid, &gEdkiiDscPlatformGuid);
- PrmAcpiTable->PrmModuleInfoOffset = OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure);
- PrmAcpiTable->PrmModuleInfoCount = (UINT32)mPrmModuleCount;
- //
- // Iterate across all PRM Modules on the list
- //
- CurrentModuleInfoStruct = &PrmAcpiTable->PrmModuleInfoStructure[0];
- for (
- CurrentPrmModuleImageContext = NULL, Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext);
- !EFI_ERROR (Status);
- Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext))
- {
- CurrentImageAddress = CurrentPrmModuleImageContext->PeCoffImageContext.ImageAddress;
- CurrentImageExportDirectory = CurrentPrmModuleImageContext->ExportDirectory;
- CurrentExportDescriptorStruct = CurrentPrmModuleImageContext->ExportDescriptor;
- CurrentModuleAcpiParamDescriptors = NULL;
- DEBUG ((
- DEBUG_INFO,
- " %a %a: PRM Module - %a with %d handlers.\n",
- _DBGMSGID_,
- __FUNCTION__,
- (CHAR8 *)((UINTN)CurrentImageAddress + CurrentImageExportDirectory->Name),
- CurrentExportDescriptorStruct->Header.NumberPrmHandlers
- ));
- CurrentModuleInfoStruct->StructureRevision = PRM_MODULE_INFORMATION_STRUCT_REVISION;
- CurrentModuleInfoStruct->StructureLength = (
- OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) +
- (CurrentExportDescriptorStruct->Header.NumberPrmHandlers * sizeof (PRM_HANDLER_INFORMATION_STRUCT))
- );
- CopyGuid (&CurrentModuleInfoStruct->Identifier, &CurrentExportDescriptorStruct->Header.ModuleGuid);
- CurrentModuleInfoStruct->HandlerCount = (UINT32)CurrentExportDescriptorStruct->Header.NumberPrmHandlers;
- CurrentModuleInfoStruct->HandlerInfoOffset = OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure);
- CurrentModuleInfoStruct->MajorRevision = 0;
- CurrentModuleInfoStruct->MinorRevision = 0;
- Status = GetImageVersionInPeCoffImage (
- (VOID *)(UINTN)CurrentImageAddress,
- &CurrentPrmModuleImageContext->PeCoffImageContext,
- &CurrentModuleInfoStruct->MajorRevision,
- &CurrentModuleInfoStruct->MinorRevision
- );
- ASSERT_EFI_ERROR (Status);
- // It is currently valid for a PRM module not to use a context buffer
- Status = GetModuleContextBuffers (
- ByModuleGuid,
- &CurrentModuleInfoStruct->Identifier,
- (CONST PRM_MODULE_CONTEXT_BUFFERS **)&CurrentModuleContextBuffers
- );
- ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);
- if (!EFI_ERROR (Status) && (CurrentModuleContextBuffers != NULL)) {
- CurrentModuleInfoStruct->RuntimeMmioRanges = (UINT64)(UINTN)CurrentModuleContextBuffers->RuntimeMmioRanges;
- CurrentModuleAcpiParamDescriptors = CurrentModuleContextBuffers->AcpiParameterBufferDescriptors;
- }
- //
- // Iterate across all PRM handlers in the PRM Module
- //
- for (HandlerIndex = 0; HandlerIndex < CurrentExportDescriptorStruct->Header.NumberPrmHandlers; HandlerIndex++) {
- CurrentHandlerInfoStruct = &(CurrentModuleInfoStruct->HandlerInfoStructure[HandlerIndex]);
- CurrentHandlerInfoStruct->StructureRevision = PRM_HANDLER_INFORMATION_STRUCT_REVISION;
- CurrentHandlerInfoStruct->StructureLength = sizeof (PRM_HANDLER_INFORMATION_STRUCT);
- CopyGuid (
- &CurrentHandlerInfoStruct->Identifier,
- &CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerGuid
- );
- CurrentExportDescriptorHandlerName = (CONST CHAR8 *)CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerName;
- Status = GetContextBuffer (
- &CurrentHandlerInfoStruct->Identifier,
- CurrentModuleContextBuffers,
- (CONST PRM_CONTEXT_BUFFER **)&CurrentContextBuffer
- );
- if (!EFI_ERROR (Status)) {
- CurrentHandlerInfoStruct->StaticDataBuffer = (UINT64)(UINTN)CurrentContextBuffer->StaticDataBuffer;
- }
- Status = GetExportEntryAddress (
- CurrentExportDescriptorHandlerName,
- CurrentImageAddress,
- CurrentImageExportDirectory,
- &HandlerPhysicalAddress
- );
- ASSERT_EFI_ERROR (Status);
- if (!EFI_ERROR (Status)) {
- CurrentHandlerInfoStruct->PhysicalAddress = HandlerPhysicalAddress;
- DEBUG ((
- DEBUG_INFO,
- " %a %a: Found %a handler physical address at 0x%016x.\n",
- _DBGMSGID_,
- __FUNCTION__,
- CurrentExportDescriptorHandlerName,
- CurrentHandlerInfoStruct->PhysicalAddress
- ));
- }
- //
- // Update the handler ACPI parameter buffer address if applicable
- //
- if (CurrentModuleAcpiParamDescriptors != NULL) {
- for (AcpiParamIndex = 0; AcpiParamIndex < CurrentModuleContextBuffers->AcpiParameterBufferDescriptorCount; AcpiParamIndex++) {
- if (CompareGuid (&CurrentModuleAcpiParamDescriptors[AcpiParamIndex].HandlerGuid, &CurrentHandlerInfoStruct->Identifier)) {
- CurrentHandlerInfoStruct->AcpiParameterBuffer = (UINT64)(UINTN)(
- CurrentModuleAcpiParamDescriptors[AcpiParamIndex].AcpiParameterBufferAddress
- );
- }
- }
- }
- }
- CurrentModuleInfoStruct = (PRM_MODULE_INFORMATION_STRUCT *)((UINTN)CurrentModuleInfoStruct + CurrentModuleInfoStruct->StructureLength);
- }
- *PrmAcpiDescriptionTable = PrmAcpiTable;
- return EFI_SUCCESS;
- }
- /**
- Publishes the PRM ACPI table (PRMT).
- @param[in] PrmAcpiDescriptionTable A pointer to a buffer with a completely populated and valid PRM
- ACPI description table.
- @retval EFI_SUCCESS The PRM ACPI was installed successfully.
- @retval EFI_INVALID_PARAMETER THe parameter PrmAcpiDescriptionTable is NULL or the table signature
- in the table provided is invalid.
- @retval EFI_NOT_FOUND The protocol gEfiAcpiTableProtocolGuid could not be found.
- @retval EFI_OUT_OF_RESOURCES Insufficient memory resources to allocate the PRM ACPI table buffer.
- **/
- EFI_STATUS
- PublishPrmAcpiTable (
- IN PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiDescriptionTable
- )
- {
- EFI_STATUS Status;
- EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
- UINTN TableKey;
- if ((PrmAcpiDescriptionTable == NULL) || (PrmAcpiDescriptionTable->Header.Signature != PRM_TABLE_SIGNATURE)) {
- return EFI_INVALID_PARAMETER;
- }
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
- if (!EFI_ERROR (Status)) {
- TableKey = 0;
- //
- // Publish the PRM ACPI table. The table checksum will be computed during installation.
- //
- Status = AcpiTableProtocol->InstallAcpiTable (
- AcpiTableProtocol,
- PrmAcpiDescriptionTable,
- PrmAcpiDescriptionTable->Header.Length,
- &TableKey
- );
- if (!EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "%a %a: The PRMT ACPI table was installed successfully.\n", _DBGMSGID_, __FUNCTION__));
- }
- }
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
- /**
- The PRM Loader END_OF_DXE protocol notification event handler.
- All PRM Modules that are eligible for dispatch should have been loaded the DXE Dispatcher at the
- time of this function invocation.
- The main responsibilities of the PRM Loader are executed from this function which include 3 phases:
- 1.) Disover PRM Modules - Find all PRM modules loaded during DXE dispatch and insert a PRM Module
- Context entry into a linked list to be handed off to phase 2.
- 2.) Process PRM Modules - Build a GUID to PRM handler mapping for each module that is described in the
- PRM ACPI table so the OS can resolve a PRM Handler GUID to the corresponding PRM Handler physical address.
- 3.) Publish PRM ACPI Table - Publish the PRM ACPI table with the information gathered in the phase 2.
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context The pointer to the notification function's context,
- which is implementation-dependent.
- **/
- VOID
- EFIAPI
- PrmLoaderEndOfDxeNotification (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_STATUS Status;
- PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiDescriptionTable;
- DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
- Status = DiscoverPrmModules (&mPrmModuleCount, &mPrmHandlerCount);
- ASSERT_EFI_ERROR (Status);
- Status = ProcessPrmModules (&PrmAcpiDescriptionTable);
- ASSERT_EFI_ERROR (Status);
- Status = PublishPrmAcpiTable (PrmAcpiDescriptionTable);
- ASSERT_EFI_ERROR (Status);
- if (PrmAcpiDescriptionTable != NULL) {
- FreePool (PrmAcpiDescriptionTable);
- }
- gBS->CloseEvent (Event);
- }
- /**
- The entry point for this module.
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval Others An error occurred when executing this entry point.
- **/
- EFI_STATUS
- EFIAPI
- PrmLoaderEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- EFI_EVENT EndOfDxeEvent;
- DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
- //
- // Discover and process installed PRM modules at the End of DXE
- // The PRM ACPI table is published if one or PRM modules are discovered
- //
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- PrmLoaderEndOfDxeNotification,
- NULL,
- &gEfiEndOfDxeEventGroupGuid,
- &EndOfDxeEvent
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a %a: EndOfDxe callback registration failed! %r.\n", _DBGMSGID_, __FUNCTION__, Status));
- ASSERT_EFI_ERROR (Status);
- }
- return EFI_SUCCESS;
- }
|