audk/MdeModulePkg/Universal/PCD/Pei/Pcd.c

802 lines
18 KiB
C

/** @file PCD PEIM
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name: Pcd.c
**/
//
// Include common header file for this module.
//
#include "CommonHeader.h"
#include "Service.h"
PCD_PPI mPcdPpiInstance = {
PeiPcdSetSku,
PeiPcdGet8,
PeiPcdGet16,
PeiPcdGet32,
PeiPcdGet64,
PeiPcdGetPtr,
PeiPcdGetBool,
PeiPcdGetSize,
PeiPcdGet8Ex,
PeiPcdGet16Ex,
PeiPcdGet32Ex,
PeiPcdGet64Ex,
PeiPcdGetPtrEx,
PeiPcdGetBoolEx,
PeiPcdGetSizeEx,
PeiPcdSet8,
PeiPcdSet16,
PeiPcdSet32,
PeiPcdSet64,
PeiPcdSetPtr,
PeiPcdSetBool,
PeiPcdSet8Ex,
PeiPcdSet16Ex,
PeiPcdSet32Ex,
PeiPcdSet64Ex,
PeiPcdSetPtrEx,
PeiPcdSetBoolEx,
PeiRegisterCallBackOnSet,
PcdUnRegisterCallBackOnSet,
PeiPcdGetNextToken,
PeiPcdGetNextTokenSpace
};
STATIC EFI_PEI_PPI_DESCRIPTOR mPpiPCD = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gPcdPpiGuid,
&mPcdPpiInstance
};
EFI_STATUS
EFIAPI
PcdPeimInit (
IN EFI_FFS_FILE_HEADER *FfsHeader,
IN EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
BuildPcdDatabase ();
Status = PeiServicesInstallPpi (&mPpiPCD);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
VOID
EFIAPI
PeiPcdSetSku (
IN UINTN SkuId
)
{
GetPcdDatabase()->Init.SystemSkuId = (SKU_ID) SkuId;
return;
}
UINT8
EFIAPI
PeiPcdGet8 (
IN UINTN TokenNumber
)
{
return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));
}
UINT16
EFIAPI
PeiPcdGet16 (
IN UINTN TokenNumber
)
{
return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
}
UINT32
EFIAPI
PeiPcdGet32 (
IN UINTN TokenNumber
)
{
return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
}
UINT64
EFIAPI
PeiPcdGet64 (
IN UINTN TokenNumber
)
{
return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));
}
VOID *
EFIAPI
PeiPcdGetPtr (
IN UINTN TokenNumber
)
{
return GetWorker (TokenNumber, 0);
}
BOOLEAN
EFIAPI
PeiPcdGetBool (
IN UINTN TokenNumber
)
{
return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));
}
UINTN
EFIAPI
PeiPcdGetSize (
IN UINTN TokenNumber
)
{
PEI_PCD_DATABASE *PeiPcdDb;
UINTN Size;
UINTN MaxSize;
//
// If DebugAssertEnabled is TRUE, we still need to provide the GET size
// function as GetWorker and SetWoker need this function to do ASSERT.
//
if ((!FeaturePcdGet(PcdPeiPcdDatabaseGetSizeEnabled)) &&
(!DebugAssertEnabled ())) {
return 0;
}
PeiPcdDb = GetPcdDatabase ();
//
// TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
// We have to decrement TokenNumber by 1 to make it usable
// as the array index.
//
TokenNumber--;
// EBC compiler is very choosy. It may report warning about comparison
// between UINTN and 0 . So we add 1 in each size of the
// comparison.
ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
Size = (PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
if (Size == 0) {
//
// For pointer type, we need to scan the SIZE_TABLE to get the current size.
//
return GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
} else {
return Size;
}
}
UINT8
EFIAPI
PeiPcdGet8Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber
)
{
return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));
}
UINT16
EFIAPI
PeiPcdGet16Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber
)
{
return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));
}
UINT32
EFIAPI
PeiPcdGet32Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber
)
{
return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));
}
UINT64
EFIAPI
PeiPcdGet64Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber
)
{
return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));
}
VOID *
EFIAPI
PeiPcdGetPtrEx (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber
)
{
return ExGetWorker (Guid, ExTokenNumber, 0);
}
BOOLEAN
EFIAPI
PeiPcdGetBoolEx (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber
)
{
return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));
}
UINTN
EFIAPI
PeiPcdGetSizeEx (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber
)
{
if ((!FeaturePcdGet (PcdPeiPcdDatabaseGetSizeEnabled)) || !FeaturePcdGet (PcdPeiPcdDatabaseExEnabled)) {
return 0;
}
return PeiPcdGetSize (GetExPcdTokenNumber (Guid, ExTokenNumber));
}
EFI_STATUS
EFIAPI
PeiPcdSet8 (
IN UINTN TokenNumber,
IN UINT8 Value
)
{
return SetValueWorker (TokenNumber, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSet16 (
IN UINTN TokenNumber,
IN UINT16 Value
)
{
return SetValueWorker (TokenNumber, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSet32 (
IN UINTN TokenNumber,
IN UINT32 Value
)
{
return SetValueWorker (TokenNumber, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSet64 (
IN UINTN TokenNumber,
IN UINT64 Value
)
{
return SetValueWorker (TokenNumber, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSetPtr (
IN UINTN TokenNumber,
IN OUT UINTN *SizeOfBuffer,
IN VOID *Buffer
)
{
return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
}
EFI_STATUS
EFIAPI
PeiPcdSetBool (
IN UINTN TokenNumber,
IN BOOLEAN Value
)
{
return SetValueWorker (TokenNumber, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSet8Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber,
IN UINT8 Value
)
{
return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSet16Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber,
IN UINT16 Value
)
{
return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSet32Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber,
IN UINT32 Value
)
{
return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSet64Ex (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber,
IN UINT64 Value
)
{
return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiPcdSetPtrEx (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber,
IN UINTN *SizeOfBuffer,
IN VOID *Value
)
{
return ExSetWorker (ExTokenNumber, Guid, Value, SizeOfBuffer, TRUE);
}
EFI_STATUS
EFIAPI
PeiPcdSetBoolEx (
IN CONST EFI_GUID *Guid,
IN UINTN ExTokenNumber,
IN BOOLEAN Value
)
{
return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
}
EFI_STATUS
EFIAPI
PeiRegisterCallBackOnSet (
IN CONST EFI_GUID *Guid, OPTIONAL
IN UINTN ExTokenNumber,
IN PCD_PPI_CALLBACK CallBackFunction
)
{
if (!FeaturePcdGet(PcdPeiPcdDatabaseCallbackOnSetEnabled)) {
return EFI_UNSUPPORTED;
}
ASSERT (CallBackFunction != NULL);
return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, TRUE);
}
EFI_STATUS
EFIAPI
PcdUnRegisterCallBackOnSet (
IN CONST EFI_GUID *Guid, OPTIONAL
IN UINTN ExTokenNumber,
IN PCD_PPI_CALLBACK CallBackFunction
)
{
if (!FeaturePcdGet(PcdPeiPcdDatabaseCallbackOnSetEnabled)) {
return EFI_UNSUPPORTED;
}
ASSERT (CallBackFunction != NULL);
return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, FALSE);
}
EFI_STATUS
EFIAPI
PeiPcdGetNextToken (
IN CONST EFI_GUID *Guid, OPTIONAL
IN OUT UINTN *TokenNumber
)
{
UINTN GuidTableIdx;
PEI_PCD_DATABASE *PeiPcdDb;
EFI_GUID *MatchGuid;
DYNAMICEX_MAPPING *ExMapTable;
UINTN i;
BOOLEAN Found;
BOOLEAN PeiExMapTableEmpty;
if (!FeaturePcdGet (PcdPeiPcdDatabaseTraverseEnabled)) {
return EFI_UNSUPPORTED;
}
PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
if (Guid == NULL) {
if (*TokenNumber > PEI_NEX_TOKEN_NUMBER) {
return EFI_NOT_FOUND;
}
(*TokenNumber)++;
if (*TokenNumber > PEI_NEX_TOKEN_NUMBER) {
*TokenNumber = PCD_INVALID_TOKEN_NUMBER;
}
return EFI_SUCCESS;
} else {
if (PeiExMapTableEmpty) {
*TokenNumber = PCD_INVALID_TOKEN_NUMBER;
return EFI_SUCCESS;
}
//
// Assume PCD Database AutoGen tool is sorting the ExMap based on the following order
// 1) ExGuid
// 2) ExTokenNumber
//
PeiPcdDb = GetPcdDatabase ();
MatchGuid = ScanGuid (PeiPcdDb->Init.GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);
if (MatchGuid == NULL) {
*TokenNumber = PCD_INVALID_TOKEN_NUMBER;
return EFI_NOT_FOUND;
}
GuidTableIdx = MatchGuid - PeiPcdDb->Init.GuidTable;
ExMapTable = PeiPcdDb->Init.ExMapTable;
Found = FALSE;
//
// Locate the GUID in ExMapTable first.
//
for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
if (ExMapTable[i].ExGuidIndex == GuidTableIdx) {
Found = TRUE;
break;
}
}
if (Found) {
if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
*TokenNumber = ExMapTable[i].ExTokenNumber;
return EFI_SUCCESS;
}
for ( ; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
if (ExMapTable[i].ExTokenNumber == *TokenNumber) {
i++;
if (i == PEI_EXMAPPING_TABLE_SIZE) {
//
// Exceed the length of ExMap Table
//
*TokenNumber = PCD_INVALID_TOKEN_NUMBER;
return EFI_SUCCESS;
}
if (ExMapTable[i].ExGuidIndex == GuidTableIdx) {
*TokenNumber = ExMapTable[i].ExTokenNumber;
return EFI_SUCCESS;
} else {
*TokenNumber = PCD_INVALID_TOKEN_NUMBER;
return EFI_SUCCESS;
}
}
}
return EFI_NOT_FOUND;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
EFIAPI
PeiPcdGetNextTokenSpace (
IN OUT CONST EFI_GUID **Guid
)
{
UINTN GuidTableIdx;
EFI_GUID *MatchGuid;
PEI_PCD_DATABASE *PeiPcdDb;
DYNAMICEX_MAPPING *ExMapTable;
UINTN i;
BOOLEAN Found;
BOOLEAN PeiExMapTableEmpty;
if (!FeaturePcdGet (PcdPeiPcdDatabaseTraverseEnabled)) {
return EFI_UNSUPPORTED;
}
ASSERT (Guid != NULL);
PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
if (PeiExMapTableEmpty) {
if (*Guid != NULL) {
return EFI_NOT_FOUND;
} else {
return EFI_SUCCESS;
}
}
//
// Assume PCD Database AutoGen tool is sorting the ExMap based on the following order
// 1) ExGuid
// 2) ExTokenNumber
//
PeiPcdDb = GetPcdDatabase ();
ExMapTable = PeiPcdDb->Init.ExMapTable;
if (*Guid == NULL) {
//
// return the first Token Space Guid.
//
*Guid = &PeiPcdDb->Init.GuidTable[ExMapTable[0].ExGuidIndex];
return EFI_SUCCESS;
}
MatchGuid = ScanGuid (PeiPcdDb->Init.GuidTable, sizeof(PeiPcdDb->Init.GuidTable), *Guid);
if (MatchGuid == NULL) {
return EFI_NOT_FOUND;
}
GuidTableIdx = MatchGuid - PeiPcdDb->Init.GuidTable;
Found = FALSE;
for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
if (ExMapTable[i].ExGuidIndex == GuidTableIdx) {
Found = TRUE;
break;
}
}
if (Found) {
i++;
for ( ; i < PEI_EXMAPPING_TABLE_SIZE; i++ ) {
if (ExMapTable[i].ExGuidIndex != GuidTableIdx ) {
*Guid = &PeiPcdDb->Init.GuidTable[ExMapTable[i].ExGuidIndex];
return EFI_SUCCESS;
}
}
*Guid = NULL;
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
UINTN
GetPtrTypeSize (
IN UINTN LocalTokenNumberTableIdx,
OUT UINTN *MaxSize,
IN PEI_PCD_DATABASE *Database
)
{
INTN SizeTableIdx;
UINTN LocalTokenNumber;
SKU_ID *SkuIdTable;
SIZE_INFO *SizeTable;
UINTN i;
SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
SizeTable = Database->Init.SizeTable;
*MaxSize = SizeTable[SizeTableIdx];
//
// SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
// PCD entry.
//
if (LocalTokenNumber & PCD_TYPE_VPD) {
//
// We have only one entry for VPD enabled PCD entry:
// 1) MAX Size.
// We consider current size is equal to MAX size.
//
return *MaxSize;
} else {
if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
//
// We have only two entry for Non-Sku enabled PCD entry:
// 1) MAX SIZE
// 2) Current Size
//
return SizeTable[SizeTableIdx + 1];
} else {
//
// We have these entry for SKU enabled PCD entry
// 1) MAX SIZE
// 2) Current Size for each SKU_ID (It is equal to MaxSku).
//
SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);
for (i = 0; i < SkuIdTable[0]; i++) {
if (SkuIdTable[1 + i] == Database->Init.SystemSkuId) {
return SizeTable[SizeTableIdx + 1 + i];
}
}
return SizeTable[SizeTableIdx + 1];
}
}
}
BOOLEAN
SetPtrTypeSize (
IN UINTN LocalTokenNumberTableIdx,
IN OUT UINTN *CurrentSize,
IN PEI_PCD_DATABASE *Database
)
{
INTN SizeTableIdx;
UINTN LocalTokenNumber;
SKU_ID *SkuIdTable;
SIZE_INFO *SizeTable;
UINTN i;
UINTN MaxSize;
SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
SizeTable = Database->Init.SizeTable;
MaxSize = SizeTable[SizeTableIdx];
//
// SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
// PCD entry.
//
if (LocalTokenNumber & PCD_TYPE_VPD) {
//
// We shouldn't come here as we don't support SET for VPD
//
ASSERT (FALSE);
return FALSE;
} else {
if ((*CurrentSize > MaxSize) ||
(*CurrentSize == MAX_ADDRESS)) {
*CurrentSize = MaxSize;
return FALSE;
}
if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
//
// We have only two entry for Non-Sku enabled PCD entry:
// 1) MAX SIZE
// 2) Current Size
//
SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
return TRUE;
} else {
//
// We have these entry for SKU enabled PCD entry
// 1) MAX SIZE
// 2) Current Size for each SKU_ID (It is equal to MaxSku).
//
SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);
for (i = 0; i < SkuIdTable[0]; i++) {
if (SkuIdTable[1 + i] == Database->Init.SystemSkuId) {
SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;
return TRUE;
}
}
SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
return TRUE;
}
}
}