diff options
Diffstat (limited to 'EDK/Foundation/Core/Pei')
-rw-r--r-- | EDK/Foundation/Core/Pei/BootMode/BootMode.c | 108 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/DebugMask/DebugMask.c | 156 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Dependency/dependency.c | 268 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Dependency/dependency.h | 38 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Dispatcher/Dispatcher.c | 593 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/FwVol/FwVol.c | 484 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Hob/Hob.c | 191 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Ia32/SwitchCoreStacks.asm | 87 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Image/Image.c | 277 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Include/PeiCore.h | 1275 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Memory/MemoryServices.c | 395 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/PeiMain.cif | 24 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/PeiMain.inf | 82 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/PeiMain/PeiMain.c | 321 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Ppi/Ppi.c | 667 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Reset/Reset.c | 73 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/Security/Security.c | 194 | ||||
-rw-r--r-- | EDK/Foundation/Core/Pei/StatusCode/StatusCode.c | 102 |
18 files changed, 5335 insertions, 0 deletions
diff --git a/EDK/Foundation/Core/Pei/BootMode/BootMode.c b/EDK/Foundation/Core/Pei/BootMode/BootMode.c new file mode 100644 index 0000000..782950a --- /dev/null +++ b/EDK/Foundation/Core/Pei/BootMode/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/EDK/Foundation/Core/Pei/DebugMask/DebugMask.c b/EDK/Foundation/Core/Pei/DebugMask/DebugMask.c new file mode 100644 index 0000000..a804eda --- /dev/null +++ b/EDK/Foundation/Core/Pei/DebugMask/DebugMask.c @@ -0,0 +1,156 @@ +/*++ + +Copyright (c) 2009 - 2010, 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: + + DebugMask.c + +Abstract: + + Installs DebugMask PPI. + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include EFI_PPI_CONSUMER (DebugMask) +#include EFI_PPI_DEPENDENCY (Variable) +#include EFI_GUID_DEFINITION (GlobalVariable) + +EFI_STATUS +EFIAPI +DebugMaskNotifyCallback ( + 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, + &gPeiReadOnlyVariablePpiGuid, + DebugMaskNotifyCallback +}; + +VOID +InstallCoreDebugMaskPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Installs DebugMask PPI. + +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 Status; + EFI_DEBUG_MASK_PPI *DebugMaskPpi; + EFI_PEI_PPI_DESCRIPTOR *DebugMaskPpiDesc; + + if (OldCoreData == NULL) { + Status = ((*PeiServices)->AllocatePool) (PeiServices, sizeof (EFI_DEBUG_MASK_PPI), &DebugMaskPpi); + if (EFI_ERROR(Status) || (DebugMaskPpi == NULL)) { + return; + } + + Status = ((*PeiServices)->AllocatePool) (PeiServices, sizeof (EFI_PEI_PPI_DESCRIPTOR), &DebugMaskPpiDesc); + if (EFI_ERROR(Status) || (DebugMaskPpiDesc == NULL)) { + return; + } + + DebugMaskPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + DebugMaskPpiDesc->Guid = &gEfiDebugMaskPpiGuid; + DebugMaskPpiDesc->Ppi = DebugMaskPpi; + + DebugMaskPpi->ImageDebugMask = gErrorLevel; + + Status = (**PeiServices).InstallPpi (PeiServices, DebugMaskPpiDesc); + ASSERT_PEI_ERROR (PeiServices, Status); + if (EFI_ERROR(Status)) { + return; + } + + PeiNotifyPpi (PeiServices, &mNotifyList); + } + return; +} + +EFI_STATUS +EFIAPI +DebugMaskNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Callback function to update DebugMask value + +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. + +--*/ +{ + EFI_STATUS Status; + PEI_READ_ONLY_VARIABLE_PPI *VariableServices; + UINTN DebugMaskSize; + UINT64 DebugMask; + EFI_DEBUG_MASK_PPI *DebugMaskPpi; + + // + // Locate Variable Ppi + // + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiReadOnlyVariablePpiGuid, 0, NULL, &VariableServices); + + if (VariableServices) { + // + // Get L"EFIDebug" Variable + // + DebugMaskSize = sizeof (UINT32); + Status = VariableServices->PeiGetVariable ( + PeiServices, + L"EFIDebug", + &gEfiGlobalVariableGuid, + NULL, + &DebugMaskSize, + &DebugMask + ); + + if (!EFI_ERROR(Status)) { + Status = (*PeiServices)->LocatePpi (PeiServices, &gEfiDebugMaskPpiGuid, 0, NULL, &DebugMaskPpi); + + if (!EFI_ERROR(Status)) { + DebugMaskPpi->ImageDebugMask = (UINTN)DebugMask; + } + } + } + + return Status; +} diff --git a/EDK/Foundation/Core/Pei/Dependency/dependency.c b/EDK/Foundation/Core/Pei/Dependency/dependency.c new file mode 100644 index 0000000..ff3b2e4 --- /dev/null +++ b/EDK/Foundation/Core/Pei/Dependency/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/EDK/Foundation/Core/Pei/Dependency/dependency.h b/EDK/Foundation/Core/Pei/Dependency/dependency.h new file mode 100644 index 0000000..9df008b --- /dev/null +++ b/EDK/Foundation/Core/Pei/Dependency/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 diff --git a/EDK/Foundation/Core/Pei/Dispatcher/Dispatcher.c b/EDK/Foundation/Core/Pei/Dispatcher/Dispatcher.c new file mode 100644 index 0000000..9c9e499 --- /dev/null +++ b/EDK/Foundation/Core/Pei/Dispatcher/Dispatcher.c @@ -0,0 +1,593 @@ +/*++ + +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; + + +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. + // + SwitchCoreStacks ( + 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) || (DepexData == NULL)) { + 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/EDK/Foundation/Core/Pei/FwVol/FwVol.c b/EDK/Foundation/Core/Pei/FwVol/FwVol.c new file mode 100644 index 0000000..5420d90 --- /dev/null +++ b/EDK/Foundation/Core/Pei/FwVol/FwVol.c @@ -0,0 +1,484 @@ +/*++ + +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 { + PEI_ASSERT (PeiServices, (0)); + 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/EDK/Foundation/Core/Pei/Hob/Hob.c b/EDK/Foundation/Core/Pei/Hob/Hob.c new file mode 100644 index 0000000..0d7127c --- /dev/null +++ b/EDK/Foundation/Core/Pei/Hob/Hob.c @@ -0,0 +1,191 @@ +/*++ + +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: + + 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) { + 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/EDK/Foundation/Core/Pei/Ia32/SwitchCoreStacks.asm b/EDK/Foundation/Core/Pei/Ia32/SwitchCoreStacks.asm new file mode 100644 index 0000000..655d43f --- /dev/null +++ b/EDK/Foundation/Core/Pei/Ia32/SwitchCoreStacks.asm @@ -0,0 +1,87 @@ + TITLE SwitchCoreStacks.asm: Core stack switching routine + +;------------------------------------------------------------------------------ +;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: +; +; SwitchCoreStacks.asm +; +;Abstract: +; +; Core stack switching routine, invoked when real system memory is +; discovered and installed. +; +;------------------------------------------------------------------------------ + + .686P + .XMM + .MODEL SMALL + .CODE + +AsmWriteMm7 PROTO C + +AsmWriteMm7 PROC C +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm7 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ + movq mm7, [esp + 4] + ret +AsmWriteMm7 ENDP + +SwitchCoreStacks PROTO C EntryPoint: DWORD, Parameter1: DWORD, Parameter2: DWORD, NewStack: DWORD + +SwitchCoreStacks PROC C EntryPoint: DWORD, Parameter1: DWORD, Parameter2: DWORD, NewStack: DWORD + +;------------------------------------------------------------------------------ +; 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 +; +;---------------------------------------------------- + + mov ebx, Parameter1 + mov edx, Parameter2 + mov ecx, EntryPoint + mov esp, NewStack + + ; First push Parameter2, and then Parameter1. + push edx + push ebx + call ecx + + ret + +SwitchCoreStacks ENDP + +END diff --git a/EDK/Foundation/Core/Pei/Image/Image.c b/EDK/Foundation/Core/Pei/Image/Image.c new file mode 100644 index 0000000..6b67e2d --- /dev/null +++ b/EDK/Foundation/Core/Pei/Image/Image.c @@ -0,0 +1,277 @@ +/*++ + +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: + + 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; +#endif + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + EFI_TE_IMAGE_HEADER *TEImageHeader; + + 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; + } + } + +#ifdef EFI_NT_EMULATOR + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtPeiLoadFileGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + (UINT64 *) EntryPoint + ); + + 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 + 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 + + } else { + // + // 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); + PEI_DEBUG_CODE ( + 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; + } + ) + } + } + } + + 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")); + } + } + ) + + return Status; +} diff --git a/EDK/Foundation/Core/Pei/Include/PeiCore.h b/EDK/Foundation/Core/Pei/Include/PeiCore.h new file mode 100644 index 0000000..ee8a558 --- /dev/null +++ b/EDK/Foundation/Core/Pei/Include/PeiCore.h @@ -0,0 +1,1275 @@ +/*++ + +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 + +extern UINTN gErrorLevel; + +// +//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; + + 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_MAIN_ENTRY_POINT) ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ); + +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 + +--*/ +; + +// +// DebugMask support functions +// +VOID +InstallCoreDebugMaskPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Install DebugMask PPI. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permanent 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. + +--*/ +; + +#endif diff --git a/EDK/Foundation/Core/Pei/Memory/MemoryServices.c b/EDK/Foundation/Core/Pei/Memory/MemoryServices.c new file mode 100644 index 0000000..1e25179 --- /dev/null +++ b/EDK/Foundation/Core/Pei/Memory/MemoryServices.c @@ -0,0 +1,395 @@ +/*++ + +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" + +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; + + PrivateData->BottomOfCarHeap = (VOID *) (((UINTN)(VOID *)(&PrivateData)) + & (~((PeiStartupDescriptor->SizeOfCacheAsRam) - 1))); + PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + PeiStartupDescriptor->SizeOfCacheAsRam); + // + // 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); + + 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); + + 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/EDK/Foundation/Core/Pei/PeiMain.cif b/EDK/Foundation/Core/Pei/PeiMain.cif new file mode 100644 index 0000000..9a527fd --- /dev/null +++ b/EDK/Foundation/Core/Pei/PeiMain.cif @@ -0,0 +1,24 @@ +<component> + name = "PeiMain" + category = ModulePart + LocalRoot = "EDK\Foundation\Core\Pei\" + RefName = "PeiMain" +[files] +"PeiMain.inf" +"BootMode\BootMode.c" +"Dependency\dependency.c" +"Dependency\dependency.h" +"Dispatcher\Dispatcher.c" +"FwVol\FwVol.c" +"Hob\Hob.c" +"Ia32\SwitchCoreStacks.asm" +"Image\Image.c" +"Include\PeiCore.h" +"Memory\MemoryServices.c" +"PeiMain\PeiMain.c" +"Ppi\Ppi.c" +"Reset\Reset.c" +"Security\Security.c" +"StatusCode\StatusCode.c" +"DebugMask\DebugMask.c" +<endComponent> diff --git a/EDK/Foundation/Core/Pei/PeiMain.inf b/EDK/Foundation/Core/Pei/PeiMain.inf new file mode 100644 index 0000000..bf707cc --- /dev/null +++ b/EDK/Foundation/Core/Pei/PeiMain.inf @@ -0,0 +1,82 @@ +#/*++ +# +# 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.inf +# +# Abstract: +# +# Component description file for PeiMain module +# +#--*/ + +[defines] +BASE_NAME = PeiMain +FILE_GUID = 52C05B14-0B98-496c-BC3B-04B50211D680 +COMPONENT_TYPE = PEI_CORE + +[sources.common] + Include\PeiCore.h + BootMode\BootMode.c + DebugMask\DebugMask.c + Dependency\Dependency.c + Dispatcher\Dispatcher.c + FwVol\FwVol.c + Hob\Hob.c + Image\Image.c + Memory\MemoryServices.c + PeiMain\PeiMain.c + Ppi\Ppi.c + Reset\Reset.c + Security\Security.c + StatusCode\StatusCode.c + +[sources.ia32] + ia32\SwitchCoreStacks.asm +[sources.x64] + x64\SwitchCoreStacks.asm + +[sources.ipf] + ipf\SwitchToCacheMode.c + ipf\IpfCpuCore.s + ipf\IpfCpuCore.i + +[includes.common] + $(EDK_SOURCE)\Foundation + $(EDK_SOURCE)\Sample\Platform\Nt32 + $(EDK_SOURCE)\Foundation\Framework + $(EDK_SOURCE)\Foundation\Efi + . + $(EDK_SOURCE)\Foundation\Include + $(EDK_SOURCE)\Foundation\Efi\Include + $(EDK_SOURCE)\Foundation\Framework\Include + $(EDK_SOURCE)\Foundation\Include\IndustryStandard + $(EDK_SOURCE)\Foundation\Core\Dxe + $(EDK_SOURCE)\Foundation\Library\Dxe\Include + $(EDK_SOURCE)\Foundation\Include\Pei + $(EDK_SOURCE)\Foundation\Library\Pei\Include + $(EDK_SOURCE)\Foundation\Core\Pei\Include + $(EDK_SOURCE)\Framework + +[libraries.common] + EdkPpiLib + EdkFrameworkPpiLib + EdkFrameworkGuidLib + PeiHobLib + PeiLib + EfiGuidLib + +[libraries.ia32.nt32] + EdkNt32PpiLib + +[nmake.common] + IMAGE_ENTRY_POINT=PeiMain diff --git a/EDK/Foundation/Core/Pei/PeiMain/PeiMain.c b/EDK/Foundation/Core/Pei/PeiMain/PeiMain.c new file mode 100644 index 0000000..692944c --- /dev/null +++ b/EDK/Foundation/Core/Pei/PeiMain/PeiMain.c @@ -0,0 +1,321 @@ +/*++ + +Copyright (c) 2004 - 2011, 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 FIRMWARE_PERFORMANCE + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ); + +#endif + +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, + + PeiCoreResetSystem +}; + +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 FIRMWARE_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 + // +#if (defined(EFI32)) || (defined(EFIX64)) + AsmWriteMm7 ((UINT64)(UINTN)(&PrivateData.PS)); +#endif + + InitializeMemoryServices (&PrivateData.PS, PeiStartupDescriptor, OldCoreData); + + InitializePpiServices (&PrivateData.PS, OldCoreData); + + InitializeSecurityServices (&PrivateData.PS, OldCoreData); + + PEI_DEBUG_CODE ( + InstallCoreDebugMaskPpi (&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) + ) + ); + } + ) + + // + // 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); + } + } + + DispatchData = &PrivateData.DispatchData; + + // + // Call PEIM dispatcher + // + PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData); + + // + // Check if InstallPeiMemory service was called. + // + PEI_ASSERT(&PrivateData.PS, PrivateData.PeiMemoryInstalled == TRUE); + + PEI_PERF_END (&PrivateData.PS, L"PostMem", NULL, 0); + + Status = PeiLocatePpi ( + &PrivateData.PS, + &gEfiDxeIplPpiGuid, + 0, + NULL, + &TempPtr.DxeIpl + ); + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "DXE IPL Entry\n")); + Status = TempPtr.DxeIpl->Entry ( + TempPtr.DxeIpl, + &PrivateData.PS, + PrivateData.HobList + ); + + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + + return EFI_NOT_FOUND; +} + diff --git a/EDK/Foundation/Core/Pei/Ppi/Ppi.c b/EDK/Foundation/Core/Pei/Ppi/Ppi.c new file mode 100644 index 0000000..ceb2ab2 --- /dev/null +++ b/EDK/Foundation/Core/Pei/Ppi/Ppi.c @@ -0,0 +1,667 @@ +/*++ + +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; + } + + PEI_DEBUG((PeiServices, EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); + 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. + // + PEI_DEBUG((PeiServices, EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); + 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/EDK/Foundation/Core/Pei/Reset/Reset.c b/EDK/Foundation/Core/Pei/Reset/Reset.c new file mode 100644 index 0000000..8cb752c --- /dev/null +++ b/EDK/Foundation/Core/Pei/Reset/Reset.c @@ -0,0 +1,73 @@ +/*++ + +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); + } + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/EDK/Foundation/Core/Pei/Security/Security.c b/EDK/Foundation/Core/Pei/Security/Security.c new file mode 100644 index 0000000..928e21a --- /dev/null +++ b/EDK/Foundation/Core/Pei/Security/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/EDK/Foundation/Core/Pei/StatusCode/StatusCode.c b/EDK/Foundation/Core/Pei/StatusCode/StatusCode.c new file mode 100644 index 0000000..26cac94 --- /dev/null +++ b/EDK/Foundation/Core/Pei/StatusCode/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; +} + + + |