+/**\r
+ Collects BIST data from HOB.\r
+\r
+ This function collects BIST data from HOB built from Sec Platform Information\r
+ PPI or SEC Platform Information2 PPI.\r
+\r
+**/\r
+VOID\r
+CollectBistDataFromHob (\r
+ VOID\r
+ )\r
+{\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+ EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2;\r
+ EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation;\r
+ UINTN NumberOfData;\r
+ EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance;\r
+ EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance;\r
+ UINTN ProcessorNumber;\r
+ UINT32 InitialLocalApicId;\r
+ CPU_DATA_BLOCK *CpuData;\r
+\r
+ SecPlatformInformation2 = NULL;\r
+ SecPlatformInformation = NULL;\r
+\r
+ //\r
+ // Get gEfiSecPlatformInformation2PpiGuid Guided HOB firstly\r
+ //\r
+ GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformation2PpiGuid);\r
+ if (GuidHob != NULL) {\r
+ //\r
+ // Sec Platform Information2 PPI includes BSP/APs' BIST information\r
+ //\r
+ SecPlatformInformation2 = GET_GUID_HOB_DATA (GuidHob);\r
+ NumberOfData = SecPlatformInformation2->NumberOfCpus;\r
+ CpuInstance = SecPlatformInformation2->CpuInstance;\r
+ } else {\r
+ //\r
+ // Otherwise, get gEfiSecPlatformInformationPpiGuid Guided HOB\r
+ //\r
+ GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);\r
+ if (GuidHob != NULL) {\r
+ SecPlatformInformation = GET_GUID_HOB_DATA (GuidHob);\r
+ NumberOfData = 1;\r
+ //\r
+ // SEC Platform Information only includes BSP's BIST information\r
+ // does not have BSP's APIC ID\r
+ //\r
+ BspCpuInstance.CpuLocation = GetApicId ();\r
+ BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32;\r
+ CpuInstance = &BspCpuInstance;\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "Does not find any HOB stored CPU BIST information!\n"));\r
+ //\r
+ // Does not find any HOB stored BIST information\r
+ //\r
+ return;\r
+ }\r
+ }\r
+\r
+ while ((NumberOfData--) > 0) {\r
+ for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {\r
+ CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
+ InitialLocalApicId = (UINT32) CpuData->Info.ProcessorId;\r
+ if (InitialLocalApicId == CpuInstance[NumberOfData].CpuLocation) {\r
+ //\r
+ // Update CPU health status for MP Services Protocol according to BIST data.\r
+ //\r
+ if (CpuInstance[NumberOfData].InfoRecord.IA32HealthFlags.Uint32 != 0) {\r
+ CpuData->Info.StatusFlag &= ~PROCESSOR_HEALTH_STATUS_BIT;\r
+ //\r
+ // Report Status Code that self test is failed\r
+ //\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
+ (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)\r
+ );\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Callback function for ExitBootServices.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ExitBootServicesCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Avoid APs access invalid buff datas which allocated by BootServices,\r
+ // so we send INIT IPI to APs to let them wait for SIPI state.\r
+ //\r
+ SendInitIpiAllExcludingSelf ();\r
+}\r
+\r