diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/CORE_PEI/CORE_PEI_FRAMEWORK | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Core/CORE_PEI/CORE_PEI_FRAMEWORK')
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/BootMode.c | 108 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/CORE_PEISrcFramework.cif | 21 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/Dispatcher.c | 604 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/FwVol.c | 488 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/Hob.c | 198 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c | 341 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/MemoryServices.c | 440 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiCore.h | 1260 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiMain.c | 405 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/Ppi.c | 673 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/Reset.c | 77 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/Security.c | 194 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/StatusCode.c | 102 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.c | 268 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.h | 38 |
15 files changed, 5217 insertions, 0 deletions
diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/BootMode.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/BootMode.c new file mode 100644 index 0000000..782950a --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/BootMode.c @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + BootMode.c + +Abstract: + + EFI PEI Core Boot Mode services + + + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + if (BootMode == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + *BootMode = HandOffHob->BootMode; + + + return EFI_SUCCESS; +}; + + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + HandOffHob->BootMode = BootMode; + + + return EFI_SUCCESS; +}; diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/CORE_PEISrcFramework.cif b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/CORE_PEISrcFramework.cif new file mode 100644 index 0000000..9c5a51e --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/CORE_PEISrcFramework.cif @@ -0,0 +1,21 @@ +<component> + name = "CORE_PEI Source Framework (EDK)" + category = ModulePart + LocalRoot = "Core\CORE_PEI\CORE_PEI_FRAMEWORK" + RefName = "CORE_PEISrcFramework_EDK" +[files] +"BootMode.c" +"dependency.c" +"dependency.h" +"Dispatcher.c" +"FwVol.c" +"Hob.c" +"Image.c" +"MemoryServices.c" +"PeiCore.h" +"PeiMain.c" +"Ppi.c" +"Reset.c" +"Security.c" +"StatusCode.c" +<endComponent> diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Dispatcher.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Dispatcher.c new file mode 100644 index 0000000..c82752f --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Dispatcher.c @@ -0,0 +1,604 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Dispatcher.c + +Abstract: + + EFI PEI Core dispatch services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) + +EFI_STATUS +TransferOldDataToNewDataRange ( + IN PEI_CORE_INSTANCE *PrivateData, + OUT UINTN *PrivateDataInMem + ); + +EFI_GUID gEfiPeiCorePrivateGuid = EFI_PEI_CORE_PRIVATE_GUID; +//*** AMI PORTING BEGIN ***// +VOID AmiSwitchToMemory( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *EntryPoint, + IN UINTN Parameter1, IN UINTN Parameter2, + IN VOID *NewStack +); +//*** AMI PORTING END *****// + +EFI_STATUS +PeiDispatcher ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_DISPATCH_DATA *DispatchData + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR + PrivateData - Pointer to the private data passed in from caller + DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data. + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +{ + EFI_STATUS Status; + PEI_CORE_TEMP_POINTERS TempPtr; + UINTN PrivateDataInMem; + BOOLEAN NextFvFound; + EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress; + EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress; + + // + // Debug data for uninstalled Peim list + // + PEI_DEBUG_CODE ( + + UINT64 DebugNotDispatchedBitmap; + EFI_GUID DebugFoundPeimList[64]; + UINT8 DebugFoundPeimPoint; + + ) + + PEI_REPORT_STATUS_CODE_CODE ( + + EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + + ExtendedData.DataHeader.HeaderSize = (UINT16)sizeof (EFI_STATUS_CODE_DATA); + ExtendedData.DataHeader.Size = (UINT16)(sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - ExtendedData.DataHeader.HeaderSize); + + PeiCoreCopyMem ( + &ExtendedData.DataHeader.Type, + &gEfiStatusCodeSpecificDataGuid, + sizeof (EFI_GUID) + ); + ) + // + // save the Current FV Address so that we will not process it again if FindFv returns it later + // + DefaultFvAddress = DispatchData->BootFvAddress; + + // + // This is the main dispatch loop. It will search known FVs for PEIMs and + // attempt to dispatch them. If any PEIM gets dispatched through a single + // pass of the dispatcher, it will start over from the Bfv again to see + // if any new PEIMs dependencies got satisfied. With a well ordered + // FV where PEIMs are found in the order their dependencies are also + // satisfied, this dipatcher should run only once. + // + for (;;) { + // + // This is the PEIM search loop. It will scan through all PEIMs it can find + // looking for PEIMs to dispatch, and will dipatch them if they have not + // already been dispatched and all of their dependencies are met. + // If no more PEIMs can be found in this pass through all known FVs, + // then it will break out of this loop. + // + for (;;) { + + Status = FindNextPeim ( + &PrivateData->PS, + DispatchData->CurrentFvAddress, + &DispatchData->CurrentPeimAddress + ); + + // + // If we found a PEIM, check if it is dispatched. If so, go to the + // next PEIM. If not, dispatch it if its dependencies are satisfied. + // If its dependencies are not satisfied, go to the next PEIM. + // + if (Status == EFI_SUCCESS) { + + PEI_DEBUG_CODE ( + + // + // Fill list of found Peims for later list of those not installed + // + PeiCoreCopyMem ( + &DebugFoundPeimList[DispatchData->CurrentPeim], + &DispatchData->CurrentPeimAddress->Name, + sizeof (EFI_GUID) + ); + + ) + + if (!Dispatched ( + DispatchData->CurrentPeim, + DispatchData->DispatchedPeimBitMap + )) { + if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) { + Status = PeiLoadImage ( + &PrivateData->PS, + DispatchData->CurrentPeimAddress, + &TempPtr.Raw + ); + if (Status == EFI_SUCCESS) { + + // + // The PEIM has its dependencies satisfied, and its entry point + // has been found, so invoke it. + // + PEI_PERF_START ( + &PrivateData->PS, + L"PEIM", + (EFI_FFS_FILE_HEADER *)(DispatchData->CurrentPeimAddress), + 0 + ); + + PEI_REPORT_STATUS_CODE_CODE ( + + ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress; + + ) + + PEI_REPORT_STATUS_CODE_CODE ( + + PeiReportStatusCode ( + &(PrivateData->PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + + ) + + // + // Is this a authentic image + // + Status = VerifyPeim ( + &PrivateData->PS, + DispatchData->CurrentPeimAddress + ); + + if (Status != EFI_SECURITY_VIOLATION) { + + Status = TempPtr.PeimEntry ( + DispatchData->CurrentPeimAddress, + &PrivateData->PS + ); + } + + PEI_REPORT_STATUS_CODE_CODE ( + + PeiReportStatusCode ( + &(PrivateData->PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + + ) + PEI_PERF_END (&PrivateData->PS, L"PEIM", (EFI_FFS_FILE_HEADER *)(DispatchData->CurrentPeimAddress), 0); + + // + // Mark the PEIM as dispatched so we don't attempt to run it again + // + SetDispatched ( + &PrivateData->PS, + DispatchData->CurrentPeim, + &DispatchData->DispatchedPeimBitMap + ); + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (&PrivateData->PS); + + // + // If real system memory was discovered and installed by this + // PEIM, switch the stacks to the new memory. Since we are + // at dispatch level, only the Core's private data is preserved, + // nobody else should have any data on the stack. + // + if (PrivateData->SwitchStackSignal) { + TempPtr.PeiCore = PeiCore; + Status = TransferOldDataToNewDataRange ( + PrivateData, + &PrivateDataInMem + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + //Subtract 0x10 from the 4th parameter indicating the new stack base, + //in order to provide buffer protection against possible illegal stack + //access that might corrupt the stack. + // +//*** AMI PORTING BEGIN ***// + AmiSwitchToMemory ( + &((PEI_CORE_INSTANCE*)PrivateDataInMem)->PS, + //SwitchCoreStacks ( +//*** AMI PORTING END *****// + TempPtr.Raw, + (UINTN)PeiStartupDescriptor, + PrivateDataInMem, + (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - 0x10) + ); + } + } + } + } + DispatchData->CurrentPeim++; + continue; + + } else { + + // + // If we could not find another PEIM in the current FV, go try + // the FindFv PPI to look in other FVs for more PEIMs. If we can + // not locate the FindFv PPI, or if the FindFv PPI can not find + // anymore FVs, then exit the PEIM search loop. + // + if (DispatchData->FindFv == NULL) { + Status = PeiLocatePpi ( + &PrivateData->PS, + &gEfiFindFvPpiGuid, + 0, + NULL, + &DispatchData->FindFv + ); + if (Status != EFI_SUCCESS) { + break; + } + } + NextFvFound = FALSE; + while (!NextFvFound) { + Status = DispatchData->FindFv->FindFv ( + DispatchData->FindFv, + &PrivateData->PS, + &DispatchData->CurrentFv, + &NextFvAddress + ); + // + // if there is no next fv, get out of this loop of finding FVs + // + if (Status != EFI_SUCCESS) { + break; + } + // + // don't process the default Fv again. (we don't know the order in which the hobs were created) + // + if ((NextFvAddress != DefaultFvAddress) && + (NextFvAddress != DispatchData->CurrentFvAddress)) { + + // + // VerifyFv() is currently returns SUCCESS all the time, add code to it to + // actually verify the given FV + // + Status = VerifyFv (NextFvAddress); + if (Status == EFI_SUCCESS) { + NextFvFound = TRUE; + DispatchData->CurrentFvAddress = NextFvAddress; + DispatchData->CurrentPeimAddress = NULL; + // + // current PRIM number (CurrentPeim) must continue as is, don't reset it here + // + } + } + } + // + // if there is no next fv, get out of this loop of dispatching PEIMs + // + if (!NextFvFound) { + break; + } + // + // continue in the inner for(;;) loop with a new FV; + // + } + } + + // + // If all the PEIMs that we have found have been dispatched, then + // there is nothing left to dispatch and we don't need to go search + // through all PEIMs again. + // + if ((~(DispatchData->DispatchedPeimBitMap) & + (LShiftU64 (1, DispatchData->CurrentPeim)-1)) == 0) { + break; + } + + // + // Check if no more PEIMs that depex was satisfied + // + if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) { + break; + } + + // + // Case when Depex is not satisfied and has to traverse the list again + // + DispatchData->CurrentPeim = 0; + DispatchData->CurrentPeimAddress = 0; + DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap; + + // + // don't go back to the loop without making sure that the CurrentFvAddress is the + // same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and + // mess it up, always start processing the PEIMs from the default FV just like in the first time around. + // + DispatchData->CurrentFv = 0; + DispatchData->CurrentFvAddress = DefaultFvAddress; + } + + PEI_DEBUG_CODE ( + + DebugFoundPeimPoint = 0; + // + // Get bitmap of Peims that were not dispatched, + // + + DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ (LShiftU64 (1, DispatchData->CurrentPeim)-1)); + // + // Scan bitmap of Peims not installed and print GUIDS + // + while (DebugNotDispatchedBitmap != 0) { + if ((DebugNotDispatchedBitmap & 1) != 0) { + PEI_DEBUG ( + (&PrivateData->PS, EFI_D_INFO, + "WARNING -> PEIM Not Dispatched: %g\n", + &DebugFoundPeimList[DebugFoundPeimPoint]) + ); + } + DebugFoundPeimPoint++; + DebugNotDispatchedBitmap = RShiftU64 (DebugNotDispatchedBitmap, 1); + } + + ) + + return EFI_NOT_FOUND; +} + +VOID +InitializeDispatcherData ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + None. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (OldCoreData == NULL) { + PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume; + PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume; + } else { + + // + // Current peim has been dispatched, but not count + // + PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1); + } + + return; +} + + +BOOLEAN +Dispatched ( + IN UINT8 CurrentPeim, + IN UINT64 DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine checks to see if a particular PEIM has been dispatched during + the PEI core dispatch. + +Arguments: + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + TRUE - PEIM already dispatched + FALSE - Otherwise + +--*/ +{ + return (BOOLEAN)((DispatchedPeimBitMap & LShiftU64 (1, CurrentPeim)) != 0); +} + +VOID +SetDispatched ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 CurrentPeim, + OUT UINT64 *DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine sets a PEIM as having been dispatched once its entry + point has been invoked. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + None + +--*/ +{ + // + // Check if the total number of PEIMs exceed the bitmap. + // CurrentPeim is 0-based + // +PEI_DEBUG_CODE ( + if (CurrentPeim > (sizeof (*DispatchedPeimBitMap) * 8 - 1)) { + ASSERT_PEI_ERROR (PeiServices, EFI_OUT_OF_RESOURCES); + } +) + *DispatchedPeimBitMap |= LShiftU64 (1, CurrentPeim); + return; +} + +BOOLEAN +DepexSatisfied ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CurrentPeimAddress + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + PeiServices - The PEI Service Table + CurrentPeimAddress - Address of the PEIM Firmware File under investigation + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +{ + EFI_STATUS Status; + INT8 *DepexData; + BOOLEAN Runnable; + + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PEI_DEPEX, + CurrentPeimAddress, + &DepexData + ); + // + // If there is no DEPEX, assume the module can be executed + // + if (EFI_ERROR (Status)) { + return TRUE; + } + + // + // Evaluate a given DEPEX + // + Status = PeimDispatchReadiness ( + PeiServices, + DepexData, + &Runnable + ); + + return Runnable; +} + + +EFI_STATUS +TransferOldDataToNewDataRange ( + IN PEI_CORE_INSTANCE *PrivateData, + OUT UINTN *PrivateDataInMem + ) +/*++ + +Routine Description: + + This routine transfers the contents of the pre-permanent memory + PEI Core private data to a post-permanent memory data location. + +Arguments: + PrivateData - Pointer to the current PEI Core private data pre-permanent memory + PrivateDataInMem - Pointer to the PrivateData once the private data has been transferred + to permanent memory + +Returns: + EFI_SUCCESS - Successfully transfered + EFI_ERROR - Fail to transfer + +--*/ +{ + EFI_STATUS Status; + + Status = PeiBuildHobGuid ( + &(PrivateData->PS), + &gEfiPeiCorePrivateGuid, + sizeof (PEI_CORE_INSTANCE), + (VOID*)PrivateDataInMem + ); + if (EFI_ERROR (Status)) { + return Status; + } + (*PrivateDataInMem) += sizeof (EFI_HOB_GUID_TYPE); + PrivateData->PS->CopyMem ( + (VOID*)(*PrivateDataInMem), + (VOID*)PrivateData, + sizeof (PEI_CORE_INSTANCE) + ); + + return EFI_SUCCESS; +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/FwVol.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/FwVol.c new file mode 100644 index 0000000..14eb90c --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/FwVol.c @@ -0,0 +1,488 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FwVol.c + +Abstract: + + Pei Core Firmware File System service routines. + +--*/ + +#include "Tiano.h" +#include "EfiImageFormat.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#define GETOCCUPIEDSIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) + +STATIC +EFI_FFS_FILE_STATE +GetFileState( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Returns the highest bit set of the State field + +Arguments: + + ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY + in the Attributes field. + FfsHeader - Pointer to FFS File Header. + +Returns: + Returns the highest bit in the State field + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + +STATIC +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +/*++ + +Routine Description: + + Calculates the checksum of the header of a file. + +Arguments: + + FileHeader - Pointer to FFS File Header. + +Returns: + Checksum of the header. + + The header is zero byte checksum. + - Zero means the header is good. + - Non-zero means the header is bad. + + +Bugbug: For PEI performance reason, we comments this code at this time. +--*/ +{ + UINT8 *ptr; + UINTN Index; + UINT8 Sum; + + Sum = 0; + ptr = (UINT8 *)FileHeader; + + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) { + Sum = (UINT8)(Sum + ptr[Index]); + Sum = (UINT8)(Sum + ptr[Index+1]); + Sum = (UINT8)(Sum + ptr[Index+2]); + Sum = (UINT8)(Sum + ptr[Index+3]); + } + + for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + Sum = (UINT8)(Sum + ptr[Index]); + } + + // + // State field (since this indicates the different state of file). + // + Sum = (UINT8)(Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + +STATIC +EFI_STATUS +PeiFfsFindNextFileEx ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader, + IN BOOLEAN Flag + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + + + FvLength = FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // If FileHeader is not specified (NULL) start with the first file in the + // firmware volume. Otherwise, start from the FileHeader. + // + if (*FileHeader == NULL) { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); + PEI_ASSERT (PeiServices, (FileOffset <= 0xFFFFFFFF)); + + while (FileOffset < (FvLength - sizeof(EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset += sizeof(EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) == 0) { + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + if (Flag) { + if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { + + *FileHeader = FfsFileHeader; + + + return EFI_SUCCESS; + } + } else { + if ((SearchType == FfsFileHeader->Type) || + (SearchType == EFI_FV_FILETYPE_ALL)) { + + *FileHeader = FfsFileHeader; + + + return EFI_SUCCESS; + } + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + } else { +//*** AMI PORTING BEGIN ***// +// Skip the assert to support a more sophisiticated +// FV corruption handling outside of the Core. +// PEI_ASSERT (PeiServices, (0)); +//*** AMI PORTING END *****// + return EFI_NOT_FOUND; + } + break; + + case EFI_FILE_DELETED: + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + default: + return EFI_NOT_FOUND; + + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FfsFileHeader - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINT32 SectionLength; + UINT32 ParsedLength; + + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1); + FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileSize -= sizeof(EFI_FFS_FILE_HEADER); + + *SectionData = NULL; + ParsedLength = 0; + while (ParsedLength < FileSize) { + if (Section->Type == SectionType) { + *SectionData = (VOID *)(Section + 1); + + + return EFI_SUCCESS; + } + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + SectionLength = GETOCCUPIEDSIZE (SectionLength, 4); + PEI_ASSERT (PeiServices, SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; + +} + + +EFI_STATUS +FindNextPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + PeimFileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + return PeiFfsFindNextFileEx ( + PeiServices, + 0, + FwVolHeader, + PeimFileHeader, + TRUE + ); +} + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + return PeiFfsFindNextFileEx ( + PeiServices, + SearchType, + FwVolHeader, + FileHeader, + FALSE + ); +} + +EFI_STATUS +EFIAPI +PeiFvFindNextVolume ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + + Return the Firmware Volume instance requested + + BugBug -- Move this to the location of this code to where the + other FV and FFS support code lives. + Also, update to use FindFV for instances #'s >= 1. + +Arguments: + + PeiServices - The PEI core services table. + Instance - Instance of FV to find + FwVolHeader - Pointer to contain the data to return + +Returns: + Pointer to the Firmware Volume instance requested + + EFI_INVALID_PARAMETER - FwVolHeader is NULL + + EFI_SUCCESS - Firmware volume instance successfully found. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_STATUS Status; + EFI_FIND_FV_PPI *FindFvPpi; + UINT8 LocalInstance; + + + LocalInstance = (UINT8) Instance; + + Status = EFI_SUCCESS; + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + if (FwVolHeader == NULL) { + + return EFI_INVALID_PARAMETER; + } + + if (Instance == 0) { + // + // If instance is 0, the first firmware volume must be BFV. + // + *FwVolHeader = PrivateData->DispatchData.BootFvAddress; + + + return Status; + } else { + // + // Locate all instances of FindFV + // Alternately, could use FV HOBs, but the PPI is cleaner + // + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiFindFvPpiGuid, + 0, + NULL, + &FindFvPpi + ); + + if (Status != EFI_SUCCESS) { + Status = EFI_NOT_FOUND; + } else { + Status = FindFvPpi->FindFv ( + FindFvPpi, + PeiServices, + &LocalInstance, + FwVolHeader + ); + + } + } + return Status; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Hob.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Hob.c new file mode 100644 index 0000000..cffbf6c --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Hob.c @@ -0,0 +1,198 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Hob.c + +Abstract: + + EFI PEI Core HOB services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + + // + // Only check this parameter in debug mode + // + + PEI_DEBUG_CODE ( + if (HobList == NULL) { + return EFI_INVALID_PARAMETER; + } + ) + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + *HobList = PrivateData->HobList.Raw; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + + + Status = PeiGetHobList (PeiServices, Hob); + if (EFI_ERROR(Status)) { + return Status; + } + + HandOffHob = *Hob; + + Length = (UINT16)((Length + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < Length) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } + + *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = (VOID *)(UINTN)MemoryBegin; + HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1); + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BootMode; + + Hob->EfiMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = MemoryBegin; + Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c new file mode 100644 index 0000000..8ccbd68 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c @@ -0,0 +1,341 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Image.c + +Abstract: + + Pei Core Load Image Support + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_PPI_DEFINITION (LoadFile) + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *PeimFileHeader, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + PeimFileHeader - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS Status; + VOID *Pe32Data; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; +#ifdef EFI_NT_EMULATOR + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_PEI_LOAD_FILE_PPI *PeiNtService; + EFI_PHYSICAL_ADDRESS NtEntryPoint; +#endif + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + EFI_TE_IMAGE_HEADER *TEImageHeader; + UINT16 Machine; + + PEI_DEBUG_CODE (ImageAddress = 0;) + + *EntryPoint = NULL; + TEImageHeader = NULL; + PeHdr = NULL; + // + // Try to find a PE32 section. + // + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PE32, + PeimFileHeader, + &Pe32Data + ); + // + // If we didn't find a PE32 section, try to find a TE section. + // + if (Status != EFI_SUCCESS) { + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_TE, + PeimFileHeader, + (VOID **) &TEImageHeader + ); + Pe32Data = (VOID *) TEImageHeader; + } + if (Status == EFI_SUCCESS) { + if (TEImageHeader == NULL) { + if (((EFI_IMAGE_DOS_HEADER *) Pe32Data)->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) Pe32Data)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + Machine = PeHdr->FileHeader.Machine; +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of the PEIMS +//from the firmware volumes in memory. + if ( PeHdr->OptionalHeader.ImageBase + !=(UINTN)Pe32Data + ) Status=EFI_NOT_FOUND; +//Init ImageSize for to pass into UpdatedLoadedImagePpi + ImageSize = PeHdr->OptionalHeader.SizeOfImage; +//*** AMI PORTING END *****// + } else { +//*** AMI PORTING BEGIN ***// + Machine = TEImageHeader->Machine; +//This is needed to enable execution of the PEIMS +//from the firmware volumes in memory. +//The following two lines are not needed because +//we don't support reallocation of TE image into memory. +// if ( TEImageHeader->ImageBase!=(UINTN)(TEImageHeader)) +// Status=EFI_NOT_FOUND; + +//Init ImageSize for to pass into UpdatedLoadedImagePpi. +//Let's get size from the FFS section header + ImageSize = FVSECTION_SIZE(TEImageHeader); +//*** AMI PORTING END *****// + } + // + // Check PEIM image machine. A PEIM image for different processor architecture + // from the host can't be started. + // + if (Machine != EFI_IMAGE_MACHINE_TYPE) { + return EFI_UNSUPPORTED; + } + +#ifdef EFI_NT_EMULATOR + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtPeiLoadFileGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + &NtEntryPoint + ); + + if (EFI_ERROR (Status)) { + if (TEImageHeader != NULL) { + *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } + } else { + *EntryPoint = (VOID *) (UINTN) NtEntryPoint; + } + +#else + ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data; + if (TEImageHeader != NULL) { + *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } +#endif +//*** AMI PORTING BEGIN ***// +// } else { + } + if (Status!=EFI_SUCCESS){ +//*** AMI PORTING END *****// + // + // There was not a PE32 section, so assume that it's a Compressed section + // and use the LoadFile + // + Status = PeiLocatePpi ( + PeiServices, + &gPeiFvFileLoaderPpiGuid, + 0, + NULL, + &FvLoadFilePpi + ); + + if (!EFI_ERROR (Status)) { + Status = FvLoadFilePpi->FvLoadFile ( + FvLoadFilePpi, + PeimFileHeader, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); + + if (!EFI_ERROR (Status)) { + *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint); + if (((EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress)->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TEImageHeader = (EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress; + Machine = TEImageHeader->Machine; + } else { + if (((EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress)->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) ImageAddress + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) (UINTN) ImageAddress; + } + Machine = PeHdr->FileHeader.Machine; + } + // + // Check PEIM image machine. A PEIM image for different processor architecture + // from the host can't be started. + // + if (Machine != EFI_IMAGE_MACHINE_TYPE) { + return EFI_UNSUPPORTED; + } + } + } + } +//*** AMI PORTING BEGIN ***// +//Message is printed later. Disable this one +/* + PEI_DEBUG_CODE ( + { + EFI_IMAGE_DATA_DIRECTORY * DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * DebugEntry; + UINTN DirCount; + UINTN Index; + UINTN Index1; + BOOLEAN FileNameFound; + CHAR8 *AsciiString; + CHAR8 AsciiBuffer[512]; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + + if (Status == EFI_SUCCESS) { + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + PEI_DEBUG ((PeiServices, EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint)); + + // + // Find the codeview info in the image and display the file name + // being loaded. + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + DebugEntry = NULL; + DirectoryEntry = NULL; + TEImageAdjust = 0; + if (TEImageHeader == NULL) { + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress); + } + } else { + if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader + + TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + } + + if (DebugEntry != NULL && DirectoryEntry != NULL) { + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + AsciiString = NULL; + break; + } + if (AsciiString != NULL) { + FileNameFound = FALSE; + for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) { + if (AsciiString[Index] == '\\') { + Index1 = Index; + FileNameFound = TRUE; + } + } + + if (FileNameFound) { + for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) { + AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index]; + } + AsciiBuffer[Index - (Index1 + 1)] = 0; + PEI_DEBUG ((PeiServices, EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); + break; + } + } + } + } + } + } + PEI_DEBUG ((PeiServices, EFI_D_INFO | EFI_D_LOAD, "\n")); + } + } + ) +*/ +#ifdef EFI_DEBUG +if (!EFI_ERROR (Status)){ + char sName[0x100]; + if (!GetName((VOID*)(UINTN)ImageAddress,sName)) Sprintf_s(sName,sizeof(sName),"[%G]",&PeimFileHeader->Name); + PeiTrace(TRACE_PEICORE, PeiServices, "%s.Entry(%X)\n", sName, *EntryPoint); +} +else PeiTrace(TRACE_PEICORE, PeiServices, "ERROR: attempt to load FFS file [%G] has failed\n", &PeimFileHeader->Name); +#endif +//New image is loaded and is about to be launched +//Update LoadedImage PPI information +if (!EFI_ERROR (Status)) + UpdatedLoadedImagePpi(PeiServices,ImageAddress,ImageSize,PeimFileHeader); +//*** AMI PORTING END *****// + return Status; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/MemoryServices.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/MemoryServices.c new file mode 100644 index 0000000..9566e02 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/MemoryServices.c @@ -0,0 +1,440 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + MemoryServices.c + +Abstract: + + EFI PEI Core memory services + +--*/ + +#include "Tiano.h" +#include "PeiApi.h" +#include "PeiCore.h" +#include "PeiLib.h" +//*** AMI PORTING BEGIN ***// +//use SDL token 'DXE_STACK_SIZE' to define stack size +#include <Token.h> +#undef PEI_STACK_SIZE +#define PEI_STACK_SIZE DXE_STACK_SIZE +//*** AMI PORTING END *****// + +VOID +InitializeMemoryServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT64 SizeOfCarHeap; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + PrivateData->SwitchStackSignal = FALSE; + + if (OldCoreData == NULL) { + + PrivateData->PeiMemoryInstalled = FALSE; + +//*** AMI PORTING BEGIN ***// +//The original method of getting CAR top and bootom addresses assumes that CAR base address is aligned +//on CAR size boundary, which is not always the case. +//Make the algorithm more flexible +//Comment out the old code: +// PrivateData->BottomOfCarHeap = (VOID *) (((UINTN)(VOID *)(&PrivateData)) +// & (~((PeiStartupDescriptor->SizeOfCacheAsRam) - 1))); +// PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + PeiStartupDescriptor->SizeOfCacheAsRam); +//New code: +// Private data is located towards the top of the stack. +// The stack is located at the top of the CAR. +// We assume that: +// 1) CAR address and size are at least 1K aligned. +// 2) Not more than 1K of Stack is used by SEC phase. +// The top of the CAR should be the next 1K boundary +//NOTE: New PI 1.0 spec provides a better solution. +//It expends SEC to PI hand off structure to explicitly pass CAR address +//This code will be changed once PI support is added. +#define CAR_ADDRESS_AND_SIZE_ALIGNMENT 0x400 + PrivateData->TopOfCarHeap = (VOID *)( + (((UINTN)(VOID *)(&PrivateData))+CAR_ADDRESS_AND_SIZE_ALIGNMENT) + & (~(CAR_ADDRESS_AND_SIZE_ALIGNMENT-1)) + ); + PrivateData->BottomOfCarHeap = (VOID *)( + (UINTN)(PrivateData->TopOfCarHeap) + - PeiStartupDescriptor->SizeOfCacheAsRam + ); +//*** AMI PORTING END *****// + // + // SizeOfCarHeap is 1/2 (arbitrary) of CacheAsRam Size. + // + SizeOfCarHeap = (UINT64) PeiStartupDescriptor->SizeOfCacheAsRam; + SizeOfCarHeap = RShiftU64 (SizeOfCarHeap, 1); + + PEI_DEBUG_CODE ( + { + PrivateData->SizeOfCacheAsRam = PeiStartupDescriptor->SizeOfCacheAsRam; + PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) SizeOfCarHeap); + } + ) + + PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap; + + PeiCoreBuildHobHandoffInfoTable ( + BOOT_WITH_FULL_CONFIGURATION, + (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap, + (UINTN) SizeOfCarHeap + ); + // + // Copy PeiServices from ROM to Cache in PrivateData + // + PeiCoreCopyMem (&(PrivateData->ServiceTableShadow), *PeiServices, sizeof (EFI_PEI_SERVICES)); + + // + // Set PS to point to ServiceTableShadow in Cache + // + PrivateData->PS = &(PrivateData->ServiceTableShadow); + } else { + // + // Set PS to point to ServiceTableShadow in Cache one time after the + // stack switched to main memory + // + PrivateData->PS = &(PrivateData->ServiceTableShadow); +} + + return; +} + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob; + EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob; + UINT64 PeiStackSize; + UINT64 EfiFreeMemorySize; + EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + +//*** AMI PORTING BEGIN ***// + if (PrivateData->PeiMemoryInstalled) { + //This function should be called once. Report error if this is the second call + PEI_ERROR_CODE(PeiServices, PEI_MEMORY_INSTALLED_TWICE, EFI_ERROR_MINOR); + }else { + //Debug message + PEI_TRACE((TRACE_PEICORE, PeiServices, "Memory Installed: Address=%lX; Length=%lX\n",MemoryBegin,MemoryLength)); + } +//*** AMI PORTING END *****// + + PrivateData->SwitchStackSignal = TRUE; + PrivateData->PeiMemoryInstalled = TRUE; + + PrivateData->StackBase = MemoryBegin; + + PeiStackSize = RShiftU64 (MemoryLength, 1); + if (PEI_STACK_SIZE > PeiStackSize) { + PrivateData->StackSize = PeiStackSize; + } else { + PrivateData->StackSize = PEI_STACK_SIZE; + } + + OldHandOffHob = PrivateData->HobList.HandoffInformationTable; + + PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize)); + NewHandOffHob = PrivateData->HobList.HandoffInformationTable; + PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob; + + EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob; + + PeiCoreCopyMem ( + NewHandOffHob, + OldHandOffHob, + (UINTN)EfiFreeMemorySize + ); + + NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength; + NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop; + NewHandOffHob->EfiMemoryBottom = MemoryBegin; + + NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize; + + NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob + + (OldHandOffHob->EfiEndOfHobList - + PhysicalAddressOfOldHob); + + ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob); + + PeiBuildHobStack (PeiServices, PrivateData->StackBase, PrivateData->StackSize); +//*** AMI PORTING BEGIN ***// +//Update LoadedImage pointers +PrivateData->LoadedImage = (EFI_PEI_PPI_DESCRIPTOR*) + ( (UINTN)PrivateData->LoadedImage + ((UINTN)NewHandOffHob - (UINTN)OldHandOffHob) ); +//*** AMI PORTING END *****// + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob)); + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob)); + } + ) + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS Offset; + EFI_STATUS Status; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Check if Hob already available + // + if (!PrivateData->PeiMemoryInstalled) { + return EFI_NOT_AVAILABLE_YET; + } + + Hob.Raw = PrivateData->HobList.Raw; + + // + // Check to see if on 4k boundary + // + Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF; + + // + // If not aligned, make the allocation aligned. + // + if (Offset != 0) { + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset; + } + + // + // Verify that there is sufficient memory to satisfy the allocation + // + if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < + Hob.HandoffInformationTable->EfiFreeMemoryBottom) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiAllocatePages fail: Pages - 0x%08x\n", Pages)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } else { + // + // Update the PHIT to reflect the memory usage + // + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE; + + // + // Update the value for the caller + // + *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop; + + // + // Create a memory allocation HOB. + // + Status = PeiBuildHobMemoryAllocation ( + PeiServices, + Hob.HandoffInformationTable->EfiFreeMemoryTop, + Pages * EFI_PAGE_SIZE + Offset, + NULL, + MemoryType + ); + + return Status; + } +} + + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_POOL *Hob; + + + Status = PeiCreateHob ( + PeiServices, + EFI_HOB_TYPE_PEI_MEMORY_POOL, + (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size), + &Hob + ); + *Buffer = Hob+1; + + + return Status; +} + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + EfiCommonLibCopyMem (Destination, Source, Length); +} + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +{ + EfiCommonLibSetMem (Buffer, Size, Value); +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiCore.h b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiCore.h new file mode 100644 index 0000000..24130e5 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiCore.h @@ -0,0 +1,1260 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PeiCore.h + +Abstract: + + Definition of Pei Core Structures and Services + +Revision History + +--*/ + +#ifndef _PEICORE_H_ +#define _PEICORE_H_ + +#include "EfiImage.h" +#include "Pei.h" +#include "PeiHob.h" + +#ifdef EFI64 +#include "SalApi.h" +#endif + +#include "EfiCommonLib.h" + +#include EFI_PPI_DEFINITION (FindFv) +#include EFI_PPI_DEFINITION (DxeIpl) +#include EFI_PPI_DEFINITION (StatusCode) +#include EFI_PPI_DEFINITION (Security) + + +#ifdef EFI_NT_EMULATOR +#include EFI_PPI_DEFINITION (NtPeiLoadFile) +#endif + +//*** AMI PORTING BEGIN ***// +#include <PPI/LoadedImagePpi.h> +//*** AMI PORTING END *****// + +// +//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range +// +#define EFI_PEI_CORE_PRIVATE_GUID \ + {0xd641a0f5, 0xcb7c, 0x4846, 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9} + +// +// Pei Core private data structures +// +typedef union _PEI_PPI_LIST_POINTERS { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + +#define PEI_STACK_SIZE 0x20000 + +#define MAX_PPI_DESCRIPTORS 128 + +typedef struct { + INTN PpiListEnd; + INTN NotifyListEnd; + INTN DispatchListEnd; + INTN LastDispatchedInstall; + INTN LastDispatchedNotify; + PEI_PPI_LIST_POINTERS PpiListPtrs[MAX_PPI_DESCRIPTORS]; +} PEI_PPI_DATABASE; + +typedef struct { + UINT8 CurrentPeim; + UINT8 CurrentFv; + UINT64 DispatchedPeimBitMap; + UINT64 PreviousPeimBitMap; + EFI_FFS_FILE_HEADER *CurrentPeimAddress; + EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress; + EFI_FIRMWARE_VOLUME_HEADER *BootFvAddress; + EFI_FIND_FV_PPI *FindFv; +} PEI_CORE_DISPATCH_DATA; + + +// +// Pei Core private data structure instance +// + +#define PEI_CORE_HANDLE_SIGNATURE EFI_SIGNATURE_32('P','e','i','C') + +typedef struct{ + UINTN Signature; + EFI_PEI_SERVICES *PS; // Point to ServiceTableShadow + PEI_PPI_DATABASE PpiData; + PEI_CORE_DISPATCH_DATA DispatchData; + EFI_PEI_HOB_POINTERS HobList; + BOOLEAN SwitchStackSignal; + BOOLEAN PeiMemoryInstalled; + EFI_PHYSICAL_ADDRESS StackBase; + UINT64 StackSize; + VOID *BottomOfCarHeap; + VOID *TopOfCarHeap; + VOID *CpuIo; + PEI_SECURITY_PPI *PrivateSecurityPpi; + EFI_PEI_SERVICES ServiceTableShadow; +//*** AMI PORTING BEGIN ***// + EFI_PEI_PPI_DESCRIPTOR *LoadedImage; + EFI_PEI_LOADED_IMAGE_PPI LoadedImagePpi; +//*** AMI PORTING END *****// + PEI_DEBUG_CODE ( + UINTN SizeOfCacheAsRam; + VOID *MaxTopOfCarHeap; + ) +} PEI_CORE_INSTANCE; + +// +// Pei Core Instance Data Macros +// + +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \ + PEI_CR(a, PEI_CORE_INSTANCE, PS, PEI_CORE_HANDLE_SIGNATURE) + + +typedef +EFI_STATUS +(EFIAPI *PEI_CORE_ENTRY_POINT) ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +// +// Union of temporarily used function pointers (to save stack space) +// +typedef union { + PEI_CORE_ENTRY_POINT PeiCore; + EFI_PEIM_ENTRY_POINT PeimEntry; + EFI_PEIM_NOTIFY_ENTRY_POINT PeimNotifyEntry; + EFI_DXE_IPL_PPI *DxeIpl; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + VOID *Raw; +} PEI_CORE_TEMP_POINTERS; + + +// +// Main PEI entry +// +EFI_STATUS +EFIAPI +PeiMain ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + This function never returns + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + +--*/ +; + + +// +// Dispatcher support functions +// + +EFI_STATUS +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression, + IN OUT BOOLEAN *Runnable + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +; + + +EFI_STATUS +PeiDispatcher ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_DISPATCH_DATA *DispatchData + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR + PrivateData - Pointer to the private data passed in from caller + DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data. + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +; + + +VOID +InitializeDispatcherData ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + PeiStartupDescriptor - Information and services provided by SEC phase. + + +Returns: + + None + +--*/ +; + + +EFI_STATUS +FindNextPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + PeimFileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +BOOLEAN +Dispatched ( + IN UINT8 CurrentPeim, + IN UINT64 DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine checks to see if a particular PEIM has been dispatched during + the PEI core dispatch. + +Arguments: + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + TRUE if PEIM already dispatched + FALSE if not + +--*/ +; + +VOID +SetDispatched ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 CurrentPeim, + OUT UINT64 *DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine sets a PEIM as having been dispatched once its entry + point has been invoked. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + None + +--*/ +; + +BOOLEAN +DepexSatisfied ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CurrentPeimAddress + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + PeiServices - The PEI Service Table + CurrentPeimAddress - Address of the PEIM Firmware File under investigation + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +; + +VOID +SwitchCoreStacks ( + IN VOID *EntryPoint, + IN UINTN Parameter1, + IN UINTN Parameter2, + IN VOID *NewStack + ) +/*++ + +Routine Description: + + Routine for PEI switching stacks. + +Arguments: + + EntryPoint - Entry point with new stack. + Parameter1 - First parameter for entry point. + Parameter2 - Second parameter for entry point. + NewStack - Pointer to new stack. + +Returns: + + None + +--*/ +; + + +#ifdef EFI64 + // + // In Ipf we should make special changes for the PHIT pointers to support + // recovery boot in cache mode. + // +#define SWITCH_TO_CACHE_MODE(CoreData) SwitchToCacheMode(CoreData) +#define CACHE_MODE_ADDRESS_MASK 0x7FFFFFFFFFFFFFFF +VOID +SwitchToCacheMode ( + IN PEI_CORE_INSTANCE *CoreData +) +/*++ + +Routine Description: + + Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR. + +Arguments: + + CoreData - The PEI core Private Data + +Returns: + +--*/ +; + +#else + +#define SWITCH_TO_CACHE_MODE(CoreData) + +#endif + +// +// PPI support functions +// +VOID +InitializePpiServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +; + +VOID +ConvertPpiPointers ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Migrate the Hob list from the CAR stack to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +; + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +; + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +; + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ +; + +VOID +DispatchNotify ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ +; + +// +// Boot mode support functions +// +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +; + +// +// Security support functions +// +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +; + +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ) +/*++ + +Routine Description: + + Provide a callout to the OEM FV verification service. + +Arguments: + + CurrentFvAddress - Pointer to the FV under investigation. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + + +EFI_STATUS +VerifyPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +; + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +; + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +; + + +// +// FFS Fw Volume support functions +// +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FfsFileHeader - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFvFindNextVolume ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + + Return the BFV location + + BugBug -- Move this to the location of this code to where the + other FV and FFS support code lives. + Also, update to use FindFV for instances #'s >= 1. + +Arguments: + + PeiServices - The PEI core services table. + Instance - Instance of FV to find + FwVolHeader - Pointer to contain the data to return + +Returns: + Pointer to the Firmware Volume instance requested + + EFI_INVALID_PARAMETER - FwVolHeader is NULL + + EFI_SUCCESS - Firmware volume instance successfully found. + +--*/ +; + +// +// Memory support functions +// +VOID +InitializeMemoryServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of allocation. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +; + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +; + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +; + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *PeimFileHeader, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Get entry point of a Peim file. + +Arguments: + + PeiServices - Calling context. + + PeimFileHeader - Peim file's header. + + EntryPoint - Entry point of that Peim file. + +Returns: + + Status code. + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiCoreResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +; +//*** AMI PORTING BEGIN ***// +//This function is used to update LoadedImage PPI information +//LoadedImage PPI is defined in PI 1.0 specification +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +); + +#include <AmiPeiLib.h> +//*** AMI PORTING END *****// +#endif diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiMain.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiMain.c new file mode 100644 index 0000000..bfcdbe4 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiMain.c @@ -0,0 +1,405 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PeiMain.c + +Abstract: + + Pei Core Main Entry Point + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_PPI_DEFINITION (MemoryDiscovered) +#include EFI_PPI_DEFINITION (FindFv) +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) +#include EFI_GUID_DEFINITION (StatusCode) + +// +//CAR is filled with this initial value during SEC phase +// +#define INIT_CAR_VALUE 0x5AA55AA5 + +#ifdef EFI_PEI_PERFORMANCE + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ); + +#endif + +//*** AMI PORTING BEGIN ***// +VOID InitParts(VOID* p1, VOID*p2); +VOID InitPartsMem(VOID* p1, VOID*p2); +VOID ProcessLoadHob(EFI_PEI_SERVICES **PeiServices); +VOID AmiInitParts(IN EFI_PEI_SERVICES **PeiServices, VOID* InitFunction); +//*** AMI PORTING END *****// + +static EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiMemoryDiscoveredPpiGuid, + NULL +}; + +// +// Pei Core Module Variables +// +// +static EFI_PEI_SERVICES mPS = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + PeiInstallPpi, + PeiReInstallPpi, + PeiLocatePpi, + PeiNotifyPpi, + + PeiGetBootMode, + PeiSetBootMode, + + PeiGetHobList, + PeiCreateHob, + + PeiFvFindNextVolume, + PeiFfsFindNextFile, + PeiFfsFindSectionData, + + PeiInstallPeiMemory, + PeiAllocatePages, + PeiAllocatePool, + PeiCoreCopyMem, + PeiCoreSetMem, + + PeiReportStatusCode, + +//*** AMI PORTING BEGIN ***// +// This is a bug fix. +// In accordance with PEI CIS 0.91 +// this structure has been extended with two more pointers. +// PeiCoreResetSystem + PeiCoreResetSystem, + NULL, + NULL +//*** AMI PORTING END *****// +}; + +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ); + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +// +// Main entry point to the PEI Core +// +EFI_PEI_CORE_ENTRY_POINT (PeiMain) + +EFI_STATUS +EFIAPI +PeiMain ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + This function never returns + +--*/ +{ + return PeiCore (PeiStartupDescriptor, NULL); +} + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + EFI_NOT_FOUND - Never reach + +--*/ +{ + PEI_CORE_INSTANCE PrivateData; + EFI_STATUS Status; + PEI_CORE_TEMP_POINTERS TempPtr; + PEI_CORE_DISPATCH_DATA *DispatchData; + + +#ifdef EFI_PEI_PERFORMANCE + UINT64 mTick; + + mTick = 0; + if (OldCoreData == NULL) { + GetTimerValue (&mTick); + } +#endif + + + // + // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory() + // the 63-bit of address is set to 1. + // + SWITCH_TO_CACHE_MODE (OldCoreData); + + if (OldCoreData != NULL) { + PeiCoreCopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE)); + } else { + PeiCoreSetMem (&PrivateData, sizeof (PEI_CORE_INSTANCE), 0); + } + + PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; + PrivateData.PS = &mPS; + + // + // Mm7 stored PeiServicesTablePointer in EdkII Glue Library + // Update Mm7 now + // +//*** AMI PORTING BEGIN ***// +//#if (defined(EFI32)) || (defined(EFIX64)) +#ifndef EFI64 +//*** AMI PORTING END *****// + AsmWriteMm7 ((UINT64)(UINTN)(&PrivateData.PS)); +#endif + + InitializeMemoryServices (&PrivateData.PS, PeiStartupDescriptor, OldCoreData); + + InitializePpiServices (&PrivateData.PS, OldCoreData); + + InitializeSecurityServices (&PrivateData.PS, OldCoreData); + + InitializeDispatcherData (&PrivateData.PS, OldCoreData, PeiStartupDescriptor); + + if (OldCoreData != NULL) { + + PEI_PERF_END (&PrivateData.PS,L"PreMem", NULL, 0); + PEI_PERF_START (&PrivateData.PS,L"PostMem", NULL, 0); + + // + // The following code dumps out interesting cache as RAM usage information + // so we can keep tabs on how the cache as RAM is being utilized. The + // PEI_DEBUG_CODE macro is used to prevent this code from being compiled + // on a debug build. + // + PEI_DEBUG_CODE ( + { + UINTN *StackPointer; + UINTN StackValue; + + StackValue = INIT_CAR_VALUE; + for (StackPointer = (UINTN *) OldCoreData->MaxTopOfCarHeap; + ((UINTN) StackPointer < ((UINTN) OldCoreData->BottomOfCarHeap + OldCoreData->SizeOfCacheAsRam)) + && StackValue == INIT_CAR_VALUE; + StackPointer++) { + StackValue = *StackPointer; + } + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", OldCoreData->SizeOfCacheAsRam)); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR stack ever used: %d bytes.\n", + ((UINTN) OldCoreData->TopOfCarHeap - (UINTN) StackPointer) + ) + ); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR heap used: %d bytes.\n", + ((UINTN) OldCoreData->HobList.HandoffInformationTable->EfiFreeMemoryBottom - + (UINTN) OldCoreData->HobList.Raw) + ) + ); + } + ) + +//*** AMI PORTING BEGIN ***// + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; +//*** AMI PORTING END *****// + + // + // Alert any listeners that there is permanent memory available + // + PEI_PERF_START (&PrivateData.PS,L"DisMem", NULL, 0); + Status = PeiInstallPpi (&PrivateData.PS, &mMemoryDiscoveredPpi); + PEI_PERF_END (&PrivateData.PS,L"DisMem", NULL, 0); + + } else { + + // + // Report Status Code EFI_SW_PC_INIT + // + PEI_REPORT_STATUS_CODE ( + &(PrivateData.PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT, + 0, + NULL, + NULL + ); + + // + // If first pass, start performance measurement. + // + PEI_PERF_START (&PrivateData.PS,L"PreMem", NULL, mTick); + + // + // If SEC provided any PPI services to PEI, install them. + // + if (PeiStartupDescriptor->DispatchTable != NULL) { + Status = PeiInstallPpi (&PrivateData.PS, PeiStartupDescriptor->DispatchTable); + + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + } +//*** AMI PORTING BEGIN ***// +{ + static EFI_GUID gEfiPeiLoadedImagePpiGuid = EFI_PEI_LOADED_IMAGE_PPI_GUID; + static EFI_PEI_PPI_DESCRIPTOR LoadedImagePpiDesc = + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiLoadedImagePpiGuid, NULL + }; + PeiAllocatePool(&PrivateData.PS,sizeof(EFI_PEI_PPI_DESCRIPTOR),&PrivateData.LoadedImage); + *PrivateData.LoadedImage = LoadedImagePpiDesc; + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; + PeiInstallPpi (&PrivateData.PS, PrivateData.LoadedImage); +} +//*** AMI PORTING END *****// + } + + DispatchData = &PrivateData.DispatchData; + + // + // Call PEIM dispatcher + // +//*** AMI PORTING BEGIN ***// + if (OldCoreData != NULL) { + AmiInitParts(&PrivateData.PS, InitPartsMem); + ProcessLoadHob(&PrivateData.PS); + } else { + AmiInitParts(&PrivateData.PS, InitParts); + } +//*** AMI PORTING END *****// + PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData); + + // + // Check if InstallPeiMemory service was called. + // +//*** AMI PORTING BEGIN ***// + //report MEMORY_NOT_INSTALLED error + if (!PrivateData.PeiMemoryInstalled) + PEI_ERROR_CODE(&PrivateData.PS, PEI_MEMORY_NOT_INSTALLED, EFI_ERROR_MAJOR); +// PEI_ASSERT(&PrivateData.PS, PrivateData.PeiMemoryInstalled == TRUE); +//*** AMI PORTING END *****// + + PEI_PERF_END (&PrivateData.PS, L"PostMem", NULL, 0); + + Status = PeiLocatePpi ( + &PrivateData.PS, + &gEfiDxeIplPpiGuid, + 0, + NULL, + &TempPtr.DxeIpl + ); +//*** AMI PORTING BEGIN ***// + //report DXEIPL_NOT_FOUND error + if (EFI_ERROR(Status)) + PEI_ERROR_CODE(&PrivateData.PS, PEI_DXEIPL_NOT_FOUND, EFI_ERROR_MAJOR); +// ASSERT_PEI_ERROR (&PrivateData.PS, Status); +//*** AMI PORTING END *****// + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "DXE IPL Entry(%X)\n",TempPtr.DxeIpl->Entry)); + Status = TempPtr.DxeIpl->Entry ( + TempPtr.DxeIpl, + &PrivateData.PS, +//*** AMI PORTING BEGIN ***// +// PEI CIS defines parameter as EFI_PEI_HOB_POINTERS, but +// EFI_PEI_HOB_POINTERS is not defined in PEI CIS. +// Until this is fixed PEI.h defines this parameter as VOID* +// PrivateData.HobList + PrivateData.HobList.Raw +//*** AMI PORTING END *****// + ); +//*** AMI PORTING BEGIN ***// + // If DXE IPL returned control, let's call dispatcher again + // DXE IPL might have dicovered new FV or have changed a boot mode + + // reset previous bitmap so that the dispatcher will attempt to execute any new PEIMs + DispatchData->PreviousPeimBitMap = 0; + // dispatch + PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData); + // DXE IPL + Status = TempPtr.DxeIpl->Entry ( + TempPtr.DxeIpl, + &PrivateData.PS, + PrivateData.HobList.Raw + ); +//*** AMI PORTING END *****// + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + return EFI_NOT_FOUND; +} + +//*** AMI PORTING BEGIN ***// +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +) +{ + PEI_CORE_INSTANCE *Private = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + Private->LoadedImagePpi.ImageAddress = ImageAddress; + Private->LoadedImagePpi.ImageSize = ImageSize; + Private->LoadedImagePpi.FileHandle = FileHandle; + PeiReInstallPpi(PeiServices,Private->LoadedImage,Private->LoadedImage); +} +//*** AMI PORTING END *****//
\ No newline at end of file diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Ppi.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Ppi.c new file mode 100644 index 0000000..62077e3 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Ppi.c @@ -0,0 +1,673 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Ppi.c + +Abstract: + + EFI PEI Core PPI services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +VOID +InitializePpiServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + if (OldCoreData == NULL) { + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1; + } + + return; +} + +VOID +ConvertPpiPointers ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Convert PPI pointers after the Hob list was migrated from the CAR stack + to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + + None. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT8 Index; + PEI_PPI_LIST_POINTERS *PpiPointer; + UINTN Fixup; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob; + + for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) { + if (Index < PrivateData->PpiData.PpiListEnd || + Index > PrivateData->PpiData.NotifyListEnd) { + PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index]; + + if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the PEIM descriptor from the old HOB heap + // to the relocated HOB heap. + // + PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup); + + // + // Only when the PEIM descriptor is in the old HOB should it be necessary + // to try to convert the pointers in the PEIM descriptor + // + + if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the GUID in the PPI or NOTIFY descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup); + } + + // + // Assume that no code is located in the temporary memory, so the pointer to + // the notification function in the NOTIFY descriptor needs not be converted. + // + if (Index < PrivateData->PpiData.PpiListEnd && + (UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom && + (UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) { + // + // Convert the pointer to the PPI interface structure in the PPI descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup); + } + } + } + } +} + + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN LastCallbackInstall; + + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Index = PrivateData->PpiData.PpiListEnd; + LastCallbackInstall = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the NotifyList + // + if (Index == PrivateData->PpiData.NotifyListEnd + 1) { + return EFI_OUT_OF_RESOURCES; + } + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PrivateData->PpiData.PpiListEnd = LastCallbackInstall; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); +//*** AMI PORTING END *****// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = PpiList; + PrivateData->PpiData.PpiListEnd++; + + // + // Continue until the end of the PPI List. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + PpiList++; + Index++; + } + + // + // Dispatch any callback level notifies for newly installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCallbackInstall, + PrivateData->PpiData.PpiListEnd, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) { + break; + } + } + if (Index == PrivateData->PpiData.PpiListEnd) { + return EFI_NOT_FOUND; + } + + // + // Remove the old PPI from the database, add the new one. + // +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); +//*** AMI PORTING END *****// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = NewPpi; + + // + // Dispatch any callback level notifies for the newly installed PPI. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) { + if (Instance == 0) { + + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + + return EFI_SUCCESS; + } + Instance--; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN NotifyIndex; + INTN LastCallbackNotify; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr; + UINTN NotifyDispatchCount; + + + NotifyDispatchCount = 0; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Index = PrivateData->PpiData.NotifyListEnd; + LastCallbackNotify = Index; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the PpiList + // + if (Index == PrivateData->PpiData.PpiListEnd - 1) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + PrivateData->PpiData.NotifyListEnd = LastCallbackNotify; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyDispatchCount ++; + } + + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyList; + + PrivateData->PpiData.NotifyListEnd--; + PEI_DEBUG((PeiServices, EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + // + // Go the next descriptor. Remember the NotifyList moves down. + // + NotifyList++; + Index--; + } + + // + // If there is Dispatch Notify PPI installed put them on the bottom + // + if (NotifyDispatchCount > 0) { + for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) { + if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify; + + for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){ + PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify; + } + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr; + PrivateData->PpiData.DispatchListEnd--; + } + } + + LastCallbackNotify -= NotifyDispatchCount; + } + + // + // Dispatch any callback level notifies for all previously installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiListEnd, + LastCallbackNotify, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN TempValue; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + + while (TRUE) { + // + // Check if the PEIM that was just dispatched resulted in any + // Notifies getting installed. If so, go process any dispatch + // level Notifies that match the previouly installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // DispatchListEnd (with NotifyPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) { + TempValue = PrivateData->PpiData.DispatchListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + 0, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.LastDispatchedNotify, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedNotify = TempValue; + } + + + // + // Check if the PEIM that was just dispatched resulted in any + // PPIs getting installed. If so, go process any dispatch + // level Notifies that match the installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // PpiListEnd (with InstallPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) { + TempValue = PrivateData->PpiData.PpiListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.PpiListEnd, + MAX_PPI_DESCRIPTORS-1, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedInstall = TempValue; + } + + if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) { + break; + } + } + return; +} + +VOID +DispatchNotify ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Remember that Installs moves up and Notifies moves down. + // + for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) { + NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify; + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) { + PEI_DEBUG ( + ( + PeiServices, + EFI_D_INFO, + "Notify: PPI Guid: %g, Peim notify entry point: %x\n", + SearchGuid, + NotifyDescriptor->Notify + ) + ); + NotifyDescriptor->Notify ( + PeiServices, + NotifyDescriptor, + (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi + ); + } + } + } + + return; +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Reset.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Reset.c new file mode 100644 index 0000000..bbfd4a9 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Reset.c @@ -0,0 +1,77 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Reset.c + +Abstract: + + Pei Core Reset System Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (Reset) + +EFI_STATUS +EFIAPI +PeiCoreResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +{ + EFI_STATUS Status; + PEI_RESET_PPI *ResetPpi; + + Status = PeiLocatePpi ( + PeiServices, + &gPeiResetPpiGuid, + 0, + NULL, + &ResetPpi + ); + + // + // LocatePpi returns EFI_NOT_FOUND on error + // + if (!EFI_ERROR (Status)) { + return ResetPpi->ResetSystem (PeiServices); + } +//*** AMI PORTING BEGIN ***// + //Report error + PEI_ERROR_CODE(PeiServices,PEI_RESET_NOT_AVAILABLE,EFI_ERROR_MINOR); +//*** AMI PORTING END *****// + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Security.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Security.c new file mode 100644 index 0000000..928e21a --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Security.c @@ -0,0 +1,194 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Security.c + +Abstract: + + EFI PEI Core Security services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include EFI_PPI_DEFINITION (Security) + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiSecurityPpiGuid, + SecurityPpiNotifyCallback +}; + +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +{ + if (OldCoreData == NULL) { + PeiNotifyPpi (PeiServices, &mNotifyList); + } + return; +} + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Provide a callback for when the security PPI is installed. + +Arguments: + + PeiServices - The PEI core services table. + NotifyDescriptor - The descriptor for the notification event. + Ppi - Pointer to the PPI in question. + +Returns: + + EFI_SUCCESS - The function is successfully processed. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + // + // Get PEI Core private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // If there isn't a security PPI installed, use the one from notification + // + if (PrivateData->PrivateSecurityPpi == NULL) { + PrivateData->PrivateSecurityPpi = (PEI_SECURITY_PPI *)Ppi; + } + return EFI_SUCCESS; +} + +EFI_STATUS +VerifyPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_STATUS Status; + UINT32 AuthenticationStatus; + BOOLEAN StartCrisisRecovery; + + // + // Set a default authentication state + // + AuthenticationStatus = 0; + + // + // get security PPI instance from PEI private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (PrivateData->PrivateSecurityPpi == NULL) { + Status = EFI_NOT_FOUND; + } else { + // + // Check to see if the image is OK + // + Status = PrivateData->PrivateSecurityPpi->AuthenticationState ( + PeiServices, + PrivateData->PrivateSecurityPpi, + AuthenticationStatus, + CurrentPeimAddress, + &StartCrisisRecovery + ); + if (StartCrisisRecovery) { + Status = EFI_SECURITY_VIOLATION; + } + } + return Status; +} + + +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ) +/*++ + +Routine Description: + + Verify a Firmware volume + +Arguments: + + CurrentFvAddress - Pointer to the current Firmware Volume under consideration + +Returns: + + EFI_SUCCESS - Firmware Volume is legal + EFI_SECURITY_VIOLATION - Firmware Volume fails integrity test + +--*/ +{ + // + // Right now just pass the test. Future can authenticate and/or check the + // FV-header or other metric for goodness of binary. + // + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/StatusCode.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/StatusCode.c new file mode 100644 index 0000000..26cac94 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/StatusCode.c @@ -0,0 +1,102 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + StatusCode.c + +Abstract: + + Pei Core Status Code Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (StatusCode) + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +{ + EFI_STATUS Status; + PEI_STATUS_CODE_PPI *StatusCodePpi; + + + // + //Locate StatusCode Ppi. + // + Status = PeiLocatePpi ( + PeiServices, + &gPeiStatusCodePpiGuid, + 0, + NULL, + &StatusCodePpi + ); + + if (!EFI_ERROR (Status)) { + Status = StatusCodePpi->ReportStatusCode ( + PeiServices, + CodeType, + Value, + Instance, + CallerId, + Data + ); + + + return Status; + + } + + + return EFI_NOT_AVAILABLE_YET; +} + + + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.c new file mode 100644 index 0000000..ff3b2e4 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.c @@ -0,0 +1,268 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + dependency.c + +Abstract: + + PEI Dispatcher Dependency Evaluator + + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine + if a driver can be scheduled for execution. The criteria for + schedulability is that the dependency expression is satisfied. + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include "EfiDependency.h" +#include "Dependency.h" + +STATIC +BOOLEAN +IsPpiInstalled ( + IN EFI_PEI_SERVICES **PeiServices, + IN EVAL_STACK_ENTRY *Stack + ) +/*++ + +Routine Description: + + This routine determines if a PPI has been installed. + The truth value of a GUID is determined by if the PPI has + been published and can be queried from the PPI database. + +Arguments: + PeiServices - The PEI core services table. + Stack - Reference to EVAL_STACK_ENTRY that contains PPI GUID to check + +Returns: + + True if the PPI is already installed. + False if the PPI has yet to be installed. + +--*/ +{ + VOID *PeiInstance; + EFI_STATUS Status; + EFI_GUID PpiGuid; + + // + // If there is no GUID to evaluate, just return current result on stack. + // + if (Stack->Operator == NULL) { + return Stack->Result; + } + + // + // Copy the Guid into a locale variable so that there are no + // possibilities of alignment faults for cross-compilation + // environments such as Intel?Itanium(TM). + // + PeiCoreCopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID)); + + // + // Check if the PPI is installed. + // + Status = (**PeiServices).LocatePpi( + PeiServices, + &PpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + &PeiInstance // PPI + ); + + if (EFI_ERROR(Status)) { + return FALSE; + } + + return TRUE; +} + + +EFI_STATUS +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression, + OUT BOOLEAN *Runnable + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +{ + EFI_STATUS Status; + DEPENDENCY_EXPRESSION_OPERAND *Iterator; + EVAL_STACK_ENTRY *StackPtr; + EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE]; + + Status = EFI_SUCCESS; + Iterator = DependencyExpression; + *Runnable = FALSE; + + StackPtr = &EvalStack[0]; + + while (TRUE) { + + switch (*(Iterator++)) { + + // + // For performance reason we put the frequently used items in front of + // the rarely used items + // + + case (EFI_DEP_PUSH): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return EFI_INVALID_PARAMETER; + } + + // + // Push the pointer to the PUSH opcode operator (pointer to PPI GUID) + // We will evaluate if the PPI is insalled on the POP operation. + // + StackPtr->Operator = (VOID *) Iterator; + Iterator = Iterator + sizeof (EFI_GUID); + StackPtr++; + break; + + case (EFI_DEP_AND): + case (EFI_DEP_OR): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the two POPs for the AND operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did two POPs. + // + if (StackPtr < &EvalStack[2]) { + return EFI_INVALID_PARAMETER; + } + + // + // Evaluate the first POPed operator only. If the operand is + // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the + // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE, + // we don't need to check the second operator, and the result will be + // evaluation of the POPed operator. Otherwise, don't POP the second + // operator since it will now evaluate to the final result on the + // next operand that causes a POP. + // + StackPtr--; + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_AND) { + if (!(IsPpiInstalled (PeiServices, StackPtr))) { + (StackPtr-1)->Result = FALSE; + (StackPtr-1)->Operator = NULL; + } + } else { + if (IsPpiInstalled (PeiServices, StackPtr)) { + (StackPtr-1)->Result = TRUE; + (StackPtr-1)->Operator = NULL; + } + } + break; + + case (EFI_DEP_END): + StackPtr--; + // + // Check to make sure EvalStack is balanced. If not, then there is + // an error in the dependency grammar, so return EFI_INVALID_PARAMETER. + // + if (StackPtr != &EvalStack[0]) { + return EFI_INVALID_PARAMETER; + } + *Runnable = IsPpiInstalled (PeiServices, StackPtr); + return EFI_SUCCESS; + break; + + case (EFI_DEP_NOT): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the POP for the NOT operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did a POP. + // + if (StackPtr < &EvalStack[1]) { + return EFI_INVALID_PARAMETER; + } + (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1)); + (StackPtr-1)->Operator = NULL; + break; + + case (EFI_DEP_TRUE): + case (EFI_DEP_FALSE): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return EFI_INVALID_PARAMETER; + } + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_TRUE) { + StackPtr->Result = TRUE; + } else { + StackPtr->Result = FALSE; + } + StackPtr->Operator = NULL; + StackPtr++; + break; + + default: + // + // The grammar should never arrive here + // + return EFI_INVALID_PARAMETER; + break; + } + } +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.h b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.h new file mode 100644 index 0000000..9df008b --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.h @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + dependency.h + +Abstract: + + This module contains data specific to dependency expressions + and local function prototypes. + +--*/ + +#ifndef _PEI_DEPENDENCY_H_ +#define _PEI_DEPENDENCY_H_ + +#define MAX_GRAMMAR_SIZE 256 + +// +// type definitions +// +typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND; + +typedef struct { + BOOLEAN Result; + VOID *Operator; +} EVAL_STACK_ENTRY; + +#endif |