/** @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 | |
// | |
// | |
// 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; | |
} |