summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/PCD
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-03 08:28:05 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-03 08:28:05 +0000
commit80408db0ca4e3d40b37c0f3a710ad4828e26f5f4 (patch)
treecbfcc847096bbacb6cbb2774514db3e6de18f921 /MdeModulePkg/Universal/PCD
parent5e51d10e2cae33b86236de4c6f209dad3681cfb4 (diff)
downloadedk2-platforms-80408db0ca4e3d40b37c0f3a710ad4828e26f5f4.tar.xz
Import PCD dxe and PCD pei modules.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2994 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/PCD')
-rw-r--r--MdeModulePkg/Universal/PCD/Dxe/CommonHeader.h41
-rw-r--r--MdeModulePkg/Universal/PCD/Dxe/Pcd.c737
-rw-r--r--MdeModulePkg/Universal/PCD/Dxe/Pcd.dxs26
-rw-r--r--MdeModulePkg/Universal/PCD/Dxe/Pcd.inf135
-rw-r--r--MdeModulePkg/Universal/PCD/Dxe/Pcd.msa99
-rw-r--r--MdeModulePkg/Universal/PCD/Dxe/Service.c1158
-rw-r--r--MdeModulePkg/Universal/PCD/Dxe/Service.h485
-rw-r--r--MdeModulePkg/Universal/PCD/Pei/CommonHeader.h40
-rw-r--r--MdeModulePkg/Universal/PCD/Pei/Pcd.c801
-rw-r--r--MdeModulePkg/Universal/PCD/Pei/Pcd.dxs25
-rw-r--r--MdeModulePkg/Universal/PCD/Pei/Pcd.inf140
-rw-r--r--MdeModulePkg/Universal/PCD/Pei/Pcd.msa129
-rw-r--r--MdeModulePkg/Universal/PCD/Pei/Service.c733
-rw-r--r--MdeModulePkg/Universal/PCD/Pei/Service.h462
14 files changed, 5011 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/PCD/Dxe/CommonHeader.h b/MdeModulePkg/Universal/PCD/Dxe/CommonHeader.h
new file mode 100644
index 0000000000..f01b863ce0
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Dxe/CommonHeader.h
@@ -0,0 +1,41 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2006 - 2007, 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.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/Pcd.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#endif
diff --git a/MdeModulePkg/Universal/PCD/Dxe/Pcd.c b/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
new file mode 100644
index 0000000000..861de0fa84
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
@@ -0,0 +1,737 @@
+/** @file
+PCD DXE driver
+
+Copyright (c) 2006 - 2007, 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"
+
+EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_CALLBACK);
+
+PCD_PROTOCOL mPcdInstance = {
+ DxePcdSetSku,
+
+ DxePcdGet8,
+ DxePcdGet16,
+ DxePcdGet32,
+ DxePcdGet64,
+ DxePcdGetPtr,
+ DxePcdGetBool,
+ DxePcdGetSize,
+
+ DxePcdGet8Ex,
+ DxePcdGet16Ex,
+ DxePcdGet32Ex,
+ DxePcdGet64Ex,
+ DxePcdGetPtrEx,
+ DxePcdGetBoolEx,
+ DxePcdGetSizeEx,
+
+ DxePcdSet8,
+ DxePcdSet16,
+ DxePcdSet32,
+ DxePcdSet64,
+ DxePcdSetPtr,
+ DxePcdSetBool,
+
+ DxePcdSet8Ex,
+ DxePcdSet16Ex,
+ DxePcdSet32Ex,
+ DxePcdSet64Ex,
+ DxePcdSetPtrEx,
+ DxePcdSetBoolEx,
+
+ DxeRegisterCallBackOnSet,
+ DxeUnRegisterCallBackOnSet,
+ DxePcdGetNextToken,
+ DxePcdGetNextTokenSpace
+};
+
+
+//
+// Static global to reduce the code size
+//
+static EFI_HANDLE mNewHandle = NULL;
+
+EFI_STATUS
+EFIAPI
+PcdDxeInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure the Pcd Protocol is not already installed in the system
+ //
+
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);
+
+ BuildPcdDxeDataBase ();
+
+ Status = gBS->InstallProtocolInterface (
+ &mNewHandle,
+ &gPcdProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPcdInstance
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+
+}
+
+
+VOID
+EFIAPI
+DxePcdSetSku (
+ IN UINTN SkuId
+ )
+{
+ mPcdDatabase->PeiDb.Init.SystemSkuId = (SKU_ID) SkuId;
+
+ return;
+}
+
+
+
+UINT8
+EFIAPI
+DxePcdGet8 (
+ IN UINTN TokenNumber
+ )
+{
+ return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));
+}
+
+
+
+UINT16
+EFIAPI
+DxePcdGet16 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
+}
+
+
+
+UINT32
+EFIAPI
+DxePcdGet32 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
+}
+
+
+
+UINT64
+EFIAPI
+DxePcdGet64 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned64(GetWorker (TokenNumber, sizeof (UINT64)));
+}
+
+
+
+VOID *
+EFIAPI
+DxePcdGetPtr (
+ IN UINTN TokenNumber
+ )
+{
+ return GetWorker (TokenNumber, 0);
+}
+
+
+
+BOOLEAN
+EFIAPI
+DxePcdGetBool (
+ IN UINTN TokenNumber
+ )
+{
+ return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));
+}
+
+
+
+UINTN
+EFIAPI
+DxePcdGetSize (
+ IN UINTN TokenNumber
+ )
+{
+ UINTN Size;
+ UINT32 *LocalTokenNumberTable;
+ BOOLEAN IsPeiDb;
+ UINTN MaxSize;
+ UINTN TmpTokenNumber;
+ //
+ // 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--;
+
+ //
+ // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber
+ //
+ TmpTokenNumber = 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 < PCD_TOTAL_TOKEN_NUMBER + 1);
+
+ // 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.
+ IsPeiDb = (BOOLEAN) (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
+
+ TokenNumber = IsPeiDb ? TokenNumber :
+ (TokenNumber - PEI_LOCAL_TOKEN_NUMBER);
+
+ LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable
+ : mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
+
+ Size = (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 (TmpTokenNumber, &MaxSize);
+ } else {
+ return Size;
+ }
+
+}
+
+
+
+UINT8
+EFIAPI
+DxePcdGet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof(UINT8)));
+}
+
+
+
+UINT16
+EFIAPI
+DxePcdGet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT16)));
+}
+
+
+
+UINT32
+EFIAPI
+DxePcdGet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT32)));
+}
+
+
+
+UINT64
+EFIAPI
+DxePcdGet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT64)));
+}
+
+
+
+VOID *
+EFIAPI
+DxePcdGetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ExGetWorker (Guid, ExTokenNumber, 0);
+}
+
+
+
+BOOLEAN
+EFIAPI
+DxePcdGetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof(BOOLEAN)));
+}
+
+
+
+UINTN
+EFIAPI
+DxePcdGetSizeEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return DxePcdGetSize(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet8 (
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet16 (
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet32 (
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet64 (
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetPtr (
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+{
+ return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetBool (
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT8 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT16 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT32 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT64 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+{
+ return ExSetWorker(ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN BOOLEAN Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+
+
+
+EFI_STATUS
+EFIAPI
+DxeRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (CallBackFunction != NULL);
+
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxeUnRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (CallBackFunction != NULL);
+
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdGetNextToken (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN OUT UINTN *TokenNumber
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN PeiExMapTableEmpty;
+ BOOLEAN DxeExMapTableEmpty;
+
+ if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EFI_NOT_FOUND;
+ PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
+ DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;
+
+ //
+ // Scan the local token space
+ //
+ if (Guid == NULL) {
+ // 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.
+ if (((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) && (*TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1)) ||
+ ((*TokenNumber + 1 > (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1)))) {
+ return EFI_NOT_FOUND;
+ }
+
+ (*TokenNumber)++;
+ if ((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) &&
+ (*TokenNumber <= PEI_LOCAL_TOKEN_NUMBER)) {
+ //
+ // The first Non-Ex type Token Number for DXE PCD
+ // database is PEI_LOCAL_TOKEN_NUMBER
+ //
+ *TokenNumber = PEI_LOCAL_TOKEN_NUMBER;
+ } else if (*TokenNumber + 1 > DXE_NEX_TOKEN_NUMBER + PEI_LOCAL_TOKEN_NUMBER + 1) {
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ }
+ return EFI_SUCCESS;
+ }
+
+ if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_NOT_FOUND;
+ }
+
+ if (!PeiExMapTableEmpty) {
+ Status = ExGetNextTokeNumber (
+ Guid,
+ TokenNumber,
+ mPcdDatabase->PeiDb.Init.GuidTable,
+ sizeof(mPcdDatabase->PeiDb.Init.GuidTable),
+ mPcdDatabase->PeiDb.Init.ExMapTable,
+ sizeof(mPcdDatabase->PeiDb.Init.ExMapTable)
+ );
+ }
+
+ if (Status == EFI_SUCCESS) {
+ return Status;
+ }
+
+ if (!DxeExMapTableEmpty) {
+ Status = ExGetNextTokeNumber (
+ Guid,
+ TokenNumber,
+ mPcdDatabase->DxeDb.Init.GuidTable,
+ sizeof(mPcdDatabase->DxeDb.Init.GuidTable),
+ mPcdDatabase->DxeDb.Init.ExMapTable,
+ sizeof(mPcdDatabase->DxeDb.Init.ExMapTable)
+ );
+ }
+
+ return Status;
+}
+
+STATIC
+EFI_GUID **
+GetDistinctTokenSpace (
+ IN OUT UINTN *ExMapTableSize,
+ IN DYNAMICEX_MAPPING *ExMapTable,
+ IN EFI_GUID *GuidTable
+ )
+{
+ EFI_GUID **DistinctTokenSpace;
+ UINTN OldGuidIndex;
+ UINTN TsIdx;
+ UINTN Idx;
+
+
+ DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));
+ ASSERT (DistinctTokenSpace != NULL);
+
+ TsIdx = 0;
+ OldGuidIndex = ExMapTable[0].ExGuidIndex;
+ DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];
+ for (Idx = 1; Idx < *ExMapTableSize; Idx++) {
+ if (ExMapTable[Idx].ExGuidIndex != OldGuidIndex) {
+ OldGuidIndex = ExMapTable[Idx].ExGuidIndex;
+ DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];
+ }
+ }
+
+ //
+ // The total number of Distinct Token Space
+ // is TsIdx + 1 because we use TsIdx as a index
+ // to the DistinctTokenSpace[]
+ //
+ *ExMapTableSize = TsIdx + 1;
+ return DistinctTokenSpace;
+
+}
+
+//
+// Just pre-allocate a memory buffer that is big enough to
+// host all distinct TokenSpace guid in both
+// PEI ExMap and DXE ExMap.
+//
+STATIC EFI_GUID *TmpTokenSpaceBuffer[PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE] = { 0 };
+
+EFI_STATUS
+EFIAPI
+DxePcdGetNextTokenSpace (
+ IN OUT CONST EFI_GUID **Guid
+ )
+{
+ UINTN Idx;
+ UINTN Idx2;
+ UINTN Idx3;
+ UINTN PeiTokenSpaceTableSize;
+ UINTN DxeTokenSpaceTableSize;
+ EFI_GUID **PeiTokenSpaceTable;
+ EFI_GUID **DxeTokenSpaceTable;
+ BOOLEAN Match;
+ BOOLEAN PeiExMapTableEmpty;
+ BOOLEAN DxeExMapTableEmpty;
+
+ if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ASSERT (Guid != NULL);
+
+ PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
+ DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;
+
+ if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
+ if (*Guid != NULL) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+
+ if (TmpTokenSpaceBuffer[0] == NULL) {
+ PeiTokenSpaceTableSize = 0;
+
+ if (!PeiExMapTableEmpty) {
+ PeiTokenSpaceTableSize = PEI_EXMAPPING_TABLE_SIZE;
+ PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize,
+ mPcdDatabase->PeiDb.Init.ExMapTable,
+ mPcdDatabase->PeiDb.Init.GuidTable
+ );
+ CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize);
+ }
+
+ if (!DxeExMapTableEmpty) {
+ DxeTokenSpaceTableSize = DXE_EXMAPPING_TABLE_SIZE;
+ DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize,
+ mPcdDatabase->DxeDb.Init.ExMapTable,
+ mPcdDatabase->DxeDb.Init.GuidTable
+ );
+
+ //
+ // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable
+ //
+ for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {
+ Match = FALSE;
+ for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {
+ if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {
+ Match = TRUE;
+ break;
+ }
+ }
+ if (!Match) {
+ TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];
+ }
+ }
+ }
+ }
+
+ if (*Guid == NULL) {
+ *Guid = TmpTokenSpaceBuffer[0];
+ return EFI_SUCCESS;
+ }
+
+ for (Idx = 0; Idx < (PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE); Idx++) {
+ if(CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {
+ Idx++;
+ *Guid = TmpTokenSpaceBuffer[Idx];
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+
+}
+
+
diff --git a/MdeModulePkg/Universal/PCD/Dxe/Pcd.dxs b/MdeModulePkg/Universal/PCD/Dxe/Pcd.dxs
new file mode 100644
index 0000000000..860153705b
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Dxe/Pcd.dxs
@@ -0,0 +1,26 @@
+/*++
+
+Copyright (c) 2006 - 2007, 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.dxs
+
+Abstract:
+
+ Dependency expression source file.
+
+--*/
+
+#include <DxeDepex.h>
+
+DEPENDENCY_START
+ TRUE
+DEPENDENCY_END
diff --git a/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf b/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
new file mode 100644
index 0000000000..6b4103566e
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
@@ -0,0 +1,135 @@
+#/** @file
+# Component description file for PCD service DXE driver.
+#
+# This DXE driver implement and produce the PCD protocol.
+# Copyright (c) 2006 - 2007, 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.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcdDxe
+ FILE_GUID = 80CF7257-87AB-47f9-A3FE-D50B76D89541
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ PCD_DRIVER = DXE_PCD_DRIVER
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = PcdDxeInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ Pcd.c
+ Service.c
+ Service.h
+ CommonHeader.h
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ HobLib
+ PcdLib
+ UefiDriverEntryPoint
+ UefiLib
+ DebugLib
+ BaseLib
+
+
+################################################################################
+#
+# Guid C Name Section - list of Guids that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gPcdDataBaseHobGuid # ALWAYS_CONSUMED Hob: GUID_EXTENSION
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gPcdProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+
+################################################################################
+#
+# Pcd FEATURE_FLAG - list of PCDs that this module is coded for.
+#
+################################################################################
+
+[PcdsFeatureFlag.common]
+ PcdDxePcdDatabaseTraverseEnabled|gEfiEdkModulePkgTokenSpaceGuid
+
+
+################################################################################
+#
+# Pcd FIXED_AT_BUILD - list of PCDs that this module is coded for.
+#
+################################################################################
+
+[PcdsFixedAtBuild.common]
+ PcdVpdBaseAddress|gEfiEdkModulePkgTokenSpaceGuid
+
+
+################################################################################
+#
+# Dependency Expression Section - list of Dependency expressions that are required for
+# this module.
+#
+################################################################################
+
+[Depex]
+ TRUE
+
diff --git a/MdeModulePkg/Universal/PCD/Dxe/Pcd.msa b/MdeModulePkg/Universal/PCD/Dxe/Pcd.msa
new file mode 100644
index 0000000000..d920f68e92
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Dxe/Pcd.msa
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0">
+ <MsaHeader>
+ <ModuleName>PcdDxe</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>80CF7257-87AB-47f9-A3FE-D50B76D89541</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for PCD service DXE driver.</Abstract>
+ <Description>This DXE driver implement and produce the PCD protocol.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>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.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>PcdDxe</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED" RecommendedInstanceGuid="bda39d3a-451b-4350-8266-81ab10fa0523">
+ <Keyword>DebugLib</Keyword>
+ <HelpText>Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg.</HelpText>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PcdLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>HobLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Service.h</Filename>
+ <Filename>Service.c</Filename>
+ <Filename>Pcd.c</Filename>
+ <Filename>Pcd.dxs</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gPcdProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Hobs>
+ <HobTypes Usage="ALWAYS_CONSUMED" HobGuidCName="gPcdDataBaseHobGuid">
+ <HobType>GUID_EXTENSION</HobType>
+ </HobTypes>
+ </Hobs>
+ <Externs>
+ <PcdIsDriver>DXE_PCD_DRIVER</PcdIsDriver>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>PcdDxeInit</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+ <PcdCoded>
+ <PcdEntry PcdItemType="FIXED_AT_BUILD">
+ <C_Name>PcdVpdBaseAddress</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>The base address of the VPD (Vital Product Data) region. It is
+ normally a region reserved on flash.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG">
+ <C_Name>PcdDxePcdDatabaseTraverseEnabled</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>This feature flag can be used to enable or disable the Pcd DXE database
+ traverse capability. Disable it can reduce the size of final image generated.</HelpText>
+ </PcdEntry>
+ </PcdCoded>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/MdeModulePkg/Universal/PCD/Dxe/Service.c b/MdeModulePkg/Universal/PCD/Dxe/Service.c
new file mode 100644
index 0000000000..96a40291af
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Dxe/Service.c
@@ -0,0 +1,1158 @@
+/** @file
+Private functions used by PCD DXE driver.
+
+Copyright (c) 2006 - 2007, 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: Service.c
+
+**/
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Service.h"
+
+
+PCD_DATABASE * mPcdDatabase;
+
+LIST_ENTRY *mCallbackFnTable;
+
+VOID *
+GetWorker (
+ UINTN TokenNumber,
+ UINTN GetSize
+ )
+{
+ UINT32 *LocalTokenNumberTable;
+ EFI_GUID *GuidTable;
+ UINT16 *StringTable;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+ VARIABLE_HEAD *VariableHead;
+ UINT8 *VaraiableDefaultBuffer;
+ UINT8 *Data;
+ VPD_HEAD *VpdHead;
+ UINT8 *PcdDb;
+ VOID *RetPtr;
+ UINTN MaxSize;
+ UINTN TmpTokenNumber;
+ UINTN DataSize;
+ EFI_STATUS Status;
+ UINT32 LocalTokenNumber;
+ UINT32 Offset;
+ UINT16 StringTableIdx;
+ BOOLEAN IsPeiDb;
+
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ RetPtr = NULL;
+ //
+ // 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--;
+
+ TmpTokenNumber = TokenNumber;
+
+ //
+ // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.
+ // It could be zero. EBC compiler is very choosy. It may
+ // report warning. So we add 1 in each size of the
+ // comparison.
+ //
+ ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
+
+ ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));
+
+ // 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.
+ IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);
+
+ LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
+ mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
+
+ TokenNumber = IsPeiDb ? TokenNumber :
+ TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
+
+ LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
+ if (GetSize == 0) {
+ GetPtrTypeSize (TmpTokenNumber, &MaxSize);
+ } else {
+ MaxSize = GetSize;
+ }
+ LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
+ }
+
+ PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
+ StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
+ mPcdDatabase->DxeDb.Init.StringTable;
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);
+ RetPtr = (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
+ break;
+
+ case PCD_TYPE_HII:
+ GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
+ mPcdDatabase->DxeDb.Init.GuidTable;
+
+ VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
+
+ Guid = &(GuidTable[VariableHead->GuidTableIndex]);
+ Name = &(StringTable[VariableHead->StringIndex]);
+ VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;
+
+ Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
+ if (Status == EFI_SUCCESS) {
+ if (GetSize == 0) {
+ //
+ // It is a pointer type. So get the MaxSize reserved for
+ // this PCD entry.
+ //
+ GetPtrTypeSize (TmpTokenNumber, &GetSize);
+ }
+ CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);
+ FreePool (Data);
+ }
+ //
+ // If the operation is successful, we copy the data
+ // to the default value buffer in the PCD Database.
+ // So that we can free the Data allocated in GetHiiVariable.
+ //
+ //
+ // If the operation is not successful,
+ // Return 1) either the default value specified by Platform Integrator
+ // 2) Or the value Set by a PCD set operation.
+ //
+ RetPtr = (VOID *) VaraiableDefaultBuffer;
+ break;
+
+ case PCD_TYPE_STRING:
+ StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset);
+ RetPtr = (VOID *) &StringTable[StringTableIdx];
+ break;
+
+ case PCD_TYPE_DATA:
+ RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+
+ }
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return RetPtr;
+
+}
+
+
+
+EFI_STATUS
+DxeRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+)
+{
+ CALLBACK_FN_ENTRY *FnTableEntry;
+ LIST_ENTRY *ListHead;
+ LIST_ENTRY *ListNode;
+
+ if (Guid != NULL) {
+ TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
+ }
+
+ //
+ // 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--;
+
+ ListHead = &mCallbackFnTable[TokenNumber];
+ ListNode = GetFirstNode (ListHead);
+
+ while (ListNode != ListHead) {
+ FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
+
+ if (FnTableEntry->CallbackFn == CallBackFunction) {
+ //
+ // We only allow a Callback function to be register once
+ // for a TokenNumber. So just return EFI_SUCCESS
+ //
+ return EFI_SUCCESS;
+ }
+ ListNode = GetNextNode (ListHead, ListNode);
+ }
+
+ FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));
+ ASSERT (FnTableEntry != NULL);
+
+ FnTableEntry->CallbackFn = CallBackFunction;
+ InsertTailList (ListHead, &FnTableEntry->Node);
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+EFI_STATUS
+DxeUnRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+)
+{
+ CALLBACK_FN_ENTRY *FnTableEntry;
+ LIST_ENTRY *ListHead;
+ LIST_ENTRY *ListNode;
+
+ if (Guid != NULL) {
+ TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
+ }
+
+ //
+ // 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--;
+
+ ListHead = &mCallbackFnTable[TokenNumber];
+ ListNode = GetFirstNode (ListHead);
+
+ while (ListNode != ListHead) {
+ FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
+
+ if (FnTableEntry->CallbackFn == CallBackFunction) {
+ //
+ // We only allow a Callback function to be register once
+ // for a TokenNumber. So we can safely remove the Node from
+ // the Link List and return EFI_SUCCESS.
+ //
+ RemoveEntryList (ListNode);
+ FreePool (FnTableEntry);
+
+ return EFI_SUCCESS;
+ }
+ ListNode = GetNextNode (ListHead, ListNode);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+
+
+EFI_STATUS
+ExGetNextTokeNumber (
+ IN CONST EFI_GUID *Guid,
+ IN OUT UINTN *TokenNumber,
+ IN EFI_GUID *GuidTable,
+ IN UINTN SizeOfGuidTable,
+ IN DYNAMICEX_MAPPING *ExMapTable,
+ IN UINTN SizeOfExMapTable
+ )
+{
+ EFI_GUID *MatchGuid;
+ UINTN Idx;
+ UINTN GuidTableIdx;
+ BOOLEAN Found;
+
+ MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);
+ if (MatchGuid == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Found = FALSE;
+ GuidTableIdx = MatchGuid - GuidTable;
+ for (Idx = 0; Idx < SizeOfExMapTable; Idx++) {
+ if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (Found) {
+ if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ *TokenNumber = ExMapTable[Idx].ExTokenNumber;
+ return EFI_SUCCESS;
+ }
+
+ for ( ; Idx < SizeOfExMapTable; Idx++) {
+ if (ExMapTable[Idx].ExTokenNumber == *TokenNumber) {
+ Idx++;
+ if (Idx == SizeOfExMapTable) {
+ //
+ // Exceed the length of ExMap Table
+ //
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_SUCCESS;
+ } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
+ //
+ // Found the next match
+ //
+ *TokenNumber = ExMapTable[Idx].ExTokenNumber;
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Guid has been changed. It is the next Token Space Guid.
+ // We should flag no more TokenNumber.
+ //
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+
+
+VOID
+BuildPcdDxeDataBase (
+ VOID
+ )
+{
+ PEI_PCD_DATABASE *PeiDatabase;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UINTN Idx;
+
+ mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));
+ ASSERT (mPcdDatabase != NULL);
+
+ GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
+ if (GuidHob != NULL) {
+
+ //
+ // We will copy over the PEI phase's PCD Database.
+ //
+ // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
+ // should not be included at all. So the GuidHob could
+ // be NULL. If it is NULL, we just copy over the DXE Default
+ // Value to PCD Database.
+ //
+
+ PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
+ //
+ // Copy PCD Entries refereneced in PEI phase to PCD DATABASE
+ //
+ CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));
+ }
+
+ //
+ // Copy PCD Entries with default value to PCD DATABASE
+ //
+ CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));
+
+
+ //
+ // Initialized the Callback Function Table
+ //
+
+ mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));
+
+ // 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.
+ for (Idx = 0; Idx + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Idx++) {
+ InitializeListHead (&mCallbackFnTable[Idx]);
+ }
+
+ return;
+}
+
+
+
+EFI_STATUS
+GetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ OUT UINT8 **VariableData,
+ OUT UINTN *VariableSize
+ )
+{
+ UINTN Size;
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+
+ Size = 0;
+ Buffer = NULL;
+
+ Status = gRT->GetVariable (
+ (UINT16 *)VariableName,
+ VariableGuid,
+ NULL,
+ &Size,
+ Buffer
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = (UINT8 *) AllocatePool (Size);
+
+ ASSERT (Buffer != NULL);
+
+ Status = gRT->GetVariable (
+ VariableName,
+ VariableGuid,
+ NULL,
+ &Size,
+ Buffer
+ );
+
+ ASSERT (Status == EFI_SUCCESS);
+ *VariableData = Buffer;
+ *VariableSize = Size;
+ }
+
+ return Status;
+}
+
+
+UINT32
+GetSkuEnabledTokenNumber (
+ UINT32 LocalTokenNumber,
+ UINTN Size,
+ BOOLEAN IsPeiDb
+ )
+{
+ SKU_HEAD *SkuHead;
+ SKU_ID *SkuIdTable;
+ INTN i;
+ UINT8 *Value;
+ SKU_ID *PhaseSkuIdTable;
+ UINT8 *PcdDb;
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
+
+ PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;
+
+ SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+ Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset);
+
+ PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :
+ mPcdDatabase->DxeDb.Init.SkuIdTable;
+
+ SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];
+
+ for (i = 0; i < SkuIdTable[0]; i++) {
+ if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) {
+ break;
+ }
+ }
+ ASSERT (i < SkuIdTable[0]);
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);
+
+ case PCD_TYPE_HII:
+ Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);
+
+ case PCD_TYPE_STRING:
+ Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]);
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);
+
+ case PCD_TYPE_DATA:
+ Value += Size * i;
+ return (UINT32) (Value - PcdDb);
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ ASSERT (FALSE);
+
+ return 0;
+
+}
+
+
+
+
+STATIC
+VOID
+InvokeCallbackOnSet (
+ UINT32 ExTokenNumber,
+ CONST EFI_GUID *Guid, OPTIONAL
+ UINTN TokenNumber,
+ VOID *Data,
+ UINTN Size
+ )
+{
+ CALLBACK_FN_ENTRY *FnTableEntry;
+ LIST_ENTRY *ListHead;
+ LIST_ENTRY *ListNode;
+
+ //
+ // 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--;
+
+ ListHead = &mCallbackFnTable[TokenNumber];
+ ListNode = GetFirstNode (ListHead);
+
+ while (ListNode != ListHead) {
+ FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
+
+ FnTableEntry->CallbackFn(Guid,
+ (Guid == NULL) ? TokenNumber : ExTokenNumber,
+ Data,
+ Size);
+
+ ListNode = GetNextNode (ListHead, ListNode);
+ }
+
+ return;
+}
+
+
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ return SetWorker (TokenNumber, Data, &Size, FALSE);
+}
+
+
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+{
+ UINT32 *LocalTokenNumberTable;
+ BOOLEAN IsPeiDb;
+ UINT32 LocalTokenNumber;
+ EFI_GUID *GuidTable;
+ UINT16 *StringTable;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+ UINTN VariableOffset;
+ VOID *InternalData;
+ VARIABLE_HEAD *VariableHead;
+ UINTN Offset;
+ UINT8 *PcdDb;
+ EFI_STATUS Status;
+ UINTN MaxSize;
+ UINTN TmpTokenNumber;
+
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ //
+ // 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--;
+
+ TmpTokenNumber = 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 < PCD_TOTAL_TOKEN_NUMBER + 1);
+
+ if (!PtrType) {
+ ASSERT (*Size == DxePcdGetSize (TokenNumber + 1));
+ }
+
+ // 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.
+ IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);
+
+ LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
+ mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
+
+ // 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.
+ if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||
+ (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {
+ InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
+ }
+
+ TokenNumber = IsPeiDb ? TokenNumber
+ : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
+
+ LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
+ if (PtrType) {
+ GetPtrTypeSize (TmpTokenNumber, &MaxSize);
+ } else {
+ MaxSize = *Size;
+ }
+ LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
+ }
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+
+ PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
+
+ StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
+ mPcdDatabase->DxeDb.Init.StringTable;
+
+ InternalData = PcdDb + Offset;
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case PCD_TYPE_STRING:
+ if (SetPtrTypeSize (TmpTokenNumber, Size)) {
+ CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, *Size);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ break;
+
+ case PCD_TYPE_HII:
+ if (PtrType) {
+ if (!SetPtrTypeSize (TmpTokenNumber, Size)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ }
+
+ GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
+ mPcdDatabase->DxeDb.Init.GuidTable;
+
+ VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
+
+ Guid = &(GuidTable[VariableHead->GuidTableIndex]);
+ Name = &(StringTable[VariableHead->StringIndex]);
+ VariableOffset = VariableHead->Offset;
+
+ Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);
+
+ if (EFI_NOT_FOUND == Status) {
+ CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);
+ Status = EFI_SUCCESS;
+ }
+ break;
+
+ case PCD_TYPE_DATA:
+ if (PtrType) {
+ if (SetPtrTypeSize (TmpTokenNumber, Size)) {
+ CopyMem (InternalData, Data, *Size);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ Status = EFI_SUCCESS;
+ switch (*Size) {
+ case sizeof(UINT8):
+ *((UINT8 *) InternalData) = *((UINT8 *) Data);
+ break;
+
+ case sizeof(UINT16):
+ *((UINT16 *) InternalData) = *((UINT16 *) Data);
+ break;
+
+ case sizeof(UINT32):
+ *((UINT32 *) InternalData) = *((UINT32 *) Data);
+ break;
+
+ case sizeof(UINT64):
+ *((UINT64 *) InternalData) = *((UINT64 *) Data);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ break;
+
+ default:
+ ASSERT (FALSE);
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return Status;
+}
+
+
+
+
+
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ )
+{
+ return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);
+}
+
+
+
+
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN SetSize
+ )
+{
+ return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);
+}
+
+
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *SetSize,
+ IN BOOLEAN PtrType
+ )
+{
+ UINTN TokenNumber;
+
+ TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);
+
+ InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);
+
+ return SetWorker (TokenNumber, Data, SetSize, PtrType);
+
+}
+
+
+
+
+EFI_STATUS
+SetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ IN UINTN Offset
+ )
+{
+ UINTN Size;
+ VOID *Buffer;
+ EFI_STATUS Status;
+ UINT32 Attribute;
+
+ Size = 0;
+
+ Status = gRT->GetVariable (
+ (UINT16 *)VariableName,
+ VariableGuid,
+ NULL,
+ &Size,
+ NULL
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+
+ Buffer = AllocatePool (Size);
+
+ ASSERT (Buffer != NULL);
+
+ Status = gRT->GetVariable (
+ VariableName,
+ VariableGuid,
+ &Attribute,
+ &Size,
+ Buffer
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);
+
+ Status = gRT->SetVariable (
+ VariableName,
+ VariableGuid,
+ Attribute,
+ Size,
+ Buffer
+ );
+
+ FreePool (Buffer);
+ return Status;
+
+ }
+
+ //
+ // If we drop to here, we don't have a Variable entry in
+ // the variable service yet. So, we will save the data
+ // in the PCD Database's volatile area.
+ //
+ return Status;
+}
+
+
+
+
+
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINT32 ExTokenNumber
+ )
+{
+ UINT32 i;
+ DYNAMICEX_MAPPING *ExMap;
+ EFI_GUID *GuidTable;
+ EFI_GUID *MatchGuid;
+ UINTN MatchGuidIdx;
+
+ if (!PEI_DATABASE_EMPTY) {
+ ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;
+ GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;
+
+ MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);
+
+ if (MatchGuid != NULL) {
+
+ MatchGuidIdx = MatchGuid - GuidTable;
+
+ for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
+ if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
+ (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
+ return ExMap[i].LocalTokenNumber;
+
+ }
+ }
+ }
+ }
+
+ ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;
+ GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;
+
+ MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);
+ //
+ // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
+ // error in the BUILD system.
+ //
+ ASSERT (MatchGuid != NULL);
+
+ MatchGuidIdx = MatchGuid - GuidTable;
+
+ for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {
+ if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
+ (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
+ return ExMap[i].LocalTokenNumber;
+ }
+ }
+
+ ASSERT (FALSE);
+
+ return 0;
+}
+
+
+STATIC
+SKU_ID *
+GetSkuIdArray (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN BOOLEAN IsPeiPcd
+ )
+{
+ SKU_HEAD *SkuHead;
+ UINTN LocalTokenNumber;
+ UINT8 *Database;
+
+ if (IsPeiPcd) {
+ LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
+ Database = (UINT8 *) &mPcdDatabase->PeiDb;
+ } else {
+ LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];
+ Database = (UINT8 *) &mPcdDatabase->DxeDb;
+ }
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
+
+ SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+
+ return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);
+
+}
+
+
+STATIC
+UINTN
+GetSizeTableIndexA (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN UINT32 *LocalTokenNumberTable,
+ IN BOOLEAN IsPeiDb
+ )
+{
+ UINTN i;
+ UINTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+
+ SizeTableIdx = 0;
+
+ for (i=0; i<LocalTokenNumberTableIdx; i++) {
+ LocalTokenNumber = LocalTokenNumberTable[i];
+
+ if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
+ //
+ // 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.
+ //
+ SizeTableIdx++;
+ } 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
+ //
+ SizeTableIdx += 2;
+ } 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 (i, IsPeiDb);
+ SizeTableIdx += (UINTN)*SkuIdTable + 1;
+ }
+ }
+ }
+
+ }
+
+ return SizeTableIdx;
+}
+
+
+
+STATIC
+UINTN
+GetSizeTableIndex (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN BOOLEAN IsPeiDb
+ )
+{
+ UINT32 *LocalTokenNumberTable;
+
+ if (IsPeiDb) {
+ LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
+ } else {
+ LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
+ }
+ return GetSizeTableIndexA (LocalTokenNumberTableIdx,
+ LocalTokenNumberTable,
+ IsPeiDb);
+}
+
+
+
+UINTN
+GetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ OUT UINTN *MaxSize
+ )
+{
+ INTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+ SIZE_INFO *SizeTable;
+ UINTN i;
+ BOOLEAN IsPeiDb;
+ UINT32 *LocalTokenNumberTable;
+
+ // 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.
+ IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
+
+
+ if (IsPeiDb) {
+ LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
+ SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
+ } else {
+ LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
+ LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
+ SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
+ }
+
+ LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
+
+ ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+ SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
+
+ *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, IsPeiDb);
+ for (i = 0; i < SkuIdTable[0]; i++) {
+ if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
+ return SizeTable[SizeTableIdx + 1 + i];
+ }
+ }
+ return SizeTable[SizeTableIdx + 1];
+ }
+ }
+}
+
+
+
+BOOLEAN
+SetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN OUT UINTN *CurrentSize
+ )
+{
+ INTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+ SIZE_INFO *SizeTable;
+ UINTN i;
+ UINTN MaxSize;
+ BOOLEAN IsPeiDb;
+ UINT32 *LocalTokenNumberTable;
+
+ // 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.
+ IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
+
+ if (IsPeiDb) {
+ LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;
+ SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;
+ } else {
+ LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;
+ LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
+ SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;
+ }
+
+ LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
+
+ ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+ SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
+
+ 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, IsPeiDb);
+ for (i = 0; i < SkuIdTable[0]; i++) {
+ if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {
+ SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ }
+ }
+ SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ }
+ }
+}
+
diff --git a/MdeModulePkg/Universal/PCD/Dxe/Service.h b/MdeModulePkg/Universal/PCD/Dxe/Service.h
new file mode 100644
index 0000000000..da38053e13
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Dxe/Service.h
@@ -0,0 +1,485 @@
+/** @file
+Private functions used by PCD DXE driver.
+
+Copyright (c) 2006 - 2007, 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: Service.h
+
+**/
+
+#ifndef _SERVICE_H
+#define _SERVICE_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+//
+// Please make sure the PCD Serivce PEIM Version is consistent with
+// the version of PCD Database generation tool
+//
+#define PCD_SERVICE_DXE_DRIVER_VERSION 2
+
+//
+// PCD_DXE_DATABASE_GENTOOL_VERSION is defined in Autogen.h
+// and generated by PCD Database generation tool.
+//
+#if (PCD_SERVICE_DXE_DRIVER_VERSION != PCD_DXE_SERVICE_DRIVER_AUTOGEN_VERSION)
+ #error "Please make sure the version of PCD Service DXE Driver and PCD DXE Database Generation Tool matches"
+#endif
+
+//
+// Protocol Interface function declaration.
+//
+VOID
+EFIAPI
+DxePcdSetSku (
+ IN UINTN SkuId
+ )
+;
+
+
+UINT8
+EFIAPI
+DxePcdGet8 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT16
+EFIAPI
+DxePcdGet16 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT32
+EFIAPI
+DxePcdGet32 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT64
+EFIAPI
+DxePcdGet64 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+VOID *
+EFIAPI
+DxePcdGetPtr (
+ IN UINTN TokenNumber
+ )
+;
+
+
+BOOLEAN
+EFIAPI
+DxePcdGetBool (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINTN
+EFIAPI
+DxePcdGetSize (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT8
+EFIAPI
+DxePcdGet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT16
+EFIAPI
+DxePcdGet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT32
+EFIAPI
+DxePcdGet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+
+UINT64
+EFIAPI
+DxePcdGet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+
+VOID *
+EFIAPI
+DxePcdGetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+BOOLEAN
+EFIAPI
+DxePcdGetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINTN
+EFIAPI
+DxePcdGetSizeEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet8 (
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet16 (
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet32 (
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet64 (
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetPtr (
+ IN UINTN TokenNumber,
+ IN UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetBool (
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdSetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ )
+;
+
+
+
+EFI_STATUS
+EFIAPI
+DxeRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxeUnRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+DxePcdGetNextToken (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN OUT UINTN *TokenNumber
+ )
+;
+
+
+
+EFI_STATUS
+EFIAPI
+DxePcdGetNextTokenSpace (
+ IN OUT CONST EFI_GUID **Guid
+ )
+;
+
+
+typedef struct {
+ LIST_ENTRY Node;
+ PCD_PROTOCOL_CALLBACK CallbackFn;
+} CALLBACK_FN_ENTRY;
+
+#define CR_FNENTRY_FROM_LISTNODE(Record, Type, Field) _CR(Record, Type, Field)
+
+//
+// Internal Functions
+//
+
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+;
+
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+;
+
+
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN SetSize
+ )
+;
+
+
+
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+;
+
+
+VOID *
+GetWorker (
+ IN UINTN TokenNumber,
+ IN UINTN GetSize
+ )
+;
+
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ )
+;
+
+UINT32
+GetSkuEnabledTokenNumber (
+ UINT32 LocalTokenNumber,
+ UINTN Size,
+ BOOLEAN IsPeiDb
+ )
+;
+
+EFI_STATUS
+GetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ OUT UINT8 **VariableData,
+ OUT UINTN *VariableSize
+ )
+;
+
+EFI_STATUS
+SetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ IN UINTN Offset
+ )
+;
+
+EFI_STATUS
+DxeRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+);
+
+EFI_STATUS
+DxeUnRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+);
+
+VOID
+BuildPcdDxeDataBase (
+ VOID
+);
+
+
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINT32 ExTokenNumber
+ )
+;
+
+
+
+EFI_STATUS
+ExGetNextTokeNumber (
+ IN CONST EFI_GUID *Guid,
+ IN OUT UINTN *TokenNumber,
+ IN EFI_GUID *GuidTable,
+ IN UINTN SizeOfGuidTable,
+ IN DYNAMICEX_MAPPING *ExMapTable,
+ IN UINTN SizeOfExMapTable
+ )
+;
+
+
+UINTN
+GetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ OUT UINTN *MaxSize
+ )
+;
+
+
+
+BOOLEAN
+SetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN OUT UINTN *CurrentSize
+ )
+;
+
+extern EFI_GUID gPcdDataBaseHobGuid;
+
+extern PCD_DATABASE * mPcdDatabase;
+
+extern DXE_PCD_DATABASE_INIT gDXEPcdDbInit;
+
+extern EFI_LOCK mPcdDatabaseLock;
+
+#endif
diff --git a/MdeModulePkg/Universal/PCD/Pei/CommonHeader.h b/MdeModulePkg/Universal/PCD/Pei/CommonHeader.h
new file mode 100644
index 0000000000..c488c38e9e
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Pei/CommonHeader.h
@@ -0,0 +1,40 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2006 - 2007, 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.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Ppi/ReadOnlyVariable.h>
+#include <Ppi/Pcd.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#endif
diff --git a/MdeModulePkg/Universal/PCD/Pei/Pcd.c b/MdeModulePkg/Universal/PCD/Pei/Pcd.c
new file mode 100644
index 0000000000..b018e5a95d
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Pei/Pcd.c
@@ -0,0 +1,801 @@
+/** @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;
+ }
+ }
+
+}
diff --git a/MdeModulePkg/Universal/PCD/Pei/Pcd.dxs b/MdeModulePkg/Universal/PCD/Pei/Pcd.dxs
new file mode 100644
index 0000000000..3bad561b78
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Pei/Pcd.dxs
@@ -0,0 +1,25 @@
+/*++
+
+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.dxs
+
+Abstract:
+
+ Dependency expression source file.
+
+--*/
+#include <DxeDepex.h>
+
+DEPENDENCY_START
+ TRUE
+DEPENDENCY_END
diff --git a/MdeModulePkg/Universal/PCD/Pei/Pcd.inf b/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
new file mode 100644
index 0000000000..506ab026cd
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
@@ -0,0 +1,140 @@
+#/** @file
+# Component description file for Pcd Database PEIM module
+#
+# This PEIM driver implement and produce PCD PPI.
+# Copyright (c) 2006 - 2007, 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.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcdPeim
+ FILE_GUID = 9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ PCD_DRIVER = PEI_PCD_DRIVER
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = PcdPeimInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ Service.c
+ Service.h
+ Pcd.c
+ CommonHeader.h
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ BaseMemoryLib
+ PeiServicesTablePointerLib
+ PcdLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+
+
+################################################################################
+#
+# Guid C Name Section - list of Guids that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gPcdPeiCallbackFnTableHobGuid # ALWAYS_PRODUCED Hob: GUID_EXTENSION
+ gPcdDataBaseHobGuid # ALWAYS_PRODUCED Hob: GUID_EXTENSION
+
+
+################################################################################
+#
+# PPI C Name Section - list of PPI and PPI Notify C Names that this module
+# uses or produces.
+#
+################################################################################
+
+[Ppis]
+ gEfiPeiReadOnlyVariablePpiGuid # PPI ALWAYS_CONSUMED
+ gPcdPpiGuid # PPI ALWAYS_PRODUCED
+
+
+################################################################################
+#
+# Pcd FEATURE_FLAG - list of PCDs that this module is coded for.
+#
+################################################################################
+
+[PcdsFeatureFlag.common]
+ PcdPeiPcdDatabaseSetEnabled|gEfiEdkModulePkgTokenSpaceGuid
+ PcdPeiPcdDatabaseGetSizeEnabled|gEfiEdkModulePkgTokenSpaceGuid
+ PcdPeiPcdDatabaseExEnabled|gEfiEdkModulePkgTokenSpaceGuid
+ PcdPeiPcdDatabaseCallbackOnSetEnabled|gEfiEdkModulePkgTokenSpaceGuid
+ PcdPeiPcdDatabaseTraverseEnabled|gEfiEdkModulePkgTokenSpaceGuid
+
+
+################################################################################
+#
+# Pcd FIXED_AT_BUILD - list of PCDs that this module is coded for.
+#
+################################################################################
+
+[PcdsFixedAtBuild.common]
+ PcdVpdBaseAddress|gEfiEdkModulePkgTokenSpaceGuid
+ PcdMaxPeiPcdCallBackNumberPerPcdEntry|gEfiEdkModulePkgTokenSpaceGuid
+
+
+################################################################################
+#
+# Dependency Expression Section - list of Dependency expressions that are required for
+# this module.
+#
+################################################################################
+
+[Depex]
+ TRUE
+
diff --git a/MdeModulePkg/Universal/PCD/Pei/Pcd.msa b/MdeModulePkg/Universal/PCD/Pei/Pcd.msa
new file mode 100644
index 0000000000..155a576443
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Pei/Pcd.msa
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>PcdPeim</ModuleName>
+ <ModuleType>PEIM</ModuleType>
+ <GuidValue>9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for Pcd Database PEIM module</Abstract>
+ <Description>This PEIM driver implement and produce PCD PPI.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>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.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>PcdPeim</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED" RecommendedInstanceGuid="bda39d3a-451b-4350-8266-81ab10fa0523">
+ <Keyword>DebugLib</Keyword>
+ <HelpText>Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg.</HelpText>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeimEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>HobLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeiServicesLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PcdLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeiServicesTablePointerLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Pcd.dxs</Filename>
+ <Filename>Pcd.c</Filename>
+ <Filename>Service.h</Filename>
+ <Filename>Service.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Hobs>
+ <HobTypes Usage="ALWAYS_PRODUCED" HobGuidCName="gPcdDataBaseHobGuid">
+ <HobType>GUID_EXTENSION</HobType>
+ </HobTypes>
+ <HobTypes Usage="ALWAYS_PRODUCED" HobGuidCName="gPcdPeiCallbackFnTableHobGuid">
+ <HobType>GUID_EXTENSION</HobType>
+ </HobTypes>
+ </Hobs>
+ <PPIs>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gPcdPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">
+ <PpiCName>gEfiPeiReadOnlyVariablePpiGuid</PpiCName>
+ </Ppi>
+ </PPIs>
+ <Externs>
+ <PcdIsDriver>PEI_PCD_DRIVER</PcdIsDriver>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>PcdPeimInit</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+ <PcdCoded>
+ <PcdEntry PcdItemType="FIXED_AT_BUILD" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdMaxPeiPcdCallBackNumberPerPcdEntry</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>The maximum number of callback function, which will be triggered when
+ a PCD entry is been set, can be registered for a single PCD entry in PEI phase.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FIXED_AT_BUILD" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdVpdBaseAddress</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>The base address of the VPD (Vital Product Data) region. It is
+ normally a region reserved on flash.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdPeiPcdDatabaseTraverseEnabled</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>This feature flag can be used to enable or disable the Pcd PEIM database
+ traverse capability. Disable it can reduce the size of final image generated.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdPeiPcdDatabaseCallbackOnSetEnabled</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>FALSE</DefaultValue>
+ <HelpText>This feature flag can be used to enable or disable the Callback On SET capability of PCD service PEIM. If a platform does not register any callback on set in PEI phase. This flag can be set to DISABLE to save size.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdPeiPcdDatabaseExEnabled</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>FALSE</DefaultValue>
+ <HelpText>This feature flag can be used to enable or disable the PCD service PEIM to handle DynamicEX PCD. If a platform has no module to use DynamicEX in PEI phase. This flag can be set to DISABLE to save size.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdPeiPcdDatabaseGetSizeEnabled</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>FALSE</DefaultValue>
+ <HelpText>This feature flag can be used to enable or disable the GET size capability of PCD service PEIM. If a platform does not do PCD get size operation in PEI phase. This flag can be set to DISABLE to save size.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdPeiPcdDatabaseSetEnabled</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>FALSE</DefaultValue>
+ <HelpText>This feature flag can be used to enable or disable the SET capability of PCD service PEIM. If a platform does not do PCD SET operation in PEI phase. This flag can be set to DISABLE to save size.</HelpText>
+ </PcdEntry>
+ </PcdCoded>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/MdeModulePkg/Universal/PCD/Pei/Service.c b/MdeModulePkg/Universal/PCD/Pei/Service.c
new file mode 100644
index 0000000000..cb980daa39
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Pei/Service.c
@@ -0,0 +1,733 @@
+/** @file
+Private functions used by 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: Service.c
+
+**/
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Service.h"
+
+/**
+ The function registers the CallBackOnSet fucntion
+ according to TokenNumber and EFI_GUID space.
+
+ @param TokenNumber The token number.
+ @param Guid The GUID space.
+ @param CallBackFunction The Callback function to be registered.
+ @param Register To register or unregister the callback function.
+
+ @retval EFI_SUCCESS If the Callback function is registered.
+ @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
+ @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
+ slot left in the CallbackFnTable.
+--*/
+EFI_STATUS
+PeiRegisterCallBackWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PPI_CALLBACK CallBackFunction,
+ IN BOOLEAN Register
+)
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ PCD_PPI_CALLBACK *CallbackTable;
+ PCD_PPI_CALLBACK Compare;
+ PCD_PPI_CALLBACK Assign;
+ UINT32 LocalTokenNumber;
+ UINTN TokenNumber;
+ UINTN Idx;
+
+ if (Guid == NULL) {
+ TokenNumber = ExTokenNumber;
+
+ //
+ // 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--;
+ ASSERT (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1);
+ } else {
+ TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
+
+ //
+ // 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);
+ }
+
+
+ LocalTokenNumber = GetPcdDatabase()->Init.LocalTokenNumberTable[TokenNumber];
+
+ //
+ // We don't support SET for HII and VPD type PCD entry in PEI phase.
+ // So we will assert if any register callback for such PCD entry.
+ //
+ ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);
+ ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);
+
+ GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);
+ ASSERT (GuidHob != NULL);
+
+ CallbackTable = GET_GUID_HOB_DATA (GuidHob);
+ CallbackTable = CallbackTable + (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));
+
+ Compare = Register? NULL: CallBackFunction;
+ Assign = Register? CallBackFunction: NULL;
+
+
+ for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
+ if (CallbackTable[Idx] == Compare) {
+ CallbackTable[Idx] = Assign;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND;
+
+}
+
+
+
+
+/**
+ The function builds the PCD database.
+
+ @param VOID
+
+ @retval VOID
+--*/
+VOID
+BuildPcdDatabase (
+ VOID
+ )
+{
+ PEI_PCD_DATABASE *Database;
+ VOID *CallbackFnTable;
+ UINTN SizeOfCallbackFnTable;
+
+ Database = BuildGuidHob (&gPcdDataBaseHobGuid, sizeof (PEI_PCD_DATABASE));
+
+ ZeroMem (Database, sizeof (PEI_PCD_DATABASE));
+
+ //
+ // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE
+ //
+
+ CopyMem (&Database->Init, &gPEIPcdDbInit, sizeof (gPEIPcdDbInit));
+
+ SizeOfCallbackFnTable = PEI_LOCAL_TOKEN_NUMBER * sizeof (PCD_PPI_CALLBACK) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry);
+
+ CallbackFnTable = BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid, SizeOfCallbackFnTable);
+
+ ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);
+
+ return;
+}
+
+
+
+/**
+ The function is provided by PCD PEIM and PCD DXE driver to
+ do the work of reading a HII variable from variable service.
+
+ @param VariableGuid The Variable GUID.
+ @param VariableName The Variable Name.
+ @param VariableData The output data.
+ @param VariableSize The size of the variable.
+
+ @retval EFI_SUCCESS Operation successful.
+ @retval EFI_NOT_FOUND Variablel not found.
+--*/
+STATIC
+EFI_STATUS
+GetHiiVariable (
+ IN CONST EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ OUT VOID **VariableData,
+ OUT UINTN *VariableSize
+ )
+{
+ UINTN Size;
+ EFI_STATUS Status;
+ VOID *Buffer;
+ EFI_PEI_READ_ONLY_VARIABLE_PPI *VariablePpi;
+
+ Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, (VOID **) &VariablePpi);
+ ASSERT_EFI_ERROR (Status);
+
+ Size = 0;
+ Status = VariablePpi->PeiGetVariable (
+ GetPeiServicesTablePointer (),
+ VariableName,
+ (EFI_GUID *) VariableGuid,
+ NULL,
+ &Size,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+
+
+ Status = PeiServicesAllocatePool (Size, &Buffer);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = VariablePpi->PeiGetVariable (
+ GetPeiServicesTablePointer (),
+ (UINT16 *) VariableName,
+ (EFI_GUID *) VariableGuid,
+ NULL,
+ &Size,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *VariableSize = Size;
+ *VariableData = Buffer;
+
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+
+}
+
+STATIC
+UINT32
+GetSkuEnabledTokenNumber (
+ UINT32 LocalTokenNumber,
+ UINTN Size
+ )
+{
+ PEI_PCD_DATABASE *PeiPcdDb;
+ SKU_HEAD *SkuHead;
+ SKU_ID *SkuIdTable;
+ INTN i;
+ UINT8 *Value;
+
+ PeiPcdDb = GetPcdDatabase ();
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
+
+ SkuHead = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+ Value = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));
+ SkuIdTable = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));
+
+ for (i = 0; i < SkuIdTable[0]; i++) {
+ if (PeiPcdDb->Init.SystemSkuId == SkuIdTable[i + 1]) {
+ break;
+ }
+ }
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);
+
+ case PCD_TYPE_HII:
+ Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);
+
+ case PCD_TYPE_STRING:
+ Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]);
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_STRING);
+
+ case PCD_TYPE_DATA:
+ Value += Size * i;
+ return (UINT32) (Value - (UINT8 *) PeiPcdDb);
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ ASSERT (FALSE);
+
+ return 0;
+
+}
+
+
+
+STATIC
+VOID
+InvokeCallbackOnSet (
+ UINTN ExTokenNumber,
+ CONST EFI_GUID *Guid, OPTIONAL
+ UINTN TokenNumber,
+ VOID *Data,
+ UINTN Size
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ PCD_PPI_CALLBACK *CallbackTable;
+ UINTN Idx;
+
+ //
+ // 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--;
+
+ if (Guid == NULL) {
+ // 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);
+ }
+
+ GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);
+ ASSERT (GuidHob != NULL);
+
+ CallbackTable = GET_GUID_HOB_DATA (GuidHob);
+
+ CallbackTable += (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));
+
+ for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
+ if (CallbackTable[Idx] != NULL) {
+ CallbackTable[Idx] (Guid,
+ (Guid == NULL)? TokenNumber: ExTokenNumber,
+ Data,
+ Size
+ );
+ }
+ }
+
+}
+
+
+
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ return SetWorker (TokenNumber, Data, &Size, FALSE);
+}
+
+
+
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN OUT VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+{
+ UINT32 LocalTokenNumber;
+ PEI_PCD_DATABASE *PeiPcdDb;
+ UINT16 StringTableIdx;
+ UINTN Offset;
+ VOID *InternalData;
+ UINTN MaxSize;
+
+ if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // 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);
+
+ PeiPcdDb = GetPcdDatabase ();
+
+ LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];
+
+ if (!PtrType) {
+ ASSERT (PeiPcdGetSize(TokenNumber + 1) == *Size);
+ }
+
+ //
+ // We only invoke the callback function for Dynamic Type PCD Entry.
+ // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
+ // type PCD entry in ExSetWorker.
+ //
+ if (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) {
+ InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
+ }
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
+ if (PtrType) {
+ MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
+ } else {
+ MaxSize = *Size;
+ }
+ LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);
+ }
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+ InternalData = (VOID *) ((UINT8 *) PeiPcdDb + Offset);
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ case PCD_TYPE_HII:
+ {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ case PCD_TYPE_STRING:
+ if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {
+ StringTableIdx = *((UINT16 *)InternalData);
+ CopyMem (&PeiPcdDb->Init.StringTable[StringTableIdx], Data, *Size);
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ case PCD_TYPE_DATA:
+ {
+ if (PtrType) {
+ if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {
+ CopyMem (InternalData, Data, *Size);
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ switch (*Size) {
+ case sizeof(UINT8):
+ *((UINT8 *) InternalData) = *((UINT8 *) Data);
+ return EFI_SUCCESS;
+
+ case sizeof(UINT16):
+ *((UINT16 *) InternalData) = *((UINT16 *) Data);
+ return EFI_SUCCESS;
+
+ case sizeof(UINT32):
+ *((UINT32 *) InternalData) = *((UINT32 *) Data);
+ return EFI_SUCCESS;
+
+ case sizeof(UINT64):
+ *((UINT64 *) InternalData) = *((UINT64 *) Data);
+ return EFI_SUCCESS;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ }
+
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+
+}
+
+
+
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);
+}
+
+
+
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+{
+ UINTN TokenNumber;
+
+ if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
+
+ InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);
+
+ return SetWorker (TokenNumber, Data, Size, PtrType);
+
+}
+
+
+
+
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ )
+{
+ if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled)) {
+ ASSERT (FALSE);
+ return 0;
+ }
+
+ return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);
+}
+
+
+
+
+VOID *
+GetWorker (
+ UINTN TokenNumber,
+ UINTN GetSize
+ )
+{
+ UINT32 Offset;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+ VARIABLE_HEAD *VariableHead;
+ EFI_STATUS Status;
+ UINTN DataSize;
+ VOID *Data;
+ UINT16 *StringTable;
+ UINT16 StringTableIdx;
+ PEI_PCD_DATABASE *PeiPcdDb;
+ UINT32 LocalTokenNumber;
+ UINTN MaxSize;
+
+ //
+ // 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);
+
+ ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));
+
+ PeiPcdDb = GetPcdDatabase ();
+
+ LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
+ if (GetSize == 0) {
+ MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
+ } else {
+ MaxSize = GetSize;
+ }
+ LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);
+ }
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+ StringTable = PeiPcdDb->Init.StringTable;
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ {
+ VPD_HEAD *VpdHead;
+ VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
+ return (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
+ }
+
+ case PCD_TYPE_HII:
+ {
+ VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
+
+ Guid = &(PeiPcdDb->Init.GuidTable[VariableHead->GuidTableIndex]);
+ Name = &StringTable[VariableHead->StringIndex];
+
+ Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
+
+ if (Status == EFI_SUCCESS) {
+ return (VOID *) ((UINT8 *) Data + VariableHead->Offset);
+ } else {
+ //
+ // Return the default value specified by Platform Integrator
+ //
+ return (VOID *) ((UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset);
+ }
+ }
+
+ case PCD_TYPE_DATA:
+ return (VOID *) ((UINT8 *)PeiPcdDb + Offset);
+
+ case PCD_TYPE_STRING:
+ StringTableIdx = (UINT16) *((UINT8 *) PeiPcdDb + Offset);
+ return (VOID *) (&StringTable[StringTableIdx]);
+
+ default:
+ ASSERT (FALSE);
+ break;
+
+ }
+
+ ASSERT (FALSE);
+
+ return NULL;
+
+}
+
+
+
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ UINT32 i;
+ DYNAMICEX_MAPPING *ExMap;
+ EFI_GUID *GuidTable;
+ EFI_GUID *MatchGuid;
+ UINTN MatchGuidIdx;
+ PEI_PCD_DATABASE *PeiPcdDb;
+
+ PeiPcdDb = GetPcdDatabase();
+
+ ExMap = PeiPcdDb->Init.ExMapTable;
+ GuidTable = PeiPcdDb->Init.GuidTable;
+
+ MatchGuid = ScanGuid (GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);
+ //
+ // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
+ // error in the BUILD system.
+ //
+ ASSERT (MatchGuid != NULL);
+
+ MatchGuidIdx = MatchGuid - GuidTable;
+
+ for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
+ if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
+ (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
+ return ExMap[i].LocalTokenNumber;
+ }
+ }
+
+ ASSERT (FALSE);
+
+ return 0;
+}
+
+
+
+PEI_PCD_DATABASE *
+GetPcdDatabase (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
+ ASSERT (GuidHob != NULL);
+
+ return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
+}
+
+
+
+SKU_ID *
+GetSkuIdArray (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ )
+{
+ SKU_HEAD *SkuHead;
+ UINTN LocalTokenNumber;
+
+ LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
+
+ SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+
+ return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);
+
+}
+
+
+
+UINTN
+GetSizeTableIndex (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ )
+{
+ UINTN i;
+ UINTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+
+ SizeTableIdx = 0;
+
+ for (i=0; i<LocalTokenNumberTableIdx; i++) {
+ LocalTokenNumber = Database->Init.LocalTokenNumberTable[i];
+
+ if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
+ //
+ // 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.
+ //
+ SizeTableIdx++;
+ } 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
+ //
+ SizeTableIdx += 2;
+ } 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 (i, Database);
+ SizeTableIdx += (UINTN)*SkuIdTable + 1;
+ }
+ }
+ }
+
+ }
+
+ return SizeTableIdx;
+}
diff --git a/MdeModulePkg/Universal/PCD/Pei/Service.h b/MdeModulePkg/Universal/PCD/Pei/Service.h
new file mode 100644
index 0000000000..9c3c70a0d0
--- /dev/null
+++ b/MdeModulePkg/Universal/PCD/Pei/Service.h
@@ -0,0 +1,462 @@
+/** @file
+Private functions used by 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: Service.h
+
+**/
+
+#ifndef _SERVICE_H
+#define _SERVICE_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+//
+// Please make sure the PCD Serivce PEIM Version is consistent with
+// the version of PCD Database generation tool
+//
+#define PCD_SERVICE_PEIM_VERSION 2
+
+//
+// PCD_PEI_DATABASE_GENTOOL_VERSION is defined in Autogen.h
+// and generated by PCD Database generation tool.
+//
+#if (PCD_SERVICE_PEIM_VERSION != PCD_PEI_SERVICE_DRIVER_AUTOGEN_VERSION )
+ #error "Please make sure the version of PCD Service PEIM and PCD PEI Database Generation Tool matches"
+#endif
+
+//
+// PPI Interface Implementation Declaration.
+//
+VOID
+EFIAPI
+PeiPcdSetSku (
+ IN UINTN SkuId
+ )
+;
+
+
+UINT8
+EFIAPI
+PeiPcdGet8 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT16
+EFIAPI
+PeiPcdGet16 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT32
+EFIAPI
+PeiPcdGet32 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT64
+EFIAPI
+PeiPcdGet64 (
+ IN UINTN TokenNumber
+ )
+;
+
+
+VOID *
+EFIAPI
+PeiPcdGetPtr (
+ IN UINTN TokenNumber
+ )
+;
+
+
+BOOLEAN
+EFIAPI
+PeiPcdGetBool (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINTN
+EFIAPI
+PeiPcdGetSize (
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT8
+EFIAPI
+PeiPcdGet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT16
+EFIAPI
+PeiPcdGet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+UINT32
+EFIAPI
+PeiPcdGet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINT64
+EFIAPI
+PeiPcdGet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+VOID *
+EFIAPI
+PeiPcdGetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+BOOLEAN
+EFIAPI
+PeiPcdGetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+UINTN
+EFIAPI
+PeiPcdGetSizeEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet8 (
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet16 (
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet32 (
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet64 (
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ )
+;
+
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtr (
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSetBool (
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ )
+;
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdSetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ )
+;
+
+
+
+EFI_STATUS
+EFIAPI
+PeiRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PPI_CALLBACK CallBackFunction
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PcdUnRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PPI_CALLBACK CallBackFunction
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextToken (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN OUT UINTN *TokenNumber
+ )
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextTokenSpace (
+ IN CONST EFI_GUID **Guid
+ )
+;
+
+
+/* Internal Function definitions */
+
+PEI_PCD_DATABASE *
+GetPcdDatabase (
+ VOID
+ )
+;
+
+
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+;
+
+
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+;
+
+
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+;
+
+
+
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+;
+
+
+
+VOID *
+GetWorker (
+ IN UINTN TokenNumber,
+ IN UINTN GetSize
+ )
+;
+
+
+
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ )
+;
+
+typedef struct {
+ UINTN TokenNumber;
+ UINTN Size;
+ UINT32 LocalTokenNumberAlias;
+} EX_PCD_ENTRY_ATTRIBUTE;
+
+
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+;
+
+
+
+
+EFI_STATUS
+PeiRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST GUID *Guid, OPTIONAL
+ IN PCD_PPI_CALLBACK CallBackFunction,
+ IN BOOLEAN Register
+);
+
+
+
+
+VOID
+BuildPcdDatabase (
+ VOID
+ )
+;
+
+SKU_ID *
+GetSkuIdArray (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ )
+;
+
+UINTN
+GetSizeTableIndex (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ )
+;
+
+UINTN
+GetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ OUT UINTN *MaxSize,
+ IN PEI_PCD_DATABASE *Database
+ )
+;
+
+
+
+BOOLEAN
+SetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN OUT UINTN *CurrentSize,
+ IN PEI_PCD_DATABASE *Database
+ )
+;
+
+
+extern EFI_GUID gPcdDataBaseHobGuid;
+
+extern EFI_GUID gPcdPeiCallbackFnTableHobGuid;
+
+extern PEI_PCD_DATABASE_INIT gPEIPcdDbInit;
+
+#endif