/** @file UpdatePcdPei - UBA PCD Update PEIM This PEIM locates the UBA PCD update table via the UBA configuration protocol and invokes the board-specific PCD update function during PEI phase.
Source: PurleyPlatPkg/Library/PeiUbaPlatLib/UbaPcdUpdateLib.c Copyright (C) 2024, Intel Corporation. All rights reserved.
**/
#include "UpdatePcdPei.h"
/**Entry point of the UpdatePcdPei module.
Delegates to UbaPcdUpdateEntry().
@param[in] ImageHandle Handle for this PEIM's image.
@param[in] SystemTable Pointer to the EFI system table.
@retval EFI_SUCCESS The PCD update completed successfully.
@retval others An error occurred.
**/
EFI_STATUS EFIAPI ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return UbaPcdUpdateEntry ();
}
/**Locates the UBA PCD Update protocol and invokes the board-specific PCD update callback.
1. Retrieves the PEI services table pointer via IDT.
2. Locates the "gUbaPcdUpdateProtocolGuid" protocol.
3. Reads the PCD_UPDATE_TABLE (12 bytes) from the protocol's data.
4. Validates signature ('PPCD') and version (1).
5. Calls the function pointer at offset 8 within the table.
6. If the callback fails, triggers an ASSERT.
@retval EFI_SUCCESS PCD update executed successfully.
@retval others PCD update failed or protocol not found.
**/
INT32 UbaPcdUpdateEntry (
VOID
)
{
EFI_STATUS Status;
VOID *Interface;
UINT32 n12;
PCD_UPDATE_TABLE PcdTable;
Interface = NULL;
Status = PeiServicesLocatePpi (
&gUbaPcdUpdatePpiGuid,
0,
NULL,
&Interface
);
if (EFI_ERROR (Status)) {
return Status;
}
n12 = sizeof (PCD_UPDATE_TABLE);
Status = PeiPpiGetData (Interface, &gUbaPcdUpdatePpiGuid, (VOID *)&PcdTable, &n12);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (PcdTable.Signature == PCD_UPDATE_TABLE_SIGNATURE);
ASSERT (PcdTable.Version == PCD_UPDATE_TABLE_VERSION);
Status = PcdTable.UpdatePcd ();
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT_EFI_ERROR (FALSE);
}
return Status;
}
/**Retrieves the PEI Services Table pointer via the IDT-based pointer mechanism.
@return Pointer to the PEI Services Table, or NULL if not available.
**/
INT32 GetPeiServicesTablePointer (
VOID
)
{
IA32_DESCRIPTOR Idtr;
UINT32 *Ptr;
X86ReadIdtr (&Idtr);
Ptr = *(UINT32 **)(*(UINT32 *)&Idtr.IdtBase - 4);
if (Ptr == NULL) {
DEBUG ((EFI_D_ERROR, "PeiServices != ((void *) 0)\n"));
}
return (INT32)Ptr;
}
/**Locate the PCD debug protocol for reporting debug messages and asserts.
@return Pointer to the debug protocol interface, or 0 if not found.
**/
INT32 PcdDebugProtocolLocate (
VOID
)
{
INT32 DebugProtocol;
if (PeiServicesLocatePpi (
&gEfiPeiDebugPpiGuid,
0,
NULL,
&DebugProtocol
) >= 0) {
return DebugProtocol;
}
return 0;
}
/**Prints a debug message using the PCD debug protocol.
@param[in] ErrorLevel Debug error level.
@param[in] Format Format string.
@param[in] ... Variable arguments.
**/
INT32 PcdDebugPrint (
IN INT32 ErrorLevel,
IN CHAR8 *Format,
...
)
{
INT32 DebugProtocol;
INT32 ( **PrintFn)(INT32, CHAR8 *, ...);
DebugProtocol = PcdDebugProtocolLocate ();
if (DebugProtocol != 0) {
PrintFn = (INT32 ( **)(INT32, CHAR8 *, ...))DebugProtocol;
return (*PrintFn)(ErrorLevel, Format);
}
return DebugProtocol;
}
/**Asserts a condition and prints a debug message if the condition is FALSE.
@param[in] ErrorLevel Assertion error level.
@param[in] Format Format string for assert.
@param[in] ... Variable arguments.
**/
INT32 PcdDebugAssert (
IN INT32 ErrorLevel,
IN CHAR8 *Format,
...
)
{
INT32 Result;
INT32 ( **AssertFn)(INT32, CHAR8 *, ...);
VA_LIST Marker;
VA_START (Marker, Format);
Result = PcdDebugProtocolLocate ();
if (Result != 0) {
if ((PcdGetBootMode () & ErrorLevel) != 0) {
AssertFn = (INT32 ( **)(INT32, CHAR8 *, ...))Result;
return (*AssertFn)(ErrorLevel, Format, (CHAR8 *)Marker);
}
}
return Result;
}
/**Read the current boot mode from the CMOS.
Reads CMOS index 0x4A (preserving bit 7 of index 0x70).
Interprets the value at port 0x71 as boot mode.
@return Boot mode value:
0 = BOOT_WITH_FULL_CONFIGURATION 1 = BOOT_WITH_MINIMAL_CONFIGURATION 0xFF = invalid (default)
-2147483644 = BOOT_WITH_DEFAULT_SETTINGS
-2147483578 = BOOT_WITH_FULL_CONFIG_PLUS_DIAG
**/
INT32 PcdGetBootMode (
VOID
)
{
UINT8 Index;
UINT8 CmosData;
Index = __inbyte (0x70);
__outbyte (0x70, Index & 0x80 | 0x4A);
CmosData = __inbyte (0x71);
if ((UINT8)CmosData <= 3) {
if (CmosData == 0)
return 0;
if (CmosData == 1)
return -2147483644;
return -2147483578;
}
if (CmosData == 0) {
CmosData = (MEMORY[0xFDAF0490] & 2) | 1;
if (CmosData == 0)
return 0;
if (CmosData == 1)
return -2147483644;
return -2147483578;
}
if (CmosData != (CHAR8)-1)
return -2147483578;
return 0;
}
/**Reads the IDTR register into the provided descriptor buffer.
@param[out] Idtr Pointer to the IA32_DESCRIPTOR buffer.
@return Pointer to Idtr.
**/
VOID *__thiscall X86ReadIdtr (
VOID *Idtr
)
{
if (Idtr == NULL) {
DEBUG ((EFI_D_ERROR, "Idtr != ((void *) 0)\n"));
}
__sidt (Idtr);
return Idtr;
}