audk/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfi.../DxeContextBufferModuleConfi...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

219 lines
7.0 KiB
C
Raw Normal View History

/** @file
The boot services environment configuration library for the Context Buffer Sample PRM module.
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/PrmConfig.h>
#include <Samples/PrmSampleContextBufferModule/Include/StaticData.h>
#include <PrmContextBuffer.h>
#include <PrmDataBuffer.h>
STATIC EFI_HANDLE mPrmConfigProtocolHandle;
// {5a6cf42b-8bb4-472c-a233-5c4dc4033dc7}
STATIC CONST EFI_GUID mPrmModuleGuid = {
0x5a6cf42b, 0x8bb4, 0x472c, { 0xa2, 0x33, 0x5c, 0x4d, 0xc4, 0x03, 0x3d, 0xc7 }
};
// {e1466081-7562-430f-896b-b0e523dc335a}
STATIC CONST EFI_GUID mCheckStaticDataBufferPrmHandlerGuid = {
0xe1466081, 0x7562, 0x430f, { 0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a }
};
/**
Populates the static data buffer for this PRM module.
@param[out] StaticDataBuffer A pointer to the static data buffer.
@retval EFI_SUCCESS The static data buffer was populated successfully.
@retval EFI_INVALID_PARAMETER The StaticDataBuffer pointer argument is NULL.
**/
EFI_STATUS
PopulateStaticDataBuffer (
OUT STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *StaticDataBuffer
)
{
if (StaticDataBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Note: In a real-world module these values would likely come from somewhere
// like a Setup menu option, PCD, binary data, runtime device info, etc. Ideally,
// this configuration library would be provided an API to get what it needs (the data)
// and not be concerned with how the data is provided. This makes the PRM module more
// portable across systems.
//
StaticDataBuffer->Policy1Enabled = TRUE;
StaticDataBuffer->Policy2Enabled = FALSE;
SetMem (StaticDataBuffer->SomeValueArray, ARRAY_SIZE (StaticDataBuffer->SomeValueArray), 'D');
return EFI_SUCCESS;
}
/**
Allocates and populates the static data buffer for this PRM module.
@param[out] StaticDataBuffer A pointer to a pointer to the static data buffer.
@retval EFI_SUCCESS The static data buffer was allocated and filled successfully.
@retval EFI_INVALID_PARAMETER The StaticDataBuffer pointer argument is NULL.
@retval EFI_OUT_OF_RESOURCES Insufficient memory resources to allocate the static data buffer.
**/
EFI_STATUS
GetStaticDataBuffer (
OUT PRM_DATA_BUFFER **StaticDataBuffer
)
{
EFI_STATUS Status;
PRM_DATA_BUFFER *DataBuffer;
UINTN DataBufferLength;
if (StaticDataBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
*StaticDataBuffer = NULL;
//
// Length of the data buffer = Buffer Header Size + Buffer Data Size
//
DataBufferLength = sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE);
DataBuffer = AllocateRuntimeZeroPool (DataBufferLength);
if (DataBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize the data buffer header
//
DataBuffer->Header.Signature = PRM_DATA_BUFFER_HEADER_SIGNATURE;
DataBuffer->Header.Length = (UINT32)DataBufferLength;
Status = PopulateStaticDataBuffer ((STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *)&DataBuffer->Data[0]);
ASSERT_EFI_ERROR (Status);
*StaticDataBuffer = DataBuffer;
return EFI_SUCCESS;
}
/**
Constructor of the PRM configuration library.
@param[in] ImageHandle The image handle of the driver.
@param[in] SystemTable The EFI System Table pointer.
@retval EFI_SUCCESS The shell command handlers were installed successfully.
@retval EFI_UNSUPPORTED The shell level required was not found.
**/
EFI_STATUS
EFIAPI
ContextBufferModuleConfigLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
PRM_CONTEXT_BUFFER *PrmContextBuffer;
PRM_DATA_BUFFER *StaticDataBuffer;
PRM_CONFIG_PROTOCOL *PrmConfigProtocol;
PrmContextBuffer = NULL;
StaticDataBuffer = NULL;
PrmConfigProtocol = NULL;
/*
In this sample PRM module, the protocol describing this sample module's resources is simply
installed in the constructor.
However, if some data is not available until later, this constructor could register a callback
on the dependency for the data to be available (e.g. ability to communicate with some device)
and then install the protocol. The requirement is that the protocol is installed before end of DXE.
*/
//
// Allocate and populate the static data buffer
//
Status = GetStaticDataBuffer (&StaticDataBuffer);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status) || (StaticDataBuffer == NULL)) {
goto Done;
}
//
// Allocate and populate the context buffer
//
PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option There's currently two approaches being considered for how to allocate the context buffer passed to PRM handlers: 1. The context buffer is allocated and populated in firmware. As such, the FW converts all pointers internal to the buffer to virtual memory addresses at the virtual address change event. A single context buffer pointer is given to the OS via the PRM ACPI table and the OS converts this single physical address to a virtual address when it passes the context buffer as a pointer to PRM handlers. 2. The context buffer is allocated and populated in the OS. The OS gets all the information needed to populate the context buffer from other pre-existing resources (mainly physical addresses in the PRM ACPI table). The OS converts all the physical addresses to virtual addresses, allocates the context buffer instances, and fills in the information. The OS passes the context buffer virtual address to PRM handlers. The prior behavior was (1). The current POR behavior has moved to (2). Until (2) is used more widely, it can be kept around with fairly minimal overhead via a build flag in a few places. So the default behavior is now (2) (the expected permanent behavior) with (1) easily enabled by defining "ALLOCATE_CONTEXT_BUFFER_IN_FW" in the compiler defined macros. A DSC define was added in PrmPkg.dsc to set this compiler macro in the package build. At some point in the future, all code (and some peripheral code) surrounded with this build flag can be removed if (2) is fully decided upon. Cc: Andrew Fish <afish@apple.com> Cc: Kang Gao <kang.gao@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Michael Kubacki <michael.kubacki@microsoft.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Benjamin You <benjamin.you@intel.com> Cc: Liu Yun <yun.y.liu@intel.com> Cc: Ankit Sinha <ankit.sinha@intel.com> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Acked-by: Michael D Kinney <michael.d.kinney@intel.com> Acked-by: Liming Gao <gaoliming@byosoft.com.cn> Acked-by: Leif Lindholm <quic_llindhol@quicinc.com> Reviewed-by: Ankit Sinha <ankit.sinha@intel.com>
2020-04-14 01:38:19 +02:00
//
// This context buffer is not actually used by PRM handler at OS runtime. The OS will allocate
// the actual context buffer passed to the PRM handler.
//
// This context buffer is used internally in the firmware to associate a PRM handler with a
// a static data buffer and a runtime MMIO ranges array so those can be placed into the
// PRM_HANDLER_INFORMATION_STRUCT and PRM_MODULE_INFORMATION_STRUCT respectively for the PRM handler.
//
PrmContextBuffer = AllocateZeroPool (sizeof (*PrmContextBuffer));
ASSERT (PrmContextBuffer != NULL);
if (PrmContextBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
CopyGuid (&PrmContextBuffer->HandlerGuid, &mCheckStaticDataBufferPrmHandlerGuid);
PrmContextBuffer->Signature = PRM_CONTEXT_BUFFER_SIGNATURE;
PrmContextBuffer->Version = PRM_CONTEXT_BUFFER_INTERFACE_VERSION;
PrmContextBuffer->StaticDataBuffer = StaticDataBuffer;
PrmConfigProtocol = AllocateZeroPool (sizeof (*PrmConfigProtocol));
ASSERT (PrmConfigProtocol != NULL);
if (PrmConfigProtocol == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
CopyGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, &mPrmModuleGuid);
PrmConfigProtocol->ModuleContextBuffers.BufferCount = 1;
PrmConfigProtocol->ModuleContextBuffers.Buffer = PrmContextBuffer;
//
// Install the PRM Configuration Protocol for this module. This indicates the configuration
// library has completed resource initialization for the PRM module.
//
Status = gBS->InstallProtocolInterface (
&mPrmConfigProtocolHandle,
&gPrmConfigProtocolGuid,
EFI_NATIVE_INTERFACE,
(VOID *)PrmConfigProtocol
);
Done:
if (EFI_ERROR (Status)) {
if (StaticDataBuffer != NULL) {
FreePool (StaticDataBuffer);
}
if (PrmContextBuffer != NULL) {
FreePool (PrmContextBuffer);
}
if (PrmConfigProtocol != NULL) {
FreePool (PrmConfigProtocol);
}
}
return Status;
}