+///\r
+/// Instance of EFI_PEI_PCD_PPI which is defined in PI 1.2 Vol 3.\r
+/// This PPI instance only support dyanmicEx type PCD.\r
+///\r
+EFI_PEI_PCD_PPI mEfiPcdPpiInstance = {\r
+ PeiPcdSetSku,\r
+\r
+ PeiPcdGet8Ex,\r
+ PeiPcdGet16Ex,\r
+ PeiPcdGet32Ex,\r
+ PeiPcdGet64Ex,\r
+ PeiPcdGetPtrEx,\r
+ PeiPcdGetBoolEx,\r
+ PeiPcdGetSizeEx,\r
+ PeiPcdSet8Ex,\r
+ PeiPcdSet16Ex,\r
+ PeiPcdSet32Ex,\r
+ PeiPcdSet64Ex,\r
+ PeiPcdSetPtrEx,\r
+ PeiPcdSetBoolEx,\r
+ (EFI_PEI_PCD_PPI_CALLBACK_ON_SET) PeiRegisterCallBackOnSet,\r
+ (EFI_PEI_PCD_PPI_CANCEL_CALLBACK) PcdUnRegisterCallBackOnSet,\r
+ PeiPcdGetNextToken,\r
+ PeiPcdGetNextTokenSpace\r
+};\r
+\r
+///\r
+/// Instance of GET_PCD_INFO_PPI protocol is EDKII native implementation.\r
+/// This protocol instance support dynamic and dynamicEx type PCDs.\r
+///\r
+GET_PCD_INFO_PPI mGetPcdInfoInstance = {\r
+ PeiGetPcdInfoGetInfo,\r
+ PeiGetPcdInfoGetInfoEx,\r
+ PeiGetPcdInfoGetSku\r
+};\r
+\r
+///\r
+/// Instance of EFI_GET_PCD_INFO_PPI which is defined in PI 1.2.1 Vol 3.\r
+/// This PPI instance only support dyanmicEx type PCD.\r
+///\r
+EFI_GET_PCD_INFO_PPI mEfiGetPcdInfoInstance = {\r
+ PeiGetPcdInfoGetInfoEx,\r
+ PeiGetPcdInfoGetSku\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
+ {\r
+ EFI_PEI_PPI_DESCRIPTOR_PPI,\r
+ &gPcdPpiGuid,\r
+ &mPcdPpiInstance\r
+ },\r
+ {\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEfiPeiPcdPpiGuid,\r
+ &mEfiPcdPpiInstance\r
+ }\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPpiList2[] = {\r
+ {\r
+ EFI_PEI_PPI_DESCRIPTOR_PPI,\r
+ &gGetPcdInfoPpiGuid,\r
+ &mGetPcdInfoInstance\r
+ },\r
+ {\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEfiGetPcdInfoPpiGuid,\r
+ &mEfiGetPcdInfoInstance\r
+ }\r
+};\r
+\r
+/**\r
+ Callback on SET PcdSetNvStoreDefaultId\r
+\r
+ Once PcdSetNvStoreDefaultId is set, the default NV storage will be found from\r
+ PcdNvStoreDefaultValueBuffer, and built into VariableHob.\r
+\r
+ @param[in] CallBackGuid The PCD token GUID being set.\r
+ @param[in] CallBackToken The PCD token number being set.\r
+ @param[in, out] TokenData A pointer to the token data being set.\r
+ @param[in] TokenDataSize The size, in bytes, of the data being set.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PcdSetNvStoreDefaultIdCallBack (\r
+ IN CONST EFI_GUID *CallBackGuid, OPTIONAL\r
+ IN UINTN CallBackToken,\r
+ IN OUT VOID *TokenData,\r
+ IN UINTN TokenDataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 DefaultId;\r
+ SKU_ID SkuId;\r
+ UINTN FullSize;\r
+ UINTN Index;\r
+ UINT8 *DataBuffer;\r
+ UINT8 *VarStoreHobData;\r
+ UINT8 *BufferEnd;\r
+ BOOLEAN IsFound;\r
+ VARIABLE_STORE_HEADER *NvStoreBuffer;\r
+ PCD_DEFAULT_DATA *DataHeader;\r
+ PCD_DEFAULT_INFO *DefaultInfo;\r
+ PCD_DATA_DELTA *DeltaData;\r
+\r
+ DefaultId = *(UINT16 *) TokenData;\r
+ SkuId = GetPcdDatabase()->SystemSkuId;\r
+ IsFound = FALSE;\r
+\r
+ if (PeiPcdGetSizeEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer)) > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {\r
+ DataBuffer = (UINT8 *) PeiPcdGetPtrEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer));\r
+ FullSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *) DataBuffer)->Length;\r
+ DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));\r
+ //\r
+ // The first section data includes NV storage default setting.\r
+ //\r
+ NvStoreBuffer = (VARIABLE_STORE_HEADER *) ((UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);\r
+ VarStoreHobData = (UINT8 *) BuildGuidHob (&NvStoreBuffer->Signature, NvStoreBuffer->Size);\r
+ ASSERT (VarStoreHobData != NULL);\r
+ CopyMem (VarStoreHobData, NvStoreBuffer, NvStoreBuffer->Size);\r
+ //\r
+ // Find the matched SkuId and DefaultId in the first section\r
+ //\r
+ DefaultInfo = &(DataHeader->DefaultInfo[0]);\r
+ BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;\r
+ while ((UINT8 *) DefaultInfo < BufferEnd) {\r
+ if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == SkuId) {\r
+ IsFound = TRUE;\r
+ break;\r
+ }\r
+ DefaultInfo ++;\r
+ }\r
+ //\r
+ // Find the matched SkuId and DefaultId in the remaining section\r
+ //\r
+ Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));\r
+ DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);\r
+ while (!IsFound && Index < FullSize && DataHeader->DataSize != 0xFFFFFFFF) {\r
+ DefaultInfo = &(DataHeader->DefaultInfo[0]);\r
+ BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;\r
+ while ((UINT8 *) DefaultInfo < BufferEnd) {\r
+ if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == SkuId) {\r
+ IsFound = TRUE;\r
+ break;\r
+ }\r
+ DefaultInfo ++;\r
+ }\r
+ if (IsFound) {\r
+ DeltaData = (PCD_DATA_DELTA *) BufferEnd;\r
+ BufferEnd = (UINT8 *) DataHeader + DataHeader->DataSize;\r
+ while ((UINT8 *) DeltaData < BufferEnd) {\r
+ *(VarStoreHobData + DeltaData->Offset) = (UINT8) DeltaData->Value;\r
+ DeltaData ++;\r
+ }\r
+ break;\r
+ }\r
+ Index = (Index + DataHeader->DataSize + 7) & (~7) ;\r
+ DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);\r
+ }\r
+ }\r
+\r
+ Status = PcdUnRegisterCallBackOnSet (\r
+ &gEfiMdeModulePkgTokenSpaceGuid,\r
+ PcdToken(PcdSetNvStoreDefaultId),\r
+ PcdSetNvStoreDefaultIdCallBack\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Report Pei PCD database of all SKUs as Guid HOB so that DxePcd can access it.\r
+\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
+ @param NotifyDescriptor Address of the notification descriptor data structure.\r
+ @param Ppi Address of the PPI that was installed.\r
+\r
+ @retval EFI_SUCCESS Successfully update the Boot records.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EndOfPeiSignalPpiNotifyCallback (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
+ IN VOID *Ppi\r
+ )\r
+{\r
+ PEI_PCD_DATABASE *Database;\r
+ EFI_BOOT_MODE BootMode;\r
+ EFI_STATUS Status;\r
+ UINTN Instance;\r
+ EFI_PEI_FV_HANDLE VolumeHandle;\r
+ EFI_PEI_FILE_HANDLE FileHandle;\r
+ VOID *PcdDb;\r
+ UINT32 Length;\r
+ PEI_PCD_DATABASE *PeiPcdDb;\r
+\r
+ Status = PeiServicesGetBootMode(&BootMode);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Don't need to report it on S3 boot.\r
+ //\r
+ if (BootMode == BOOT_ON_S3_RESUME) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ PeiPcdDb = GetPcdDatabase();\r
+ if (PeiPcdDb->SystemSkuId != (SKU_ID) 0) {\r
+ //\r
+ // SkuId has been set. Don't need to report it to DXE phase.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Get full PCD database from PcdPeim FileHandle\r
+ //\r
+ Instance = 0;\r
+ FileHandle = NULL;\r
+ while (TRUE) {\r
+ //\r
+ // Traverse all firmware volume instances\r
+ //\r
+ Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);\r
+ //\r
+ // Error should not happen\r
+ //\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Find PcdDb file from the beginning in this firmware volume.\r
+ //\r
+ FileHandle = NULL;\r
+ Status = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Find PcdPeim FileHandle in this volume\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // We cannot find PcdPeim in this firmware volume, then search the next volume.\r
+ //\r
+ Instance++;\r
+ }\r
+\r
+ //\r
+ // Find PEI PcdDb and Build second PcdDB GuidHob\r
+ //\r
+ Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Length = PeiPcdDb->LengthForAllSkus;\r
+ Database = BuildGuidHob (&gPcdDataBaseHobGuid, Length);\r
+ CopyMem (Database, PcdDb, Length);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiSignalPpiNotifyList[] = {\r
+ {\r
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEfiEndOfPeiSignalPpiGuid,\r
+ EndOfPeiSignalPpiNotifyCallback\r
+ }\r