summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Core/Pei
diff options
context:
space:
mode:
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-04 07:51:48 +0000
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-04 07:51:48 +0000
commit192f6d4c29fa0dd595b8d5a36bd2078e1474aa4e (patch)
tree5f0afdc001df93627963ec0d4a94d8d2e388ffb8 /MdeModulePkg/Core/Pei
parent6afbfebff49d81d833c08f94aaa2187b8a034525 (diff)
downloadedk2-platforms-192f6d4c29fa0dd595b8d5a36bd2078e1474aa4e.tar.xz
Add PeiCore module for enabling NT32Pkg, please attention this PeiCore does follows PI specification except some FV definitions.
Also the old definition of MdeModulePkg/Include/Ppi/LoadFile.h and EFI_PEI_STARTUP_DESCRIPTOR in MdePkg/Include/PiPei.h will be removed when enabling PI. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3029 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Core/Pei')
-rw-r--r--MdeModulePkg/Core/Pei/BootMode/BootMode.c111
-rw-r--r--MdeModulePkg/Core/Pei/CommonHeader.h44
-rw-r--r--MdeModulePkg/Core/Pei/Dependency/dependency.c267
-rw-r--r--MdeModulePkg/Core/Pei/Dependency/dependency.h43
-rw-r--r--MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c543
-rw-r--r--MdeModulePkg/Core/Pei/Dispatcher/Stack.c55
-rw-r--r--MdeModulePkg/Core/Pei/FwVol/FwVol.c479
-rw-r--r--MdeModulePkg/Core/Pei/Hob/Hob.c197
-rw-r--r--MdeModulePkg/Core/Pei/Image/Image.c272
-rw-r--r--MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.i98
-rw-r--r--MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.s197
-rw-r--r--MdeModulePkg/Core/Pei/Ipf/IpfPeiMain.h57
-rw-r--r--MdeModulePkg/Core/Pei/Ipf/Stack.c63
-rw-r--r--MdeModulePkg/Core/Pei/Ipf/SwitchToCacheMode.c76
-rw-r--r--MdeModulePkg/Core/Pei/Memory/MemoryServices.c326
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.h1147
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.inf146
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.msa117
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain/PeiMain.c251
-rw-r--r--MdeModulePkg/Core/Pei/Ppi/Ppi.c663
-rw-r--r--MdeModulePkg/Core/Pei/Reset/Reset.c73
-rw-r--r--MdeModulePkg/Core/Pei/Security/Security.c199
-rw-r--r--MdeModulePkg/Core/Pei/StatusCode/StatusCode.c100
23 files changed, 5524 insertions, 0 deletions
diff --git a/MdeModulePkg/Core/Pei/BootMode/BootMode.c b/MdeModulePkg/Core/Pei/BootMode/BootMode.c
new file mode 100644
index 0000000000..0576ab0926
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/BootMode/BootMode.c
@@ -0,0 +1,111 @@
+/*++
+
+Copyright (c) 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:
+
+ BootMode.c
+
+Abstract:
+
+ EFI PEI Core Boot Mode services
+
+
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.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/MdeModulePkg/Core/Pei/CommonHeader.h b/MdeModulePkg/Core/Pei/CommonHeader.h
new file mode 100644
index 0000000000..dc64dcad61
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/CommonHeader.h
@@ -0,0 +1,44 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2006 - 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.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+#include <PiPei.h>
+#include <FrameworkPei.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Ppi/DxeIpl.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/FindFv.h>
+#include <Ppi/StatusCode.h>
+#include <Ppi/Security.h>
+#include <Ppi/Reset.h>
+#include <Ppi/LoadFile.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/PeiCoreEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+
+#endif
diff --git a/MdeModulePkg/Core/Pei/Dependency/dependency.c b/MdeModulePkg/Core/Pei/Dependency/dependency.c
new file mode 100644
index 0000000000..ec3c68b137
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Dependency/dependency.c
@@ -0,0 +1,267 @@
+/*++
+
+Copyright (c) 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:
+
+ 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 common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.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).
+ //
+ CopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID));
+
+ //
+ // Check if the PPI is installed.
+ //
+ Status = PeiServicesLocatePpi(
+ &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.
+--*/
+{
+ DEPENDENCY_EXPRESSION_OPERAND *Iterator;
+ EVAL_STACK_ENTRY *StackPtr;
+ EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE];
+
+ 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/MdeModulePkg/Core/Pei/Dependency/dependency.h b/MdeModulePkg/Core/Pei/Dependency/dependency.h
new file mode 100644
index 0000000000..2ac2ddb17b
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Dependency/dependency.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 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:
+
+ dependency.h
+
+Abstract:
+
+ This module contains data specific to dependency expressions
+ and local function prototypes.
+
+--*/
+
+#ifndef _PEI_DEPENDENCY_H_
+#define _PEI_DEPENDENCY_H_
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.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/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
new file mode 100644
index 0000000000..15b23604b6
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -0,0 +1,543 @@
+/*++
+
+Copyright (c) 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:
+
+ Dispatcher.c
+
+Abstract:
+
+ EFI PEI Core dispatch services
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+STATIC
+VOID *
+TransferOldDataToNewDataRange (
+ IN PEI_CORE_INSTANCE *PrivateData
+ );
+
+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;
+ VOID *TopOfStack;
+ //
+ // Debug data for uninstalled Peim list
+ //
+ EFI_GUID DebugFoundPeimList[32];
+ EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
+
+ //
+ // 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) {
+
+ DEBUG_CODE_BEGIN ();
+
+ //
+ // Fill list of found Peims for later list of those not installed
+ //
+ CopyMem (
+ &DebugFoundPeimList[DispatchData->CurrentPeim],
+ &DispatchData->CurrentPeimAddress->Name,
+ sizeof (EFI_GUID)
+ );
+
+ DEBUG_CODE_END ();
+
+ 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.
+ //
+ PERF_START (
+ (VOID *) (UINTN) (DispatchData->CurrentPeimAddress),
+ "PEIM",
+ NULL,
+ 0
+ );
+
+ //
+ // BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE
+ //
+ ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress;
+
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN,
+ (VOID *)(&ExtendedData),
+ sizeof (ExtendedData)
+ );
+
+ //
+ // Is this a authentic image
+ //
+ Status = VerifyPeim (
+ &PrivateData->PS,
+ DispatchData->CurrentPeimAddress
+ );
+
+ if (Status != EFI_SECURITY_VIOLATION) {
+
+ //
+ // BUGBUG: Before enable PI, we need cast EFI_FFS_FILE_HEADER* to EFI_PEI_FILE_HANDLE*
+ // Because we use new MdePkg's definition, but they are binary compatible in fact.
+ //
+ Status = TempPtr.PeimEntry (
+ (EFI_PEI_FILE_HANDLE*)DispatchData->CurrentPeimAddress,
+ &PrivateData->PS
+ );
+ }
+
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END,
+ (VOID *)(&ExtendedData),
+ sizeof (ExtendedData)
+ );
+
+ PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 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 = (PEI_CORE_ENTRY_POINT)PeiCore;
+ PrivateDataInMem = (UINTN) TransferOldDataToNewDataRange (PrivateData);
+ ASSERT (PrivateDataInMem != 0);
+ //
+ // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT
+ //
+ TopOfStack = (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - CPU_STACK_ALIGNMENT);
+ TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
+
+ PeiSwitchStacks (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)TempPtr.Raw,
+ PeiStartupDescriptor,
+ (VOID*)PrivateDataInMem,
+ TopOfStack,
+ (VOID*)(UINTN)PrivateData->StackBase
+ );
+ }
+ }
+ }
+ }
+ 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 = PeiServicesLocatePpi (
+ &gEfiFindFvPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&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) &
+ ((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;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Debug data for uninstalled Peim list
+ //
+ UINT32 DebugNotDispatchedBitmap;
+ UINT8 DebugFoundPeimPoint;
+
+ DebugFoundPeimPoint = 0;
+ //
+ // Get bitmap of Peims that were not dispatched,
+ //
+
+ DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1));
+ //
+ // Scan bitmap of Peims not installed and print GUIDS
+ //
+ while (DebugNotDispatchedBitmap != 0) {
+ if ((DebugNotDispatchedBitmap & 1) != 0) {
+ DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n",
+ &DebugFoundPeimList[DebugFoundPeimPoint]
+ ));
+ }
+ DebugFoundPeimPoint++;
+ DebugNotDispatchedBitmap >>= 1;
+ }
+
+ DEBUG_CODE_END ();
+
+ 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 UINT32 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 & (1 << CurrentPeim)) != 0);
+}
+
+VOID
+SetDispatched (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT8 CurrentPeim,
+ OUT UINT32 *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
+ //
+ ASSERT (CurrentPeim < (sizeof (*DispatchedPeimBitMap) * 8));
+ *DispatchedPeimBitMap |= (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 = PeiServicesFfsFindSectionData (
+ EFI_SECTION_PEI_DEPEX,
+ CurrentPeimAddress,
+ (VOID **)&DepexData
+ );
+ //
+ // If there is no DEPEX, assume the module can be executed
+ //
+ if (EFI_ERROR (Status)) {
+ return TRUE;
+ }
+
+ //
+ // Evaluate a given DEPEX
+ //
+ Status = PeimDispatchReadiness (
+ PeiServices,
+ DepexData,
+ &Runnable
+ );
+
+ return Runnable;
+}
+
+STATIC
+VOID *
+TransferOldDataToNewDataRange (
+ IN PEI_CORE_INSTANCE *PrivateData
+ )
+/*++
+
+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
+
+Returns:
+
+ Pointer to the PrivateData once the private data has been transferred to permanent memory
+
+--*/
+{
+ //
+ //Build private HOB to PEI core to transfer old NEM-range data to new NEM-range
+ //
+ return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE));
+}
+
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Stack.c b/MdeModulePkg/Core/Pei/Dispatcher/Stack.c
new file mode 100644
index 0000000000..8895cae4d1
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Stack.c
@@ -0,0 +1,55 @@
+/** @file
+ PeiSwitchStacks() function for PEI dispatcher.
+
+ Copyright (c) 2006, Intel Corporation<BR>
+ 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: String.c
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+/**
+ Transfers control to a function starting with a new stack.
+
+ Transfers control to the function specified by EntryPoint using the new stack
+ specified by NewStack and passing in the parameters specified by Context1 and
+ Context2. Context1 and Context2 are optional and may be NULL. The function
+ EntryPoint must never return.
+
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ @param EntryPoint A pointer to function to call with the new stack.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function.
+ @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
+ Reserved on other architectures.
+
+**/
+VOID
+EFIAPI
+PeiSwitchStacks (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack,
+ IN VOID *NewBsp
+ )
+{
+ SwitchStack (EntryPoint, Context1, Context2, NewStack);
+}
diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.c b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
new file mode 100644
index 0000000000..679825cabc
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
@@ -0,0 +1,479 @@
+/*++
+
+Copyright (c) 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:
+
+ FwVol.c
+
+Abstract:
+
+ Pei Core Firmware File System service routines.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.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_FVB2_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_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_FVB2_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);
+ ASSERT (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 {
+ ASSERT (FALSE);
+ 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);
+ ASSERT (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 (
+ 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 (
+ 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 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.
+
+--*/
+{
+ PEI_CORE_INSTANCE *PrivateData;
+ EFI_STATUS Status;
+ EFI_PEI_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) {
+ *FwVolHeader = PrivateData->DispatchData.BootFvAddress;
+
+
+ return Status;
+ } else {
+ //
+ // Locate all instances of FindFV
+ // Alternately, could use FV HOBs, but the PPI is cleaner
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiFindFvPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&FindFvPpi
+ );
+
+ if (Status != EFI_SUCCESS) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ Status = FindFvPpi->FindFv (
+ FindFvPpi,
+ PeiServices,
+ &LocalInstance,
+ FwVolHeader
+ );
+
+ }
+ }
+ return Status;
+}
diff --git a/MdeModulePkg/Core/Pei/Hob/Hob.c b/MdeModulePkg/Core/Pei/Hob/Hob.c
new file mode 100644
index 0000000000..9128b12e93
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Hob/Hob.c
@@ -0,0 +1,197 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Hob.c
+
+Abstract:
+
+ EFI PEI Core HOB services
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.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
+ //
+
+ DEBUG_CODE_BEGIN ();
+ if (HobList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_END ();
+
+ 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) {
+ DEBUG ((EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length));
+ DEBUG ((EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop));
+ DEBUG ((EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0;
+
+ HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length);
+ HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+ HobEnd++;
+ HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+PeiCoreBuildHobHandoffInfoTable (
+ IN EFI_BOOT_MODE BootMode,
+ IN EFI_PHYSICAL_ADDRESS MemoryBegin,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ Builds a Handoff Information Table HOB
+
+Arguments:
+
+ BootMode - Current Bootmode
+ MemoryBegin - Start Memory Address.
+ MemoryLength - Length of Memory.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *Hob;
+ EFI_HOB_GENERIC_HEADER *HobEnd;
+
+ Hob = (VOID *)(UINTN)MemoryBegin;
+ HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1);
+ Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;
+ Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE);
+ Hob->Header.Reserved = 0;
+
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+
+ Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;
+ Hob->BootMode = BootMode;
+
+ Hob->EfiMemoryTop = MemoryBegin + MemoryLength;
+ Hob->EfiMemoryBottom = MemoryBegin;
+ Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength;
+ Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1);
+ Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c
new file mode 100644
index 0000000000..391290d018
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Image/Image.c
@@ -0,0 +1,272 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Image.c
+
+Abstract:
+
+ Pei Core Load Image Support
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+
+
+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_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi;
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+ EFI_PHYSICAL_ADDRESS ImageEntryPoint;
+ EFI_TE_IMAGE_HEADER *TEImageHeader;
+ UINT16 Machine;
+
+ *EntryPoint = NULL;
+ TEImageHeader = NULL;
+
+ //
+ // Try to find a PE32 section.
+ //
+ Status = PeiServicesFfsFindSectionData (
+ EFI_SECTION_PE32,
+ PeimFileHeader,
+ &Pe32Data
+ );
+ //
+ // If we didn't find a PE32 section, try to find a TE section.
+ //
+ if (EFI_ERROR (Status)) {
+ Status = PeiServicesFfsFindSectionData (
+ EFI_SECTION_TE,
+ PeimFileHeader,
+ (VOID **) &TEImageHeader
+ );
+ if (EFI_ERROR (Status) || TEImageHeader == NULL) {
+ //
+ // There was not a PE32 or a TE section, so assume that it's a Compressed section
+ // and use the LoadFile
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiFvFileLoaderPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&FvLoadFilePpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = FvLoadFilePpi->FvLoadFile (
+ FvLoadFilePpi,
+ PeimFileHeader,
+ &ImageAddress,
+ &ImageSize,
+ &ImageEntryPoint
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Got the entry point from ImageEntryPoint and ImageStartAddress
+ //
+ Pe32Data = (VOID *) ((UINTN) ImageAddress);
+ *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);
+ } else {
+ //
+ // Retrieve the entry point from the TE image header
+ //
+ ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader;
+ *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +
+ TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize);
+ }
+ } else {
+ //
+ // Retrieve the entry point from the PE/COFF image header
+ //
+ ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;
+ Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (((EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress)->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress;
+ Machine = TEImageHeader->Machine;
+ } else {
+ Machine = PeCoffLoaderGetMachineType (Pe32Data);
+ }
+
+ if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
+ //
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint));
+ DEBUG_CODE_BEGIN ();
+ 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;
+ EFI_IMAGE_DOS_HEADER *DosHeader;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
+ UINT32 NumberOfRvaAndSizes;
+
+ Hdr.Pe32 = NULL;
+ if (TEImageHeader == NULL) {
+ DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
+ if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header
+ //
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHeader->e_lfanew) & 0x0ffff));
+ } else {
+ //
+ // DOS image header is not present, so PE header is at the image base
+ //
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
+ }
+ }
+
+ //
+ // 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;
+ NumberOfRvaAndSizes = 0;
+ TEImageAdjust = 0;
+
+ if (TEImageHeader == NULL) {
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset get Debug Directory Entry
+ //
+ NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
+ } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ //
+ // Use PE32+ offset get Debug Directory Entry
+ //
+ NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
+ }
+
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ DirectoryEntry = NULL;
+ DebugEntry = NULL;
+ }
+ } 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 += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), 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;
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ DEBUG_CODE_END ();
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.i b/MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.i
new file mode 100644
index 0000000000..548271aa73
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.i
@@ -0,0 +1,98 @@
+//++
+// Copyright (c) 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:
+//
+// IpfCpuCore.i
+//
+// Abstract:
+// IPF CPU definitions
+//
+//--
+
+#ifndef _IPF_CPU_CORE_
+#define _IPF_CPU_CORE_
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#define PEI_BSP_STORE_SIZE 0x4000
+#define ResetFn 0x00
+#define MachineCheckFn 0x01
+#define InitFn 0x02
+#define RecoveryFn 0x03
+#define GuardBand 0x10
+
+//
+// Define hardware RSE Configuration Register
+//
+
+//
+// RS Configuration (RSC) bit field positions
+//
+#define RSC_MODE 0
+#define RSC_PL 2
+#define RSC_BE 4
+//
+// RSC bits 5-15 reserved
+//
+#define RSC_MBZ0 5
+#define RSC_MBZ0_V 0x3ff
+#define RSC_LOADRS 16
+#define RSC_LOADRS_LEN 14
+//
+// RSC bits 30-63 reserved
+//
+#define RSC_MBZ1 30
+#define RSC_MBZ1_V 0x3ffffffffULL
+
+//
+// RSC modes
+//
+
+//
+// Lazy
+//
+#define RSC_MODE_LY (0x0)
+//
+// Store intensive
+//
+#define RSC_MODE_SI (0x1)
+//
+// Load intensive
+//
+#define RSC_MODE_LI (0x2)
+//
+// Eager
+//
+#define RSC_MODE_EA (0x3)
+
+//
+// RSC Endian bit values
+//
+#define RSC_BE_LITTLE 0
+#define RSC_BE_BIG 1
+
+//
+// RSC while in kernel: enabled, little endian, pl = 0, eager mode
+//
+#define RSC_KERNEL ((RSC_MODE_EA<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE))
+//
+// Lazy RSC in kernel: enabled, little endian, pl = 0, lazy mode
+//
+#define RSC_KERNEL_LAZ ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE))
+//
+// RSE disabled: disabled, pl = 0, little endian, eager mode
+//
+#define RSC_KERNEL_DISABLED ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE))
+
+#endif
diff --git a/MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.s b/MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.s
new file mode 100644
index 0000000000..b66192eeb4
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Ipf/IpfCpuCore.s
@@ -0,0 +1,197 @@
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+//++
+// Copyright (c) 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:
+//
+// IpfCpuCore.s
+//
+// Abstract:
+// IPF Specific assembly routines
+//
+//--
+
+.file "IpfCpuCore.s"
+
+#include "IpfMacro.i"
+#include "Ipf/IpfCpuCore.i"
+
+//----------------------------------------------------------------------------------
+// This module supports terminating CAR (Cache As RAM) stage. It copies all the
+// CAR data into real RAM and then makes a stack switch.
+
+// EFI_STATUS
+// SwitchCoreStacks (
+// IN VOID *EntryPoint,
+// IN UINTN CopySize,
+// IN VOID *OldBase,
+// IN VOID *NewBase
+// IN UINTN NewSP, OPTIONAL
+// IN UINTN NewBSP OPTIONAL
+// )
+// EFI_STATUS
+// SwitchCoreStacks (
+// IN VOID *EntryPointForContinuationFunction,
+// IN UINTN StartupDescriptor,
+// IN VOID PEICorePointer,
+// IN UINTN NewSP
+// )
+//----------------------------------------------------------------------------------
+PROCEDURE_ENTRY (SwitchCoreStacks)
+
+ NESTED_SETUP (4,2,0,0)
+
+ // first save all stack registers in GPRs.
+ mov r13 = in0;; // this is a pointer to the PLABEL of the continuation function.
+ ld8 r16 = [r13],8;; // r16 = address of continuation function from the PLABEL
+ ld8 gp = [r13];; // gp = gp of continuation function from the PLABEL
+ mov b1 = r16;;
+
+ // save the parameters in r5, r6. these 2 seemed to be preserved across PAL calls
+ mov r5 = in1;; // this is the parameter1 to pass to the continuation function
+ mov r6 = in2;; // this is the parameter2 to pass to the continuation function
+ dep r6=0,r6,63,1;; // zero the bit 63.
+
+ mov r8 = in3;; // new stack pointer.
+
+ // r8 has the sp, this is 128K stack size, from this we will reserve 16K for the bspstore
+ movl r15 = PEI_BSP_STORE_SIZE;;
+ sub r8 = r8, r15;;
+ add r15 = (GuardBand),r8;; // some little buffer, now r15 will be our bspstore
+
+ // save the bspstore value to r4, save sp value to r7
+ mov r4 = r15
+ mov r7 = r8
+ mov r16 = r8;; // will be the new sp in uncache mode
+
+
+ alloc r11=0,0,0,0;; // Set 0-size frame
+ flushrs;;
+
+ mov r21 = RSC_KERNEL_DISABLED;; // for rse disable
+ mov ar.rsc = r21;; // turn off RSE
+
+ add sp = r0, r16 // transfer to the EFI stack
+ mov ar.bspstore = r15 // switch to EFI BSP
+ invala // change of ar.bspstore needs invala.
+
+ mov r19 = RSC_KERNEL_LAZ;; // RSC enabled, Lazy mode
+ mov ar.rsc = r19;; // turn rse on, in kernel mode
+
+//-----------------------------------------------------------------------------------
+// Save here the meaningful stuff for next few lines and then make the PAL call.
+// Make PAL call to terminate the CAR status.
+ // AVL: do this only for recovery check call...
+
+ mov r28=ar.k3;;
+ dep r2 = r28,r0,0,8;; // Extract Function bits from GR20.
+ cmp.eq p6,p7 = RecoveryFn,r2;; // Is it Recovery check
+ (p7) br.sptk.few DoneCARTermination; // if not, don't terminate car..
+
+TerminateCAR::
+
+ mov r28 = ip;;
+ add r28 = (DoneCARTerminationPALCall - TerminateCAR),r28;;
+ mov b0 = r28
+
+ mov r8 = ar.k5;;
+ mov b6 = r8
+ mov r28 = 0x208
+
+ mov r29 = r0
+ mov r30 = r0
+ mov r31 = r0
+ mov r8 = r0;;
+ br.sptk.few b6;; // Call PAL-A call.
+
+DoneCARTerminationPALCall::
+
+// don't check error in soft sdv, it is always returning -1 for this call for some reason
+#if SOFT_SDV
+#else
+ReturnToPEIMain::
+ cmp.eq p6,p7 = r8,r0;;
+ //
+ // dead loop if the PAL call failed, we have the CAR on but the stack is now pointing to memory
+ //
+ (p7) br.sptk.few ReturnToPEIMain;;
+ //
+ // PAL call successed,now the stack are in memory so come into cache mode
+ // instead of uncache mode
+ //
+
+ alloc r11=0,0,0,0;; // Set 0-size frame
+ flushrs;;
+
+ mov r21 = RSC_KERNEL_DISABLED;; // for rse disable
+ mov ar.rsc = r21;; // turn off RSE
+
+ dep r6 = 0,r6,63,1 // zero the bit 63
+ dep r7 = 0,r7,63,1 // zero the bit 63
+ dep r4 = 0,r4,63,1;; // zero the bit 63
+ add sp = r0, r7 // transfer to the EFI stack in cache mode
+ mov ar.bspstore = r4 // switch to EFI BSP
+ invala // change of ar.bspstore needs invala.
+
+ mov r19 = RSC_KERNEL_LAZ;; // RSC enabled, Lazy mode
+ mov ar.rsc = r19;; // turn rse on, in kernel mode
+
+#endif
+
+DoneCARTermination::
+
+ // allocate a stack frame:
+ alloc r11=0,2,2,0 ;; // alloc outs going to ensuing DXE IPL service
+ // on the new stack
+ mov out0 = r5;;
+ mov out1 = r6;;
+
+ mov r16 = b1;;
+ mov b6 = r16;;
+ br.call.sptk.few b0=b6;; // Call the continuation function
+
+ NESTED_RETURN
+
+PROCEDURE_EXIT(SwitchCoreStacks)
+//-----------------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------------
+//++
+// GetHandOffStatus
+//
+// This routine is called by all processors simultaneously, to get some hand-off
+// status that has been captured by IPF dispatcher and recorded in kernel registers.
+//
+// Arguments :
+//
+// On Entry : None.
+//
+// Return Value: Lid, R20Status.
+//
+//--
+//----------------------------------------------------------------------------------
+PROCEDURE_ENTRY (GetHandOffStatus)
+
+ NESTED_SETUP (0,2+0,0,0)
+
+ mov r8 = ar.k6 // Health Status (Self test params)
+ mov r9 = ar.k4 // LID bits
+ mov r10 = ar.k3;; // SAL_E entry state
+ mov r11 = ar.k7 // Return address to PAL
+
+ NESTED_RETURN
+PROCEDURE_EXIT (GetHandOffStatus)
+//----------------------------------------------------------------------------------
+
+
diff --git a/MdeModulePkg/Core/Pei/Ipf/IpfPeiMain.h b/MdeModulePkg/Core/Pei/Ipf/IpfPeiMain.h
new file mode 100644
index 0000000000..e5b160f76b
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Ipf/IpfPeiMain.h
@@ -0,0 +1,57 @@
+/*++
+
+Copyright (c) 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:
+
+ IpfPeiMain.h
+
+Abstract:
+
+ Definition of IPF specific function
+
+Revision History
+
+--*/
+
+#ifndef _IPF_PEI_MAIN_H_
+#define _IPF_PEI_MAIN_H_
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+SAL_RETURN_REGS
+GetHandOffStatus (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called by all processors simultaneously, to get some hand-off
+ status that has been captured by IPF dispatcher and recorded in kernel registers.
+
+Arguments :
+
+ On Entry : None.
+
+Returns:
+
+ Lid, R20Status.
+
+--*/
+
+;
+
+#endif
diff --git a/MdeModulePkg/Core/Pei/Ipf/Stack.c b/MdeModulePkg/Core/Pei/Ipf/Stack.c
new file mode 100644
index 0000000000..600a41dafb
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Ipf/Stack.c
@@ -0,0 +1,63 @@
+/** @file
+ PeiSwitchStacks() function for PEI dispatcher.
+
+ Copyright (c) 2006 - 2007, Intel Corporation<BR>
+ 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: String.c
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+/**
+ Transfers control to a function starting with a new stack.
+
+ Transfers control to the function specified by EntryPoint using the new stack
+ specified by NewStack and passing in the parameters specified by Context1 and
+ Context2. Context1 and Context2 are optional and may be NULL. The function
+ EntryPoint must never return.
+
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ @param EntryPoint A pointer to function to call with the new stack.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function.
+ @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
+ Reserved on other architectures.
+
+**/
+VOID
+EFIAPI
+PeiSwitchStacks (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack,
+ IN VOID *NewBsp
+ )
+{
+ SwitchStack (
+ EntryPoint,
+ Context1,
+ Context2,
+ NewStack,
+ NewBsp
+ );
+}
diff --git a/MdeModulePkg/Core/Pei/Ipf/SwitchToCacheMode.c b/MdeModulePkg/Core/Pei/Ipf/SwitchToCacheMode.c
new file mode 100644
index 0000000000..f4e90e13c3
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Ipf/SwitchToCacheMode.c
@@ -0,0 +1,76 @@
+/*++
+
+Copyright (c) 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:
+
+ SwitchToCacheMode.c
+
+Abstract:
+
+ Ipf CAR specific function used to switch to cache mode for the later memory access
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "IpfPeiMain.h"
+#include "IpfCpuCore.i"
+
+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:
+
+--*/
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *Phit;
+
+ if (CoreData == NULL) {
+ //
+ // the first call with CoreData as NULL.
+ //
+ return;
+ }
+
+ if ((GetHandOffStatus().r10 & 0xFF) == RecoveryFn) {
+ CoreData->StackBase = CoreData->StackBase & CACHE_MODE_ADDRESS_MASK;
+ CoreData->HobList.Raw = (UINT8 *)((UINTN)CoreData->HobList.Raw & CACHE_MODE_ADDRESS_MASK);
+
+ //
+ // Change the PHIT pointer value to cache mode
+ //
+ Phit = CoreData->HobList.HandoffInformationTable;
+
+ Phit->EfiMemoryTop = Phit->EfiMemoryTop & CACHE_MODE_ADDRESS_MASK;
+ Phit->EfiFreeMemoryTop = Phit->EfiFreeMemoryTop & CACHE_MODE_ADDRESS_MASK;
+ Phit->EfiMemoryBottom = Phit->EfiMemoryBottom & CACHE_MODE_ADDRESS_MASK;
+ Phit->EfiFreeMemoryBottom = Phit->EfiFreeMemoryBottom & CACHE_MODE_ADDRESS_MASK;
+ Phit->EfiEndOfHobList = Phit->EfiEndOfHobList & CACHE_MODE_ADDRESS_MASK;
+ }
+
+ return;
+}
diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
new file mode 100644
index 0000000000..86f4487899
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
@@ -0,0 +1,326 @@
+/*++
+
+Copyright (c) 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:
+
+ MemoryServices.c
+
+Abstract:
+
+ EFI PEI Core memory services
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.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);
+
+ DEBUG_CODE_BEGIN ();
+ PrivateData->SizeOfCacheAsRam = PeiStartupDescriptor->SizeOfCacheAsRam;
+ PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) SizeOfCarHeap);
+ DEBUG_CODE_END ();
+
+ 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
+ //
+ CopyMem (&(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;
+
+ DEBUG ((EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob));
+ DEBUG ((EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob));
+
+ CopyMem (
+ 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);
+
+ BuildStackHob (PrivateData->StackBase, PrivateData->StackSize);
+
+
+ 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;
+
+ 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) {
+ DEBUG ((EFI_D_ERROR, "AllocatePages failed: No 0x%x Pages is available.\n", Pages));
+ DEBUG ((EFI_D_ERROR, "There is only left 0x%x pages memory resource to be allocated.\n", \
+ EFI_SIZE_TO_PAGES ((UINTN) (Hob.HandoffInformationTable->EfiFreeMemoryTop - 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.
+ //
+ BuildMemoryAllocationHob (
+ Hob.HandoffInformationTable->EfiFreeMemoryTop,
+ Pages * EFI_PAGE_SIZE + Offset,
+ MemoryType
+ );
+
+ return EFI_SUCCESS;
+ }
+}
+
+
+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;
+
+ //
+ // If some "post-memory" PEIM wishes to allocate larger pool,
+ // it should use AllocatePages service instead.
+ //
+ ASSERT (Size < 0x10000 - sizeof (EFI_HOB_MEMORY_POOL));
+ Status = PeiServicesCreateHob (
+ EFI_HOB_TYPE_MEMORY_POOL,
+ (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
+ (VOID **)&Hob
+ );
+ *Buffer = Hob+1;
+
+
+ return Status;
+}
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
new file mode 100644
index 0000000000..e136041698
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -0,0 +1,1147 @@
+/*++
+
+Copyright (c) 2006 - 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:
+
+ PeiMain.h
+
+Abstract:
+
+ Definition of Pei Core Structures and Services
+
+Revision History
+
+--*/
+
+#ifndef _PEI_MAIN_H_
+#define _PEI_MAIN_H_
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+extern EFI_GUID gEfiPeiCorePrivateGuid;
+
+//
+// Pei Core private data structures
+//
+typedef union {
+ 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 64
+
+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;
+ UINT32 DispatchedPeimBitMap;
+ UINT32 PreviousPeimBitMap;
+ EFI_FFS_FILE_HEADER *CurrentPeimAddress;
+ EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress;
+ EFI_FIRMWARE_VOLUME_HEADER *BootFvAddress;
+ EFI_PEI_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;
+ EFI_PEI_SECURITY_PPI *PrivateSecurityPpi;
+ EFI_PEI_SERVICES ServiceTableShadow;
+ UINTN SizeOfCacheAsRam;
+ VOID *MaxTopOfCarHeap;
+} PEI_CORE_INSTANCE;
+
+//
+// Pei Core Instance Data Macros
+//
+
+#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \
+ CR(a, PEI_CORE_INSTANCE, PS, PEI_CORE_HANDLE_SIGNATURE)
+
+//
+// BUGBUG: Where does this go really?
+//
+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;
+
+
+//
+// PeiCore function
+//
+EFI_STATUS
+EFIAPI
+PeiCore (
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
+ IN VOID *Data
+ )
+/*++
+
+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
+
+--*/
+;
+
+//
+// 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 UINT32 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 UINT32 *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
+
+--*/
+;
+
+#if defined (MDE_CPU_IPF)
+ //
+ // 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 0x7FFFFFFFFFFFFFFFULL
+VOID
+SwitchToCacheMode (
+ IN PEI_CORE_INSTANCE *CoreData
+)
+/*++
+
+Routine Description:
+
+ Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR.
+
+Arguments:
+
+ CoreData - The PEI core Private Data
+
+Returns:
+
+--*/
+;
+
+#else
+
+#define SWITCH_TO_CACHE_MODE(CoreData)
+
+#endif
+
+//
+// PPI support functions
+//
+VOID
+InitializePpiServices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CORE_INSTANCE *OldCoreData
+ )
+/*++
+
+Routine Description:
+
+ Initialize PPI services.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ OldCoreData - Pointer to the PEI Core data.
+ NULL if being run in non-permament memory mode.
+
+Returns:
+ Nothing
+
+--*/
+;
+
+VOID
+ConvertPpiPointers (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob,
+ IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob
+ )
+/*++
+
+Routine Description:
+
+ Migrate the Hob list from the CAR stack to PEI installed memory.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ OldHandOffHob - The old handoff HOB list.
+ NewHandOffHob - The new handoff HOB list.
+
+Returns:
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiInstallPpi (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PPI_DESCRIPTOR *PpiList
+ )
+/*++
+
+Routine Description:
+
+ Install PPI services.
+
+Arguments:
+
+ PeiServices - Pointer to the PEI Service Table
+ PpiList - Pointer to a list of PEI PPI Descriptors.
+
+Returns:
+
+ EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
+ EFI_INVALID_PARAMETER - if PpiList is NULL pointer
+ EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
+ EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiReInstallPpi (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PPI_DESCRIPTOR *OldPpi,
+ IN EFI_PEI_PPI_DESCRIPTOR *NewPpi
+ )
+/*++
+
+Routine Description:
+
+ Re-Install PPI services.
+
+Arguments:
+
+ PeiServices - Pointer to the PEI Service Table
+ OldPpi - Pointer to the old PEI PPI Descriptors.
+ NewPpi - Pointer to the new PEI PPI Descriptors.
+
+Returns:
+
+ EFI_SUCCESS - if the operation was successful
+ EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
+ EFI_INVALID_PARAMETER - if NewPpi is not valid
+ EFI_NOT_FOUND - if the PPI was not in the database
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiLocatePpi (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_GUID *Guid,
+ IN UINTN Instance,
+ IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
+ IN OUT VOID **Ppi
+ )
+/*++
+
+Routine Description:
+
+ Locate a given named PPI.
+
+Arguments:
+
+ PeiServices - Pointer to the PEI Service Table
+ Guid - Pointer to GUID of the PPI.
+ Instance - Instance Number to discover.
+ PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
+ returns a pointer to the descriptor (includes flags, etc)
+ Ppi - Pointer to reference the found PPI
+
+Returns:
+
+ Status - EFI_SUCCESS if the PPI is in the database
+ EFI_NOT_FOUND if the PPI is not in the database
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiNotifyPpi (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
+ )
+/*++
+
+Routine Description:
+
+ Install a notification for a given PPI.
+
+Arguments:
+
+ PeiServices - Pointer to the PEI Service Table
+ NotifyList - Pointer to list of Descriptors to notify upon.
+
+Returns:
+
+ Status - EFI_SUCCESS if successful
+ EFI_OUT_OF_RESOURCES if no space in the database
+ EFI_INVALID_PARAMETER if not a good decriptor
+
+--*/
+;
+
+VOID
+ProcessNotifyList (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ Process the Notify List at dispatch level.
+
+Arguments:
+
+ PeiServices - Pointer to the PEI Service Table
+
+Returns:
+
+--*/
+;
+
+VOID
+DispatchNotify (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINTN NotifyType,
+ IN INTN InstallStartIndex,
+ IN INTN InstallStopIndex,
+ IN INTN NotifyStartIndex,
+ IN INTN NotifyStopIndex
+ )
+/*++
+
+Routine Description:
+
+ Dispatch notifications.
+
+Arguments:
+
+ PeiServices - Pointer to the PEI Service Table
+ NotifyType - Type of notify to fire.
+ InstallStartIndex - Install Beginning index.
+ InstallStopIndex - Install Ending index.
+ NotifyStartIndex - Notify Beginning index.
+ NotifyStopIndex - Notify Ending index.
+
+Returns: None
+
+--*/
+;
+
+//
+// Boot mode support functions
+//
+EFI_STATUS
+EFIAPI
+PeiGetBootMode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT EFI_BOOT_MODE *BootMode
+ )
+/*++
+
+Routine Description:
+
+ This service enables PEIMs to ascertain the present value of the boot mode.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ BootMode - A pointer to contain the value of the boot mode.
+
+Returns:
+
+ EFI_SUCCESS - The boot mode was returned successfully.
+ EFI_INVALID_PARAMETER - BootMode is NULL.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiSetBootMode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode
+ )
+/*++
+
+Routine Description:
+
+ This service enables PEIMs to update the boot mode variable.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ BootMode - The value of the boot mode to set.
+
+Returns:
+
+ EFI_SUCCESS - The value was successfully updated
+
+--*/
+;
+
+//
+// Security support functions
+//
+VOID
+InitializeSecurityServices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CORE_INSTANCE *OldCoreData
+ )
+/*++
+
+Routine Description:
+
+ Initialize the security services.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ OldCoreData - Pointer to the old core data.
+ NULL if being run in non-permament memory mode.
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_STATUS
+VerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
+ )
+/*++
+
+Routine Description:
+
+ Provide a callout to the OEM FV verification service.
+
+Arguments:
+
+ CurrentFvAddress - Pointer to the FV under investigation.
+
+Returns:
+
+ Status - EFI_SUCCESS
+
+--*/
+;
+
+
+EFI_STATUS
+VerifyPeim (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_FFS_FILE_HEADER *CurrentPeimAddress
+ )
+/*++
+
+Routine Description:
+
+ Provide a callout to the security verification service.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ CurrentPeimAddress - Pointer to the Firmware File under investigation.
+
+Returns:
+
+ EFI_SUCCESS - Image is OK
+ EFI_SECURITY_VIOLATION - Image is illegal
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiGetHobList (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **HobList
+ )
+/*++
+
+Routine Description:
+
+ Gets the pointer to the HOB List.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ HobList - Pointer to the HOB List.
+
+Returns:
+
+ EFI_SUCCESS - Get the pointer of HOB List
+ EFI_NOT_AVAILABLE_YET - the HOB List is not yet published
+ EFI_INVALID_PARAMETER - HobList is NULL (in debug mode)
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiCreateHob (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT16 Type,
+ IN UINT16 Length,
+ IN OUT VOID **Hob
+ )
+/*++
+
+Routine Description:
+
+ Add a new HOB to the HOB List.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ Type - Type of the new HOB.
+ Length - Length of the new HOB to allocate.
+ Hob - Pointer to the new HOB.
+
+Returns:
+
+ Status - EFI_SUCCESS
+ - EFI_INVALID_PARAMETER if Hob is NULL
+ - EFI_NOT_AVAILABLE_YET if HobList is still not available.
+ - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist.
+
+--*/
+;
+
+EFI_STATUS
+PeiCoreBuildHobHandoffInfoTable (
+ IN EFI_BOOT_MODE BootMode,
+ IN EFI_PHYSICAL_ADDRESS MemoryBegin,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ Builds a Handoff Information Table HOB
+
+Arguments:
+
+ BootMode - Current Bootmode
+ MemoryBegin - Start Memory Address.
+ MemoryLength - Length of Memory.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
+
+
+//
+// FFS Fw Volume support functions
+//
+EFI_STATUS
+EFIAPI
+PeiFfsFindNextFile (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT8 SearchType,
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ IN OUT EFI_FFS_FILE_HEADER **FileHeader
+ )
+/*++
+
+Routine Description:
+ Given the input file pointer, search for the next matching file in the
+ FFS volume as defined by SearchType. The search starts from FileHeader inside
+ the Firmware Volume defined by FwVolHeader.
+
+Arguments:
+ PeiServices - Pointer to the PEI Core Services Table.
+
+ SearchType - Filter to find only files of this type.
+ Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
+
+ FwVolHeader - Pointer to the FV header of the volume to search.
+ This parameter must point to a valid FFS volume.
+
+ FileHeader - Pointer to the current file from which to begin searching.
+ This pointer will be updated upon return to reflect the file found.
+
+Returns:
+ EFI_NOT_FOUND - No files matching the search criteria were found
+ EFI_SUCCESS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiFfsFindSectionData (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_SECTION_TYPE SectionType,
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ IN OUT VOID **SectionData
+ )
+/*++
+
+Routine Description:
+ Given the input file pointer, search for the next matching section in the
+ FFS volume.
+
+Arguments:
+ PeiServices - Pointer to the PEI Core Services Table.
+ SearchType - Filter to find only sections of this type.
+ FfsFileHeader - Pointer to the current file to search.
+ SectionData - Pointer to the Section matching SectionType in FfsFileHeader.
+ - NULL if section not found
+
+Returns:
+ EFI_NOT_FOUND - No files matching the search criteria were found
+ EFI_SUCCESS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiFvFindNextVolume (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINTN Instance,
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
+ )
+/*++
+
+Routine Description:
+
+ Return the BFV location
+
+ BugBug -- Move this to the location of this code to where the
+ other FV and FFS support code lives.
+ Also, update to use FindFV for instances #'s >= 1.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ Instance - Instance of FV to find
+ FwVolHeader - Pointer to contain the data to return
+
+Returns:
+ Pointer to the Firmware Volume instance requested
+
+ EFI_INVALID_PARAMETER - FwVolHeader is NULL
+
+ EFI_SUCCESS - Firmware volume instance successfully found.
+
+--*/
+;
+
+//
+// Memory support functions
+//
+VOID
+InitializeMemoryServices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
+ IN PEI_CORE_INSTANCE *OldCoreData
+ )
+/*++
+
+Routine Description:
+
+ Initialize the memory services.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ PeiStartupDescriptor - Information and services provided by SEC phase.
+ OldCoreData - Pointer to the PEI Core data.
+ NULL if being run in non-permament memory mode.
+
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiInstallPeiMemory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS MemoryBegin,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ Install the permanent memory is now available.
+ Creates HOB (PHIT and Stack).
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ MemoryBegin - Start of memory address.
+ MemoryLength - Length of memory.
+
+Returns:
+
+ Status - EFI_SUCCESS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiAllocatePages (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT EFI_PHYSICAL_ADDRESS *Memory
+ )
+/*++
+
+Routine Description:
+
+ Memory allocation service on permanent memory,
+ not usable prior to the memory installation.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ Type - Type of allocation.
+ MemoryType - Type of memory to allocate.
+ Pages - Number of pages to allocate.
+ Memory - Pointer of memory allocated.
+
+Returns:
+
+ Status - EFI_SUCCESS The allocation was successful
+ EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported.
+ EFI_NOT_AVAILABLE_YET Called with permanent memory not available
+ EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement
+ to allocate the number of pages.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiAllocatePool (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Memory allocation service on the CAR.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+
+ Size - Amount of memory required
+
+ Buffer - Address of pointer to the buffer
+
+Returns:
+
+ Status - EFI_SUCCESS The allocation was successful
+ EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement
+ to allocate the requested size.
+
+--*/
+;
+
+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
+PeiResetSystem (
+ 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.
+
+--*/
+;
+
+/**
+ Transfers control to a function starting with a new stack.
+
+ Transfers control to the function specified by EntryPoint using the new stack
+ specified by NewStack and passing in the parameters specified by Context1 and
+ Context2. Context1 and Context2 are optional and may be NULL. The function
+ EntryPoint must never return.
+
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ @param EntryPoint A pointer to function to call with the new stack.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function.
+ @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
+ Reserved on other architectures.
+
+**/
+VOID
+EFIAPI
+PeiSwitchStacks (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack,
+ IN VOID *NewBsp
+ );
+
+#endif
diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf
new file mode 100644
index 0000000000..61641e3526
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -0,0 +1,146 @@
+#/** @file
+# Component description file for PeiMain module
+#
+# This module provide an DXE CIS compliant implementation.
+# Copyright (c) 2006 - 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.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiMain
+ FILE_GUID = 52C05B14-0B98-496c-BC3B-04B50211D680
+ MODULE_TYPE = PEI_CORE
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = PeiCore
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ StatusCode/StatusCode.c
+ Security/Security.c
+ Reset/Reset.c
+ Ppi/Ppi.c
+ PeiMain/PeiMain.c
+ Memory/MemoryServices.c
+ Image/Image.c
+ Hob/Hob.c
+ FwVol/FwVol.c
+ Dispatcher/Dispatcher.c
+ Dependency/dependency.c
+ Dependency/dependency.h
+ BootMode/BootMode.c
+ PeiMain.h
+ CommonHeader.h
+
+[Sources.Ia32]
+ Dispatcher/Stack.c
+
+[Sources.X64]
+ Dispatcher/Stack.c
+
+[Sources.IPF]
+ Ipf/Stack.c
+ Ipf/IpfPeiMain.h
+ Ipf/IpfCpuCore.s
+ Ipf/IpfCpuCore.i
+ Ipf/SwitchToCacheMode.c
+
+[Sources.EBC]
+ Dispatcher/Stack.c
+
+
+################################################################################
+#
+# Includes Section - list of Include locations that are required for
+# this module.
+#
+################################################################################
+
+[Includes]
+ $(WORKSPACE)/MdePkg\Include/Library
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ TimerLib
+ BaseMemoryLib
+ PeCoffGetEntryPointLib
+ ReportStatusCodeLib
+ PeiServicesLib
+ PerformanceLib
+ HobLib
+ BaseLib
+ PeiCoreEntryPoint
+ DebugLib
+
+
+################################################################################
+#
+# Guid C Name Section - list of Guids that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gEfiPeiCorePrivateGuid # PRIVATE
+
+
+################################################################################
+#
+# PPI C Name Section - list of PPI and PPI Notify C Names that this module
+# uses or produces.
+#
+################################################################################
+
+[Ppis]
+ gEfiPeiSecurityPpiGuid # PPI_NOTIFY SOMETIMES_CONSUMED
+ gEfiPeiStatusCodePpiGuid # PPI SOMETIMES_CONSUMED
+ gEfiPeiResetPpiGuid # PPI SOMETIMES_CONSUMED
+ gEfiDxeIplPpiGuid # PPI ALWAYS_CONSUMED
+ gEfiPeiFvFileLoaderPpiGuid # PPI ALWAYS_CONSUMED
+ gEfiFindFvPpiGuid # PPI ALWAYS_CONSUMED
+ gEfiPeiMemoryDiscoveredPpiGuid # PPI ALWAYS_PRODUCED
+
diff --git a/MdeModulePkg/Core/Pei/PeiMain.msa b/MdeModulePkg/Core/Pei/PeiMain.msa
new file mode 100644
index 0000000000..b8873a8ab6
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/PeiMain.msa
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>PeiMain</ModuleName>
+ <ModuleType>PEI_CORE</ModuleType>
+ <GuidValue>52C05B14-0B98-496c-BC3B-04B50211D680</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for PeiMain module</Abstract>
+ <Description>This module provide an DXE CIS compliant implementation.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>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.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>PeiMain</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeiCoreEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>HobLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PerformanceLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeiServicesLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>ReportStatusCodeLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeCoffGetEntryPointLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>TimerLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>PeiMain.h</Filename>
+ <Filename>BootMode/BootMode.c</Filename>
+ <Filename>Dependency/dependency.h</Filename>
+ <Filename>Dependency/dependency.c</Filename>
+ <Filename>Dispatcher/Dispatcher.c</Filename>
+ <Filename>FwVol/FwVol.c</Filename>
+ <Filename>Hob/Hob.c</Filename>
+ <Filename>Image/Image.c</Filename>
+ <Filename>Memory/MemoryServices.c</Filename>
+ <Filename>PeiMain/PeiMain.c</Filename>
+ <Filename>Ppi/Ppi.c</Filename>
+ <Filename>Reset/Reset.c</Filename>
+ <Filename>Security/Security.c</Filename>
+ <Filename>StatusCode/StatusCode.c</Filename>
+ <Filename SupArchList="IPF">Ipf/SwitchToCacheMode.c</Filename>
+ <Filename SupArchList="IPF">Ipf/IpfCpuCore.i</Filename>
+ <Filename SupArchList="IPF">Ipf/IpfCpuCore.s</Filename>
+ <Filename SupArchList="IPF">Ipf/IpfPeiMain.h</Filename>
+ <Filename SupArchList="IPF">Ipf/Stack.c</Filename>
+ <Filename SupArchList="IA32 X64 EBC">Dispatcher/Stack.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <PPIs>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gEfiPeiMemoryDiscoveredPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">
+ <PpiCName>gEfiFindFvPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">
+ <PpiCName>gEfiPeiFvFileLoaderPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">
+ <PpiCName>gEfiDxeIplPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">
+ <PpiCName>gEfiPeiResetPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">
+ <PpiCName>gEfiPeiStatusCodePpiGuid</PpiCName>
+ </Ppi>
+ <PpiNotify Usage="SOMETIMES_CONSUMED">
+ <PpiNotifyCName>gEfiPeiSecurityPpiGuid</PpiNotifyCName>
+ </PpiNotify>
+ </PPIs>
+ <Guids>
+ <GuidCNames Usage="PRIVATE">
+ <GuidCName>gEfiPeiCorePrivateGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>PeiCore</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
new file mode 100644
index 0000000000..db4a69f568
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -0,0 +1,251 @@
+/*++
+
+Copyright (c) 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:
+
+ PeiMain.c
+
+Abstract:
+
+ Pei Core Main Entry Point
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+//
+//CAR is filled with this initial value during SEC phase
+//
+#define INIT_CAR_VALUE 0x5AA55AA5
+
+static EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ 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,
+ (EFI_PEI_COPY_MEM)CopyMem,
+ (EFI_PEI_SET_MEM)SetMem,
+
+ PeiReportStatusCode,
+
+ PeiResetSystem
+};
+
+EFI_STATUS
+EFIAPI
+PeiCore (
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
+ IN VOID *Data
+ )
+/*++
+
+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;
+ UINT64 mTick;
+ PEI_CORE_INSTANCE *OldCoreData;
+
+ mTick = 0;
+ OldCoreData = (PEI_CORE_INSTANCE *) Data;
+
+ if (PerformanceMeasurementEnabled()) {
+ if (OldCoreData == NULL) {
+ mTick = GetPerformanceCounter ();
+ }
+ }
+
+ //
+ // 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) {
+ CopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE));
+ } else {
+ ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
+ }
+
+ PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
+ PrivateData.PS = &mPS;
+
+ //
+ // Initialize libraries that the PeiCore is linked against
+ // BUGBUG: The FfsHeader is passed in as NULL. Do we look it up or remove it from the lib init?
+ //
+ ProcessLibraryConstructorList (NULL, &PrivateData.PS);
+
+ InitializeMemoryServices (&PrivateData.PS, PeiStartupDescriptor, OldCoreData);
+
+ InitializePpiServices (&PrivateData.PS, OldCoreData);
+
+ InitializeSecurityServices (&PrivateData.PS, OldCoreData);
+
+ InitializeDispatcherData (&PrivateData.PS, OldCoreData, PeiStartupDescriptor);
+
+ if (OldCoreData != NULL) {
+
+ PERF_END (NULL,"PreMem", NULL, 0);
+ PERF_START (NULL,"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
+ // DEBUG_CODE_BEGIN macro is used to prevent this code from being compiled
+ // on a debug build.
+ //
+ DEBUG_CODE_BEGIN ();
+ 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;
+ }
+
+ DEBUG ((EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", OldCoreData->SizeOfCacheAsRam));
+ DEBUG ((EFI_D_INFO, " CAR stack ever used: %d bytes.\n",
+ ((UINTN) OldCoreData->TopOfCarHeap - (UINTN) StackPointer)
+ ));
+ DEBUG ((EFI_D_INFO, " CAR heap used: %d bytes.\n",
+ ((UINTN) OldCoreData->HobList.HandoffInformationTable->EfiFreeMemoryBottom -
+ (UINTN) OldCoreData->HobList.Raw)
+ ));
+ DEBUG_CODE_END ();
+
+ //
+ // Alert any listeners that there is permanent memory available
+ //
+
+ PERF_START (NULL,"DisMem", NULL, 0);
+ Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
+ PERF_END (NULL,"DisMem", NULL, 0);
+
+ } else {
+
+ //
+ // Report Status Code EFI_SW_PC_INIT
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT
+ );
+
+ PERF_START (NULL,"PEI", NULL, mTick);
+ //
+ // If first pass, start performance measurement.
+ //
+ PERF_START (NULL,"PreMem", NULL, mTick);
+
+ //
+ // If SEC provided any PPI services to PEI, install them.
+ //
+ if (PeiStartupDescriptor->DispatchTable != NULL) {
+ Status = PeiServicesInstallPpi (PeiStartupDescriptor->DispatchTable);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ DispatchData = &PrivateData.DispatchData;
+
+ //
+ // Call PEIM dispatcher
+ //
+ PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData);
+
+ //
+ // Check if InstallPeiMemory service was called.
+ //
+ ASSERT(PrivateData.PeiMemoryInstalled == TRUE);
+
+ PERF_END (NULL, "PostMem", NULL, 0);
+
+ Status = PeiServicesLocatePpi (
+ &gEfiDxeIplPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&TempPtr.DxeIpl
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "DXE IPL Entry\n"));
+ Status = TempPtr.DxeIpl->Entry (
+ TempPtr.DxeIpl,
+ &PrivateData.PS,
+ PrivateData.HobList
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_NOT_FOUND;
+}
+
diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
new file mode 100644
index 0000000000..0f119c7fb6
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
@@ -0,0 +1,663 @@
+/*++
+
+Copyright (c) 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:
+
+ Ppi.c
+
+Abstract:
+
+ EFI PEI Core PPI services
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.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:
+
+ 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:
+
+--*/
+{
+ 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;
+ DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG((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.
+ //
+ DEBUG((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;
+ DEBUG((EFI_D_ERROR, "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--;
+ DEBUG((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])) {
+ DEBUG ((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/MdeModulePkg/Core/Pei/Reset/Reset.c b/MdeModulePkg/Core/Pei/Reset/Reset.c
new file mode 100644
index 0000000000..b0c4b24370
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Reset/Reset.c
@@ -0,0 +1,73 @@
+/*++
+
+Copyright (c) 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:
+
+ Reset.c
+
+Abstract:
+
+ Pei Core Reset System Support
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+EFI_STATUS
+EFIAPI
+PeiResetSystem (
+ 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;
+ EFI_PEI_RESET_PPI *ResetPpi;
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiResetPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&ResetPpi
+ );
+
+ //
+ // LocatePpi returns EFI_NOT_FOUND on error
+ //
+ if (!EFI_ERROR (Status)) {
+ return ResetPpi->ResetSystem (PeiServices);
+ }
+ return EFI_NOT_AVAILABLE_YET;
+}
+
diff --git a/MdeModulePkg/Core/Pei/Security/Security.c b/MdeModulePkg/Core/Pei/Security/Security.c
new file mode 100644
index 0000000000..e7c2fbde95
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Security/Security.c
@@ -0,0 +1,199 @@
+/*++
+
+Copyright (c) 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:
+
+ Security.c
+
+Abstract:
+
+ EFI PEI Core Security services
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+STATIC
+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,
+ &gEfiPeiSecurityPpiGuid,
+ 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) {
+ PeiServicesNotifyPpi (&mNotifyList);
+ }
+ return;
+}
+
+STATIC
+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 = (EFI_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/MdeModulePkg/Core/Pei/StatusCode/StatusCode.c b/MdeModulePkg/Core/Pei/StatusCode/StatusCode.c
new file mode 100644
index 0000000000..9112c45dc9
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/StatusCode/StatusCode.c
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 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:
+
+ StatusCode.c
+
+Abstract:
+
+ Pei Core Status Code Support
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <PeiMain.h>
+
+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;
+ EFI_PEI_PROGRESS_CODE_PPI *StatusCodePpi;
+
+
+ //
+ //Locate StatusCode Ppi.
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiStatusCodePpiGuid,
+ 0,
+ NULL,
+ (VOID **)&StatusCodePpi
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = StatusCodePpi->ReportStatusCode (
+ PeiServices,
+ CodeType,
+ Value,
+ Instance,
+ CallerId,
+ Data
+ );
+
+ return Status;
+ }
+
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+
+