/** @file\r
EFI PEI Core PPI services\r
- \r
-Copyright (c) 2006, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-#include <PeiMain.h>\r
+#include "PeiMain.h"\r
\r
/**\r
\r
- Initialize PPI services.\r
+ Migrate Pointer from the temporary memory to PEI installed memory.\r
\r
+ @param Pointer Pointer to the Pointer needs to be converted.\r
+ @param TempBottom Base of old temporary memory\r
+ @param TempTop Top of old temporary memory\r
+ @param Offset Offset of new memory to old temporary memory.\r
+ @param OffsetPositive Positive flag of Offset value.\r
\r
- @param PrivateData Pointer to the PEI Core data.\r
- @param OldCoreData Pointer to old PEI Core data. \r
- NULL if being run in non-permament memory mode.\r
+**/\r
+VOID\r
+ConvertPointer (\r
+ IN OUT VOID **Pointer,\r
+ IN UINTN TempBottom,\r
+ IN UINTN TempTop,\r
+ IN UINTN Offset,\r
+ IN BOOLEAN OffsetPositive\r
+ )\r
+{\r
+ if (((UINTN)*Pointer < TempTop) &&\r
+ ((UINTN)*Pointer >= TempBottom))\r
+ {\r
+ if (OffsetPositive) {\r
+ *Pointer = (VOID *)((UINTN)*Pointer + Offset);\r
+ } else {\r
+ *Pointer = (VOID *)((UINTN)*Pointer - Offset);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Migrate Pointer in ranges of the temporary memory to PEI installed memory.\r
+\r
+ @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
+ and location of temporary RAM, the stack location and the BFV location.\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param Pointer Pointer to the Pointer needs to be converted.\r
\r
**/\r
VOID\r
-InitializePpiServices (\r
- IN PEI_CORE_INSTANCE *PrivateData,\r
- IN PEI_CORE_INSTANCE *OldCoreData\r
+ConvertPointerInRanges (\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN OUT VOID **Pointer\r
)\r
{\r
- if (OldCoreData == NULL) {\r
- PrivateData->PpiData.NotifyListEnd = FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1;\r
- PrivateData->PpiData.DispatchListEnd = FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1;\r
- PrivateData->PpiData.LastDispatchedNotify = FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1;\r
+ UINT8 IndexHole;\r
+\r
+ if (PrivateData->MemoryPages.Size != 0) {\r
+ //\r
+ // Convert PPI pointer in old memory pages\r
+ // It needs to be done before Convert PPI pointer in old Heap\r
+ //\r
+ ConvertPointer (\r
+ Pointer,\r
+ (UINTN)PrivateData->MemoryPages.Base,\r
+ (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size,\r
+ PrivateData->MemoryPages.Offset,\r
+ PrivateData->MemoryPages.OffsetPositive\r
+ );\r
+ }\r
+\r
+ //\r
+ // Convert PPI pointer in old Heap\r
+ //\r
+ ConvertPointer (\r
+ Pointer,\r
+ (UINTN)SecCoreData->PeiTemporaryRamBase,\r
+ (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,\r
+ PrivateData->HeapOffset,\r
+ PrivateData->HeapOffsetPositive\r
+ );\r
+\r
+ //\r
+ // Convert PPI pointer in old Stack\r
+ //\r
+ ConvertPointer (\r
+ Pointer,\r
+ (UINTN)SecCoreData->StackBase,\r
+ (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,\r
+ PrivateData->StackOffset,\r
+ PrivateData->StackOffsetPositive\r
+ );\r
+\r
+ //\r
+ // Convert PPI pointer in old TempRam Hole\r
+ //\r
+ for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole++) {\r
+ if (PrivateData->HoleData[IndexHole].Size == 0) {\r
+ continue;\r
+ }\r
+\r
+ ConvertPointer (\r
+ Pointer,\r
+ (UINTN)PrivateData->HoleData[IndexHole].Base,\r
+ (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,\r
+ PrivateData->HoleData[IndexHole].Offset,\r
+ PrivateData->HoleData[IndexHole].OffsetPositive\r
+ );\r
}\r
}\r
\r
/**\r
\r
- Migrate the Hob list from the CAR stack to PEI installed memory.\r
+ Migrate Single PPI Pointer from the temporary memory to PEI installed memory.\r
\r
- @param PeiServices The PEI core services table.\r
- @param OldCheckingBottom The old checking bottom.\r
- @param OldCheckingTop The old checking top.\r
- @param Fixup The address difference between\r
- the new Hob list and old Hob list.\r
+ @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
+ and location of temporary RAM, the stack location and the BFV location.\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param PpiPointer Pointer to Ppi\r
+\r
+**/\r
+VOID\r
+ConvertSinglePpiPointer (\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN PEI_PPI_LIST_POINTERS *PpiPointer\r
+ )\r
+{\r
+ //\r
+ // 1. Convert the pointer to the PPI descriptor from the old TempRam\r
+ // to the relocated physical memory.\r
+ // It (for the pointer to the PPI descriptor) needs to be done before 2 (for\r
+ // the pointer to the GUID) and 3 (for the pointer to the PPI interface structure).\r
+ //\r
+ ConvertPointerInRanges (SecCoreData, PrivateData, &PpiPointer->Raw);\r
+ //\r
+ // 2. Convert the pointer to the GUID in the PPI or NOTIFY descriptor\r
+ // from the old TempRam to the relocated physical memory.\r
+ //\r
+ ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **)&PpiPointer->Ppi->Guid);\r
+ //\r
+ // 3. Convert the pointer to the PPI interface structure in the PPI descriptor\r
+ // from the old TempRam to the relocated physical memory.\r
+ //\r
+ ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **)&PpiPointer->Ppi->Ppi);\r
+}\r
+\r
+/**\r
+\r
+ Migrate PPI Pointers from the temporary memory to PEI installed memory.\r
+\r
+ @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size\r
+ and location of temporary RAM, the stack location and the BFV location.\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
\r
**/\r
VOID\r
ConvertPpiPointers (\r
- IN CONST EFI_PEI_SERVICES **PeiServices,\r
- IN UINTN OldCheckingBottom,\r
- IN UINTN OldCheckingTop,\r
- IN UINTN Fixup\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
+ IN PEI_CORE_INSTANCE *PrivateData\r
)\r
{\r
- PEI_CORE_INSTANCE *PrivateData;\r
- UINT8 Index;\r
- PEI_PPI_LIST_POINTERS *PpiPointer;\r
+ UINT8 Index;\r
\r
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
+ //\r
+ // Convert normal PPIs.\r
+ //\r
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+ ConvertSinglePpiPointer (\r
+ SecCoreData,\r
+ PrivateData,\r
+ &PrivateData->PpiData.PpiList.PpiPtrs[Index]\r
+ );\r
+ }\r
\r
- for (Index = 0; Index < FixedPcdGet32 (PcdPeiCoreMaxPpiSupported); Index++) {\r
- if (Index < PrivateData->PpiData.PpiListEnd ||\r
- Index > PrivateData->PpiData.NotifyListEnd) {\r
- PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index];\r
+ //\r
+ // Convert Callback Notification PPIs.\r
+ //\r
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+ ConvertSinglePpiPointer (\r
+ SecCoreData,\r
+ PrivateData,\r
+ &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index]\r
+ );\r
+ }\r
\r
- if (((UINTN)PpiPointer->Raw < OldCheckingTop) &&\r
- ((UINTN)PpiPointer->Raw >= OldCheckingBottom)) {\r
- //\r
- // Convert the pointer to the PEIM descriptor from the old HOB heap\r
- // to the relocated HOB heap.\r
- //\r
- PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup);\r
+ //\r
+ // Convert Dispatch Notification PPIs.\r
+ //\r
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+ ConvertSinglePpiPointer (\r
+ SecCoreData,\r
+ PrivateData,\r
+ &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index]\r
+ );\r
+ }\r
+}\r
\r
- //\r
- // Only when the PEIM descriptor is in the old HOB should it be necessary\r
- // to try to convert the pointers in the PEIM descriptor\r
- //\r
+/**\r
\r
- if (((UINTN)PpiPointer->Ppi->Guid < OldCheckingTop) &&\r
- ((UINTN)PpiPointer->Ppi->Guid >= OldCheckingBottom)) {\r
- //\r
- // Convert the pointer to the GUID in the PPI or NOTIFY descriptor\r
- // from the old HOB heap to the relocated HOB heap.\r
- //\r
- PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup);\r
- }\r
+ Migrate Notify Pointers inside an FV from temporary memory to permanent memory.\r
\r
- //\r
- // Assume that no code is located in the temporary memory, so the pointer to\r
- // the notification function in the NOTIFY descriptor needs not be converted.\r
- //\r
- if (Index < PrivateData->PpiData.PpiListEnd &&\r
- (UINTN)PpiPointer->Ppi->Ppi < OldCheckingTop &&\r
- (UINTN)PpiPointer->Ppi->Ppi >= OldCheckingBottom) {\r
- //\r
- // Convert the pointer to the PPI interface structure in the PPI descriptor\r
- // from the old HOB heap to the relocated HOB heap.\r
- //\r
- PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup);\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param OrgFvHandle Address of FV Handle in temporary memory.\r
+ @param FvHandle Address of FV Handle in permanent memory.\r
+ @param FvSize Size of the FV.\r
+\r
+**/\r
+VOID\r
+ConvertPpiPointersFv (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN UINTN OrgFvHandle,\r
+ IN UINTN FvHandle,\r
+ IN UINTN FvSize\r
+ )\r
+{\r
+ UINT8 Index;\r
+ UINTN Offset;\r
+ BOOLEAN OffsetPositive;\r
+ EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;\r
+ UINT8 GuidIndex;\r
+ EFI_GUID *Guid;\r
+ EFI_GUID *GuidCheckList[2];\r
+\r
+ GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;\r
+ GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;\r
+\r
+ if (FvHandle > OrgFvHandle) {\r
+ OffsetPositive = TRUE;\r
+ Offset = FvHandle - OrgFvHandle;\r
+ } else {\r
+ OffsetPositive = FALSE;\r
+ Offset = OrgFvHandle - FvHandle;\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",\r
+ (UINTN)OrgFvHandle,\r
+ (UINTN)FvHandle,\r
+ FvSize\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ " OrgFvHandle range: 0x%08x - 0x%08x\n",\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize\r
+ ));\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+\r
+ Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;\r
+ for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {\r
+ //\r
+ // Don't use CompareGuid function here for performance reasons.\r
+ // Instead we compare the GUID as INT32 at a time and branch\r
+ // on the first failed comparison.\r
+ //\r
+ if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&\r
+ (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&\r
+ (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&\r
+ (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3]))\r
+ {\r
+ FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;\r
+ DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo));\r
+ if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {\r
+ ConvertPointer (\r
+ (VOID **)&FvInfoPpi->FvInfo,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));\r
}\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "\n"));\r
+ break;\r
}\r
}\r
}\r
\r
/**\r
\r
- Install PPI services.\r
+ Dumps the PPI lists to debug output.\r
+\r
+ @param PrivateData Points to PeiCore's private instance data.\r
+\r
+**/\r
+VOID\r
+DumpPpiList (\r
+ IN PEI_CORE_INSTANCE *PrivateData\r
+ )\r
+{\r
+ DEBUG_CODE_BEGIN ();\r
+ UINTN Index;\r
+\r
+ if (PrivateData == NULL) {\r
+ return;\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",\r
+ Index,\r
+ PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ (UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
+ (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+ )\r
+ ? "CAR" : "Post-Memory"\r
+ )\r
+ ));\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",\r
+ Index,\r
+ PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ (UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
+ (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+ )\r
+ ? "CAR" : "Post-Memory"\r
+ )\r
+ ));\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "PPI[%2d] {%g} at 0x%x (%a)\n",\r
+ Index,\r
+ PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
+ (UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
+ (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+ )\r
+ ? "CAR" : "Post-Memory"\r
+ )\r
+ ));\r
+ }\r
+\r
+ DEBUG_CODE_END ();\r
+}\r
+\r
+/**\r
+\r
+ This function installs an interface in the PEI PPI database by GUID.\r
+ The purpose of the service is to publish an interface that other parties\r
+ can use to call additional PEIMs.\r
\r
- @param PeiServices - Pointer to the PEI Service Table\r
- @param PpiList - Pointer to a list of PEI PPI Descriptors.\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param PpiList Pointer to a list of PEI PPI Descriptors.\r
+ @param Single TRUE if only single entry in the PpiList.\r
+ FALSE if the PpiList is ended with an entry which has the\r
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
\r
- @retval EFI_SUCCESS - if all PPIs in PpiList are successfully installed.\r
- @retval EFI_INVALID_PARAMETER - if PpiList is NULL pointer\r
- @retval EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid\r
- @retval EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI\r
+ @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
+ @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
+ if any PPI in PpiList is not valid\r
+ @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-PeiInstallPpi (\r
+InternalPeiInstallPpi (\r
IN CONST EFI_PEI_SERVICES **PeiServices,\r
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,\r
+ IN BOOLEAN Single\r
)\r
{\r
- PEI_CORE_INSTANCE *PrivateData;\r
- INTN Index;\r
- INTN LastCallbackInstall;\r
-\r
+ PEI_CORE_INSTANCE *PrivateData;\r
+ PEI_PPI_LIST *PpiListPointer;\r
+ UINTN Index;\r
+ UINTN LastCount;\r
+ VOID *TempPtr;\r
\r
if (PpiList == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
\r
- Index = PrivateData->PpiData.PpiListEnd;\r
- LastCallbackInstall = Index;\r
+ PpiListPointer = &PrivateData->PpiData.PpiList;\r
+ Index = PpiListPointer->CurrentCount;\r
+ LastCount = Index;\r
\r
//\r
// This is loop installs all PPI descriptors in the PpiList. It is terminated\r
// EFI_PEI_PPI_DESCRIPTOR in the list.\r
//\r
\r
- for (;;) {\r
- //\r
- // Since PpiData is used for NotifyList and InstallList, max resource\r
- // is reached if the Install reaches the NotifyList\r
- //\r
- if (Index == PrivateData->PpiData.NotifyListEnd + 1) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ for ( ; ;) {\r
//\r
// Check if it is a valid PPI.\r
// If not, rollback list to exclude all in this list.\r
// Try to indicate which item failed.\r
//\r
if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
- PrivateData->PpiData.PpiListEnd = LastCallbackInstall;\r
- DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi));\r
- return EFI_INVALID_PARAMETER;\r
+ PpiListPointer->CurrentCount = LastCount;\r
+ DEBUG ((DEBUG_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));\r
- PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*) PpiList;\r
- PrivateData->PpiData.PpiListEnd++;\r
+ if (Index >= PpiListPointer->MaxCount) {\r
+ //\r
+ // Run out of room, grow the buffer.\r
+ //\r
+ TempPtr = AllocateZeroPool (\r
+ sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP)\r
+ );\r
+ ASSERT (TempPtr != NULL);\r
+ CopyMem (\r
+ TempPtr,\r
+ PpiListPointer->PpiPtrs,\r
+ sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount\r
+ );\r
+ PpiListPointer->PpiPtrs = TempPtr;\r
+ PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP;\r
+ }\r
\r
- //\r
- // Continue until the end of the PPI List.\r
- //\r
- if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+ DEBUG ((DEBUG_INFO, "Install PPI: %g\n", PpiList->Guid));\r
+ PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)PpiList;\r
+ Index++;\r
+ PpiListPointer->CurrentCount++;\r
+\r
+ if (Single) {\r
+ //\r
+ // Only single entry in the PpiList.\r
+ //\r
+ break;\r
+ } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)\r
+ {\r
+ //\r
+ // Continue until the end of the PPI List.\r
+ //\r
break;\r
}\r
+\r
+ //\r
+ // Go to the next descriptor.\r
+ //\r
PpiList++;\r
- Index++;\r
}\r
\r
//\r
- // Dispatch any callback level notifies for newly installed PPIs.\r
+ // Process any callback level notifies for newly installed PPIs.\r
//\r
- DispatchNotify (\r
+ ProcessNotify (\r
PrivateData,\r
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
- LastCallbackInstall,\r
- PrivateData->PpiData.PpiListEnd,\r
- PrivateData->PpiData.DispatchListEnd,\r
- PrivateData->PpiData.NotifyListEnd\r
+ LastCount,\r
+ PpiListPointer->CurrentCount,\r
+ 0,\r
+ PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
);\r
\r
-\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
\r
- Re-Install PPI services.\r
+ This function installs an interface in the PEI PPI database by GUID.\r
+ The purpose of the service is to publish an interface that other parties\r
+ can use to call additional PEIMs.\r
+\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param PpiList Pointer to a list of PEI PPI Descriptors.\r
+\r
+ @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.\r
+ @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer\r
+ if any PPI in PpiList is not valid\r
+ @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiInstallPpi (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
+ )\r
+{\r
+ return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);\r
+}\r
+\r
+/**\r
+\r
+ This function reinstalls an interface in the PEI PPI database by GUID.\r
+ The purpose of the service is to publish an interface that other parties can\r
+ use to replace an interface of the same name in the protocol database with a\r
+ different interface.\r
\r
- @param PeiServices - Pointer to the PEI Service Table\r
- @param OldPpi - Pointer to the old PEI PPI Descriptors.\r
- @param NewPpi - Pointer to the new PEI PPI Descriptors.\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param OldPpi Pointer to the old PEI PPI Descriptors.\r
+ @param NewPpi Pointer to the new PEI PPI Descriptors.\r
\r
- @retval EFI_SUCCESS - if the operation was successful\r
- @retval EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL\r
- @retval EFI_INVALID_PARAMETER - if NewPpi is not valid\r
- @retval EFI_NOT_FOUND - if the PPI was not in the database\r
+ @retval EFI_SUCCESS if the operation was successful\r
+ @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL\r
+ @retval EFI_INVALID_PARAMETER if NewPpi is not valid\r
+ @retval EFI_NOT_FOUND if the PPI was not in the database\r
\r
**/\r
EFI_STATUS\r
IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi\r
)\r
{\r
- PEI_CORE_INSTANCE *PrivateData;\r
- INTN Index;\r
-\r
+ PEI_CORE_INSTANCE *PrivateData;\r
+ UINTN Index;\r
\r
if ((OldPpi == NULL) || (NewPpi == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
- return EFI_INVALID_PARAMETER;\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
\r
//\r
// Find the old PPI instance in the database. If we can not find it,\r
// return the EFI_NOT_FOUND error.\r
//\r
- for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
- if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {\r
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+ if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) {\r
break;\r
}\r
}\r
- if (Index == PrivateData->PpiData.PpiListEnd) {\r
+\r
+ if (Index == PrivateData->PpiData.PpiList.CurrentCount) {\r
return EFI_NOT_FOUND;\r
}\r
\r
//\r
- // Remove the old PPI from the database, add the new one.\r
+ // Replace the old PPI with the new one.\r
//\r
- DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
- PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;\r
+ DEBUG ((DEBUG_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
+ PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)NewPpi;\r
\r
//\r
- // Dispatch any callback level notifies for the newly installed PPI.\r
+ // Process any callback level notifies for the newly installed PPI.\r
//\r
- DispatchNotify (\r
+ ProcessNotify (\r
PrivateData,\r
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
Index,\r
Index+1,\r
- PrivateData->PpiData.DispatchListEnd,\r
- PrivateData->PpiData.NotifyListEnd\r
+ 0,\r
+ PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
);\r
\r
-\r
return EFI_SUCCESS;\r
}\r
\r
Locate a given named PPI.\r
\r
\r
- @param PeiServices - Pointer to the PEI Service Table\r
- @param Guid - Pointer to GUID of the PPI.\r
- @param Instance - Instance Number to discover.\r
- @param PpiDescriptor - Pointer to reference the found descriptor. If not NULL,\r
- returns a pointer to the descriptor (includes flags, etc)\r
- @param Ppi - Pointer to reference the found PPI\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param Guid Pointer to GUID of the PPI.\r
+ @param Instance Instance Number to discover.\r
+ @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,\r
+ returns a pointer to the descriptor (includes flags, etc)\r
+ @param Ppi Pointer to reference the found PPI\r
\r
@retval EFI_SUCCESS if the PPI is in the database\r
@retval EFI_NOT_FOUND if the PPI is not in the database\r
EFI_STATUS\r
EFIAPI\r
PeiLocatePpi (\r
- IN CONST EFI_PEI_SERVICES **PeiServices,\r
- IN CONST EFI_GUID *Guid,\r
- IN UINTN Instance,\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
+ IN CONST EFI_GUID *Guid,\r
+ IN UINTN Instance,\r
IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,\r
- IN OUT VOID **Ppi\r
+ IN OUT VOID **Ppi\r
)\r
{\r
- PEI_CORE_INSTANCE *PrivateData;\r
- INTN Index;\r
- EFI_GUID *CheckGuid;\r
+ PEI_CORE_INSTANCE *PrivateData;\r
+ UINTN Index;\r
+ EFI_GUID *CheckGuid;\r
EFI_PEI_PPI_DESCRIPTOR *TempPtr;\r
\r
-\r
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
\r
//\r
// Search the data base for the matching instance of the GUIDed PPI.\r
//\r
- for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
- TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;\r
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+ TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi;\r
CheckGuid = TempPtr->Guid;\r
\r
//\r
if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
(((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
(((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
- (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {\r
+ (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3]))\r
+ {\r
if (Instance == 0) {\r
-\r
if (PpiDescriptor != NULL) {\r
*PpiDescriptor = TempPtr;\r
}\r
*Ppi = TempPtr->Ppi;\r
}\r
\r
-\r
return EFI_SUCCESS;\r
}\r
+\r
Instance--;\r
}\r
}\r
\r
/**\r
\r
- Install a notification for a given PPI.\r
-\r
+ This function installs a notification service to be called back when a given\r
+ interface is installed or reinstalled. The purpose of the service is to publish\r
+ an interface that other parties can use to call additional PPIs that may materialize later.\r
\r
- @param PeiServices - Pointer to the PEI Service Table\r
- @param NotifyList - Pointer to list of Descriptors to notify upon.\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param NotifyList Pointer to list of Descriptors to notify upon.\r
+ @param Single TRUE if only single entry in the NotifyList.\r
+ FALSE if the NotifyList is ended with an entry which has the\r
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
\r
@retval EFI_SUCCESS if successful\r
@retval EFI_OUT_OF_RESOURCES if no space in the database\r
- @retval EFI_INVALID_PARAMETER if not a good decriptor\r
+ @retval EFI_INVALID_PARAMETER if not a good descriptor\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-PeiNotifyPpi (\r
+InternalPeiNotifyPpi (\r
IN CONST EFI_PEI_SERVICES **PeiServices,\r
- IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList\r
+ IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,\r
+ IN BOOLEAN Single\r
)\r
{\r
- PEI_CORE_INSTANCE *PrivateData;\r
- INTN Index;\r
- INTN NotifyIndex;\r
- INTN LastCallbackNotify;\r
- EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;\r
- UINTN NotifyDispatchCount;\r
-\r
-\r
- NotifyDispatchCount = 0;\r
+ PEI_CORE_INSTANCE *PrivateData;\r
+ PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer;\r
+ UINTN CallbackNotifyIndex;\r
+ UINTN LastCallbackNotifyCount;\r
+ PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer;\r
+ UINTN DispatchNotifyIndex;\r
+ UINTN LastDispatchNotifyCount;\r
+ VOID *TempPtr;\r
\r
if (NotifyList == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
\r
- Index = PrivateData->PpiData.NotifyListEnd;\r
- LastCallbackNotify = Index;\r
+ CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList;\r
+ CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount;\r
+ LastCallbackNotifyCount = CallbackNotifyIndex;\r
+\r
+ DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList;\r
+ DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount;\r
+ LastDispatchNotifyCount = DispatchNotifyIndex;\r
\r
//\r
// This is loop installs all Notify descriptors in the NotifyList. It is\r
// EFI_PEI_NOTIFY_DESCRIPTOR in the list.\r
//\r
\r
- for (;;) {\r
- //\r
- // Since PpiData is used for NotifyList and InstallList, max resource\r
- // is reached if the Install reaches the PpiList\r
- //\r
- if (Index == PrivateData->PpiData.PpiListEnd - 1) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
+ for ( ; ;) {\r
//\r
// If some of the PPI data is invalid restore original Notify PPI database value\r
//\r
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {\r
- PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;\r
- DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify));\r
- return EFI_INVALID_PARAMETER;\r
+ CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount;\r
+ DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount;\r
+ DEBUG ((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify));\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
- NotifyDispatchCount ++;\r
+ if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) {\r
+ if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) {\r
+ //\r
+ // Run out of room, grow the buffer.\r
+ //\r
+ TempPtr = AllocateZeroPool (\r
+ sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP)\r
+ );\r
+ ASSERT (TempPtr != NULL);\r
+ CopyMem (\r
+ TempPtr,\r
+ CallbackNotifyListPointer->NotifyPtrs,\r
+ sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount\r
+ );\r
+ CallbackNotifyListPointer->NotifyPtrs = TempPtr;\r
+ CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP;\r
+ }\r
+\r
+ CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList;\r
+ CallbackNotifyIndex++;\r
+ CallbackNotifyListPointer->CurrentCount++;\r
+ } else {\r
+ if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) {\r
+ //\r
+ // Run out of room, grow the buffer.\r
+ //\r
+ TempPtr = AllocateZeroPool (\r
+ sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP)\r
+ );\r
+ ASSERT (TempPtr != NULL);\r
+ CopyMem (\r
+ TempPtr,\r
+ DispatchNotifyListPointer->NotifyPtrs,\r
+ sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount\r
+ );\r
+ DispatchNotifyListPointer->NotifyPtrs = TempPtr;\r
+ DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP;\r
+ }\r
+\r
+ DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList;\r
+ DispatchNotifyIndex++;\r
+ DispatchNotifyListPointer->CurrentCount++;\r
}\r
\r
- PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
+ DEBUG ((DEBUG_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
\r
- PrivateData->PpiData.NotifyListEnd--;\r
- DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
- if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+ if (Single) {\r
+ //\r
+ // Only single entry in the NotifyList.\r
+ //\r
+ break;\r
+ } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)\r
+ {\r
+ //\r
+ // Continue until the end of the Notify List.\r
+ //\r
break;\r
}\r
+\r
//\r
- // Go the next descriptor. Remember the NotifyList moves down.\r
+ // Go to the next descriptor.\r
//\r
NotifyList++;\r
- Index--;\r
}\r
\r
//\r
- // If there is Dispatch Notify PPI installed put them on the bottom\r
- //\r
- if (NotifyDispatchCount > 0) {\r
- for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {\r
- if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
- NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;\r
-\r
- for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){\r
- PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;\r
- }\r
- PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;\r
- PrivateData->PpiData.DispatchListEnd--;\r
- }\r
- }\r
-\r
- LastCallbackNotify -= NotifyDispatchCount;\r
- }\r
-\r
+ // Process any callback level notifies for all previously installed PPIs.\r
//\r
- // Dispatch any callback level notifies for all previously installed PPIs.\r
- //\r
- DispatchNotify (\r
+ ProcessNotify (\r
PrivateData,\r
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
0,\r
- PrivateData->PpiData.PpiListEnd,\r
- LastCallbackNotify,\r
- PrivateData->PpiData.NotifyListEnd\r
+ PrivateData->PpiData.PpiList.CurrentCount,\r
+ LastCallbackNotifyCount,\r
+ CallbackNotifyListPointer->CurrentCount\r
);\r
\r
-\r
- return EFI_SUCCESS;\r
+ return EFI_SUCCESS;\r
}\r
\r
+/**\r
+\r
+ This function installs a notification service to be called back when a given\r
+ interface is installed or reinstalled. The purpose of the service is to publish\r
+ an interface that other parties can use to call additional PPIs that may materialize later.\r
+\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param NotifyList Pointer to list of Descriptors to notify upon.\r
+\r
+ @retval EFI_SUCCESS if successful\r
+ @retval EFI_OUT_OF_RESOURCES if no space in the database\r
+ @retval EFI_INVALID_PARAMETER if not a good descriptor\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiNotifyPpi (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
+ IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList\r
+ )\r
+{\r
+ return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);\r
+}\r
\r
/**\r
\r
\r
**/\r
VOID\r
-ProcessNotifyList (\r
+ProcessDispatchNotifyList (\r
IN PEI_CORE_INSTANCE *PrivateData\r
)\r
{\r
- INTN TempValue;\r
+ UINTN TempValue;\r
\r
while (TRUE) {\r
//\r
// Check if the PEIM that was just dispatched resulted in any\r
// Notifies getting installed. If so, go process any dispatch\r
- // level Notifies that match the previouly installed PPIs.\r
- // Use "while" instead of "if" since DispatchNotify can modify\r
- // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.\r
+ // level Notifies that match the previously installed PPIs.\r
+ // Use "while" instead of "if" since ProcessNotify can modify\r
+ // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have\r
+ // to iterate until the same.\r
//\r
- while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {\r
- TempValue = PrivateData->PpiData.DispatchListEnd;\r
- DispatchNotify (\r
+ while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
+ TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount;\r
+ ProcessNotify (\r
PrivateData,\r
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
0,\r
- PrivateData->PpiData.LastDispatchedInstall,\r
- PrivateData->PpiData.LastDispatchedNotify,\r
- PrivateData->PpiData.DispatchListEnd\r
+ PrivateData->PpiData.PpiList.LastDispatchedCount,\r
+ PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount,\r
+ PrivateData->PpiData.DispatchNotifyList.CurrentCount\r
);\r
- PrivateData->PpiData.LastDispatchedNotify = TempValue;\r
+ PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue;\r
}\r
\r
-\r
//\r
// Check if the PEIM that was just dispatched resulted in any\r
// PPIs getting installed. If so, go process any dispatch\r
// level Notifies that match the installed PPIs.\r
- // Use "while" instead of "if" since DispatchNotify can modify\r
- // PpiListEnd (with InstallPpi) so we have to iterate until the same.\r
+ // Use "while" instead of "if" since ProcessNotify can modify\r
+ // PpiList.CurrentCount (with InstallPpi) so we have to iterate\r
+ // until the same.\r
//\r
- while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {\r
- TempValue = PrivateData->PpiData.PpiListEnd;\r
- DispatchNotify (\r
+ while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) {\r
+ TempValue = PrivateData->PpiData.PpiList.CurrentCount;\r
+ ProcessNotify (\r
PrivateData,\r
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
- PrivateData->PpiData.LastDispatchedInstall,\r
- PrivateData->PpiData.PpiListEnd,\r
- FixedPcdGet32 (PcdPeiCoreMaxPpiSupported)-1,\r
- PrivateData->PpiData.DispatchListEnd\r
+ PrivateData->PpiData.PpiList.LastDispatchedCount,\r
+ PrivateData->PpiData.PpiList.CurrentCount,\r
+ 0,\r
+ PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount\r
);\r
- PrivateData->PpiData.LastDispatchedInstall = TempValue;\r
+ PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue;\r
}\r
\r
- if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {\r
+ if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
break;\r
}\r
}\r
+\r
return;\r
}\r
\r
/**\r
\r
- Dispatch notifications.\r
+ Process notifications.\r
\r
@param PrivateData PeiCore's private data structure\r
@param NotifyType Type of notify to fire.\r
\r
**/\r
VOID\r
-DispatchNotify (\r
+ProcessNotify (\r
IN PEI_CORE_INSTANCE *PrivateData,\r
- IN UINTN NotifyType,\r
- IN INTN InstallStartIndex,\r
- IN INTN InstallStopIndex,\r
- IN INTN NotifyStartIndex,\r
- IN INTN NotifyStopIndex\r
+ IN UINTN NotifyType,\r
+ IN INTN InstallStartIndex,\r
+ IN INTN InstallStopIndex,\r
+ IN INTN NotifyStartIndex,\r
+ IN INTN NotifyStopIndex\r
)\r
{\r
- INTN Index1;\r
- INTN Index2;\r
- EFI_GUID *SearchGuid;\r
- EFI_GUID *CheckGuid;\r
- EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;\r
-\r
- //\r
- // Remember that Installs moves up and Notifies moves down.\r
- //\r
- for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {\r
- NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;\r
+ INTN Index1;\r
+ INTN Index2;\r
+ EFI_GUID *SearchGuid;\r
+ EFI_GUID *CheckGuid;\r
+ EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;\r
+\r
+ for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) {\r
+ if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) {\r
+ NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify;\r
+ } else {\r
+ NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify;\r
+ }\r
\r
CheckGuid = NotifyDescriptor->Guid;\r
\r
for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {\r
- SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;\r
+ SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid;\r
//\r
// Don't use CompareGuid function here for performance reasons.\r
// Instead we compare the GUID as INT32 at a time and branch\r
if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&\r
(((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
(((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
- (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {\r
- DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",\r
+ (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3]))\r
+ {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Notify: PPI Guid: %g, Peim notify entry point: %p\n",\r
SearchGuid,\r
NotifyDescriptor->Notify\r
));\r
NotifyDescriptor->Notify (\r
- GetPeiServicesTablePointer (),\r
+ (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
NotifyDescriptor,\r
- (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi\r
+ (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi\r
);\r
}\r
}\r
}\r
+}\r
\r
- return;\r
+/**\r
+ Process PpiList from SEC phase.\r
+\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.\r
+ These PPI's will be installed and/or immediately signaled if they are notification type.\r
+\r
+**/\r
+VOID\r
+ProcessPpiListFromSec (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SEC_HOB_DATA_PPI *SecHobDataPpi;\r
+ EFI_HOB_GENERIC_HEADER *SecHobList;\r
+\r
+ for ( ; ;) {\r
+ if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {\r
+ //\r
+ // It is a notification PPI.\r
+ //\r
+ Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *)PpiList, TRUE);\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ //\r
+ // It is a normal PPI.\r
+ //\r
+ Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+ //\r
+ // Continue until the end of the PPI List.\r
+ //\r
+ break;\r
+ }\r
+\r
+ PpiList++;\r
+ }\r
+\r
+ //\r
+ // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,\r
+ // the PEI Foundation will call the GetHobs() member function and install all HOBs\r
+ // returned into the HOB list. It does this after installing all PPIs passed from SEC\r
+ // into the PPI database and before dispatching any PEIMs.\r
+ //\r
+ Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **)&SecHobDataPpi);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = PeiInstallSecHobData (PeiServices, SecHobList);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ }\r
}\r
\r
+/**\r
+\r
+ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.\r
+\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.\r
+\r
+**/\r
+VOID\r
+ConvertPeiCorePpiPointers (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN PEI_CORE_FV_HANDLE *CoreFvHandle\r
+ )\r
+{\r
+ EFI_FV_FILE_INFO FileInfo;\r
+ EFI_PHYSICAL_ADDRESS OrgImageBase;\r
+ EFI_PHYSICAL_ADDRESS MigratedImageBase;\r
+ UINTN PeiCoreModuleSize;\r
+ EFI_PEI_FILE_HANDLE PeiCoreFileHandle;\r
+ VOID *PeiCoreImageBase;\r
+ VOID *PeiCoreEntryPoint;\r
+ EFI_STATUS Status;\r
+\r
+ PeiCoreFileHandle = NULL;\r
+\r
+ //\r
+ // Find the PEI Core in the BFV in temporary memory.\r
+ //\r
+ Status = CoreFvHandle->FvPpi->FindFileByType (\r
+ CoreFvHandle->FvPpi,\r
+ EFI_FV_FILETYPE_PEI_CORE,\r
+ CoreFvHandle->FvHandle,\r
+ &PeiCoreFileHandle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeiCoreFileHandle, &FileInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Find PEI Core EntryPoint in the BFV in temporary memory.\r
+ //\r
+ Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, &PeiCoreEntryPoint);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ OrgImageBase = (UINTN)PeiCoreImageBase;\r
+ MigratedImageBase = (UINTN)_ModuleEntryPoint - ((UINTN)PeiCoreEntryPoint - (UINTN)PeiCoreImageBase);\r
+\r
+ //\r
+ // Size of loaded PEI_CORE in permanent memory.\r
+ //\r
+ PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN)OrgImageBase - (UINTN)FileInfo.Buffer);\r
+\r
+ //\r
+ // Migrate PEI_CORE PPI pointers from temporary memory to newly\r
+ // installed PEI_CORE in permanent memory.\r
+ //\r
+ ConvertPpiPointersFv (PrivateData, (UINTN)OrgImageBase, (UINTN)MigratedImageBase, PeiCoreModuleSize);\r
+ }\r
+}\r