[edk2-devel] [PATCH 30/33] AMD/VanGoghBoard: Check in EDK2 override files.

duke.zhai via groups.io posted 33 patches 7 months, 3 weeks ago
There is a newer version of this series
[edk2-devel] [PATCH 30/33] AMD/VanGoghBoard: Check in EDK2 override files.
Posted by duke.zhai via groups.io 7 months, 3 weeks ago
From: Duke Zhai <Duke.Zhai@amd.com>


BZ #:4640

ChachaniBoard Use FSP for open source. FSP is needed to provide some

AGESA related pcds as the interface for Platform BIOS.

Override those EDK2 files to support reading AGESA-related PCDs from FSP.



Signed-off-by: Ken Yao <ken.yao@amd.com>

Cc: Eric Xing <eric.xing@amd.com>

Cc: Duke Zhai <duke.zhai@amd.com>

Cc: Igniculus Fu <igniculus.fu@amd.com>

Cc: Abner Chang <abner.chang@amd.com>

---

 .../edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c | 1529 +++++++++++++

 .../MdeModulePkg/Universal/PCD/Dxe/Pcd.inf    |  366 ++++

 .../edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c | 1885 +++++++++++++++++

 .../MdeModulePkg/Universal/PCD/Pei/Pcd.inf    |  368 ++++

 .../Register/Intel/SmramSaveStateMap.h        |  333 +++

 5 files changed, 4481 insertions(+)

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h



diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c

new file mode 100644

index 0000000000..cce92be6a6

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c

@@ -0,0 +1,1529 @@

+/** @file

+  Implements Dxe Pcd.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  PCD DXE driver manage all PCD entry initialized in PEI phase and DXE phase, and

+  produce the implementation of native PCD protocol and EFI_PCD_PROTOCOL defined in

+  PI 1.4a Vol3.

+

+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>

+SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include "Service.h"

+

+extern EFI_GUID  gEfiAmdAgesaModulePkgTokenSpaceGuid;

+extern EFI_GUID  gEfiAmdAgesaPkgTokenSpaceGuid;

+extern EFI_GUID  gFspEfiGetPcdInfoProtocolGuid;

+extern EFI_GUID  gFspEfiPcdProtocolGuid;

+

+// Cache the FSP PiPcd Protocols.

+STATIC EFI_PCD_PROTOCOL           *CachedFspPiPcdProtocol;

+STATIC EFI_GET_PCD_INFO_PROTOCOL  *CachedFspPiGetPcdInfoProtocol;

+

+STATIC

+BOOLEAN

+CheckPcdInFsp (

+  IN CONST EFI_GUID  *InputGuid

+  )

+{

+  if (  (FixedPcdGet8 (PcdFspModeSelection) == 0)                        // Dispatch mode

+     && (  CompareGuid (InputGuid, &gEfiAmdAgesaModulePkgTokenSpaceGuid) // AgesaModulePkg

+        || CompareGuid (InputGuid, &gEfiAmdAgesaPkgTokenSpaceGuid)       // AgesaPkg

+        || CompareGuid (InputGuid, &gAmdFspPkgGuid)                      // FspPkg

+        || CompareGuid (InputGuid, &gAmdCpmPkgTokenSpaceGuid)))                       // AmdCpmPkg

+  {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+VOID

+EFIAPI

+FspPiPcdProtocolInstalled (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  gBS->LocateProtocol (&gFspEfiPcdProtocolGuid, NULL, (VOID **)&CachedFspPiPcdProtocol);

+  gBS->CloseEvent (Event);

+  return;

+}

+

+VOID

+EFIAPI

+FspPiGetPcdInfoProtocolInstalled (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  gBS->LocateProtocol (&gFspEfiGetPcdInfoProtocolGuid, NULL, (VOID **)&CachedFspPiGetPcdInfoProtocol);

+  gBS->CloseEvent (Event);

+  return;

+}

+

+STATIC EFI_EVENT  mFspPiPcdProtocolInstalledEvent;

+STATIC EFI_EVENT  mFspPiGetPcdInfoProtocolInstalledEvent;

+

+///

+/// PCD database lock.

+///

+EFI_LOCK  mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);

+

+///

+/// PCD_PROTOCOL the EDKII native implementation which support dynamic

+/// type and dynamicEx type PCDs.

+///

+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

+};

+

+///

+/// EFI_PCD_PROTOCOL is defined in PI 1.2 Vol 3 which only support dynamicEx type

+/// PCD.

+///

+EFI_PCD_PROTOCOL  mEfiPcdInstance = {

+  DxePcdSetSku,

+  DxePcdGet8Ex,

+  DxePcdGet16Ex,

+  DxePcdGet32Ex,

+  DxePcdGet64Ex,

+  DxePcdGetPtrEx,

+  DxePcdGetBoolEx,

+  DxePcdGetSizeEx,

+  DxePcdSet8Ex,

+  DxePcdSet16Ex,

+  DxePcdSet32Ex,

+  DxePcdSet64Ex,

+  DxePcdSetPtrEx,

+  DxePcdSetBoolEx,

+  (EFI_PCD_PROTOCOL_CALLBACK_ON_SET)DxeRegisterCallBackOnSet,

+  (EFI_PCD_PROTOCOL_CANCEL_CALLBACK)DxeUnRegisterCallBackOnSet,

+  DxePcdGetNextToken,

+  DxePcdGetNextTokenSpace

+};

+

+///

+/// Instance of GET_PCD_INFO_PROTOCOL protocol is EDKII native implementation.

+/// This protocol instance support dynamic and dynamicEx type PCDs.

+///

+GET_PCD_INFO_PROTOCOL  mGetPcdInfoInstance = {

+  DxeGetPcdInfoGetInfo,

+  DxeGetPcdInfoGetInfoEx,

+  DxeGetPcdInfoGetSku

+};

+

+///

+/// Instance of EFI_GET_PCD_INFO_PROTOCOL which is defined in PI 1.2.1 Vol 3.

+/// This PPI instance only support dyanmicEx type PCD.

+///

+EFI_GET_PCD_INFO_PROTOCOL  mEfiGetPcdInfoInstance = {

+  DxeGetPcdInfoGetInfoEx,

+  DxeGetPcdInfoGetSku

+};

+

+EFI_HANDLE  mPcdHandle      = NULL;

+UINTN       mVpdBaseAddress = 0;

+

+/**

+  Main entry for PCD DXE driver.

+

+  This routine initialize the PCD database and install PCD_PROTOCOL.

+

+  @param ImageHandle     Image handle for PCD DXE driver.

+  @param SystemTable     Pointer to SystemTable.

+

+  @return Status of gBS->InstallProtocolInterface()

+

+**/

+EFI_STATUS

+EFIAPI

+PcdDxeInit (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  EFI_STATUS  Status;

+  VOID        *Registration;

+

+  //

+  // Make sure the Pcd Protocol is not already installed in the system

+  //

+

+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);

+

+  BuildPcdDxeDataBase ();

+

+  //

+  // Install PCD_PROTOCOL to handle dynamic type PCD

+  // Install EFI_PCD_PROTOCOL to handle dynamicEx type PCD

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &mPcdHandle,

+                  &gPcdProtocolGuid,

+                  &mPcdInstance,

+                  &gEfiPcdProtocolGuid,

+                  &mEfiPcdInstance,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Install GET_PCD_INFO_PROTOCOL to handle dynamic type PCD

+  // Install EFI_GET_PCD_INFO_PROTOCOL to handle dynamicEx type PCD

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &mPcdHandle,

+                  &gGetPcdInfoProtocolGuid,

+                  &mGetPcdInfoInstance,

+                  &gEfiGetPcdInfoProtocolGuid,

+                  &mEfiGetPcdInfoInstance,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  // Wait FSP Pcd Protocol.

+  gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, FspPiPcdProtocolInstalled, NULL, &mFspPiPcdProtocolInstalledEvent);

+  gBS->RegisterProtocolNotify (&gFspEfiPcdProtocolGuid, mFspPiPcdProtocolInstalledEvent, &Registration);

+  gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, FspPiGetPcdInfoProtocolInstalled, NULL, &mFspPiGetPcdInfoProtocolInstalledEvent);

+  gBS->RegisterProtocolNotify (&gFspEfiGetPcdInfoProtocolGuid, mFspPiGetPcdInfoProtocolInstalledEvent, &Registration);

+

+  //

+  // Register callback function upon VariableLockProtocol

+  // to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.

+  //

+  EfiCreateProtocolNotifyEvent (

+    &gEdkiiVariableLockProtocolGuid,

+    TPL_CALLBACK,

+    VariableLockCallBack,

+    NULL,

+    &Registration

+    );

+

+  //

+  // Cache VpdBaseAddress in entry point for the following usage.

+  //

+

+  //

+  // PcdVpdBaseAddress64 is DynamicEx PCD only. So, DxePcdGet64Ex() is used to get its value.

+  //

+  mVpdBaseAddress = (UINTN)DxePcdGet64Ex (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdVpdBaseAddress64));

+  if (mVpdBaseAddress == 0) {

+    //

+    // PcdVpdBaseAddress64 is not set, get value from PcdVpdBaseAddress.

+    //

+    mVpdBaseAddress = (UINTN)PcdGet32 (PcdVpdBaseAddress);

+  }

+

+  return Status;

+}

+

+/**

+  Retrieve additional information associated with a PCD token in the default token space.

+

+  This includes information such as the type of value the TokenNumber is associated with as well as possible

+  human readable name that is associated with the token.

+

+  @param[in]    TokenNumber The PCD token number.

+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.

+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.

+

+  @retval  EFI_SUCCESS      The PCD information was returned successfully.

+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.

+**/

+EFI_STATUS

+EFIAPI

+DxeGetPcdInfoGetInfo (

+  IN        UINTN         TokenNumber,

+  OUT       EFI_PCD_INFO  *PcdInfo

+  )

+{

+  return DxeGetPcdInfo (NULL, TokenNumber, PcdInfo);

+}

+

+/**

+  Retrieve additional information associated with a PCD token.

+

+  This includes information such as the type of value the TokenNumber is associated with as well as possible

+  human readable name that is associated with the token.

+

+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]    TokenNumber The PCD token number.

+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.

+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.

+

+  @retval  EFI_SUCCESS      The PCD information was returned successfully.

+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.

+**/

+EFI_STATUS

+EFIAPI

+DxeGetPcdInfoGetInfoEx (

+  IN CONST  EFI_GUID      *Guid,

+  IN        UINTN         TokenNumber,

+  OUT       EFI_PCD_INFO  *PcdInfo

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiGetPcdInfoProtocol != NULL);

+    return CachedFspPiGetPcdInfoProtocol->GetInfo (Guid, TokenNumber, PcdInfo);

+  }

+

+  return DxeGetPcdInfo (Guid, TokenNumber, PcdInfo);

+}

+

+/**

+  Retrieve the currently set SKU Id.

+

+  @return   The currently set SKU Id. If the platform has not set at a SKU Id, then the

+            default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU

+            Id is returned.

+**/

+UINTN

+EFIAPI

+DxeGetPcdInfoGetSku (

+  VOID

+  )

+{

+  return (UINTN)mPcdDatabase.DxeDb->SystemSkuId;

+}

+

+/**

+  Sets the SKU value for subsequent calls to set or get PCD token values.

+

+  SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.

+  SetSku() is normally called only once by the system.

+

+  For each item (token), the database can hold a single value that applies to all SKUs,

+  or multiple values, where each value is associated with a specific SKU Id. Items with multiple,

+  SKU-specific values are called SKU enabled.

+

+  The SKU Id of zero is reserved as a default.

+  For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the

+  single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the

+  last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,

+  the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been

+  set for that Id, the results are unpredictable.

+

+  @param[in]  SkuId The SKU value that will be used when the PCD service will retrieve and

+              set values associated with a PCD token.

+

+**/

+VOID

+EFIAPI

+DxePcdSetSku (

+  IN  UINTN  SkuId

+  )

+{

+  SKU_ID      *SkuIdTable;

+  UINTN       Index;

+  EFI_STATUS  Status;

+

+  DEBUG ((DEBUG_INFO, "PcdDxe - SkuId 0x%lx is to be set.\n", (SKU_ID)SkuId));

+

+  if (SkuId == mPcdDatabase.DxeDb->SystemSkuId) {

+    //

+    // The input SKU Id is equal to current SKU Id, return directly.

+    //

+    DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is same to current system Sku.\n"));

+    return;

+  }

+

+  if (mPcdDatabase.DxeDb->SystemSkuId != (SKU_ID)0) {

+    DEBUG ((DEBUG_ERROR, "PcdDxe - The SKU Id could be changed only once."));

+    DEBUG ((

+      DEBUG_ERROR,

+      "PcdDxe - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",

+      mPcdDatabase.DxeDb->SystemSkuId,

+      (SKU_ID)SkuId

+      ));

+    ASSERT (FALSE);

+    return;

+  }

+

+  SkuIdTable = (SKU_ID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SkuIdTableOffset);

+  for (Index = 0; Index < SkuIdTable[0]; Index++) {

+    if (SkuId == SkuIdTable[Index + 1]) {

+      DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is found in SkuId table.\n"));

+      Status = UpdatePcdDatabase (SkuId, TRUE);

+      if (!EFI_ERROR (Status)) {

+        mPcdDatabase.DxeDb->SystemSkuId = (SKU_ID)SkuId;

+        DEBUG ((DEBUG_INFO, "PcdDxe - Set current SKU Id to 0x%lx.\n", (SKU_ID)SkuId));

+        return;

+      }

+    }

+  }

+

+  //

+  // Invalid input SkuId, the default SKU Id will be still used for the system.

+  //

+  DEBUG ((DEBUG_ERROR, "PcdDxe - Invalid input SkuId, the default SKU Id will be still used.\n"));

+  return;

+}

+

+/**

+  Retrieves an 8-bit value for a given PCD token.

+

+  Retrieves the current byte-sized value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT8 value.

+

+**/

+UINT8

+EFIAPI

+DxePcdGet8 (

+  IN UINTN  TokenNumber

+  )

+{

+  return *((UINT8 *)GetWorker (TokenNumber, sizeof (UINT8)));

+}

+

+/**

+  Retrieves an 16-bit value for a given PCD token.

+

+  Retrieves the current 16-bits value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT16 value.

+

+**/

+UINT16

+EFIAPI

+DxePcdGet16 (

+  IN UINTN  TokenNumber

+  )

+{

+  return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));

+}

+

+/**

+  Retrieves an 32-bit value for a given PCD token.

+

+  Retrieves the current 32-bits value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT32 value.

+

+**/

+UINT32

+EFIAPI

+DxePcdGet32 (

+  IN UINTN  TokenNumber

+  )

+{

+  return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));

+}

+

+/**

+  Retrieves an 64-bit value for a given PCD token.

+

+  Retrieves the current 64-bits value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT64 value.

+

+**/

+UINT64

+EFIAPI

+DxePcdGet64 (

+  IN UINTN  TokenNumber

+  )

+{

+  return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));

+}

+

+/**

+  Retrieves a pointer to a value for a given PCD token.

+

+  Retrieves the current pointer to the buffer for a PCD token number.

+  Do not make any assumptions about the alignment of the pointer that

+  is returned by this function call.  If the TokenNumber is invalid,

+  the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The pointer to the buffer to be retrived.

+

+**/

+VOID *

+EFIAPI

+DxePcdGetPtr (

+  IN UINTN  TokenNumber

+  )

+{

+  return GetWorker (TokenNumber, 0);

+}

+

+/**

+  Retrieves a Boolean value for a given PCD token.

+

+  Retrieves the current boolean value for a PCD token number.

+  Do not make any assumptions about the alignment of the pointer that

+  is returned by this function call.  If the TokenNumber is invalid,

+  the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The Boolean value.

+

+**/

+BOOLEAN

+EFIAPI

+DxePcdGetBool (

+  IN UINTN  TokenNumber

+  )

+{

+  return *((BOOLEAN *)GetWorker (TokenNumber, sizeof (BOOLEAN)));

+}

+

+/**

+  Retrieves the size of the value for a given PCD token.

+

+  Retrieves the current size of a particular PCD token.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The size of the value for the PCD token.

+

+**/

+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 < mPcdTotalTokenCount + 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 < mPeiLocalTokenCount + 1);

+

+  TokenNumber = IsPeiDb ? TokenNumber :

+                (TokenNumber - mPeiLocalTokenCount);

+

+  LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset)

+                                  : (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);

+

+  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;

+  }

+}

+

+/**

+  Retrieves an 8-bit value for a given PCD token.

+

+  Retrieves the 8-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid          The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size 8-bit value for the PCD token.

+

+**/

+UINT8

+EFIAPI

+DxePcdGet8Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Get8 (Guid, ExTokenNumber);

+  }

+

+  return *((UINT8 *)ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));

+}

+

+/**

+  Retrieves an 16-bit value for a given PCD token.

+

+  Retrieves the 16-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size 16-bit value for the PCD token.

+

+**/

+UINT16

+EFIAPI

+DxePcdGet16Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Get16 (Guid, ExTokenNumber);

+  }

+

+  return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));

+}

+

+/**

+  Retrieves an 32-bit value for a given PCD token.

+

+  Retrieves the 32-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size 32-bit value for the PCD token.

+

+**/

+UINT32

+EFIAPI

+DxePcdGet32Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Get32 (Guid, ExTokenNumber);

+  }

+

+  return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));

+}

+

+/**

+  Retrieves an 64-bit value for a given PCD token.

+

+  Retrieves the 64-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size 64-bit value for the PCD token.

+

+**/

+UINT64

+EFIAPI

+DxePcdGet64Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Get64 (Guid, ExTokenNumber);

+  }

+

+  return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));

+}

+

+/**

+  Retrieves a pointer to a value for a given PCD token.

+

+  Retrieves the current pointer to the buffer for a PCD token number.

+  Do not make any assumptions about the alignment of the pointer that

+  is returned by this function call.  If the TokenNumber is invalid,

+  the results are unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The pointer to the buffer to be retrived.

+

+**/

+VOID *

+EFIAPI

+DxePcdGetPtrEx (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->GetPtr (Guid, ExTokenNumber);

+  }

+

+  return ExGetWorker (Guid, ExTokenNumber, 0);

+}

+

+/**

+  Retrieves an Boolean value for a given PCD token.

+

+  Retrieves the Boolean value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size Boolean value for the PCD token.

+

+**/

+BOOLEAN

+EFIAPI

+DxePcdGetBoolEx (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->GetBool (Guid, ExTokenNumber);

+  }

+

+  return *((BOOLEAN *)ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));

+}

+

+/**

+  Retrieves the size of the value for a given PCD token.

+

+  Retrieves the current size of a particular PCD token.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size of the value for the PCD token.

+

+**/

+UINTN

+EFIAPI

+DxePcdGetSizeEx (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->GetSize (Guid, ExTokenNumber);

+  }

+

+  return DxePcdGetSize (GetExPcdTokenNumber (Guid, (UINT32)ExTokenNumber));

+}

+

+/**

+  Sets an 8-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet8 (

+  IN UINTN  TokenNumber,

+  IN UINT8  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 16-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet16 (

+  IN UINTN   TokenNumber,

+  IN UINT16  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 32-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet32 (

+  IN UINTN   TokenNumber,

+  IN UINT32  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 64-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet64 (

+  IN UINTN   TokenNumber,

+  IN UINT64  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets a value of a specified size for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.

+                              On input, if the SizeOfValue is greater than the maximum size supported

+                              for this TokenNumber then the output value of SizeOfValue will reflect

+                              the maximum size supported for this TokenNumber.

+  @param[in]  Buffer The buffer to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSetPtr (

+  IN          UINTN  TokenNumber,

+  IN OUT      UINTN  *SizeOfBuffer,

+  IN          VOID   *Buffer

+  )

+{

+  return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);

+}

+

+/**

+  Sets an Boolean value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSetBool (

+  IN UINTN    TokenNumber,

+  IN BOOLEAN  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 8-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet8Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT8           Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Set8 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 16-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet16Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT16          Value

+  )

+{

+  //

+  // PcdSetNvStoreDefaultId should be set in PEI phase to take effect.

+  //

+  ASSERT (

+    !(CompareGuid (Guid, &gEfiMdeModulePkgTokenSpaceGuid) &&

+      (ExTokenNumber == PcdToken (PcdSetNvStoreDefaultId)))

+    );

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Set16 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 32-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet32Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT32          Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Set32 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 64-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSet64Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT64          Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->Set64 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets a value of a specified size for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.

+                              On input, if the SizeOfValue is greater than the maximum size supported

+                              for this TokenNumber then the output value of SizeOfValue will reflect

+                              the maximum size supported for this TokenNumber.

+  @param[in]  Buffer The buffer to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSetPtrEx (

+  IN            CONST EFI_GUID  *Guid,

+  IN            UINTN           ExTokenNumber,

+  IN OUT        UINTN           *SizeOfBuffer,

+  IN            VOID            *Buffer

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->SetPtr (Guid, ExTokenNumber, SizeOfBuffer, Buffer);

+  }

+

+  return ExSetWorker (ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);

+}

+

+/**

+  Sets an Boolean value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdSetBoolEx (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN BOOLEAN         Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    ASSERT (CachedFspPiPcdProtocol != NULL);

+    return CachedFspPiPcdProtocol->SetBool (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Specifies a function to be called anytime the value of a designated token is changed.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.

+

+  @retval EFI_SUCCESS  The PCD service has successfully established a call event

+                        for the CallBackToken requested.

+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxeRegisterCallBackOnSet (

+  IN  CONST EFI_GUID         *Guid  OPTIONAL,

+  IN  UINTN                  TokenNumber,

+  IN  PCD_PROTOCOL_CALLBACK  CallBackFunction

+  )

+{

+  EFI_STATUS  Status;

+

+  if (CallBackFunction == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Aquire lock to prevent reentrance from TPL_CALLBACK level

+  //

+  EfiAcquireLock (&mPcdDatabaseLock);

+

+  Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);

+

+  EfiReleaseLock (&mPcdDatabaseLock);

+

+  return Status;

+}

+

+/**

+  Cancels a previously set callback function for a particular PCD token number.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.

+

+  @retval EFI_SUCCESS  The PCD service has successfully established a call event

+                        for the CallBackToken requested.

+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxeUnRegisterCallBackOnSet (

+  IN  CONST EFI_GUID         *Guid  OPTIONAL,

+  IN  UINTN                  TokenNumber,

+  IN  PCD_PROTOCOL_CALLBACK  CallBackFunction

+  )

+{

+  EFI_STATUS  Status;

+

+  if (CallBackFunction == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Aquire lock to prevent reentrance from TPL_CALLBACK level

+  //

+  EfiAcquireLock (&mPcdDatabaseLock);

+

+  Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);

+

+  EfiReleaseLock (&mPcdDatabaseLock);

+

+  return Status;

+}

+

+/**

+  Retrieves the next valid token number in a given namespace.

+

+  This is useful since the PCD infrastructure contains a sparse list of token numbers,

+  and one cannot a priori know what token numbers are valid in the database.

+

+  If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.

+  If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.

+  If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.

+  If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.

+  The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.

+  If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.

+  If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.

+  If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.

+

+

+  @param[in]      Guid    The 128-bit unique value that designates the namespace from which to retrieve the next token.

+                          This is an optional parameter that may be NULL.  If this parameter is NULL, then a request is

+                          being made to retrieve tokens from the default token space.

+  @param[in, out] TokenNumber

+                          A pointer to the PCD token number to use to find the subsequent token number.

+

+  @retval EFI_SUCCESS   The PCD service has retrieved the next valid token number.

+  @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+DxePcdGetNextToken (

+  IN CONST EFI_GUID  *Guid  OPTIONAL,

+  IN OUT   UINTN     *TokenNumber

+  )

+{

+  EFI_STATUS  Status;

+  BOOLEAN     PeiExMapTableEmpty;

+  BOOLEAN     DxeExMapTableEmpty;

+

+  Status             = EFI_NOT_FOUND;

+  PeiExMapTableEmpty = mPeiExMapTableEmpty;

+  DxeExMapTableEmpty = mDxeExMapTableEmpty;

+

+  //

+  // 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 > mPeiNexTokenCount + 1) && (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||

+        ((*TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1))))

+    {

+      return EFI_NOT_FOUND;

+    }

+

+    (*TokenNumber)++;

+    if ((*TokenNumber + 1 > mPeiNexTokenCount + 1) &&

+        (*TokenNumber + 1 <= mPeiLocalTokenCount + 1))

+    {

+      //

+      // The first Non-Ex type Token Number for DXE PCD

+      // database is mPeiLocalTokenCount + 1

+      //

+      if (mDxeNexTokenCount > 0) {

+        *TokenNumber = mPeiLocalTokenCount + 1;

+      } else {

+        *TokenNumber = PCD_INVALID_TOKEN_NUMBER;

+        return EFI_NOT_FOUND;

+      }

+    } else if (*TokenNumber + 1 > mDxeNexTokenCount + mPeiLocalTokenCount + 1) {

+      *TokenNumber = PCD_INVALID_TOKEN_NUMBER;

+      return EFI_NOT_FOUND;

+    }

+

+    return EFI_SUCCESS;

+  }

+

+  if (PeiExMapTableEmpty && DxeExMapTableEmpty) {

+    return EFI_NOT_FOUND;

+  }

+

+  if (!PeiExMapTableEmpty) {

+    Status = ExGetNextTokeNumber (

+               Guid,

+               TokenNumber,

+               (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset),

+               mPeiGuidTableSize,

+               (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),

+               mPeiExMapppingTableSize

+               );

+  }

+

+  if (Status == EFI_SUCCESS) {

+    return Status;

+  }

+

+  if (!DxeExMapTableEmpty) {

+    Status = ExGetNextTokeNumber (

+               Guid,

+               TokenNumber,

+               (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset),

+               mDxeGuidTableSize,

+               (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),

+               mDxeExMapppingTableSize

+               );

+  }

+

+  return Status;

+}

+

+/**

+  Get all token space guid table which is different with given token space guid.

+

+  @param ExMapTableSize  The size of ExMapTable in item

+  @param ExMapTable      Token space guid table that want to be scaned.

+  @param GuidTable       Guid table

+

+  @return all token space guid table which is different with given token space guid.

+

+**/

+EFI_GUID **

+GetDistinctTokenSpace (

+  IN OUT    UINTN              *ExMapTableSize,

+  IN        DYNAMICEX_MAPPING  *ExMapTable,

+  IN        EFI_GUID           *GuidTable

+  )

+{

+  EFI_GUID  **DistinctTokenSpace;

+  UINTN     OldGuidIndex;

+  UINTN     TsIdx;

+  UINTN     TempTsIdx;

+  UINTN     Idx;

+  BOOLEAN   Match;

+

+  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++) {

+    Match        = FALSE;

+    OldGuidIndex = ExMapTable[Idx].ExGuidIndex;

+    for (TempTsIdx = 0; TempTsIdx <= TsIdx; TempTsIdx++) {

+      if (&GuidTable[OldGuidIndex] == DistinctTokenSpace[TempTsIdx]) {

+        //

+        // Have recorded this GUID.

+        //

+        Match = TRUE;

+        break;

+      }

+    }

+

+    if (!Match) {

+      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;

+}

+

+/**

+  Retrieves the next valid PCD token namespace for a given namespace.

+

+  Gets the next valid token namespace for a given namespace. This is useful to traverse the valid

+  token namespaces on a platform.

+

+  @param[in, out]   Guid    An indirect pointer to EFI_GUID. On input it designates a known token

+                            namespace from which the search will start. On output, it designates the next valid

+                            token namespace on the platform. If *Guid is NULL, then the GUID of the first token

+                            space of the current platform is returned. If the search cannot locate the next valid

+                            token namespace, an error is returned and the value of *Guid is undefined.

+

+  @retval  EFI_SUCCESS      The PCD service retrieved the value requested.

+  @retval  EFI_NOT_FOUND    The PCD service could not find the next valid token namespace.

+

+**/

+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;

+

+  ASSERT (Guid != NULL);

+

+  PeiExMapTableEmpty = mPeiExMapTableEmpty;

+  DxeExMapTableEmpty = mDxeExMapTableEmpty;

+

+  if (PeiExMapTableEmpty && DxeExMapTableEmpty) {

+    return EFI_NOT_FOUND;

+  }

+

+  if (TmpTokenSpaceBuffer[0] == NULL) {

+    PeiTokenSpaceTableSize = 0;

+

+    if (!PeiExMapTableEmpty) {

+      PeiTokenSpaceTableSize = mPeiExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);

+      PeiTokenSpaceTable     = GetDistinctTokenSpace (

+                                 &PeiTokenSpaceTableSize,

+                                 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),

+                                 (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset)

+                                 );

+      CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID *) * PeiTokenSpaceTableSize);

+      TmpTokenSpaceBufferCount = PeiTokenSpaceTableSize;

+      FreePool (PeiTokenSpaceTable);

+    }

+

+    if (!DxeExMapTableEmpty) {

+      DxeTokenSpaceTableSize = mDxeExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);

+      DxeTokenSpaceTable     = GetDistinctTokenSpace (

+                                 &DxeTokenSpaceTableSize,

+                                 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),

+                                 (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset)

+                                 );

+

+      //

+      // 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];

+        }

+      }

+

+      TmpTokenSpaceBufferCount = Idx3;

+      FreePool (DxeTokenSpaceTable);

+    }

+  }

+

+  if (*Guid == NULL) {

+    *Guid = TmpTokenSpaceBuffer[0];

+    return EFI_SUCCESS;

+  }

+

+  for (Idx = 0; Idx < TmpTokenSpaceBufferCount; Idx++) {

+    if (CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {

+      if (Idx == TmpTokenSpaceBufferCount - 1) {

+        //

+        // It has been the last token namespace.

+        //

+        *Guid = NULL;

+        return EFI_NOT_FOUND;

+      } else {

+        Idx++;

+        *Guid = TmpTokenSpaceBuffer[Idx];

+        return EFI_SUCCESS;

+      }

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

new file mode 100644

index 0000000000..0799e4cd96

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

@@ -0,0 +1,366 @@

+## @file

+#  PCD DXE Module INF file

+#

+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+## @file

+# PCD DXE driver manage database contains all dynamic PCD entries and produce the implementation of PCD protocol.

+#

+# This version PCD DXE depends on the external PCD database binary file, not built in PCD data base.

+# There are two PCD Protocols as follows:

+#   1) PCD_PROTOCOL

+#      It is EDKII implementation which support Dynamic/DynamicEx type Pcds.

+#   2) EFI_PCD_PROTOCOL

+#      It is defined by PI specification 1.2, Vol 3 which only support dynamicEx

+#      type Pcd.

+#

+# For dynamicEx type PCD, it is compatible between PCD_PROTOCOL and EFI_PCD_PROTOCOL.

+# PCD DXE driver will produce above two protocols at same time.

+#

+# PCD database is generated as the separate binary image at build time. The binary image

+# will be intergrated into Firmware volume together with PCD driver.

+#

+# ////////////////////////////////////////////////////////////////////////////////

+# //                                                                            //

+# //                      Introduction of PCD database                          //

+# //                                                                            //

+# ////////////////////////////////////////////////////////////////////////////////

+#

+# 1, Introduction

+#    PCD database hold all dynamic type PCD information. The structure of PEI PCD

+#    database is generated by build tools according to dynamic PCD usage for

+#    specified platform.

+#

+# 2, Dynamic Type PCD

+#    Dynamic type PCD is used for the configuration/setting which value is determined

+#    dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,

+#    PatchablePcd) is fixed in final generated FD image in build time.

+#

+#    2.1 The "dynamic" determination means one of below cases:

+#      a) The PCD setting value is produced by someone driver and consumed by

+#         other driver in execution time.

+#      b) The PCD setting value is set/get by user from FrontPage.

+#      c) The PCD setting value is produced by platform OEM vendor in specified area.

+#

+#    2.2 According to module distribution way, dynamic PCD could be classfied as:

+#      a) Dynamic:

+#         If module is released in source code and will be built with platform

+#         DSC, the dynamic PCD used by this module can be accessed as:

+#                 PcdGetxx(PcdSampleDynamicPcd);

+#         In building platform, build tools will translate PcdSampleDynamicPcd to

+#         pair of {Token Space Guid: Token Number} for this PCD.

+#      b) DynamicEx:

+#         If module is release as binary and will not pariticpate platform building,

+#         the dynamic PCD used by this module need be accessed as:

+#               PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)

+#         Developer need explicity gives {Token Space Guid:Token Number} as parameter

+#         in writting source code.

+#

+#    2.3 According to PCD value's storage method, dynamic PCD could be classfied as:

+#      a) Default Storage:

+#         - The PCD value is stored in PCD database maintained by PCD driver in boot

+#           time memory.

+#         - This type is used for communication between PEIM/DXE driver, DXE/DXE

+#           driver. But all set/get value will be losted after boot-time memory

+#           is turn off.

+#         - [PcdsDynamicDefault] is used as section name for this type PCD in

+#           platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.

+#

+#      b) Variable Storage:

+#         - The PCD value is stored in variable area.

+#         - As default storage type, this type PCD could be used for PEI/DXE driver

+#           communication. But beside it, this type PCD could also be used to store

+#           the value associate with a HII setting via variable interface.

+#         - In PEI phase, the PCD value could only be got but can not be set due

+#           to variable area is readonly.

+#         - [PcdsDynamicHii] is used as section name for this type PCD in platform

+#           DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.

+#

+#      c) OEM specificed storage area:

+#         - The PCD value is stored in OEM specified area which base address is

+#           specified by PCD setting - PcdVpdBaseAddress64 or PcdVpdBaseAddress.

+#         - The area is read only for PEI and DXE phase.

+#         - [PcdsDynamicVpd] is used as section name for this type PCD in platform

+#           DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.

+#

+#    2.4 When and how to use dynamic PCD

+#      Module developer do not care the used PCD is dynamic or static when writting

+#      source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator

+#      in platform DSC file. Please ref section 2.3 to get matching between dynamic

+#      PCD type and section name in DSC file.

+#

+# 3, PCD database:

+#    Although dynamic PCD could be in different storage type as above description,

+#    but the basic information and default value for all dynamic PCD is hold

+#    by PCD database maintained by PEI/DXE driver.

+#

+#    As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database

+#    also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.

+#    To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic

+#    PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD

+#    database contains all PCDs used in PEI/DXE phase in memory.

+#

+#    Build tool will generate PCD database into the separate binary file for

+#    PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.

+#

+#    3.1 PcdPeim and PcdDxe

+#      PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver

+#      build guid hob in temporary memory and copy the binary data base from flash

+#      to temporary memory for PEI PCD database.

+#      DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,

+#      a new PCD database is allocated in boot-time memory which including all

+#      PEI PCD and DXE PCD entry.

+#

+#      Pcd driver should run as early as possible before any other driver access

+#      dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by

+#      making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.

+#

+#    3.2 Token space Guid/Token number, Platform token, Local token number

+#           Dynamic PCD

+#          +-----------+               +---------+

+#          |TokenSpace |               |Platform |

+#          |   Guid    |  build tool   | Token   |

+#          |    +      +-------------->| Number  |

+#          |  Token    |               +---------+`._

+#          |  Number   |                             `.

+#          +-----------+                               `.  +------+

+#                                                        `-|Local |

+#                                                          |Token |

+#                               DynamicEx PCD            ,-|Number|

+#                               +-----------+         ,-'  +------+

+#                               |TokenSpace |      ,-'

+#                               |   Guid    |  _,-'

+#                               |    +      +.'

+#                               |  Token    |

+#                               |  Number   |

+#                               +-----------+

+#

+#

+#      3.2.1 Pair of Token space guid + Token number

+#        Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it

+#        is not easy maintained by PCD driver, and hashed token number will make

+#        searching slowly.

+#

+#      3.2.2 Platform Token Number

+#        "Platform token number" concept is introduced for mapping to a pair of

+#        "TokenSpaceGuid + TokenNumber". The platform token number is generated by

+#        build tool in autogen.h and all of them are continual in a platform scope

+#        started from 1.(0 meaning invalid internal token number)

+#        With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)

+#        in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)

+#        in autogen.h.

+#        Notes: The mapping between pair of "tokenspace guid + token number" and

+#        "internal token number" need build tool establish, so "platform token number"

+#        mechanism is not suitable for binary module which use DynamicEx type PCD.

+#        To access a dynamicEx type PCD, pair of "token space guid/token number" all need

+#        to be specificed for PcdSet/PcdGet accessing macro.

+#

+#        Platform Token Number is started from 1, and inceased continuous. From whole

+#        platform scope, there are two zones: PEI Zone and DXE Zone

+#                  |                      Platform Token Number

+#        ----------|----------------------------------------------------------------

+#        PEI Zone: |            1                 ~  PEI_LOCAL_TOKEN_NUMBER

+#        DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)

+#

+#      3.2.3 Local Token Number

+#        To fast searching a PCD entry in PCD database, PCD driver translate

+#        platform token number to local token number via a mapping table.

+#        For binary DynamicEx type PCD, there is a another mapping table to translate

+#        "token space guid + token number" to local token number directly.

+#        Local token number is identifier for all internal interface in PCD PEI/DXE

+#        driver.

+#

+#        A local token number is a 32-bit value in following meaning:

+#         32 ------------- 28 ---------- 24 -------- 0

+#          | PCD type mask  | Datum Type  |  Offset  |

+#          +-----------------------------------------+

+#        where:

+#          PCd type mask: indicate Pcd type from following macro:

+#                         PCD_TYPE_DATA

+#                         PCD_TYPE_HII

+#                         PCD_TYPE_VPD

+#                         PCD_TYPE_STRING

+#          Datum Type   : indicate PCD vaue type from following macro:

+#                         PCD_DATUM_TYPE_POINTER

+#                         PCD_DATUM_TYPE_UINT8

+#                         PCD_DATUM_TYPE_UINT16

+#                         PCD_DATUM_TYPE_UINT32

+#                         PCD_DATUM_TYPE_UINT64

+#          Offset      : indicate the related offset of PCD value in PCD database array.

+#       Based on local token number, PCD driver could fast determine PCD type, value

+#       type and get PCD entry from PCD database.

+#

+#    3.3 PCD Database binary file

+#      PCD Database binary file will be created at build time as the standalone binary image.

+#      To understand the binary image layout, PCD Database C structure is still generated

+#      as comments by build tools in PCD driver's autogen.h/

+#      autogen.c file. In generated C structure, following information is stored:

+#      - ExMapTable: This table is used translate a binary dynamicex type PCD's

+#                    "tokenguid + token" to local token number.

+#      - LocalTokenNumberTable:

+#                    This table stores all local token number in array, use "Internal

+#                    token number" as array index to get PCD entry's offset fastly.

+#      - SizeTable:  This table stores the size information for all PCD entry.

+#      - GuidTable:  This table stores guid value for DynamicEx's token space,

+#                    HII type PCD's variable GUID.

+#      - SkuIdTable: TBD

+#      - SystemSkuId: TBD

+#      - PCD value structure:

+#                    Every PCD has a value record in PCD database. For different

+#                    datum type PCD has different record structure which will be

+#                    introduced in 3.3.1

+#

+#      In a PCD database structure, there are two major area: Init and UnInit.

+#      Init area is use stored above PCD internal structure such as ExMapTable,

+#      LocalTokenNumberTable etc and the (default) value of PCD which has default

+#      value specified in platform DSC file.

+#      Unint area is used stored the value of PCD which has no default value in

+#      platform DSC file, the value of NULL, 0 specified in platform DSC file can

+#      be seemed as "no default value".

+#

+#      3.3.1 Simple Sample PCD Database C Structure

+#        A general sample of PCD database structue is as follows:

+#        typedef struct _PCD_DATABASE {

+#          typedef struct _PCD_DATABASE_INIT {

+#            //===== Following is PCD database internal maintain structures

+#            DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];

+#            UINT32            LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];

+#            GUID              GuidTable[PEI_GUID_TABLE_SIZE];

+#            SIZE_INFO         SizeTable[PEI_SIZE_TABLE_SIZE];

+#            UINT8             SkuIdTable[PEI_SKUID_TABLE_SIZE];

+#            SKU_ID            SystemSkuId;

+#

+#            //===== Following is value structure for PCD with default value

+#            ....

+#            ....

+#            ....

+#          } Init;

+#          typedef struct _PCD_DATABSE_UNINIT {

+#            //==== Following is value structure for PCD without default value

+#            ....

+#            ....

+#          } UnInit;

+#        }

+#

+#      3.3.2 PCD value structure in PCD database C structure

+#        The value's structure is generated by build tool in PCD database C structure.

+#        The PCDs in different datum type has different value structure.

+#

+#        3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD

+#          The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64

+#          data member in PCD database, For example:

+#          UINT16  PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;

+#          Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"

+#          Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration

+#          in DEC file.

+#

+#        3.3.2.2 VOID* datum type PCD

+#          The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.

+#

+#          3.3.2.2.1 VOID* - string type

+#            If the default value for VOID* datum type PCD like L"xxx", the PCD is

+#            used for unicode string, and C structure of this datum type PCD is

+#            UINT16 string array in PCD database, for example:

+#            UINT16 StringTable[29];

+#            The number of 29 in above sample is max size of a unicode string.

+#

+#            If the default value for VOID* datum type PCD like "xxx", the PCD is

+#            used for ascii string, and C structure of this datum type PCD is

+#            UINT8 string array in PCD database, for example:

+#            UINT8 StringTable[20];

+#            The number of 20 in above sample is max size of a ascii string.

+#

+#          3.3.2.2.2 VOID* - byte array

+#            If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}

+#            the PCD is used for byte array. The generated structrue is same as

+#            above ascii string table,

+#            UINT8 StringTable[13];

+#            The number of 13 in above sample is max size of byte array.

+#

+#      3.3.3 Some utility structures in PCD Database

+#        3.3.3.1 GuidTable

+#          GuidTable array is used to store all related GUID value in PCD database:

+#            - Variable GUID for HII type PCD

+#            - Token space GUID for dynamicex type PCD

+#

+#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>

+#

+#  SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = PcdDxe

+  MODULE_UNI_FILE                = PcdDxe.uni

+  FILE_GUID                      = 80CF7257-87AB-47f9-A3FE-D50B76D89541

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 4.0

+  PCD_IS_DRIVER                  = DXE_PCD_DRIVER

+  ENTRY_POINT                    = PcdDxeInit

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64 EBC

+#

+

+[Sources]

+  Pcd.c

+  Service.c

+  Service.h

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  ChachaniBoardPkg/Project.dec

+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec

+

+[LibraryClasses]

+  UefiRuntimeServicesTableLib

+  BaseMemoryLib

+  UefiBootServicesTableLib

+  MemoryAllocationLib

+  HobLib

+  UefiDriverEntryPoint

+  UefiLib

+  DebugLib

+  BaseLib

+  PcdLib

+  DxeServicesLib

+

+[Guids]

+  gPcdDataBaseHobGuid                           ## SOMETIMES_CONSUMES  ## HOB

+  gPcdDataBaseSignatureGuid                     ## CONSUMES  ## GUID  # PCD database signature GUID.

+  gEfiMdeModulePkgTokenSpaceGuid                ## SOMETIMES_CONSUMES  ## GUID

+  gEfiAmdAgesaModulePkgTokenSpaceGuid

+  gEfiAmdAgesaPkgTokenSpaceGuid

+  gAmdCpmPkgTokenSpaceGuid

+  gAmdFspPkgGuid

+

+[Protocols]

+  gPcdProtocolGuid                              ## PRODUCES

+  gEfiPcdProtocolGuid                           ## PRODUCES

+  gGetPcdInfoProtocolGuid                       ## SOMETIMES_PRODUCES

+  gEfiGetPcdInfoProtocolGuid                    ## SOMETIMES_PRODUCES

+  ## NOTIFY

+  ## SOMETIMES_CONSUMES

+  gEdkiiVariableLockProtocolGuid

+  gFspEfiPcdProtocolGuid

+  gFspEfiGetPcdInfoProtocolGuid

+

+[Pcd]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress      ## SOMETIMES_CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64    ## SOMETIMES_CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNvStoreDefaultId ## SOMETIMES_CONSUMES

+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection

+

+[Depex]

+  TRUE

+

+[UserExtensions.TianoCore."ExtraFiles"]

+  PcdDxeExtra.uni

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c

new file mode 100644

index 0000000000..129f03e684

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c

@@ -0,0 +1,1885 @@

+/** @file

+  Implements PEI Pcd.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  All Pcd Ppi services are implemented here.

+

+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>

+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>

+SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include "Service.h"

+

+extern EFI_GUID  gEfiAmdAgesaModulePkgTokenSpaceGuid;

+extern EFI_GUID  gEfiAmdAgesaPkgTokenSpaceGuid;

+extern EFI_GUID  gFspEfiGetPcdInfoPpiGuid;

+extern EFI_GUID  gFspEfiPeiPcdPpiGuid;

+

+STATIC

+BOOLEAN

+CheckPcdInFsp (

+  IN CONST EFI_GUID  *InputGuid

+  )

+{

+  if ((FixedPcdGet8 (PcdFspModeSelection) == 0)                        // Dispatch mode

+     && (CompareGuid (InputGuid, &gEfiAmdAgesaModulePkgTokenSpaceGuid) // AgesaModulePkg

+        || CompareGuid (InputGuid, &gEfiAmdAgesaPkgTokenSpaceGuid)     // AgesaPkg

+        || CompareGuid (InputGuid, &gAmdFspPkgGuid)                    // FspPkg

+        || CompareGuid (InputGuid, &gAmdCpmPkgTokenSpaceGuid)))        // AmdCpmPkg

+  {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+///

+/// Instance of PCD_PPI protocol is EDKII native implementation.

+/// This protocol instance support dynamic and dynamicEx type PCDs.

+///

+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

+};

+

+///

+/// Instance of EFI_PEI_PCD_PPI which is defined in PI 1.2 Vol 3.

+/// This PPI instance only support dyanmicEx type PCD.

+///

+EFI_PEI_PCD_PPI  mEfiPcdPpiInstance = {

+  PeiPcdSetSku,

+

+  PeiPcdGet8Ex,

+  PeiPcdGet16Ex,

+  PeiPcdGet32Ex,

+  PeiPcdGet64Ex,

+  PeiPcdGetPtrEx,

+  PeiPcdGetBoolEx,

+  PeiPcdGetSizeEx,

+  PeiPcdSet8Ex,

+  PeiPcdSet16Ex,

+  PeiPcdSet32Ex,

+  PeiPcdSet64Ex,

+  PeiPcdSetPtrEx,

+  PeiPcdSetBoolEx,

+  (EFI_PEI_PCD_PPI_CALLBACK_ON_SET)PeiRegisterCallBackOnSet,

+  (EFI_PEI_PCD_PPI_CANCEL_CALLBACK)PcdUnRegisterCallBackOnSet,

+  PeiPcdGetNextToken,

+  PeiPcdGetNextTokenSpace

+};

+

+///

+/// Instance of GET_PCD_INFO_PPI protocol is EDKII native implementation.

+/// This protocol instance support dynamic and dynamicEx type PCDs.

+///

+GET_PCD_INFO_PPI  mGetPcdInfoInstance = {

+  PeiGetPcdInfoGetInfo,

+  PeiGetPcdInfoGetInfoEx,

+  PeiGetPcdInfoGetSku

+};

+

+///

+/// Instance of EFI_GET_PCD_INFO_PPI which is defined in PI 1.2.1 Vol 3.

+/// This PPI instance only support dyanmicEx type PCD.

+///

+EFI_GET_PCD_INFO_PPI  mEfiGetPcdInfoInstance = {

+  PeiGetPcdInfoGetInfoEx,

+  PeiGetPcdInfoGetSku

+};

+

+EFI_PEI_PPI_DESCRIPTOR  mPpiList[] = {

+  {

+    EFI_PEI_PPI_DESCRIPTOR_PPI,

+    &gPcdPpiGuid,

+    &mPcdPpiInstance

+  },

+  {

+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+    &gEfiPeiPcdPpiGuid,

+    &mEfiPcdPpiInstance

+  }

+};

+

+EFI_PEI_PPI_DESCRIPTOR  mPpiList2[] = {

+  {

+    EFI_PEI_PPI_DESCRIPTOR_PPI,

+    &gGetPcdInfoPpiGuid,

+    &mGetPcdInfoInstance

+  },

+  {

+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+    &gEfiGetPcdInfoPpiGuid,

+    &mEfiGetPcdInfoInstance

+  }

+};

+

+/**

+  Callback on SET PcdSetNvStoreDefaultId

+

+  Once PcdSetNvStoreDefaultId is set, the default NV storage will be found from

+  PcdNvStoreDefaultValueBuffer, and built into VariableHob.

+

+  @param[in]      CallBackGuid  The PCD token GUID being set.

+  @param[in]      CallBackToken The PCD token number being set.

+  @param[in, out] TokenData     A pointer to the token data being set.

+  @param[in]      TokenDataSize The size, in bytes, of the data being set.

+

+**/

+VOID

+EFIAPI

+PcdSetNvStoreDefaultIdCallBack (

+  IN CONST EFI_GUID  *CallBackGuid  OPTIONAL,

+  IN       UINTN     CallBackToken,

+  IN OUT   VOID      *TokenData,

+  IN       UINTN     TokenDataSize

+  )

+{

+  EFI_STATUS             Status;

+  UINT16                 DefaultId;

+  SKU_ID                 SkuId;

+  UINTN                  FullSize;

+  UINTN                  Index;

+  UINT8                  *DataBuffer;

+  UINT8                  *VarStoreHobData;

+  UINT8                  *BufferEnd;

+  BOOLEAN                IsFound;

+  VARIABLE_STORE_HEADER  *NvStoreBuffer;

+  PCD_DEFAULT_DATA       *DataHeader;

+  PCD_DEFAULT_INFO       *DefaultInfo;

+  PCD_DATA_DELTA         *DeltaData;

+

+  DefaultId = *(UINT16 *)TokenData;

+  SkuId     = GetPcdDatabase ()->SystemSkuId;

+  IsFound   = FALSE;

+

+  if (PeiPcdGetSizeEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer)) > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {

+    DataBuffer = (UINT8 *)PeiPcdGetPtrEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer));

+    FullSize   = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;

+    DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));

+    //

+    // The first section data includes NV storage default setting.

+    //

+    NvStoreBuffer   = (VARIABLE_STORE_HEADER *)((UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);

+    VarStoreHobData = (UINT8 *)BuildGuidHob (&NvStoreBuffer->Signature, NvStoreBuffer->Size);

+    ASSERT (VarStoreHobData != NULL);

+    CopyMem (VarStoreHobData, NvStoreBuffer, NvStoreBuffer->Size);

+    //

+    // Find the matched SkuId and DefaultId in the first section

+    //

+    DefaultInfo = &(DataHeader->DefaultInfo[0]);

+    BufferEnd   = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;

+    while ((UINT8 *)DefaultInfo < BufferEnd) {

+      if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == SkuId)) {

+        IsFound = TRUE;

+        break;

+      }

+

+      DefaultInfo++;

+    }

+

+    //

+    // Find the matched SkuId and DefaultId in the remaining section

+    //

+    Index      = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));

+    DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);

+    while (!IsFound && Index < FullSize && DataHeader->DataSize != 0xFFFFFFFF) {

+      DefaultInfo = &(DataHeader->DefaultInfo[0]);

+      BufferEnd   = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;

+      while ((UINT8 *)DefaultInfo < BufferEnd) {

+        if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == SkuId)) {

+          IsFound = TRUE;

+          break;

+        }

+

+        DefaultInfo++;

+      }

+

+      if (IsFound) {

+        DeltaData = (PCD_DATA_DELTA *)BufferEnd;

+        BufferEnd = (UINT8 *)DataHeader + DataHeader->DataSize;

+        while ((UINT8 *)DeltaData < BufferEnd) {

+          *(VarStoreHobData + DeltaData->Offset) = (UINT8)DeltaData->Value;

+          DeltaData++;

+        }

+

+        break;

+      }

+

+      Index      = (Index + DataHeader->DataSize + 7) & (~7);

+      DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);

+    }

+  }

+

+  Status = PcdUnRegisterCallBackOnSet (

+             &gEfiMdeModulePkgTokenSpaceGuid,

+             PcdToken (PcdSetNvStoreDefaultId),

+             PcdSetNvStoreDefaultIdCallBack

+             );

+  ASSERT_EFI_ERROR (Status);

+}

+

+/**

+  Report Pei PCD database of all SKUs as Guid HOB so that DxePcd can access it.

+

+  @param PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation

+  @param NotifyDescriptor  Address of the notification descriptor data structure.

+  @param Ppi               Address of the PPI that was installed.

+

+  @retval EFI_SUCCESS      Successfully update the Boot records.

+**/

+EFI_STATUS

+EFIAPI

+EndOfPeiSignalPpiNotifyCallback (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+{

+  PEI_PCD_DATABASE     *Database;

+  EFI_BOOT_MODE        BootMode;

+  EFI_STATUS           Status;

+  UINTN                Instance;

+  EFI_PEI_FV_HANDLE    VolumeHandle;

+  EFI_PEI_FILE_HANDLE  FileHandle;

+  VOID                 *PcdDb;

+  UINT32               Length;

+  PEI_PCD_DATABASE     *PeiPcdDb;

+

+  Status = PeiServicesGetBootMode (&BootMode);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Don't need to report it on S3 boot.

+  //

+  if (BootMode == BOOT_ON_S3_RESUME) {

+    return EFI_SUCCESS;

+  }

+

+  PeiPcdDb = GetPcdDatabase ();

+  if (PeiPcdDb->SystemSkuId != (SKU_ID)0) {

+    //

+    // SkuId has been set. Don't need to report it to DXE phase.

+    //

+    return EFI_SUCCESS;

+  }

+

+  //

+  // Get full PCD database from PcdPeim FileHandle

+  //

+  Instance   = 0;

+  FileHandle = NULL;

+  while (TRUE) {

+    //

+    // Traverse all firmware volume instances

+    //

+    Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);

+    //

+    // Error should not happen

+    //

+    ASSERT_EFI_ERROR (Status);

+

+    //

+    // Find PcdDb file from the beginning in this firmware volume.

+    //

+    FileHandle = NULL;

+    Status     = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);

+    if (!EFI_ERROR (Status)) {

+      //

+      // Find PcdPeim FileHandle in this volume

+      //

+      break;

+    }

+

+    //

+    // We cannot find PcdPeim in this firmware volume, then search the next volume.

+    //

+    Instance++;

+  }

+

+  //

+  // Find PEI PcdDb and Build second PcdDB GuidHob

+  //

+  Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);

+  ASSERT_EFI_ERROR (Status);

+  Length   = PeiPcdDb->LengthForAllSkus;

+  Database = BuildGuidHob (&gPcdDataBaseHobGuid, Length);

+  CopyMem (Database, PcdDb, Length);

+

+  return EFI_SUCCESS;

+}

+

+EFI_PEI_NOTIFY_DESCRIPTOR  mEndOfPeiSignalPpiNotifyList[] = {

+  {

+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+    &gEfiEndOfPeiSignalPpiGuid,

+    EndOfPeiSignalPpiNotifyCallback

+  }

+};

+

+/**

+  Main entry for PCD PEIM driver.

+

+  This routine initialize the PCD database for PEI phase and install PCD_PPI/EFI_PEI_PCD_PPI.

+

+  @param  FileHandle  Handle of the file being invoked.

+  @param  PeiServices Describes the list of possible PEI Services.

+

+  @return Status of install PCD_PPI

+

+**/

+EFI_STATUS

+EFIAPI

+PcdPeimInit (

+  IN       EFI_PEI_FILE_HANDLE  FileHandle,

+  IN CONST EFI_PEI_SERVICES     **PeiServices

+  )

+{

+  EFI_STATUS  Status;

+

+  Status = PeiServicesRegisterForShadow (FileHandle);

+  if (Status == EFI_ALREADY_STARTED) {

+    //

+    // This is now starting in memory, the second time starting.

+    //

+    EFI_PEI_PPI_DESCRIPTOR  *OldPpiList;

+    EFI_PEI_PPI_DESCRIPTOR  *OldPpiList2;

+    VOID                    *Ppi;

+    VOID                    *Ppi2;

+

+    OldPpiList = NULL;

+    Status     = PeiServicesLocatePpi (

+                   &gPcdPpiGuid,

+                   0,

+                   &OldPpiList,

+                   &Ppi

+                   );

+    ASSERT_EFI_ERROR (Status);

+

+    if (OldPpiList != NULL) {

+      Status = PeiServicesReInstallPpi (OldPpiList, &mPpiList[0]);

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    OldPpiList2 = NULL;

+    Status      = PeiServicesLocatePpi (

+                    &gGetPcdInfoPpiGuid,

+                    0,

+                    &OldPpiList2,

+                    &Ppi2

+                    );

+    ASSERT_EFI_ERROR (Status);

+

+    if (OldPpiList2 != NULL) {

+      Status = PeiServicesReInstallPpi (OldPpiList2, &mPpiList2[0]);

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    OldPpiList = NULL;

+    Status     = PeiServicesLocatePpi (

+                   &gEfiPeiPcdPpiGuid,

+                   0,

+                   &OldPpiList,

+                   &Ppi

+                   );

+    ASSERT_EFI_ERROR (Status);

+

+    if (OldPpiList != NULL) {

+      Status = PeiServicesReInstallPpi (OldPpiList, &mPpiList[1]);

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    OldPpiList2 = NULL;

+    Status      = PeiServicesLocatePpi (

+                    &gEfiGetPcdInfoPpiGuid,

+                    0,

+                    &OldPpiList2,

+                    &Ppi2

+                    );

+    ASSERT_EFI_ERROR (Status);

+

+    if (OldPpiList2 != NULL) {

+      Status = PeiServicesReInstallPpi (OldPpiList2, &mPpiList2[1]);

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    return Status;

+  }

+

+  BuildPcdDatabase (FileHandle);

+

+  //

+  // Install PCD_PPI and EFI_PEI_PCD_PPI.

+  //

+  Status = PeiServicesInstallPpi (&mPpiList[0]);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Install GET_PCD_INFO_PPI and EFI_GET_PCD_INFO_PPI.

+  //

+  Status = PeiServicesInstallPpi (&mPpiList2[0]);

+  ASSERT_EFI_ERROR (Status);

+

+  Status = PeiServicesNotifyPpi (&mEndOfPeiSignalPpiNotifyList[0]);

+  ASSERT_EFI_ERROR (Status);

+

+  Status = PeiRegisterCallBackOnSet (

+             &gEfiMdeModulePkgTokenSpaceGuid,

+             PcdToken (PcdSetNvStoreDefaultId),

+             PcdSetNvStoreDefaultIdCallBack

+             );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

+

+/**

+  Retrieve additional information associated with a PCD token in the default token space.

+

+  This includes information such as the type of value the TokenNumber is associated with as well as possible

+  human readable name that is associated with the token.

+

+  @param[in]    TokenNumber The PCD token number.

+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.

+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.

+

+  @retval  EFI_SUCCESS      The PCD information was returned successfully.

+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.

+**/

+EFI_STATUS

+EFIAPI

+PeiGetPcdInfoGetInfo (

+  IN        UINTN         TokenNumber,

+  OUT       EFI_PCD_INFO  *PcdInfo

+  )

+{

+  return PeiGetPcdInfo (NULL, TokenNumber, PcdInfo);

+}

+

+/**

+  Retrieve additional information associated with a PCD token.

+

+  This includes information such as the type of value the TokenNumber is associated with as well as possible

+  human readable name that is associated with the token.

+

+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]    TokenNumber The PCD token number.

+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.

+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.

+

+  @retval  EFI_SUCCESS      The PCD information was returned successfully.

+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.

+**/

+EFI_STATUS

+EFIAPI

+PeiGetPcdInfoGetInfoEx (

+  IN CONST  EFI_GUID      *Guid,

+  IN        UINTN         TokenNumber,

+  OUT       EFI_PCD_INFO  *PcdInfo

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_GET_PCD_INFO_PPI  *FspPcdGetInfoPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiGetPcdInfoPpiGuid, 0, NULL, (VOID **)&FspPcdGetInfoPpi);

+    ASSERT (FspPcdGetInfoPpi != NULL);

+    return FspPcdGetInfoPpi->GetInfo (Guid, TokenNumber, PcdInfo);

+  }

+

+  return PeiGetPcdInfo (Guid, TokenNumber, PcdInfo);

+}

+

+/**

+  Retrieve the currently set SKU Id.

+

+  @return   The currently set SKU Id. If the platform has not set at a SKU Id, then the

+            default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU

+            Id is returned.

+**/

+UINTN

+EFIAPI

+PeiGetPcdInfoGetSku (

+  VOID

+  )

+{

+  return (UINTN)GetPcdDatabase ()->SystemSkuId;

+}

+

+/**

+  Sets the SKU value for subsequent calls to set or get PCD token values.

+

+  SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.

+  SetSku() is normally called only once by the system.

+

+  For each item (token), the database can hold a single value that applies to all SKUs,

+  or multiple values, where each value is associated with a specific SKU Id. Items with multiple,

+  SKU-specific values are called SKU enabled.

+

+  The SKU Id of zero is reserved as a default.

+  For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the

+  single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the

+  last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,

+  the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been

+  set for that Id, the results are unpredictable.

+

+  @param[in]  SkuId The SKU value that will be used when the PCD service will retrieve and

+              set values associated with a PCD token.

+

+**/

+VOID

+EFIAPI

+PeiPcdSetSku (

+  IN  UINTN  SkuId

+  )

+{

+  PEI_PCD_DATABASE        *PeiPcdDb;

+  SKU_ID                  *SkuIdTable;

+  UINTN                   Index;

+  EFI_STATUS              Status;

+  UINTN                   Instance;

+  EFI_PEI_FV_HANDLE       VolumeHandle;

+  EFI_PEI_FILE_HANDLE     FileHandle;

+  VOID                    *PcdDb;

+  UINT32                  Length;

+  PCD_DATABASE_SKU_DELTA  *SkuDelta;

+  PCD_DATA_DELTA          *SkuDeltaData;

+

+  DEBUG ((DEBUG_INFO, "PcdPei - SkuId 0x%lx is to be set.\n", (SKU_ID)SkuId));

+

+  PeiPcdDb = GetPcdDatabase ();

+

+  if (SkuId == PeiPcdDb->SystemSkuId) {

+    //

+    // The input SKU Id is equal to current SKU Id, return directly.

+    //

+    DEBUG ((DEBUG_INFO, "PcdPei - SkuId is same to current system Sku.\n"));

+    return;

+  }

+

+  if (PeiPcdDb->SystemSkuId != (SKU_ID)0) {

+    DEBUG ((DEBUG_ERROR, "PcdPei - The SKU Id could be changed only once."));

+    DEBUG ((

+      DEBUG_ERROR,

+      "PcdPei - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",

+      PeiPcdDb->SystemSkuId,

+      (SKU_ID)SkuId

+      ));

+    ASSERT (FALSE);

+    return;

+  }

+

+  SkuIdTable = (SKU_ID *)((UINT8 *)PeiPcdDb + PeiPcdDb->SkuIdTableOffset);

+  for (Index = 0; Index < SkuIdTable[0]; Index++) {

+    if (SkuId == SkuIdTable[Index + 1]) {

+      DEBUG ((DEBUG_INFO, "PcdPei - SkuId is found in SkuId table.\n"));

+      break;

+    }

+  }

+

+  if (Index < SkuIdTable[0]) {

+    //

+    // Get full PCD database from PcdPeim FileHandle

+    //

+    Instance   = 0;

+    FileHandle = NULL;

+    while (TRUE) {

+      //

+      // Traverse all firmware volume instances

+      //

+      Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);

+      //

+      // Error should not happen

+      //

+      ASSERT_EFI_ERROR (Status);

+

+      //

+      // Find PcdDb file from the beginning in this firmware volume.

+      //

+      FileHandle = NULL;

+      Status     = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);

+      if (!EFI_ERROR (Status)) {

+        //

+        // Find PcdPeim FileHandle in this volume

+        //

+        break;

+      }

+

+      //

+      // We cannot find PcdPeim in this firmware volume, then search the next volume.

+      //

+      Instance++;

+    }

+

+    //

+    // Find the delta data between the different Skus

+    //

+    Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);

+    ASSERT_EFI_ERROR (Status);

+    Length   = PeiPcdDb->LengthForAllSkus;

+    Index    = (PeiPcdDb->Length + 7) & (~7);

+    SkuDelta = NULL;

+    while (Index < Length) {

+      SkuDelta = (PCD_DATABASE_SKU_DELTA *)((UINT8 *)PcdDb + Index);

+      if ((SkuDelta->SkuId == SkuId) && (SkuDelta->SkuIdCompared == 0)) {

+        break;

+      }

+

+      Index = (Index + SkuDelta->Length + 7) & (~7);

+    }

+

+    //

+    // Patch the delta data into current PCD database

+    //

+    if ((Index < Length) && (SkuDelta != NULL)) {

+      SkuDeltaData = (PCD_DATA_DELTA *)(SkuDelta + 1);

+      while ((UINT8 *)SkuDeltaData < (UINT8 *)SkuDelta + SkuDelta->Length) {

+        *((UINT8 *)PeiPcdDb + SkuDeltaData->Offset) = (UINT8)SkuDeltaData->Value;

+        SkuDeltaData++;

+      }

+

+      PeiPcdDb->SystemSkuId = (SKU_ID)SkuId;

+      DEBUG ((DEBUG_INFO, "PcdPei - Set current SKU Id to 0x%lx.\n", (SKU_ID)SkuId));

+      return;

+    }

+  }

+

+  //

+  // Invalid input SkuId, the default SKU Id will be still used for the system.

+  //

+  DEBUG ((DEBUG_ERROR, "PcdPei - Invalid input SkuId, the default SKU Id will be still used.\n"));

+

+  return;

+}

+

+/**

+  Retrieves an 8-bit value for a given PCD token.

+

+  Retrieves the current byte-sized value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT8 value.

+

+**/

+UINT8

+EFIAPI

+PeiPcdGet8 (

+  IN UINTN  TokenNumber

+  )

+{

+  return *((UINT8 *)GetWorker (TokenNumber, sizeof (UINT8)));

+}

+

+/**

+  Retrieves an 16-bit value for a given PCD token.

+

+  Retrieves the current 16-bits value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT16 value.

+

+**/

+UINT16

+EFIAPI

+PeiPcdGet16 (

+  IN UINTN  TokenNumber

+  )

+{

+  return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));

+}

+

+/**

+  Retrieves an 32-bit value for a given PCD token.

+

+  Retrieves the current 32-bits value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT32 value.

+

+**/

+UINT32

+EFIAPI

+PeiPcdGet32 (

+  IN UINTN  TokenNumber

+  )

+{

+  return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));

+}

+

+/**

+  Retrieves an 64-bit value for a given PCD token.

+

+  Retrieves the current 64-bits value for a PCD token number.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The UINT64 value.

+

+**/

+UINT64

+EFIAPI

+PeiPcdGet64 (

+  IN UINTN  TokenNumber

+  )

+{

+  return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));

+}

+

+/**

+  Retrieves a pointer to a value for a given PCD token.

+

+  Retrieves the current pointer to the buffer for a PCD token number.

+  Do not make any assumptions about the alignment of the pointer that

+  is returned by this function call.  If the TokenNumber is invalid,

+  the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The pointer to the buffer to be retrieved.

+

+**/

+VOID *

+EFIAPI

+PeiPcdGetPtr (

+  IN UINTN  TokenNumber

+  )

+{

+  return GetWorker (TokenNumber, 0);

+}

+

+/**

+  Retrieves a Boolean value for a given PCD token.

+

+  Retrieves the current boolean value for a PCD token number.

+  Do not make any assumptions about the alignment of the pointer that

+  is returned by this function call.  If the TokenNumber is invalid,

+  the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The Boolean value.

+

+**/

+BOOLEAN

+EFIAPI

+PeiPcdGetBool (

+  IN UINTN  TokenNumber

+  )

+{

+  return *((BOOLEAN *)GetWorker (TokenNumber, sizeof (BOOLEAN)));

+}

+

+/**

+  Retrieves the size of the value for a given PCD token.

+

+  Retrieves the current size of a particular PCD token.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  TokenNumber The PCD token number.

+

+  @return The size of the value for the PCD token.

+

+**/

+UINTN

+EFIAPI

+PeiPcdGetSize (

+  IN UINTN  TokenNumber

+  )

+{

+  PEI_PCD_DATABASE  *PeiPcdDb;

+  UINTN             Size;

+  UINTN             MaxSize;

+  UINT32            LocalTokenCount;

+

+  PeiPcdDb        = GetPcdDatabase ();

+  LocalTokenCount = PeiPcdDb->LocalTokenCount;

+  //

+  // 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 < (LocalTokenCount + 1));

+

+  Size = (*((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + 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;

+  }

+}

+

+/**

+  Retrieves an 8-bit value for a given PCD token.

+

+  Retrieves the 8-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid              The token space for the token number.

+  @param[in]  ExTokenNumber     The PCD token number.

+

+  @return The size 8-bit value for the PCD token.

+

+**/

+UINT8

+EFIAPI

+PeiPcdGet8Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Get8 (Guid, ExTokenNumber);

+  }

+

+  return *((UINT8 *)ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));

+}

+

+/**

+  Retrieves an 16-bit value for a given PCD token.

+

+  Retrieves the 16-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid          The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size 16-bit value for the PCD token.

+

+**/

+UINT16

+EFIAPI

+PeiPcdGet16Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Get16 (Guid, ExTokenNumber);

+  }

+

+  return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));

+}

+

+/**

+  Retrieves an 32-bit value for a given PCD token.

+

+  Retrieves the 32-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size 32-bit value for the PCD token.

+

+**/

+UINT32

+EFIAPI

+PeiPcdGet32Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Get32 (Guid, ExTokenNumber);

+  }

+

+  return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));

+}

+

+/**

+  Retrieves an 64-bit value for a given PCD token.

+

+  Retrieves the 64-bit value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size 64-bit value for the PCD token.

+

+**/

+UINT64

+EFIAPI

+PeiPcdGet64Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Get64 (Guid, ExTokenNumber);

+  }

+

+  return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));

+}

+

+/**

+  Retrieves a pointer to a value for a given PCD token.

+

+  Retrieves the current pointer to the buffer for a PCD token number.

+  Do not make any assumptions about the alignment of the pointer that

+  is returned by this function call.  If the TokenNumber is invalid,

+  the results are unpredictable.

+

+  @param[in]  Guid          The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The pointer to the buffer to be retrieved.

+

+**/

+VOID *

+EFIAPI

+PeiPcdGetPtrEx (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->GetPtr (Guid, ExTokenNumber);

+  }

+

+  return ExGetWorker (Guid, ExTokenNumber, 0);

+}

+

+/**

+  Retrieves an Boolean value for a given PCD token.

+

+  Retrieves the Boolean value of a particular PCD token.

+  If the TokenNumber is invalid or the token space

+  specified by Guid does not exist, the results are

+  unpredictable.

+

+  @param[in]  Guid          The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size Boolean value for the PCD token.

+

+**/

+BOOLEAN

+EFIAPI

+PeiPcdGetBoolEx (

+  IN CONST  EFI_GUID  *Guid,

+  IN UINTN            ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->GetBool (Guid, ExTokenNumber);

+  }

+

+  return *((BOOLEAN *)ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));

+}

+

+/**

+  Retrieves the size of the value for a given PCD token.

+

+  Retrieves the current size of a particular PCD token.

+  If the TokenNumber is invalid, the results are unpredictable.

+

+  @param[in]  Guid          The token space for the token number.

+  @param[in]  ExTokenNumber The PCD token number.

+

+  @return The size of the value for the PCD token.

+

+**/

+UINTN

+EFIAPI

+PeiPcdGetSizeEx (

+  IN CONST  EFI_GUID  *Guid,

+  IN UINTN            ExTokenNumber

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->GetSize (Guid, ExTokenNumber);

+  }

+

+  return PeiPcdGetSize (GetExPcdTokenNumber (Guid, ExTokenNumber));

+}

+

+/**

+  Sets an 8-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet8 (

+  IN UINTN  TokenNumber,

+  IN UINT8  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 16-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet16 (

+  IN UINTN   TokenNumber,

+  IN UINT16  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 32-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet32 (

+  IN UINTN   TokenNumber,

+  IN UINT32  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 64-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet64 (

+  IN UINTN   TokenNumber,

+  IN UINT64  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets a value of a specified size for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.

+                              On input, if the SizeOfValue is greater than the maximum size supported

+                              for this TokenNumber then the output value of SizeOfValue will reflect

+                              the maximum size supported for this TokenNumber.

+  @param[in]  Buffer The buffer to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSetPtr (

+  IN      UINTN  TokenNumber,

+  IN OUT  UINTN  *SizeOfBuffer,

+  IN      VOID   *Buffer

+  )

+{

+  return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);

+}

+

+/**

+  Sets an Boolean value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  TokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSetBool (

+  IN UINTN    TokenNumber,

+  IN BOOLEAN  Value

+  )

+{

+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 8-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value         The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet8Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT8           Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Set8 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 16-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet16Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT16          Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Set16 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 32-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value         The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet32Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT32          Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Set32 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets an 64-bit value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  Value         The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSet64Ex (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN UINT64          Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->Set64 (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Sets a value of a specified size for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param[in]        Guid            The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]        ExTokenNumber   The PCD token number.

+  @param[in, out]   SizeOfBuffer    A pointer to the length of the value being set for the PCD token.

+                                    On input, if the SizeOfValue is greater than the maximum size supported

+                                    for this TokenNumber then the output value of SizeOfValue will reflect

+                                    the maximum size supported for this TokenNumber.

+  @param[in]        Value           The buffer to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSetPtrEx (

+  IN     CONST EFI_GUID  *Guid,

+  IN     UINTN           ExTokenNumber,

+  IN OUT UINTN           *SizeOfBuffer,

+  IN     VOID            *Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->SetPtr (Guid, ExTokenNumber, SizeOfBuffer, Value);

+  }

+

+  return ExSetWorker (ExTokenNumber, Guid, Value, SizeOfBuffer, TRUE);

+}

+

+/**

+  Sets an Boolean value for a given PCD token.

+

+  When the PCD service sets a value, it will check to ensure that the

+  size of the value being set is compatible with the Token's existing definition.

+  If it is not, an error will be returned.

+

+  @param [in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.

+  @param [in]  ExTokenNumber The PCD token number.

+  @param [in]  Value         The value to set for the PCD token.

+

+  @retval EFI_SUCCESS  Procedure returned successfully.

+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data

+                                  being set was incompatible with a call to this function.

+                                  Use GetSize() to retrieve the size of the target data.

+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdSetBoolEx (

+  IN CONST EFI_GUID  *Guid,

+  IN UINTN           ExTokenNumber,

+  IN BOOLEAN         Value

+  )

+{

+  if (CheckPcdInFsp (Guid)) {

+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;

+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);

+    ASSERT (FspPcdPpi != NULL);

+    return FspPcdPpi->SetBool (Guid, ExTokenNumber, Value);

+  }

+

+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));

+}

+

+/**

+  Specifies a function to be called anytime the value of a designated token is changed.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.

+

+  @retval EFI_SUCCESS  The PCD service has successfully established a call event

+                        for the CallBackToken requested.

+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiRegisterCallBackOnSet (

+  IN  CONST EFI_GUID    *Guid  OPTIONAL,

+  IN  UINTN             ExTokenNumber,

+  IN  PCD_PPI_CALLBACK  CallBackFunction

+  )

+{

+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if (CallBackFunction == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, TRUE);

+}

+

+/**

+  Cancels a previously set callback function for a particular PCD token number.

+

+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.

+  @param[in]  ExTokenNumber The PCD token number.

+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.

+

+  @retval EFI_SUCCESS  The PCD service has successfully established a call event

+                        for the CallBackToken requested.

+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PcdUnRegisterCallBackOnSet (

+  IN  CONST EFI_GUID    *Guid  OPTIONAL,

+  IN  UINTN             ExTokenNumber,

+  IN  PCD_PPI_CALLBACK  CallBackFunction

+  )

+{

+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if (CallBackFunction == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, FALSE);

+}

+

+/**

+  Retrieves the next valid token number in a given namespace.

+

+  This is useful since the PCD infrastructure contains a sparse list of token numbers,

+  and one cannot a priori know what token numbers are valid in the database.

+

+  If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.

+  If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.

+  If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.

+  If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.

+  The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.

+  If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.

+  If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.

+  If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.

+

+

+  @param[in]       Guid        The 128-bit unique value that designates the namespace from which to extract the value.

+                               This is an optional parameter that may be NULL.  If this parameter is NULL, then a request

+                               is being made to retrieve tokens from the default token space.

+  @param[in, out]  TokenNumber A pointer to the PCD token number to use to find the subsequent token number.

+

+  @retval EFI_SUCCESS   The PCD service has retrieved the next valid token number.

+  @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdGetNextToken (

+  IN CONST EFI_GUID  *Guid  OPTIONAL,

+  IN OUT  UINTN      *TokenNumber

+  )

+{

+  UINTN              GuidTableIdx;

+  PEI_PCD_DATABASE   *PeiPcdDb;

+  EFI_GUID           *MatchGuid;

+  EFI_GUID           *GuidTable;

+  DYNAMICEX_MAPPING  *ExMapTable;

+  UINTN              Index;

+  BOOLEAN            Found;

+  BOOLEAN            PeiExMapTableEmpty;

+  UINTN              PeiNexTokenNumber;

+

+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  PeiPcdDb          = GetPcdDatabase ();

+  PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;

+  GuidTable         = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);

+

+  if (PeiPcdDb->ExTokenCount == 0) {

+    PeiExMapTableEmpty = TRUE;

+  } else {

+    PeiExMapTableEmpty = FALSE;

+  }

+

+  if (Guid == NULL) {

+    if (*TokenNumber > PeiNexTokenNumber) {

+      return EFI_NOT_FOUND;

+    }

+

+    (*TokenNumber)++;

+    if (*TokenNumber > PeiNexTokenNumber) {

+      *TokenNumber = PCD_INVALID_TOKEN_NUMBER;

+      return EFI_NOT_FOUND;

+    }

+

+    return EFI_SUCCESS;

+  } else {

+    if (PeiExMapTableEmpty) {

+      return EFI_NOT_FOUND;

+    }

+

+    MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof (EFI_GUID), Guid);

+

+    if (MatchGuid == NULL) {

+      return EFI_NOT_FOUND;

+    }

+

+    GuidTableIdx = MatchGuid - GuidTable;

+

+    ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);

+

+    Found = FALSE;

+    //

+    // Locate the GUID in ExMapTable first.

+    //

+    for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {

+      if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {

+        Found = TRUE;

+        break;

+      }

+    }

+

+    if (Found) {

+      //

+      // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first

+      // token number in found token space.

+      //

+      if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {

+        *TokenNumber = ExMapTable[Index].ExTokenNumber;

+        return EFI_SUCCESS;

+      }

+

+      for ( ; Index < PeiPcdDb->ExTokenCount; Index++) {

+        if ((ExMapTable[Index].ExTokenNumber == *TokenNumber) && (ExMapTable[Index].ExGuidIndex == GuidTableIdx)) {

+          break;

+        }

+      }

+

+      while (Index < PeiPcdDb->ExTokenCount) {

+        Index++;

+        if (Index == PeiPcdDb->ExTokenCount) {

+          //

+          // Exceed the length of ExMap Table

+          //

+          *TokenNumber = PCD_INVALID_TOKEN_NUMBER;

+          return EFI_NOT_FOUND;

+        } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {

+          //

+          // Found the next match

+          //

+          *TokenNumber = ExMapTable[Index].ExTokenNumber;

+          return EFI_SUCCESS;

+        }

+      }

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+/**

+  Retrieves the next valid PCD token namespace for a given namespace.

+

+  Gets the next valid token namespace for a given namespace. This is useful to traverse the valid

+  token namespaces on a platform.

+

+  @param[in, out]   Guid    An indirect pointer to EFI_GUID. On input it designates a known token

+                            namespace from which the search will start. On output, it designates the next valid

+                            token namespace on the platform. If *Guid is NULL, then the GUID of the first token

+                            space of the current platform is returned. If the search cannot locate the next valid

+                            token namespace, an error is returned and the value of *Guid is undefined.

+

+  @retval  EFI_SUCCESS      The PCD service retrieved the value requested.

+  @retval  EFI_NOT_FOUND    The PCD service could not find the next valid token namespace.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiPcdGetNextTokenSpace (

+  IN OUT CONST EFI_GUID  **Guid

+  )

+{

+  UINTN              GuidTableIdx;

+  EFI_GUID           *MatchGuid;

+  PEI_PCD_DATABASE   *PeiPcdDb;

+  DYNAMICEX_MAPPING  *ExMapTable;

+  UINTN              Index;

+  UINTN              Index2;

+  BOOLEAN            Found;

+  BOOLEAN            PeiExMapTableEmpty;

+  EFI_GUID           *GuidTable;

+

+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  ASSERT (Guid != NULL);

+

+  PeiPcdDb = GetPcdDatabase ();

+

+  if (PeiPcdDb->ExTokenCount == 0) {

+    PeiExMapTableEmpty = TRUE;

+  } else {

+    PeiExMapTableEmpty = FALSE;

+  }

+

+  if (PeiExMapTableEmpty) {

+    return EFI_NOT_FOUND;

+  }

+

+  ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);

+  GuidTable  = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);

+

+  if (*Guid == NULL) {

+    //

+    // return the first Token Space Guid.

+    //

+    *Guid = GuidTable + ExMapTable[0].ExGuidIndex;

+    return EFI_SUCCESS;

+  }

+

+  MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof (GuidTable[0]), *Guid);

+

+  if (MatchGuid == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

+  GuidTableIdx = MatchGuid - GuidTable;

+

+  Found = FALSE;

+  for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {

+    if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {

+      Found = TRUE;

+      break;

+    }

+  }

+

+  if (Found) {

+    Index++;

+    for ( ; Index < PeiPcdDb->ExTokenCount; Index++ ) {

+      if (ExMapTable[Index].ExGuidIndex != GuidTableIdx) {

+        Found = FALSE;

+        for (Index2 = 0; Index2 < Index; Index2++) {

+          if (ExMapTable[Index2].ExGuidIndex == ExMapTable[Index].ExGuidIndex) {

+            //

+            // This token namespace should have been found and output at preceding getting.

+            //

+            Found = TRUE;

+            break;

+          }

+        }

+

+        if (!Found) {

+          *Guid = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + ExMapTable[Index].ExGuidIndex;

+          return EFI_SUCCESS;

+        }

+      }

+    }

+

+    *Guid = NULL;

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+/**

+  Get PCD value's size for POINTER type PCD.

+

+  The POINTER type PCD's value will be stored into a buffer in specified size.

+  The max size of this PCD's value is described in PCD's definition in DEC file.

+

+  @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table

+  @param MaxSize                  Maximum size of PCD's value

+  @param Database                 Pcd database in PEI phase.

+

+  @return PCD value's size for POINTER type PCD.

+

+**/

+UINTN

+GetPtrTypeSize (

+  IN    UINTN             LocalTokenNumberTableIdx,

+  OUT   UINTN             *MaxSize,

+  IN    PEI_PCD_DATABASE  *Database

+  )

+{

+  INTN       SizeTableIdx;

+  UINTN      LocalTokenNumber;

+  SIZE_INFO  *SizeTable;

+

+  SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);

+

+  LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);

+

+  ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);

+

+  SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);

+

+  *MaxSize = SizeTable[SizeTableIdx];

+  //

+  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type

+  // PCD entry.

+  //

+  if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {

+    //

+    // We have only two entry for VPD enabled PCD entry:

+    // 1) MAX Size.

+    // 2) Current Size

+    // We consider current size is equal to MAX size.

+    //

+    return *MaxSize;

+  } else {

+    //

+    // We have only two entry for Non-Sku enabled PCD entry:

+    // 1) MAX SIZE

+    // 2) Current Size

+    //

+    return SizeTable[SizeTableIdx + 1];

+  }

+}

+

+/**

+  Set PCD value's size for POINTER type PCD.

+

+  The POINTER type PCD's value will be stored into a buffer in specified size.

+  The max size of this PCD's value is described in PCD's definition in DEC file.

+

+  @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table

+  @param CurrentSize              Maximum size of PCD's value

+  @param Database                 Pcd database in PEI phase.

+

+  @retval TRUE  Success to set PCD's value size, which is not exceed maximum size

+  @retval FALSE Fail to set PCD's value size, which maybe exceed maximum size

+

+**/

+BOOLEAN

+SetPtrTypeSize (

+  IN          UINTN             LocalTokenNumberTableIdx,

+  IN    OUT   UINTN             *CurrentSize,

+  IN          PEI_PCD_DATABASE  *Database

+  )

+{

+  INTN       SizeTableIdx;

+  UINTN      LocalTokenNumber;

+  SIZE_INFO  *SizeTable;

+  UINTN      MaxSize;

+

+  SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);

+

+  LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);

+

+  ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);

+

+  SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);

+

+  MaxSize = SizeTable[SizeTableIdx];

+  //

+  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type

+  // PCD entry.

+  //

+  if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {

+    //

+    // 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;

+    }

+

+    //

+    // 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;

+  }

+}

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf

new file mode 100644

index 0000000000..204f08b958

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf

@@ -0,0 +1,368 @@

+## @file

+#  PCD PEI Module INF file

+#

+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+## @file

+# PCD PEIM produces PCD database to manage all dynamic PCD in PEI phase and install Pcd Ppi service.

+#

+# This version PCD PEIM depends on the external PCD database binary file, not built in PCD data base.

+# There are two PCD PPIs as follows:

+#   1) PCD_PPI

+#      It is EDKII implementation which support Dynamic/DynamicEx Pcds.

+#   2) EFI_PEI_PCD_PPI

+#      It is defined by PI specification 1.2, Vol 3 which only support dynamicEx

+#      type Pcd.

+# For dynamicEx type PCD, it is compatible between PCD_PPI and EFI_PEI_PCD_PPI.

+# PCD PEIM driver will produce above two PPIs at same time.

+#

+# PCD database is generated as the separate binary image at build time. The binary image

+# will be intergrated into Firmware volume together with PCD driver.

+#

+# ////////////////////////////////////////////////////////////////////////////////

+# //                                                                            //

+# //                      Introduction of PCD database                          //

+# //                                                                            //

+# ////////////////////////////////////////////////////////////////////////////////

+#

+# 1, Introduction

+#    PCD database hold all dynamic type PCD information. The structure of PEI PCD

+#    database is generated by build tools according to dynamic PCD usage for

+#    specified platform.

+#

+# 2, Dynamic Type PCD

+#    Dynamic type PCD is used for the configuration/setting which value is determined

+#    dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,

+#    PatchablePcd) is fixed in final generated FD image in build time.

+#

+#    2.1 The "dynamic" determination means one of below cases:

+#      a) The PCD setting value is produced by someone driver and consumed by

+#         other driver in execution time.

+#      b) The PCD setting value is set/get by user from FrontPage.

+#      c) The PCD setting value is produced by platform OEM vendor in specified area.

+#

+#    2.2 According to module distribution way, dynamic PCD could be classfied as:

+#      a) Dynamic:

+#         If module is released in source code and will be built with platform

+#         DSC, the dynamic PCD used by this module can be accessed as:

+#                 PcdGetxx(PcdSampleDynamicPcd);

+#         In building platform, build tools will translate PcdSampleDynamicPcd to

+#         pair of {Token Space Guid: Token Number} for this PCD.

+#      b) DynamicEx:

+#         If module is release as binary and will not pariticpate platform building,

+#         the dynamic PCD used by this module need be accessed as:

+#               PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)

+#         Developer need explicity gives {Token Space Guid:Token Number} as parameter

+#         in writting source code.

+#

+#    2.3 According to PCD value's storage method, dynamic PCD could be classfied as:

+#      a) Default Storage:

+#         - The PCD value is stored in PCD database maintained by PCD driver in boot

+#           time memory.

+#         - This type is used for communication between PEIM/DXE driver, DXE/DXE

+#           driver. But all set/get value will be losted after boot-time memory

+#           is turn off.

+#         - [PcdsDynamicDefault] is used as section name for this type PCD in

+#           platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.

+#

+#      b) Variable Storage:

+#         - The PCD value is stored in variable area.

+#         - As default storage type, this type PCD could be used for PEI/DXE driver

+#           communication. But beside it, this type PCD could also be used to store

+#           the value associate with a HII setting via variable interface.

+#         - In PEI phase, the PCD value could only be got but can not be set due

+#           to variable area is readonly.

+#         - [PcdsDynamicHii] is used as section name for this type PCD in platform

+#           DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.

+#

+#      c) OEM specificed storage area:

+#         - The PCD value is stored in OEM specified area which base address is

+#           specified by PCD setting - PcdVpdBaseAddress64 or PcdVpdBaseAddress.

+#         - The area is read only for PEI and DXE phase.

+#         - [PcdsDynamicVpd] is used as section name for this type PCD in platform

+#           DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.

+#

+#    2.4 When and how to use dynamic PCD

+#      Module developer do not care the used PCD is dynamic or static when writting

+#      source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator

+#      in platform DSC file. Please ref section 2.3 to get matching between dynamic

+#      PCD type and section name in DSC file.

+#

+# 3, PCD database:

+#    Although dynamic PCD could be in different storage type as above description,

+#    but the basic information and default value for all dynamic PCD is hold

+#    by PCD database maintained by PEI/DXE driver.

+#

+#    As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database

+#    also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.

+#    To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic

+#    PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD

+#    database contains all PCDs used in PEI/DXE phase in memory.

+#

+#    Build tool will generate PCD database into the separate binary file for

+#    PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.

+#

+#    3.1 PcdPeim and PcdDxe

+#      PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver

+#      build guid hob in temporary memory and copy the binary data base from flash

+#      to temporary memory for PEI PCD database.

+#      DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,

+#      a new PCD database is allocated in boot-time memory which including all

+#      PEI PCD and DXE PCD entry.

+#

+#      Pcd driver should run as early as possible before any other driver access

+#      dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by

+#      making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.

+#

+#    3.2 Token space Guid/Token number, Platform token, Local token number

+#           Dynamic PCD

+#          +-----------+               +---------+

+#          |TokenSpace |               |Platform |

+#          |   Guid    |  build tool   | Token   |

+#          |    +      +-------------->| Number  |

+#          |  Token    |               +---------+`._

+#          |  Number   |                             `.

+#          +-----------+                               `.  +------+

+#                                                        `-|Local |

+#                                                          |Token |

+#                               DynamicEx PCD            ,-|Number|

+#                               +-----------+         ,-'  +------+

+#                               |TokenSpace |      ,-'

+#                               |   Guid    |  _,-'

+#                               |    +      +.'

+#                               |  Token    |

+#                               |  Number   |

+#                               +-----------+

+#

+#

+#      3.2.1 Pair of Token space guid + Token number

+#        Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it

+#        is not easy maintained by PCD driver, and hashed token number will make

+#        searching slowly.

+#

+#      3.2.2 Platform Token Number

+#        "Platform token number" concept is introduced for mapping to a pair of

+#        "TokenSpaceGuid + TokenNumber". The platform token number is generated by

+#        build tool in autogen.h and all of them are continual in a platform scope

+#        started from 1.(0 meaning invalid internal token number)

+#        With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)

+#        in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)

+#        in autogen.h.

+#        Notes: The mapping between pair of "tokenspace guid + token number" and

+#        "internal token number" need build tool establish, so "platform token number"

+#        mechanism is not suitable for binary module which use DynamicEx type PCD.

+#        To access a dynamicEx type PCD, pair of "token space guid/token number" all need

+#        to be specificed for PcdSet/PcdGet accessing macro.

+#

+#        Platform Token Number is started from 1, and inceased continuous. From whole

+#        platform scope, there are two zones: PEI Zone and DXE Zone

+#                  |                      Platform Token Number

+#        ----------|----------------------------------------------------------------

+#        PEI Zone: |            1                 ~  PEI_LOCAL_TOKEN_NUMBER

+#        DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)

+#

+#      3.2.3 Local Token Number

+#        To fast searching a PCD entry in PCD database, PCD driver translate

+#        platform token number to local token number via a mapping table.

+#        For binary DynamicEx type PCD, there is a another mapping table to translate

+#        "token space guid + token number" to local token number directly.

+#        Local token number is identifier for all internal interface in PCD PEI/DXE

+#        driver.

+#

+#        A local token number is a 32-bit value in following meaning:

+#         32 ------------- 28 ---------- 24 -------- 0

+#          | PCD type mask  | Datum Type  |  Offset  |

+#          +-----------------------------------------+

+#        where:

+#          PCd type mask: indicate Pcd type from following macro:

+#                         PCD_TYPE_DATA

+#                         PCD_TYPE_HII

+#                         PCD_TYPE_VPD

+#                         PCD_TYPE_STRING

+#          Datum Type   : indicate PCD vaue type from following macro:

+#                         PCD_DATUM_TYPE_POINTER

+#                         PCD_DATUM_TYPE_UINT8

+#                         PCD_DATUM_TYPE_UINT16

+#                         PCD_DATUM_TYPE_UINT32

+#                         PCD_DATUM_TYPE_UINT64

+#          Offset      : indicate the related offset of PCD value in PCD database array.

+#       Based on local token number, PCD driver could fast determine PCD type, value

+#       type and get PCD entry from PCD database.

+#

+#    3.3 PCD Database binary file

+#      PCD Database binary file will be created at build time as the standalone binary image.

+#      To understand the binary image layout, PCD Database C structure is still generated

+#      as comments by build tools in PCD driver's autogen.h/

+#      autogen.c file. In generated C structure, following information is stored:

+#      - ExMapTable: This table is used translate a binary dynamicex type PCD's

+#                    "tokenguid + token" to local token number.

+#      - LocalTokenNumberTable:

+#                    This table stores all local token number in array, use "Internal

+#                    token number" as array index to get PCD entry's offset fastly.

+#      - SizeTable:  This table stores the size information for all PCD entry.

+#      - GuidTable:  This table stores guid value for DynamicEx's token space,

+#                    HII type PCD's variable GUID.

+#      - SkuIdTable: TBD

+#      - SystemSkuId: TBD

+#      - PCD value structure:

+#                    Every PCD has a value record in PCD database. For different

+#                    datum type PCD has different record structure which will be

+#                    introduced in 3.3.1

+#

+#      In a PCD database structure, there are two major area: Init and UnInit.

+#      Init area is use stored above PCD internal structure such as ExMapTable,

+#      LocalTokenNumberTable etc and the (default) value of PCD which has default

+#      value specified in platform DSC file.

+#      Unint area is used stored the value of PCD which has no default value in

+#      platform DSC file, the value of NULL, 0 specified in platform DSC file can

+#      be seemed as "no default value".

+#

+#      3.3.1 Simple Sample PCD Database C Structure

+#        A general sample of PCD database structue is as follows:

+#        typedef struct _PCD_DATABASE {

+#          typedef struct _PCD_DATABASE_INIT {

+#            //===== Following is PCD database internal maintain structures

+#            DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];

+#            UINT32            LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];

+#            GUID              GuidTable[PEI_GUID_TABLE_SIZE];

+#            SIZE_INFO         SizeTable[PEI_SIZE_TABLE_SIZE];

+#            UINT8             SkuIdTable[PEI_SKUID_TABLE_SIZE];

+#            SKU_ID            SystemSkuId;

+#

+#            //===== Following is value structure for PCD with default value

+#            ....

+#            ....

+#            ....

+#          } Init;

+#          typedef struct _PCD_DATABSE_UNINIT {

+#            //==== Following is value structure for PCD without default value

+#            ....

+#            ....

+#          } UnInit;

+#        }

+#

+#      3.3.2 PCD value structure in PCD database C structure

+#        The value's structure is generated by build tool in PCD database C structure.

+#        The PCDs in different datum type has different value structure.

+#

+#        3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD

+#          The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64

+#          data member in PCD database, For example:

+#          UINT16  PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;

+#          Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"

+#          Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration

+#          in DEC file.

+#

+#        3.3.2.2 VOID* datum type PCD

+#          The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.

+#

+#          3.3.2.2.1 VOID* - string type

+#            If the default value for VOID* datum type PCD like L"xxx", the PCD is

+#            used for unicode string, and C structure of this datum type PCD is

+#            UINT16 string array in PCD database, for example:

+#            UINT16 StringTable[29];

+#            The number of 29 in above sample is max size of a unicode string.

+#

+#            If the default value for VOID* datum type PCD like "xxx", the PCD is

+#            used for ascii string, and C structure of this datum type PCD is

+#            UINT8 string array in PCD database, for example:

+#            UINT8 StringTable[20];

+#            The number of 20 in above sample is max size of a ascii string.

+#

+#          3.3.2.2.2 VOID* - byte array

+#            If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}

+#            the PCD is used for byte array. The generated structrue is same as

+#            above ascii string table,

+#            UINT8 StringTable[13];

+#            The number of 13 in above sample is max size of byte array.

+#

+#      3.3.3 Some utility structures in PCD Database

+#        3.3.3.1 GuidTable

+#          GuidTable array is used to store all related GUID value in PCD database:

+#            - Variable GUID for HII type PCD

+#            - Token space GUID for dynamicex type PCD

+#

+#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>

+#

+#  SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = PcdPeim

+  MODULE_UNI_FILE                = PcdPeim.uni

+  FILE_GUID                      = 9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50

+  MODULE_TYPE                    = PEIM

+  VERSION_STRING                 = 4.0

+  PCD_IS_DRIVER                  = PEI_PCD_DRIVER

+  ENTRY_POINT                    = PcdPeimInit

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64 EBC (EBC is for build only)

+#

+

+[Sources]

+  Service.c

+  Service.h

+  Pcd.c

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  ChachaniBoardPkg/Project.dec

+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec

+

+[LibraryClasses]

+  BaseMemoryLib

+  PcdLib

+  PeiServicesLib

+  HobLib

+  BaseLib

+  PeimEntryPoint

+  DebugLib

+  MemoryAllocationLib

+

+[Guids]

+  ## PRODUCES            ## HOB

+  ## SOMETIMES_CONSUMES  ## HOB

+  gPcdDataBaseHobGuid

+  gPcdDataBaseSignatureGuid                     ## CONSUMES  ## GUID  # PCD database signature GUID.

+  gEfiMdeModulePkgTokenSpaceGuid                ## SOMETIMES_CONSUMES  ## GUID

+  gEfiAmdAgesaModulePkgTokenSpaceGuid

+  gEfiAmdAgesaPkgTokenSpaceGuid

+  gAmdCpmPkgTokenSpaceGuid

+  gAmdFspPkgGuid

+

+[Ppis]

+  gEfiPeiReadOnlyVariable2PpiGuid               ## SOMETIMES_CONSUMES

+  gPcdPpiGuid                                   ## PRODUCES

+  gEfiPeiPcdPpiGuid                             ## PRODUCES

+  gGetPcdInfoPpiGuid                            ## SOMETIMES_PRODUCES

+  gEfiGetPcdInfoPpiGuid                         ## SOMETIMES_PRODUCES

+  gEfiEndOfPeiSignalPpiGuid                     ## NOTIFY

+  gFspEfiPeiPcdPpiGuid                          ## SOMETIMES_PRODUCES

+  gFspEfiGetPcdInfoPpiGuid                      ## SOMETIMES_PRODUCES

+

+[FeaturePcd]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiFullPcdDatabaseEnable  ## CONSUMES

+

+[Pcd]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress ## SOMETIMES_CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64 ## SOMETIMES_CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry ## SOMETIMES_CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer ## SOMETIMES_CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNvStoreDefaultId       ## CONSUMES

+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection

+

+[Depex]

+  TRUE

+

+[UserExtensions.TianoCore."ExtraFiles"]

+  PcdPeimExtra.uni

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h b/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h

new file mode 100644

index 0000000000..b6da9625d7

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h

@@ -0,0 +1,333 @@

+/** @file

+  Implements SmramSaveStateMap.h

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+SMRAM Save State Map Definitions.

+

+SMRAM Save State Map definitions based on contents of the

+Intel(R) 64 and IA-32 Architectures Software Developer's Manual

+  Volume 3C, Section 34.4 SMRAM

+  Volume 3C, Section 34.5 SMI Handler Execution Environment

+  Volume 3C, Section 34.7 Managing Synchronous and Asynchronous SMIs

+

+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>

+SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef __INTEL_SMRAM_SAVE_STATE_MAP_H__

+#define __INTEL_SMRAM_SAVE_STATE_MAP_H__

+#define AMD_CPU  1

+///

+/// Default SMBASE address

+///

+#define SMM_DEFAULT_SMBASE  0x30000

+

+///

+/// Offset of SMM handler from SMBASE

+///

+#define SMM_HANDLER_OFFSET  0x8000

+

+///

+/// Offset of SMRAM Save State Map from SMBASE

+///

+#if AMD_CPU

+#define SMRAM_SAVE_STATE_MAP_OFFSET  0xfe00

+#else

+#define SMRAM_SAVE_STATE_MAP_OFFSET  0xfc00

+#endif

+

+#pragma pack (1)

+

+#if AMD_CPU

+///

+/// CPU save-state strcuture for AMD64 Architecture

+///

+typedef struct {

+  UINT8     Reserved[0xF8];  // FE00h - FEF7h , Reserved, 248 Bytes, --

+  UINT32    SMBASE;          // FEF8h, SMBASE, Doubleword, Read/Write

+  UINT32    SMMRevId;        // FEFCh, SMM-Revision identifier, Doubleword, Read-Only

+  UINT16    IORestart;       // FF00h, I/O Instruction Restart, Word, Read/Write

+  UINT16    AutoHALTRestart; // FF02h, Auti-Halt Restart, Word, Read/Write

+  UINT8     Reserved1[0x84]; // FF04h - FF87h, Reserved, 132 Bytes --

+  UINT32    GdtBase;         // FF88h, GDT Base, Doubleword, Read-Only

+  UINT64    Reserved2;       // FF8Ch - FF93h, Quadword, --

+  UINT32    IDTBase;         // FF94h, IDT Base, Doubleword, Read-Only

+  UINT8     Reserved3[0x10]; // FF98 - FFA7h, Reserved, 16Bytes, --

+  UINT32    _ES;             // FFA8h, ES, Doubleword, Read-Only

+  UINT32    _CS;             // FFACh, CS, Doubleword, Read-Only

+  UINT32    _SS;             // FFB0h, SS, Doubleword, Read-Only

+  UINT32    _DS;             // FFB4h, DS, Doubleword, Read-Only

+  UINT32    _FS;             // FFB8h, FS, Doubleword, Read-Only

+  UINT32    _GS;             // FFBCh, GS, Doubleword, Read-Only

+  UINT32    LDTBase;         // FFC0h, LDT Base, Doubleword, Read-Only

+  UINT32    _TR;             // FFC4h, TR, Doubleword, Read-Only

+  UINT32    _DR7;            // FFC8h, DR7, Doubleword, Read-Only

+  UINT32    _DR6;            // FFCCh, DR6, Doubleword, Read-Only

+  UINT32    _EAX;            // FFD0h, EAX, Doubleword, Read/Write

+  UINT32    _ECX;            // FFD4h, ECX, Doubleword, Read/Write

+  UINT32    _EDX;            // FFD8h, EDX, Doubleword, Read/Write

+  UINT32    _EBX;            // FFDCh, EBX, Doubleword, Read/Write

+  UINT32    _ESP;            // FFE0h, ESP, Doubleword, Read/Write

+  UINT32    _EBP;            // FFE4h, EBP, Doubleword, Read/Write

+  UINT32    _ESI;            // FFE8h, ESI, Doubleword, Read/Write

+  UINT32    _EDI;            // FFECh, EDI, Doubleword, Read/Write

+  UINT32    _EIP;            // FFF0h, EIP, Doubleword, Read/Write

+  UINT32    _EFLAGS;         // FFF4h, EFLAGS, Doubleword, Read/Write

+  UINT32    _CR3;            // FFF8h, CR3, Doubleword, Read/Write

+  UINT32    _CR0;            // FFFCh, CR0, Doubleword, Read/Write

+} SMRAM_SAVE_STATE_MAP32;

+

+typedef struct {

+  UINT16    _ES;                 // FE00h, ES Selector, Word, Read-Only

+  UINT16    ESAttributes;        // FE02h, ES Attributes, Word, Read-Only

+  UINT32    ESLimit;             // FE04h, ES Limit, Doubleword, Read-Only

+  UINT64    ESBase;              // FE08h, ES Base, Quadword, Read-Only

+  UINT16    _CS;                 // FE10h, CS Selector, Word, Read-Only

+  UINT16    CSAttributes;        // FE12h, CS Attributes, Word, Read-Only

+  UINT32    CSLimit;             // FE14h, CS Limit, Doubleword, Read-Only

+  UINT64    CSBase;              // FE18h, CS Base, Quadword, Read-Only

+  UINT16    _SS;                 // FE20h, SS Selector, Word, Read-Only

+  UINT16    SSAttributes;        // FE22h, SS Attributes, Word, Read-Only

+  UINT32    SSLimit;             // FE24h, SS Limit, Doubleword, Read-Only

+  UINT64    SSBase;              // FE28h, SS Base, Quadword, Read-Only

+  UINT16    _DS;                 // FE30h, DS Selector, Word, Read-Only

+  UINT16    DSAttributes;        // FE32h, DS Attributes, Word, Read-Only

+  UINT32    DSLimit;             // FE34h, DS Limit, Doubleword, Read-Only

+  UINT64    DSBase;              // FE38h, DS Base, Quadword, Read-Only

+  UINT16    _FS;                 // FE40h, FS Selector, Word, Read-Only

+  UINT16    FSAttributes;        // FE42h, FS Attributes, Word, Read-Only

+  UINT32    FSLimit;             // FE44h, FS Limit, Doubleword, Read-Only

+  UINT64    FSBase;              // FE48h, FS Base, Quadword, Read-Only

+  UINT16    _GS;                 // FE50h, GS Selector, Word, Read-Only

+  UINT16    GSAttributes;        // FE52h, GS Attributes, Word, Read-Only

+  UINT32    GSLimit;             // FE54h, GS Limit, Doubleword, Read-Only

+  UINT64    GSBase;              // FE58h, GS Base, Quadword, Read-Only

+  UINT8     Reserved1[4];        // FE60h - FE63h, GDTR Reserved, 4 Bytes, Read-Only

+  UINT16    GdtrLimit;           // FE64h, GDTR Limit, Word, Read-Only

+  UINT8     Reserved2[2];        // FE66h - FE67h, Reserved, 2 Bytes, Read-Only

+  //  UINT64  GDTR_Base;            // FE68h, GDTR Base, Quadword, Read-Only

+  UINT32    GdtrBaseLoDword;

+  UINT32    GdtrBaseHiDword;

+  UINT16    LdtrSelector;        // FE70h, LDTR Selector, Word, Read-Only

+  UINT16    LdtrAttributes;      // FE72h, LDTR Attributes, Word, Read-Only

+  UINT32    LdtrLimit;           // FE74h, LDTR Limit, Doubleword, Read-Only

+  //  UINT64  LDTR_Base;            // FE78h, LDTR Base, Quadword, Read-Only

+  UINT32    LdtrBaseLoDword;

+  UINT32    LdtrBaseHiDword;

+  UINT8     Reserved3[4];        // FE80h - FE83h (PID: 24593 (PUB) 3.20 p.279 has a technical errors), IDTR Reserved, 4 Bytes, Read-Only

+  UINT16    IdtrLimit;           // FE84h, IDTR Limit, Word, Read-Only

+  UINT8     Reserved4[2];        // FE86h - FE87h (PID: 24593 (PUB) 3.20 p.279 has a technical errors), IDTR Reserved, 2 Bytes, Read-Only

+  //  UINT64  IDTR_Base;            // FE88h, IDTR Base, Quadword, Read-Only

+  UINT32    IdtrBaseLoDword;

+  UINT32    IdtrBaseHiDword;

+  UINT16    TrSelector;           // FE90h, TR Selector, Word, Read-Only

+  UINT16    TrAttributes;         // FE92h, TR Attributes, Word, Read-Only

+  UINT32    TrLimit;              // FE94h, TR Limit, Doubleword, Read-Only

+  UINT64    TrBase;               // FE98h, TR Base, Quadword, Read-Only

+  UINT64    IO_RESTART_RIP;       // FEA0h, I/O Instruction Restart RIP, Quadword, Read-Only

+  UINT64    IO_RESTART_RCX;       // FEA8h, I/O Instruction Restart RCX, Quadword, Read-Only

+  UINT64    IO_RESTART_RSI;       // FEB0h, I/O Instruction Restart RSI, Quadword, Read-Only

+  UINT64    IO_RESTART_RDI;       // FEB8h, I/O Instruction Restart RDI, Quadword, Read-Only

+  UINT32    SMM_IO_TRAP;          // FEC0h, I/O Instruction Restart Dword SMMFEC0 [SMM IO Trap Offset], Read-Only

+  UINT32    LocalSmiStatus;       // FEC4h, SMMFEC4 [Local SMI Status], Doubleword, Read-Only

+  UINT8     SMM_IO_RESTART;       // FEC8h, SMMFEC8 [SMM IO Restart Byte], Byte, Read/Write

+  UINT8     AutoHALTRestart;      // FEC9h, SMMFEC9 [Auto Halt Restart Offset], Byte, Read/Write

+  UINT8     NMI_MASK;             // FECAh, SMMFECA [NMI Mask], Byte, Read/Write

+  UINT8     Reserved5[5];         // FECBh - FECFh, Reserved, 5 Bytes, --

+  UINT64    EFER;                 // FED0h, EFER, Quadword, Read-Only

+  UINT64    SMM_SVM_State;        // FED8h, SMMFED8 [SMM SVM State], Read-Only

+  UINT64    Guest_VMCB_PHY_ADDR;  // FEE0h, Guest VMCB physical address, Read-Only

+  UINT64    SVM_Virtual_INT_CTRL; // FEE8h, SVM Virtual Interrupt Control, Read-Only

+  UINT8     Reserved6[12];        // FEF0h - FEFBh, Reserved, 12 Bytes (PID: 42300 Family 15h BKDG (NDA) 1.11 p.49 has a technial error), --

+  UINT32    SMMRevId;             // FEFCh, SMMFEFC [SMM-Revision-Indentifier], Doubleword, Read/Write

+  UINT32    SMBASE;               // FF00h, SMMFF00 [SMM Base Address (SMM_BASE)], Read/Write

+  UINT8     Reserved7[28];        // FF04h, Reserved, 24 Bytes, --

+  UINT64    GuestPAT;             // FF20h, Guest PAT, Quadword, Read-Only

+  UINT64    HostEFER;             // FF28h, Host EFER, Quadword, Read-Only

+  UINT64    HostCR4;              // FF30h, Host CR4, Quadword, Read-Only

+  UINT64    NestedCR3;            // FF38h, Nested CR3, Quadword, Read-Only

+  UINT64    HostCR0;              // FF40h, Host CR0, Quadword, Read-Only

+  UINT64    _CR4;                 // FF48h, CR4, Quadword, Read-Only

+  UINT64    _CR3;                 // FF50h, CR3, Quadword, Read-Only

+  UINT64    _CR0;                 // FF58h, CR0, Quadword, Read-Only

+  UINT64    _DR7;                 // FF60h, DR7, Quadword, Read-Only

+  UINT64    _DR6;                 // FF68h, DR6, Quadword, Read-Only

+  UINT64    _RFLAGS;              // FF70h, RFLAGS, Quadword, Read/Write

+  UINT64    _RIP;                 // FF78h, RIP, Quadword, Read/Write

+  UINT64    _R15;                 // FF80h, R15, Quadword, Read/Write

+  UINT64    _R14;                 // FF88h, R14, Quadword, Read/Write

+  UINT64    _R13;                 // FF90h, R13, Quadword, Read/Write

+  UINT64    _R12;                 // FF98h, R12, Quadword, Read/Write

+  UINT64    _R11;                 // FFA0h, R11, Quadword, Read/Write

+  UINT64    _R10;                 // FFA8h, R10, Quadword, Read/Write

+  UINT64    _R9;                  // FFB0h, R9, Quadword, Read/Write

+  UINT64    _R8;                  // FFB8, R8, Quadword, Read/Write

+  UINT64    _RDI;                 // FFC0h, RDI, Quadword, Read/Write

+  UINT64    _RSI;                 // FFD8h, RSI, Quadword, Read/Write

+  UINT64    _RBP;                 // FFD0h, RBP, Quadword, Read/Write

+  UINT64    _RSP;                 // FFE0h, RSP, Quadword, Read/Write

+  UINT64    _RBX;                 // FFE0h, RBX, Quadword, Read/Write

+  UINT64    _RDX;                 // FFE8h, RDX, Quadword, Read/Write

+  UINT64    _RCX;                 // FFF0h, RCX, Quadword, Read/Write

+  UINT64    _RAX;                 // FFF8h, RAX, Quadword, Read/Write

+} SMRAM_SAVE_STATE_MAP64;

+#else

+///

+/// 32-bit SMRAM Save State Map

+///

+typedef struct {

+  UINT8     Reserved[0x200]; // 7c00h

+                             // Padded an extra 0x200 bytes so 32-bit and 64-bit

+                             // SMRAM Save State Maps are the same size

+  UINT8     Reserved1[0xf8]; // 7e00h

+  UINT32    SMBASE;          // 7ef8h

+  UINT32    SMMRevId;        // 7efch

+  UINT16    IORestart;       // 7f00h

+  UINT16    AutoHALTRestart; // 7f02h

+  UINT8     Reserved2[0x9C]; // 7f08h

+  UINT32    IOMemAddr;       // 7fa0h

+  UINT32    IOMisc;          // 7fa4h

+  UINT32    _ES;             // 7fa8h

+  UINT32    _CS;             // 7fach

+  UINT32    _SS;             // 7fb0h

+  UINT32    _DS;             // 7fb4h

+  UINT32    _FS;             // 7fb8h

+  UINT32    _GS;             // 7fbch

+  UINT32    Reserved3;       // 7fc0h

+  UINT32    _TR;             // 7fc4h

+  UINT32    _DR7;            // 7fc8h

+  UINT32    _DR6;            // 7fcch

+  UINT32    _EAX;            // 7fd0h

+  UINT32    _ECX;            // 7fd4h

+  UINT32    _EDX;            // 7fd8h

+  UINT32    _EBX;            // 7fdch

+  UINT32    _ESP;            // 7fe0h

+  UINT32    _EBP;            // 7fe4h

+  UINT32    _ESI;            // 7fe8h

+  UINT32    _EDI;            // 7fech

+  UINT32    _EIP;            // 7ff0h

+  UINT32    _EFLAGS;         // 7ff4h

+  UINT32    _CR3;            // 7ff8h

+  UINT32    _CR0;            // 7ffch

+} SMRAM_SAVE_STATE_MAP32;

+

+///

+/// 64-bit SMRAM Save State Map

+///

+typedef struct {

+  UINT8     Reserved1[0x1d0]; // 7c00h

+  UINT32    GdtBaseHiDword;   // 7dd0h

+  UINT32    LdtBaseHiDword;   // 7dd4h

+  UINT32    IdtBaseHiDword;   // 7dd8h

+  UINT8     Reserved2[0xc];   // 7ddch

+  UINT64    IO_EIP;           // 7de8h

+  UINT8     Reserved3[0x50];  // 7df0h

+  UINT32    _CR4;             // 7e40h

+  UINT8     Reserved4[0x48];  // 7e44h

+  UINT32    GdtBaseLoDword;   // 7e8ch

+  UINT32    Reserved5;        // 7e90h

+  UINT32    IdtBaseLoDword;   // 7e94h

+  UINT32    Reserved6;        // 7e98h

+  UINT32    LdtBaseLoDword;   // 7e9ch

+  UINT8     Reserved7[0x38];  // 7ea0h

+  UINT64    EptVmxControl;    // 7ed8h

+  UINT32    EnEptVmxControl;  // 7ee0h

+  UINT8     Reserved8[0x14];  // 7ee4h

+  UINT32    SMBASE;           // 7ef8h

+  UINT32    SMMRevId;         // 7efch

+  UINT16    IORestart;        // 7f00h

+  UINT16    AutoHALTRestart;  // 7f02h

+  UINT8     Reserved9[0x18];  // 7f04h

+  UINT64    _R15;             // 7f1ch

+  UINT64    _R14;

+  UINT64    _R13;

+  UINT64    _R12;

+  UINT64    _R11;

+  UINT64    _R10;

+  UINT64    _R9;

+  UINT64    _R8;

+  UINT64    _RAX;            // 7f5ch

+  UINT64    _RCX;

+  UINT64    _RDX;

+  UINT64    _RBX;

+  UINT64    _RSP;

+  UINT64    _RBP;

+  UINT64    _RSI;

+  UINT64    _RDI;

+  UINT64    IOMemAddr;       // 7f9ch

+  UINT32    IOMisc;          // 7fa4h

+  UINT32    _ES;             // 7fa8h

+  UINT32    _CS;

+  UINT32    _SS;

+  UINT32    _DS;

+  UINT32    _FS;

+  UINT32    _GS;

+  UINT32    _LDTR;           // 7fc0h

+  UINT32    _TR;

+  UINT64    _DR7;            // 7fc8h

+  UINT64    _DR6;

+  UINT64    _RIP;            // 7fd8h

+  UINT64    IA32_EFER;       // 7fe0h

+  UINT64    _RFLAGS;         // 7fe8h

+  UINT64    _CR3;            // 7ff0h

+  UINT64    _CR0;            // 7ff8h

+} SMRAM_SAVE_STATE_MAP64;

+#endif

+

+///

+/// Union of 32-bit and 64-bit SMRAM Save State Maps

+///

+typedef union  {

+  SMRAM_SAVE_STATE_MAP32    x86;

+  SMRAM_SAVE_STATE_MAP64    x64;

+} SMRAM_SAVE_STATE_MAP;

+

+///

+/// Minimum SMM Revision ID that supports IOMisc field in SMRAM Save State Map

+///

+#define SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC  0x30004

+

+///

+/// SMRAM Save State Map IOMisc I/O Length Values

+///

+#define  SMM_IO_LENGTH_BYTE   0x01

+#define  SMM_IO_LENGTH_WORD   0x02

+#define  SMM_IO_LENGTH_DWORD  0x04

+

+///

+/// SMRAM Save State Map IOMisc I/O Instruction Type Values

+///

+#define  SMM_IO_TYPE_IN_IMMEDIATE   0x9

+#define  SMM_IO_TYPE_IN_DX          0x1

+#define  SMM_IO_TYPE_OUT_IMMEDIATE  0x8

+#define  SMM_IO_TYPE_OUT_DX         0x0

+#define  SMM_IO_TYPE_INS            0x3

+#define  SMM_IO_TYPE_OUTS           0x2

+#define  SMM_IO_TYPE_REP_INS        0x7

+#define  SMM_IO_TYPE_REP_OUTS       0x6

+

+///

+/// SMRAM Save State Map IOMisc structure

+///

+typedef union {

+  struct {

+    UINT32    SmiFlag   : 1;

+    UINT32    Length    : 3;

+    UINT32    Type      : 4;

+    UINT32    Reserved1 : 8;

+    UINT32    Port      : 16;

+  } Bits;

+  UINT32    Uint32;

+} SMRAM_SAVE_STATE_IOMISC;

+

+#pragma pack ()

+

+#endif

--

2.31.1





-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114079): https://edk2.groups.io/g/devel/message/114079
Mute This Topic: https://groups.io/mt/103831202/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-