/** @file
UBA Configuration Database PEIM
Source: CpPlatPkg/Uba/CfgDb/Pei/CfgDbPei.c
This PEIM implements a configuration database service for UBA (UEFI BIOS
Abstraction) during the PEI phase. UBA producers register configuration
records keyed by GUID. On notification (HOB notify), the database is
serialized into a HOB for consumption by the DXE phase counterpart.
Copyright (c) 2024, American Megatrends International LLC.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Library/HobLib.h>
#include "UbaConfigDatabasePei.h"
/**
Retrieves the PEI Services pointer from the IDT-based table.
**/
INTN
GetPeiServices (
VOID
)
{
IA32_DESCRIPTOR Idtr;
UINTN *PeiServices;
AsmReadIdtr (&Idtr);
PeiServices = *(UINTN **)(*(UINTN *)&Idtr.Base - 4);
ASSERT (PeiServices != NULL);
return (INTN)PeiServices;
}
/**
Locate and get the Debug Service PPI.
**/
EFI_PEI_PPI_DESCRIPTOR *
EFIAPI
PeiServicesGetDebugLibPpi (
VOID
)
{
EFI_STATUS Status;
INTN PeiServices;
UINTN Instance;
EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor;
VOID *Ppi;
PeiServices = GetPeiServices ();
Instance = 0;
Status = ((EFI_PEI_SERVICES **)PeiServices)->LocatePpi (
PeiServices,
&gEfiDebugServicePpiGuid,
Instance,
&PpiDescriptor,
&Ppi
);
if (!EFI_ERROR (Status)) {
return (EFI_PEI_PPI_DESCRIPTOR *)Ppi;
}
return NULL;
}
/**
Debug print via the Debug Service PPI.
**/
VOID
EFIAPI
PeiDebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
EFI_PEI_PPI_DESCRIPTOR *DebugPpi;
UINTN Enabled;
DebugPpi = PeiServicesGetDebugLibPpi ();
if (DebugPpi != NULL) {
Enabled = DebugPrintEnabled ();
if ((Enabled & ErrorLevel) != 0) {
VA_LIST Va;
VA_START (Va, Format);
((DEBUG_PRINT_PROTOCOL *)DebugPpi)->DebugPrint (ErrorLevel, Format, Va);
VA_END (Va);
}
}
}
/**
Debug assert via the Debug Service PPI.
**/
VOID
EFIAPI
PeiDebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
EFI_PEI_PPI_DESCRIPTOR *DebugPpi;
DebugPpi = PeiServicesGetDebugLibPpi ();
if (DebugPpi != NULL) {
((DEBUG_ASSERT_PROTOCOL *)DebugPpi)->DebugAssert (FileName, LineNumber, Description);
}
}
//
// Config Database helper functions
//
/**
Get the signature field from a configuration database node.
@param[in] Node Pointer to a UBA_CFG_DB_NODE (or its ListRecord field).
@param[out] Count Records count from the node.
@retval EFI_SUCCESS Signature validated and count retrieved.
**/
EFI_STATUS
EFIAPI
CfgDbLibGetNodeSignature (
IN VOID *Node,
OUT UINT32 *Count
)
{
UBA_CFG_DB_RECORD *Record;
UBA_CFG_DB_NODE *DbNode;
Record = (UBA_CFG_DB_RECORD *)Node;
if (Record->Signature == UBA_CFG_DB_SIGNATURE) {
//
// Node is a UBA_CFG_DB_RECORD; get count from container
//
DbNode = (UBA_CFG_DB_NODE *)((UINT8 *)Record - OFFSET_OF (UBA_CFG_DB_RECORD, ListEntry));
} else {
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
DbNode = (UBA_CFG_DB_NODE *)Record;
}
*Count = DbNode->RecordCount;
return EFI_SUCCESS;
}
/**
Allocate and initialize a new config database node.
@param[in] DbName Name for this database.
@param[in] Type Database type identifier.
@param[in] DbGuid GUID key for this database.
@param[in] Description Human-readable description.
@param[out] NewNode Pointer to the newly allocated node.
@retval EFI_SUCCESS Node created.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
**/
EFI_STATUS
EFIAPI
CfgDbLibInitNode (
IN CHAR8 *DbName,
IN UINT32 Type,
IN GUID *DbGuid,
IN CHAR8 *Description,
OUT UBA_CFG_DB_NODE **NewNode
)
{
UBA_CFG_DB_RECORD *Record;
UBA_CFG_DB_NODE *DbNode;
UINT32 Signature;
//
// Check if DbName is actually a record; resolve to the container node
//
Record = (UBA_CFG_DB_RECORD *)DbName;
if (Record->Signature == UBA_CFG_DB_SIGNATURE) {
DbNode = (UBA_CFG_DB_NODE *)((UINT8 *)DbName - OFFSET_OF (UBA_CFG_DB_RECORD, ListEntry));
} else {
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
DbNode = (UBA_CFG_DB_NODE *)DbName;
}
DbNode = (UBA_CFG_DB_NODE *)PeiServicesAllocateZeroPool (sizeof (UBA_CFG_DB_NODE));
if (DbNode == NULL) {
return EFI_OUT_OF_RESOURCES;
}
DbNode->Signature = UBA_CFG_DB_SIGNATURE;
DbNode->Version = 1;
DbNode->RecordCount = Type;
if (Description != NULL) {
AsciiStrnCpyS (Description, ASCII_STR_N (sizeof (DbNode->Name)));
}
if (DbGuid != NULL) {
CopyMem (DbNode->Name, DbGuid, sizeof (GUID));
}
InitializeListHead (&DbNode->RecordListHead);
if (NewNode != NULL) {
*NewNode = DbNode;
//
// Update the database pointer in the original node
//
((UBA_CFG_DB_NODE *)((UINT8 *)DbName - OFFSET_OF (UBA_CFG_DB_RECORD, ListEntry)))->RecordCount = (UINT32)(UINTN)DbNode;
}
return EFI_SUCCESS;
}
//
// CR (Container Record) macros
//
#define CR_FROM_LIST_ENTRY(Record, Type, Field) \
(Type *)((UINT8 *)(Record) - OFFSET_OF (Type, Field))
/**
Adjust offsets within a config database after relocation.
This function adjusts internal pointers (linked list forward/back links,
record data pointers) when the database is relocated within PEI memory.
@param[in] NodeBase Pointer to the database record's ListEntry field.
@param[in] Increase TRUE if addresses increased, FALSE if decreased.
@param[in] Delta Size of the relocation.
**/
EFI_STATUS
EFIAPI
CfgDbLibAdjustOffsets (
IN VOID *NodeBase,
IN BOOLEAN Increase,
IN INTN Delta
)
{
UBA_CFG_DB_RECORD *Record;
LIST_ENTRY *ListHead;
LIST_ENTRY *Entry;
Record = (UBA_CFG_DB_RECORD *)NodeBase;
if (Record->Signature == UBA_CFG_DB_SIGNATURE) {
Record = Record;
} else {
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
Record = (UBA_CFG_DB_RECORD *)NodeBase;
}
//
// Only adjust if the relocation hasn't been applied yet
//
if (Record->Type != (UINT32)(UINTN)NodeBase) {
if (Record->Guid.Data1 != 0) {
if (Increase) {
Record->Guid.Data1 += (UINT32)Delta;
} else {
Record->Guid.Data1 -= (UINT32)Delta;
}
ListHead = (LIST_ENTRY *)(Record->Guid.Data1 + OFFSET_OF (LIST_ENTRY, Flink));
if (Increase) {
ListHead->Flink += Delta;
ListHead->Blink += Delta;
} else {
ListHead->Flink -= Delta;
ListHead->Blink -= Delta;
}
Entry = (LIST_ENTRY *)ListHead->Flink;
while (Entry != ListHead) {
if (Increase) {
Entry->Flink += Delta;
Entry->Blink += Delta;
} else {
Entry->Flink -= Delta;
Entry->Blink -= Delta;
}
Record = CR_FROM_LIST_ENTRY (Entry, UBA_CFG_DB_RECORD, ListEntry);
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
if (Increase) {
Record->DataSize += (UINT32)Delta;
} else {
Record->DataSize -= (UINT32)Delta;
}
Entry = (LIST_ENTRY *)Entry->Flink;
}
}
Record->Type = (UINT32)(UINTN)NodeBase;
}
return EFI_SUCCESS;
}
/**
Fixup relocations for a config database.
@param[in] RecordBase Pointer to a UBA_CFG_DB_RECORD (ListEntry field).
**/
EFI_STATUS
EFIAPI
CfgDbLibFixupRelocation (
IN VOID *RecordBase
)
{
UBA_CFG_DB_RECORD *Record;
UINTN RelocDelta;
Record = (UBA_CFG_DB_RECORD *)RecordBase;
if (Record->Signature == UBA_CFG_DB_SIGNATURE) {
Record = Record;
} else {
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
Record = (UBA_CFG_DB_RECORD *)RecordBase;
}
if (Record->Type != (UINT32)(UINTN)RecordBase) {
if (RecordBase <= (VOID *)(UINTN)Record->Type) {
RelocDelta = (UINTN)Record->Type - (UINTN)RecordBase;
return CfgDbLibAdjustOffsets (RecordBase, TRUE, RelocDelta);
} else {
RelocDelta = (UINTN)RecordBase - (UINTN)Record->Type;
return CfgDbLibAdjustOffsets (RecordBase, FALSE, RelocDelta);
}
}
return EFI_SUCCESS;
}
/**
Get the database pointer from a record.
This function resolves the UBA_CFG_DB_NODE pointer from a UBA_CFG_DB_RECORD
and returns it via the database handle.
@param[in] NodeBase Pointer to a UBA_CFG_DB_RECORD's ListEntry.
@param[out] Database Pointer to receive the UBA_CFG_DB_NODE.
@retval EFI_SUCCESS Database found.
@retval Others Error from LocatePpi.
**/
EFI_STATUS
EFIAPI
CfgDbPeiGetDatabase (
IN VOID *NodeBase,
OUT UBA_CFG_DB_NODE **Database
)
{
return EFI_SUCCESS; // Not found as standalone - resolved via PPI pointer
}
/**
Get record count and key info from the database.
@param[in] DbName Database name.
@param[out] Count Record count.
@param[out] DbGuid Database GUID.
@param[out] DbDesc Database description.
@retval EFI_SUCCESS Info retrieved.
**/
EFI_STATUS
EFIAPI
CfgDbLibGetRecord (
IN CHAR8 *DbName,
OUT UINT32 *Count,
OUT GUID *DbGuid,
OUT CHAR8 *DbDesc
)
{
EFI_STATUS Status;
UBA_CFG_DB_NODE *DbNode;
UBA_CFG_DB_RECORD *Record;
Record = (UBA_CFG_DB_RECORD *)DbName;
CfgDbLibFixupRelocation (Record);
Status = CfgDbPeiGetDatabase (DbName, &DbNode);
if (EFI_ERROR (Status)) {
return Status;
}
if (Count != NULL) {
*Count = DbNode->RecordCount;
}
if (DbDesc != NULL) {
UINT32 Len;
Len = AsciiStrLen (DbNode->Name);
AsciiStrCpyS (DbDesc, Len + 1, DbNode->Name);
}
if (DbGuid != NULL) {
CopyMem (DbGuid, &DbNode->RecordListHead.Flink, sizeof (GUID));
}
return EFI_SUCCESS;
}
/**
Find a record in the database by GUID key.
@param[in] DbNode Database node.
@param[in] Key GUID key to search for.
@param[out] Data Buffer to receive record data.
@param[out] DataSize On input, max buffer size; on output, actual size.
@retval EFI_SUCCESS Record found.
@retval EFI_NOT_FOUND No matching record.
@retval EFI_BUFFER_TOO_SMALL Buffer too small for data.
@retval EFI_INVALID_PARAMETER Null parameter.
**/
EFI_STATUS
EFIAPI
CfgDbLibFindRecord (
IN UBA_CFG_DB_NODE *DbNode,
IN GUID *Key,
OUT VOID *Data,
IN OUT UINT32 *DataSize
)
{
LIST_ENTRY *ListHead;
LIST_ENTRY *Entry;
UBA_CFG_DB_RECORD *Record;
if ((DbNode == NULL) || (Key == NULL)) {
return EFI_INVALID_PARAMETER;
}
ListHead = &DbNode->RecordListHead;
if (IsListEmpty (ListHead)) {
return EFI_NOT_FOUND;
}
Entry = GetFirstNode (ListHead);
while (!IsNull (ListHead, Entry)) {
Record = CR_FROM_LIST_ENTRY (Entry, UBA_CFG_DB_RECORD, ListEntry);
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
if (Record == NULL) {
ASSERT (Record != NULL);
return EFI_NOT_FOUND;
}
if (CompareGuid (Key, &Record->Guid)) {
if (DataSize != NULL) {
if (*DataSize < Record->DataSize) {
*DataSize = Record->DataSize;
return EFI_BUFFER_TOO_SMALL;
}
*DataSize = Record->DataSize;
if (Data != NULL && Record->DataSize > 0) {
CopyMem (Data, Record->Data, Record->DataSize);
}
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
Entry = GetNextNode (ListHead, Entry);
}
return EFI_NOT_FOUND;
}
/**
Add a record to the config database.
@param[in] DbBase Pointer to a config database record's ListEntry.
@param[in] Src Record data.
@param[in] DataSize Size of record data.
@param[in] Key GUID key.
@retval EFI_SUCCESS Record added.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval EFI_INVALID_PARAMETER Bad parameter.
**/
EFI_STATUS
EFIAPI
CfgDbLibAddRecord (
IN VOID *DbBase,
IN VOID *Src,
IN UINT32 DataSize,
IN GUID *Key
)
{
UBA_CFG_DB_RECORD *Record;
UBA_CFG_DB_NODE *DbNode;
UBA_CFG_DB_RECORD *NewRecord;
UINT32 *NotifyPpi;
if ((Src == NULL) || (DataSize == 0) || (Key == NULL)) {
return EFI_INVALID_PARAMETER;
}
Record = (UBA_CFG_DB_RECORD *)DbBase;
if (Record->Signature == UBA_CFG_DB_SIGNATURE) {
Record = Record;
} else {
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
Record = (UBA_CFG_DB_RECORD *)DbBase;
}
Status = CfgDbPeiGetDatabase (DbBase, &DbNode);
if (EFI_ERROR (Status)) {
return Status;
}
NewRecord = (UBA_CFG_DB_RECORD *)PeiServicesAllocateZeroPool (sizeof (UBA_CFG_DB_RECORD));
if (NewRecord == NULL) {
return EFI_OUT_OF_RESOURCES;
}
NewRecord->Signature = UBA_CFG_DB_SIGNATURE;
NewRecord->Version = 1;
NewRecord->Type = Record->Type;
NewRecord->DataSize = DataSize;
//
// Allocate copy pool for the data
//
NewRecord->Data = PeiServicesAllocateCopyPool (DataSize, Src);
if (NewRecord->Data == NULL) {
// DataSize field still set but data=0 - proceed
}
//
// Copy the GUID key
//
CopyMem (&NewRecord->Guid, Src, sizeof (GUID));
CopyMem (&NewRecord->Guid, Key, sizeof (GUID));
//
// Insert into linked list
//
InsertTailList (&DbNode->RecordListHead, &NewRecord->ListEntry);
DbNode->RecordCount++;
DbNode->TotalRecords++;
Record->Type++; // Increment type counter
//
// Install notification PPI for the added record
//
{
UINT32 *NotifyDescriptor;
NotifyDescriptor = (UINT32 *)PeiServicesAllocateZeroPool (0x0C);
if (NotifyDescriptor != NULL) {
NotifyDescriptor[0] = (UINT32)EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK;
NotifyDescriptor[1] = (UINT32)(UINTN)NewRecord;
NotifyDescriptor[2] = (UINT32)(UINTN)&Record->ListEntry.Flink;
Status = ((EFI_PEI_SERVICES **)GetPeiServices ())->NotifyPpi (
GetPeiServices (),
(EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyDescriptor
);
ASSERT_EFI_ERROR (Status);
} else {
return EFI_OUT_OF_RESOURCES;
}
}
return EFI_SUCCESS;
}
/**
Get data from the database by GUID key.
@param[in] DbName Database name.
@param[in] Key GUID key.
@param[out] Data Buffer for record data.
@param[in,out] DataSize Buffer size / actual data size.
@retval EFI_SUCCESS Data retrieved.
**/
EFI_STATUS
EFIAPI
CfgDbLibGetData (
IN CHAR8 *DbName,
IN GUID *Key,
OUT VOID *Data,
IN OUT UINT32 *DataSize
)
{
EFI_STATUS Status;
UBA_CFG_DB_NODE *DbNode;
UBA_CFG_DB_RECORD *Record;
if ((Key == NULL) || (Data == NULL) || (DataSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
Record = (UBA_CFG_DB_RECORD *)DbName;
CfgDbLibFixupRelocation (Record);
//
// Validate signature
//
if (Record->Signature != UBA_CFG_DB_SIGNATURE) {
ASSERT (Record->Signature == UBA_CFG_DB_SIGNATURE);
}
Status = CfgDbPeiGetDatabase (DbName, &DbNode);
if (EFI_ERROR (Status)) {
return Status;
}
if (CfgDbLibFindRecord (DbNode, Key, Data, DataSize) != EFI_SUCCESS) {
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/**
Build a GUID HOB containing the serialized configuration database.
@param[in] DbNode Database node to serialize.
@param[in] HobGuid GUID for the HOB.
@retval EFI_SUCCESS HOB built.
@retval others Error from HOB creation.
**/
EFI_STATUS
EFIAPI
CfgDbLibBuildHob (
IN UBA_CFG_DB_NODE *DbNode,
IN GUID *HobGuid
)
{
UINT32 HobSize;
UBA_CFG_DB_HOB *HobData;
UBA_CFG_DB_HOB_RECORD *HobRecord;
LIST_ENTRY *ListHead;
LIST_ENTRY *Entry;
UBA_CFG_DB_RECORD *DbRecord;
UINT32 Index;
UINT8 *DataPtr;
UINT32 NameLen;
if (DbNode->RecordCount == 0) {
return EFI_SUCCESS;
}
//
// Calculate total HOB size:
// - Fixed header: sizeof(UBA_CFG_DB_HOB) = 68 bytes
// - Record array: RecordCount * 36 bytes per record descriptor
// - Data payload: sum of each record's DataSize
//
HobSize = sizeof (UBA_CFG_DB_HOB) + DbNode->RecordCount * sizeof (UBA_CFG_DB_HOB_RECORD);
ListHead = &DbNode->RecordListHead;
for (Entry = GetFirstNode (ListHead);
!IsNull (ListHead, Entry);
Entry = GetNextNode (ListHead, Entry))
{
DbRecord = CR_FROM_LIST_ENTRY (Entry, UBA_CFG_DB_RECORD, ListEntry);
ASSERT (DbRecord->Signature == UBA_CFG_DB_SIGNATURE);
HobSize += DbRecord->DataSize;
}
//
// Create the HOB
//
HobData = (UBA_CFG_DB_HOB *)BuildGuidHob (HobGuid, HobSize);
if (HobData == NULL) {
ASSERT (HobData != NULL);
return EFI_OUT_OF_RESOURCES;
}
//
// Fill HOB header
//
HobData->Signature = 0x48424355; // 'UCBH'
HobData->Version = 1;
CopyGuid (&HobData->DbGuid, HobGuid);
HobData->HobDataSize = HobSize;
HobData->DatabaseId = DbNode->RecordCount;
CopyGuid (&HobData->SourceDbGuid, (GUID *)&DbNode->RecordListHead.Flink);
NameLen = AsciiStrLen (DbNode->Name) + 1;
if (NameLen > 0) {
CopyMem (HobData->SourceDbName, DbNode->Name, NameLen);
}
HobData->RecordCount = DbNode->RecordCount;
//
// Fill record array and data payload
//
HobRecord = (UBA_CFG_DB_HOB_RECORD *)((UINT8 *)HobData + sizeof (UBA_CFG_DB_HOB));
DataPtr = (UINT8 *)HobRecord + DbNode->RecordCount * sizeof (UBA_CFG_DB_HOB_RECORD);
Index = 0;
for (Entry = GetFirstNode (ListHead);
!IsNull (ListHead, Entry);
Entry = GetNextNode (ListHead, Entry))
{
DbRecord = CR_FROM_LIST_ENTRY (Entry, UBA_CFG_DB_RECORD, ListEntry);
ASSERT (DbRecord->Signature == UBA_CFG_DB_SIGNATURE);
if (DbRecord == NULL) {
ASSERT (DbRecord != NULL);
return EFI_NOT_FOUND;
}
HobRecord->DataSize = DbRecord->DataSize;
HobRecord->Type = DbRecord->Type;
CopyGuid (&HobRecord->Key, &DbRecord->Guid);
if (DbRecord->DataSize > 0) {
CopyMem (DataPtr, DbRecord->Data, DbRecord->DataSize);
}
HobRecord->DataOffset = (UINT32)(UINTN)(DataPtr - (UINT8 *)HobData);
HobRecord->Reserved = 0;
DataPtr += DbRecord->DataSize;
HobRecord++;
Index++;
}
return EFI_SUCCESS;
}
/**
HOB notification callback: serializes the configuration database into a HOB
when the notification PPI is signaled.
@retval EFI_SUCCESS HOB serialized successfully.
**/
EFI_STATUS
EFIAPI
CfgDbHobNotify (
VOID
)
{
EFI_STATUS Status;
UBA_CFG_DB_NODE *DbNode;
UBA_CFG_DB_RECORD *Record;
GUID HobGuid = { 0x249DDB57, 0x0D8E, 0x4B8B, { 0x87, 0xA0, 0xD0, 0x86, 0x26, 0x23, 0x46, 0x83 } };
INTN PeiServices;
VOID *Ppi;
PeiServices = GetPeiServices ();
Status = ((EFI_PEI_SERVICES **)PeiServices)->LocatePpi (
PeiServices,
&gUbaConfigDatabasePpiGuid,
0,
NULL,
&Ppi
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
return Status;
}
//
// Get the database node
//
Record = (UBA_CFG_DB_RECORD *)((UBA_CFG_DB_PPI *)Ppi)->Database;
Status = CfgDbLibBuildHob (DbNode, &HobGuid);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
}
return Status;
}
/**
Create a new database (vtable entry for PPI protocol).
@param[in] DbName Database name.
@param[in] Type Database type.
@param[in] DbGuid Database GUID.
@param[in] Description Database description.
@retval EFI_SUCCESS Database created.
**/
EFI_STATUS
EFIAPI
CfgDbNotifyCreateDb (
IN CHAR8 *DbName,
IN UINT32 Type,
IN GUID *DbGuid,
IN CHAR8 *Description
)
{
return CfgDbLibInitNodeAndRelocate (DbName, Type, (CHAR8 *)DbGuid, Description);
}
/**
Init a node and fixup its relocations.
@param[in] DbName Database name.
@param[in] Type Database type.
@param[in] DbGuid Database GUID.
@param[in] Description Database description.
@retval EFI_SUCCESS Node initialized.
**/
EFI_STATUS
EFIAPI
CfgDbLibInitNodeAndRelocate (
IN CHAR8 *DbName,
IN UINT32 Type,
IN CHAR8 *DbGuid,
IN CHAR8 *Description
)
{
UBA_CFG_DB_NODE *NewNode;
NewNode = NULL;
CfgDbLibFixupRelocation (DbName);
return CfgDbLibInitNode (DbName, Type, (GUID *)DbGuid, Description, &NewNode);
}
//
// Notify callbacks for the PPI protocol
//
EFI_STATUS
EFIAPI
CfgDbNotifyGetInfo (
IN CHAR8 *DbName,
OUT UINT32 *RecordCount,
OUT GUID *DbGuid,
OUT CHAR8 *DbDescription
)
{
return CfgDbLibGetRecord (DbName, RecordCount, DbGuid, DbDescription);
}
EFI_STATUS
EFIAPI
CfgDbNotifyAddRecord (
IN CHAR8 *DbName,
IN GUID *Key,
IN VOID *Data,
IN UINT32 DataSize
)
{
return CfgDbLibAddRecord (DbName, (CHAR8 *)Data, DataSize, Key);
}
EFI_STATUS
EFIAPI
CfgDbNotifyFindKey (
IN CHAR8 *DbName,
IN GUID *Key,
OUT VOID *Data,
IN OUT UINT32 *DataSize
)
{
return CfgDbLibGetData (DbName, (INTN)Key, (CHAR8 *)Data, DataSize);
}
//
// Module entry point
//
/**
Main entry for the UBA Configuration Database PEIM.
Allocates a database node, initializes the PPI protocol interface with
callback functions, installs the PPI and a notification PPI (for HOB
serialization), then returns.
@retval EFI_SUCCESS PPI installed successfully.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
**/
EFI_STATUS
EFIAPI
CfgDbPeimEntry (
VOID
)
{
EFI_STATUS Status;
UBA_CFG_DB_PPI *CfgDbPpi;
UINT32 *NotifyDescriptor;
INTN PeiServices;
EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor;
//
// Allocate the database node (0x3C = sizeof(UBA_CFG_DB_NODE))
//
CfgDbPpi = (UBA_CFG_DB_PPI *)PeiServicesAllocateZeroPool (sizeof (UBA_CFG_DB_NODE));
if (CfgDbPpi == NULL) {
return EFI_OUT_OF_RESOURCES;
}
DEBUG ((DEBUG_INFO, "UbaConfigDatabasePeimEntry!\n"));
//
// Initialize the PPI structure
//
CfgDbPpi->Reserved = UBA_CFG_DB_SIGNATURE; // Signature at offset 0-3
CfgDbPpi->Database = 1; // Version
// Database pointer filled by CfgDbLibInitNodeAndRelocate
// Function table:
// [2] = Internal list links (head - self-referential)
//
// PPI descriptor for installation
//
NotifyDescriptor = (UINT32 *)PeiServicesAllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
if (NotifyDescriptor == NULL) {
return EFI_OUT_OF_RESOURCES;
}
NotifyDescriptor[0] = (UINT32)(UINTN)&CfgDbPpi->Reserved; // Not used
NotifyDescriptor[1] = (UINT32)(UINTN)&gUbaConfigDatabasePpiGuid;
NotifyDescriptor[2] = (UINT32)(UINTN)CfgDbPpi;
//
// Install the PPI
//
PeiServices = GetPeiServices ();
Status = ((EFI_PEI_SERVICES **)PeiServices)->InstallPpi (
PeiServices,
NotifyDescriptor
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Install notification PPI for HOB serialization
//
Status = ((EFI_PEI_SERVICES **)GetPeiServices ())->NotifyPpi (
GetPeiServices (),
(EFI_PEI_NOTIFY_DESCRIPTOR *)&mUbaConfigDatabaseNotifyDescriptor
);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Module entry point (thunk).
@param[in] ImageHandle Image handle.
@param[in] SystemTable System table.
@retval EFI_SUCCESS Entry executed.
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return CfgDbPeimEntry ();
}