PrmPkg: Add initial PrmSampleContextBufferModule

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

Adds a sample PRM module that demonstrates:
  1. How to write a PRM module
  2. How to use a basic PRM OS services
  3. How to use a basic PRM module configuration library
  4. How to use a context buffer during PRM handler execution

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>
This commit is contained in:
Michael Kubacki 2020-04-07 11:33:23 -07:00 committed by mergify[bot]
parent 27b1a840e4
commit 7c41ec47ca
5 changed files with 490 additions and 0 deletions

View File

@ -0,0 +1,24 @@
/** @file
PRM Module Static Data
Defines the structure of the static data buffer for the PRM Sample Context Buffer module.
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef PRM_STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE_H_
#define PRM_STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE_H_
#include <Base.h>
#define SOME_VALUE_ARRAY_MAX_VALUES 16
typedef struct {
BOOLEAN Policy1Enabled;
BOOLEAN Policy2Enabled;
UINT8 SomeValueArray[SOME_VALUE_ARRAY_MAX_VALUES];
} STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE;
#endif

View File

@ -0,0 +1,203 @@
/** @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 mDumpStaticDataBufferPrmHandlerGuid = {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 sample module uses a single context buffer for all the handlers
// Todo: This can be done more elegantly in the future. Likely though a library service.
//
PrmContextBuffer = AllocateRuntimeZeroPool (sizeof (*PrmContextBuffer));
ASSERT (PrmContextBuffer != NULL);
if (PrmContextBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
CopyGuid (&PrmContextBuffer->HandlerGuid, &mDumpStaticDataBufferPrmHandlerGuid);
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;
}

View File

@ -0,0 +1,39 @@
## @file
# Sample PRM Configuration Library Instance
#
# The PRM configuration library instance is responsible for initializing and setting the corresponding
# PRM module's configuration in the boot environment.
#
# Copyright (c) Microsoft Corporation
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DxeContextBufferModuleConfigLib
FILE_GUID = FFB56F09-65E3-4462-A799-2F0D1930D38C
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL |DXE_DRIVER
CONSTRUCTOR = ContextBufferModuleConfigLibConstructor
[Sources]
DxeContextBufferModuleConfigLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
PrmPkg/PrmPkg.dec
[Protocols]
gPrmConfigProtocolGuid
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
MemoryAllocationLib
UefiBootServicesTableLib
UefiDriverEntryPoint

View File

@ -0,0 +1,182 @@
/** @file
This PRM Module demonstrates how to configure the module data resources in the firmware boot environment
and access those resources in a PRM handler at OS runtime.
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PrmModule.h>
#include <Library/BaseLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiLib.h>
#include <Samples/PrmSampleContextBufferModule/Include/StaticData.h>
//
// PRM Handler GUIDs
//
// {e1466081-7562-430f-896b-b0e523dc335a}
#define DUMP_STATIC_DATA_BUFFER_PRM_HANDLER_GUID {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}}
/**
Dumps the contents of a given buffer.
@param[in] OsServiceDebugPrint A pointer to the debug print OS service.
@param[in] Buffer A pointer to the buffer that should be dumped.
@param[in] BufferSize The size of Buffer in bytes.
**/
STATIC
VOID
DumpBuffer (
IN PRM_OS_SERVICE_DEBUG_PRINT OsServiceDebugPrint,
IN CONST VOID *Buffer,
IN UINTN BufferSize
)
{
UINTN Count;
CONST UINT8 *Char = Buffer;
CHAR8 DebugMessage[16];
if (OsServiceDebugPrint == NULL || Buffer == NULL) {
return;
}
OsServiceDebugPrint (" ");
for (Count = 0; Count < BufferSize; Count++)
{
if (Count && !(Count % 16)) {
OsServiceDebugPrint ("\n ");
}
AsciiSPrint (
&DebugMessage[0],
ARRAY_SIZE (DebugMessage),
"%02X ",
Char[Count]
);
OsServiceDebugPrint (&DebugMessage[0]);
}
OsServiceDebugPrint ("\n\n");
}
/**
Prints the contents of this PRM module's static data buffer.
@param[in] OsServiceDebugPrint A pointer to the debug print OS service.
@param[in] StaticDataBuffer A pointer to the static buffer.
**/
VOID
EFIAPI
PrintStaticDataBuffer (
IN PRM_OS_SERVICE_DEBUG_PRINT OsServiceDebugPrint,
IN CONST STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *StaticDataBuffer
)
{
CHAR8 DebugMessage[256];
if (OsServiceDebugPrint == NULL || StaticDataBuffer == NULL) {
return;
}
AsciiSPrint (
&DebugMessage[0],
ARRAY_SIZE (DebugMessage),
" Policy1Enabled = 0x%x.\n",
StaticDataBuffer->Policy1Enabled
);
OsServiceDebugPrint (&DebugMessage[0]);
AsciiSPrint (
&DebugMessage[0],
ARRAY_SIZE (DebugMessage),
" Policy2Enabled = 0x%x.\n",
StaticDataBuffer->Policy2Enabled
);
OsServiceDebugPrint (&DebugMessage[0]);
OsServiceDebugPrint (" Dumping SomeValueArray:\n");
DumpBuffer (
OsServiceDebugPrint,
(CONST VOID *) &StaticDataBuffer->SomeValueArray[0],
ARRAY_SIZE (StaticDataBuffer->SomeValueArray)
);
}
/**
A sample Platform Runtime Mechanism (PRM) handler.
This sample handler attempts to read the contents of the static data buffer that were configured
during the firmware boot environment and print those contents at OS runtime.
@param[in] OsServices An array of pointers to OS provided services for PRM handlers
@param[in] Context Handler context info
@retval EFI_STATUS The PRM handler executed successfully.
@retval Others An error occurred in the PRM handler.
**/
PRM_HANDLER_EXPORT (DumpStaticDataBufferPrmHandler)
{
PRM_OS_SERVICE_DEBUG_PRINT OsServiceDebugPrint;
if (ContextBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
// In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
if (OsServiceDebugPrint == NULL) {
return EFI_INVALID_PARAMETER;
}
OsServiceDebugPrint ("Context Buffer DumpStaticDataBufferPrmHandler entry.\n");
if (ContextBuffer->StaticDataBuffer == NULL) {
OsServiceDebugPrint ("The static buffer is not allocated!\n");
return EFI_INVALID_PARAMETER;
}
OsServiceDebugPrint (" Printing the contents of the static data buffer:\n");
//
// Verify PRM data buffer signature is valid
//
if (
ContextBuffer->Signature != PRM_CONTEXT_BUFFER_SIGNATURE ||
ContextBuffer->StaticDataBuffer->Header.Signature != PRM_DATA_BUFFER_HEADER_SIGNATURE) {
OsServiceDebugPrint (" A buffer signature is invalid!\n");
return EFI_NOT_FOUND;
}
PrintStaticDataBuffer (
OsServiceDebugPrint,
(CONST STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *) &(ContextBuffer->StaticDataBuffer->Data[0])
);
OsServiceDebugPrint ("Context Buffer DumpStaticDataBufferPrmHandler exit.\n");
return EFI_SUCCESS;
}
//
// Register the PRM export information for this PRM Module
//
PRM_MODULE_EXPORT (
PRM_HANDLER_EXPORT_ENTRY (DUMP_STATIC_DATA_BUFFER_PRM_HANDLER_GUID, DumpStaticDataBufferPrmHandler)
);
EFI_STATUS
EFIAPI
PrmSampleContextBufferModuleInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EFI_SUCCESS;
}

View File

@ -0,0 +1,42 @@
## @file
# Sample PRM Driver
#
# A sample PRM Module implementation. This PRM Module includes a PRM Module configuration library instance
# that applies the configuration for the PRM context data in the boot environment. A PRM handler
# is provided that accesses the context buffer resources and prints their value at OS runtime.
#
# Copyright (c) Microsoft Corporation
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PrmSampleContextBufferModule
FILE_GUID = 5A6CF42B-8BB4-472C-A233-5C4DC4033DC7
MODULE_TYPE = DXE_RUNTIME_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = PrmSampleContextBufferModuleInit
[Sources]
Include/StaticData.h
PrmSampleContextBufferModule.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
PrmPkg/PrmPkg.dec
[LibraryClasses]
BaseLib
PrintLib
UefiDriverEntryPoint
UefiLib
[Depex]
TRUE
[BuildOptions.common]
MSFT:*_*_*_DLINK_FLAGS = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0