summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Core
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Core')
-rw-r--r--EdkModulePkg/Core/Dxe/DebugImageInfo.h126
-rw-r--r--EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c1159
-rw-r--r--EdkModulePkg/Core/Dxe/Dispatcher/dependency.c450
-rw-r--r--EdkModulePkg/Core/Dxe/DxeMain.h2539
-rw-r--r--EdkModulePkg/Core/Dxe/DxeMain.mbd42
-rw-r--r--EdkModulePkg/Core/Dxe/DxeMain.msa164
-rw-r--r--EdkModulePkg/Core/Dxe/DxeMain/DxeMain.c1083
-rw-r--r--EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c266
-rw-r--r--EdkModulePkg/Core/Dxe/Event/event.c862
-rw-r--r--EdkModulePkg/Core/Dxe/Event/execdata.c55
-rw-r--r--EdkModulePkg/Core/Dxe/Event/timer.c386
-rw-r--r--EdkModulePkg/Core/Dxe/Event/tpl.c198
-rw-r--r--EdkModulePkg/Core/Dxe/FwVol/Ffs.c266
-rw-r--r--EdkModulePkg/Core/Dxe/FwVol/FwVol.c553
-rw-r--r--EdkModulePkg/Core/Dxe/FwVol/FwVolAttrib.c99
-rw-r--r--EdkModulePkg/Core/Dxe/FwVol/FwVolRead.c516
-rw-r--r--EdkModulePkg/Core/Dxe/FwVol/FwVolWrite.c60
-rw-r--r--EdkModulePkg/Core/Dxe/FwVolBlock.h324
-rw-r--r--EdkModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c598
-rw-r--r--EdkModulePkg/Core/Dxe/FwVolDriver.h466
-rw-r--r--EdkModulePkg/Core/Dxe/Gcd/gcd.c2481
-rw-r--r--EdkModulePkg/Core/Dxe/Hand/DriverSupport.c848
-rw-r--r--EdkModulePkg/Core/Dxe/Hand/Notify.c333
-rw-r--r--EdkModulePkg/Core/Dxe/Hand/handle.c1699
-rw-r--r--EdkModulePkg/Core/Dxe/Hand/locate.c737
-rw-r--r--EdkModulePkg/Core/Dxe/Image.h380
-rw-r--r--EdkModulePkg/Core/Dxe/Image/Image.c1377
-rw-r--r--EdkModulePkg/Core/Dxe/Image/ImageFile.c569
-rw-r--r--EdkModulePkg/Core/Dxe/Library.h407
-rw-r--r--EdkModulePkg/Core/Dxe/Library/Library.c613
-rw-r--r--EdkModulePkg/Core/Dxe/Mem/Page.c1589
-rw-r--r--EdkModulePkg/Core/Dxe/Mem/memdata.c41
-rw-r--r--EdkModulePkg/Core/Dxe/Mem/pool.c613
-rw-r--r--EdkModulePkg/Core/Dxe/Misc/DebugImageInfo.c260
-rw-r--r--EdkModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c214
-rw-r--r--EdkModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c83
-rw-r--r--EdkModulePkg/Core/Dxe/Misc/Stall.c82
-rw-r--r--EdkModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c1339
-rw-r--r--EdkModulePkg/Core/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Core/Dxe/exec.h209
-rw-r--r--EdkModulePkg/Core/Dxe/gcd.h51
-rw-r--r--EdkModulePkg/Core/Dxe/hand.h337
-rw-r--r--EdkModulePkg/Core/Dxe/imem.h227
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIpl.dxs29
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIpl.h146
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIpl.mbd63
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa129
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIplX64.mbd49
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa85
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeLoad.c1010
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c1018
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c70
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c72
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/build.xml47
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/build_X64.xml46
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/ia32/DxeLoadFunc.c51
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/ia32/ImageRead.c112
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c53
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c106
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm1357
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c434
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h239
-rw-r--r--EdkModulePkg/Core/Pei/BootMode/BootMode.c106
-rw-r--r--EdkModulePkg/Core/Pei/Dependency/dependency.c264
-rw-r--r--EdkModulePkg/Core/Pei/Dependency/dependency.h38
-rw-r--r--EdkModulePkg/Core/Pei/Dispatcher/Dispatcher.c535
-rw-r--r--EdkModulePkg/Core/Pei/FwVol/FwVol.c474
-rw-r--r--EdkModulePkg/Core/Pei/Hob/Hob.c189
-rw-r--r--EdkModulePkg/Core/Pei/Image/Image.c237
-rw-r--r--EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.i93
-rw-r--r--EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.s192
-rw-r--r--EdkModulePkg/Core/Pei/Ipf/SwitchToCacheMode.c76
-rw-r--r--EdkModulePkg/Core/Pei/Memory/MemoryServices.c314
-rw-r--r--EdkModulePkg/Core/Pei/PeiMain.h1141
-rw-r--r--EdkModulePkg/Core/Pei/PeiMain.mbd53
-rw-r--r--EdkModulePkg/Core/Pei/PeiMain.msa91
-rw-r--r--EdkModulePkg/Core/Pei/PeiMain/PeiMain.c243
-rw-r--r--EdkModulePkg/Core/Pei/Ppi/Ppi.c658
-rw-r--r--EdkModulePkg/Core/Pei/Reset/Reset.c68
-rw-r--r--EdkModulePkg/Core/Pei/Security/Security.c192
-rw-r--r--EdkModulePkg/Core/Pei/StatusCode/StatusCode.c95
-rw-r--r--EdkModulePkg/Core/Pei/build.xml47
82 files changed, 34970 insertions, 0 deletions
diff --git a/EdkModulePkg/Core/Dxe/DebugImageInfo.h b/EdkModulePkg/Core/Dxe/DebugImageInfo.h
new file mode 100644
index 0000000000..be1d1f1908
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/DebugImageInfo.h
@@ -0,0 +1,126 @@
+/*++
+
+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:
+
+ DebugImageInfo.h
+
+Abstract:
+
+ Support functions for managing debug image info table when loading and unloading
+ images.
+
+--*/
+
+#ifndef __DEBUG_IMAGE_INFO_H__
+#define __DEBUG_IMAGE_INFO_H__
+
+#define FOUR_MEG_PAGES 0x400
+#define FOUR_MEG_MASK ((FOUR_MEG_PAGES * EFI_PAGE_SIZE) - 1)
+
+#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof (VOID *))
+
+VOID
+CoreInitializeDebugImageInfoTable (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Creates and initializes the DebugImageInfo Table. Also creates the configuration
+ table and registers it into the system table.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+Notes:
+ This function allocates memory, frees it, and then allocates memory at an
+ address within the initial allocation. Since this function is called early
+ in DXE core initialization (before drivers are dispatched), this should not
+ be a problem.
+
+--*/
+;
+
+VOID
+CoreUpdateDebugTableCrc32 (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Update the CRC32 in the Debug Table.
+ Since the CRC32 service is made available by the Runtime driver, we have to
+ wait for the Runtime Driver to be installed before the CRC32 can be computed.
+ This function is called elsewhere by the core when the runtime architectural
+ protocol is produced.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+--*/
+;
+
+VOID
+CoreNewDebugImageInfoEntry (
+ UINTN ImageInfoType,
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
+ the table if it's not large enough to accomidate another entry.
+
+Arguments:
+
+ ImageInfoType - type of debug image information
+ LoadedImage - pointer to the loaded image protocol for the image being loaded
+ ImageHandle - image handle for the image being loaded
+
+Returns:
+ NA
+
+--*/
+;
+
+VOID
+CoreRemoveDebugImageInfoEntry (
+ EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Removes and frees an entry from the DebugImageInfo Table.
+
+Arguments:
+
+ ImageHandle - image handle for the image being unloaded
+
+Returns:
+
+ NA
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c b/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
new file mode 100644
index 0000000000..32ba23a957
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
@@ -0,0 +1,1159 @@
+/*++
+
+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:
+
+ Tiano DXE Dispatcher.
+
+ Step #1 - When a FV protocol is added to the system every driver in the FV
+ is added to the mDiscoveredList. The SOR, Before, and After Depex are
+ pre-processed as drivers are added to the mDiscoveredList. If an Apriori
+ file exists in the FV those drivers are addeded to the
+ mScheduledQueue. The mFvHandleList is used to make sure a
+ FV is only processed once.
+
+ Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and
+ start it. After mScheduledQueue is drained check the
+ mDiscoveredList to see if any item has a Depex that is ready to
+ be placed on the mScheduledQueue.
+
+ Step #3 - Adding to the mScheduledQueue requires that you process Before
+ and After dependencies. This is done recursively as the call to add
+ to the mScheduledQueue checks for Before and recursively adds
+ all Befores. It then addes the item that was passed in and then
+ processess the After dependecies by recursively calling the routine.
+
+ Dispatcher Rules:
+ The rules for the dispatcher are in chapter 10 of the DXE CIS. Figure 10-3
+ is the state diagram for the DXE dispatcher
+
+ Depex - Dependency Expresion.
+ SOR - Schedule On Request - Don't schedule if this bit is set.
+
+--*/
+
+#include <DxeMain.h>
+
+//
+// The Driver List contains one copy of every driver that has been discovered.
+// Items are never removed from the driver list. List of EFI_CORE_DRIVER_ENTRY
+//
+LIST_ENTRY mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList);
+
+//
+// Queue of drivers that are ready to dispatch. This queue is a subset of the
+// mDiscoveredList.list of EFI_CORE_DRIVER_ENTRY.
+//
+LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
+
+//
+// List of handles who's Fv's have been parsed and added to the mFwDriverList.
+//
+LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList); // list of KNOWN_HANDLE
+
+//
+// Lock for mDiscoveredList, mScheduledQueue, gDispatcherRunning.
+//
+EFI_LOCK mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
+
+
+//
+// Flag for the DXE Dispacher. TRUE if dispatcher is execuing.
+//
+BOOLEAN gDispatcherRunning = FALSE;
+
+//
+// Module globals to manage the FwVol registration notification event
+//
+EFI_EVENT mFwVolEvent;
+VOID *mFwVolEventRegistration;
+
+//
+// List of file types supported by dispatcher
+//
+static EFI_FV_FILETYPE mDxeFileTypes[] = {
+ EFI_FV_FILETYPE_DRIVER,
+ EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,
+ EFI_FV_FILETYPE_DXE_CORE,
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
+};
+
+typedef struct {
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} FV_FILEPATH_DEVICE_PATH;
+
+FV_FILEPATH_DEVICE_PATH mFvDevicePath;
+
+
+//
+// Function Prototypes
+//
+VOID
+CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
+ IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry
+ );
+
+VOID
+EFIAPI
+CoreFwVolEventProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreFvToDevicePath (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ );
+
+STATIC
+EFI_STATUS
+CoreAddToDriverList (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ );
+
+STATIC
+EFI_STATUS
+CoreProcessFvImageFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ );
+
+
+VOID
+CoreAcquireDispatcherLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by gaining lock on mDispatcherLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+
+{
+ CoreAcquireLock (&mDispatcherLock);
+}
+
+VOID
+CoreReleaseDispatcherLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing lock on mDispatcherLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&mDispatcherLock);
+}
+
+
+EFI_STATUS
+CoreGetDepexSectionAndPreProccess (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Read Depex and pre-process the Depex for Before and After. If Section Extraction
+ protocol returns an error via ReadSection defer the reading of the Depex.
+
+Arguments:
+
+ DriverEntry - Driver to work on.
+
+Returns:
+
+ EFI_SUCCESS - Depex read and preprossesed
+
+ EFI_PROTOCOL_ERROR - The section extraction protocol returned an error and
+ Depex reading needs to be retried.
+
+ Other Error - DEPEX not found.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SECTION_TYPE SectionType;
+ UINT32 AuthenticationStatus;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+
+
+ Fv = DriverEntry->Fv;
+
+ //
+ // Grab Depex info, it will never be free'ed.
+ //
+ SectionType = EFI_SECTION_DXE_DEPEX;
+ Status = Fv->ReadSection (
+ DriverEntry->Fv,
+ &DriverEntry->FileName,
+ SectionType,
+ 0,
+ &DriverEntry->Depex,
+ (UINTN *)&DriverEntry->DepexSize,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_PROTOCOL_ERROR) {
+ //
+ // The section extraction protocol failed so set protocol error flag
+ //
+ DriverEntry->DepexProtocolError = TRUE;
+ } else {
+ //
+ // If no Depex assume EFI 1.1 driver model
+ //
+ DriverEntry->Depex = NULL;
+ DriverEntry->Dependent = TRUE;
+ DriverEntry->DepexProtocolError = FALSE;
+ }
+ } else {
+ //
+ // Set Before, After, and Unrequested state information based on Depex
+ // Driver will be put in Dependent or Unrequested state
+ //
+ CorePreProcessDepex (DriverEntry);
+ DriverEntry->DepexProtocolError = FALSE;
+ }
+
+ return Status;
+}
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreSchedule (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Check every driver and locate a matching one. If the driver is found, the Unrequested
+ state flag is cleared.
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Dependent state.
+
+Returns:
+
+ EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared
+
+ EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set.
+
+--*/
+{
+ LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Check every driver
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
+ DriverEntry->Unrequested &&
+ CompareGuid (DriverName, &DriverEntry->FileName)) {
+ //
+ // Move the driver from the Unrequested to the Dependent state
+ //
+ CoreAcquireDispatcherLock ();
+ DriverEntry->Unrequested = FALSE;
+ DriverEntry->Dependent = TRUE;
+ CoreReleaseDispatcherLock ();
+
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreTrust (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Convert a driver from the Untrused back to the Scheduled state
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Scheduled state
+
+Returns:
+
+ EFI_SUCCESS - The file was found in the untrusted state, and it was promoted
+ to the trusted state.
+
+ EFI_NOT_FOUND - The file was not found in the untrusted state.
+
+--*/
+{
+ LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Check every driver
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
+ DriverEntry->Untrusted &&
+ CompareGuid (DriverName, &DriverEntry->FileName)) {
+ //
+ // Transition driver from Untrusted to Scheduled state.
+ //
+ CoreAcquireDispatcherLock ();
+ DriverEntry->Untrusted = FALSE;
+ DriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
+ CoreReleaseDispatcherLock ();
+
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This is the main Dispatcher for DXE and it exits when there are no more
+ drivers to run. Drain the mScheduledQueue and load and start a PE
+ image for each driver. Search the mDiscoveredList to see if any driver can
+ be placed on the mScheduledQueue. If no drivers are placed on the
+ mScheduledQueue exit the function. On exit it is assumed the Bds()
+ will be called, and when the Bds() exits the Dispatcher will be called
+ again.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ EFI_ALREADY_STARTED - The DXE Dispatcher is already running
+
+ EFI_NOT_FOUND - No DXE Drivers were dispatched
+
+ EFI_SUCCESS - One or more DXE Drivers were dispatched
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+ BOOLEAN ReadyToRun;
+
+ if (gDispatcherRunning) {
+ //
+ // If the dispatcher is running don't let it be restarted.
+ //
+ return EFI_ALREADY_STARTED;
+ }
+
+ gDispatcherRunning = TRUE;
+
+
+ ReturnStatus = EFI_NOT_FOUND;
+ do {
+ //
+ // Drain the Scheduled Queue
+ //
+ while (!IsListEmpty (&mScheduledQueue)) {
+ DriverEntry = CR (
+ mScheduledQueue.ForwardLink,
+ EFI_CORE_DRIVER_ENTRY,
+ ScheduledLink,
+ EFI_CORE_DRIVER_ENTRY_SIGNATURE
+ );
+
+ //
+ // Load the DXE Driver image into memory. If the Driver was transitioned from
+ // Untrused to Scheduled it would have already been loaded so we may need to
+ // skip the LoadImage
+ //
+ if (DriverEntry->ImageHandle == NULL) {
+ Status = CoreLoadImage (
+ TRUE,
+ gDxeCoreImageHandle,
+ DriverEntry->FvFileDevicePath,
+ NULL,
+ 0,
+ &DriverEntry->ImageHandle
+ );
+
+ //
+ // Update the driver state to reflect that it's been loaded
+ //
+ if (EFI_ERROR (Status)) {
+ CoreAcquireDispatcherLock ();
+
+ if (Status == EFI_SECURITY_VIOLATION) {
+ //
+ // Take driver from Scheduled to Untrused state
+ //
+ DriverEntry->Untrusted = TRUE;
+ } else {
+ //
+ // The DXE Driver could not be loaded, and do not attempt to load or start it again.
+ // Take driver from Scheduled to Initialized.
+ //
+ // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
+ //
+ DriverEntry->Initialized = TRUE;
+ }
+
+ DriverEntry->Scheduled = FALSE;
+ RemoveEntryList (&DriverEntry->ScheduledLink);
+
+ CoreReleaseDispatcherLock ();
+
+ //
+ // If it's an error don't try the StartImage
+ //
+ continue;
+ }
+ }
+
+ CoreAcquireDispatcherLock ();
+
+ DriverEntry->Scheduled = FALSE;
+ DriverEntry->Initialized = TRUE;
+ RemoveEntryList (&DriverEntry->ScheduledLink);
+
+ CoreReleaseDispatcherLock ();
+
+
+ CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle);
+ Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);
+ CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, DriverEntry->ImageHandle);
+
+ ReturnStatus = EFI_SUCCESS;
+ }
+
+ //
+ // Search DriverList for items to place on Scheduled Queue
+ //
+ ReadyToRun = FALSE;
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+
+ if (DriverEntry->DepexProtocolError){
+ //
+ // If Section Extraction Protocol did not let the Depex be read before retry the read
+ //
+ Status = CoreGetDepexSectionAndPreProccess (DriverEntry);
+ }
+
+ if (DriverEntry->Dependent) {
+ if (CoreIsSchedulable (DriverEntry)) {
+ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ ReadyToRun = TRUE;
+ }
+ }
+ }
+ } while (ReadyToRun);
+
+ gDispatcherRunning = FALSE;
+
+ return ReturnStatus;
+}
+
+
+VOID
+CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
+ IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
+ must add any driver with a before dependency on InsertedDriverEntry first.
+ You do this by recursively calling this routine. After all the Befores are
+ processed you can add InsertedDriverEntry to the mScheduledQueue.
+ Then you can add any driver with an After dependency on InsertedDriverEntry
+ by recursively calling this routine.
+
+Arguments:
+
+ InsertedDriverEntry - The driver to insert on the ScheduledLink Queue
+
+Returns:
+
+ NONE
+
+--*/
+{
+ LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Process Before Dependency
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->Before && DriverEntry->Dependent) {
+ if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
+ //
+ // Recursively process BEFORE
+ //
+ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ }
+ }
+ }
+
+ //
+ // Convert driver from Dependent to Scheduled state
+ //
+ CoreAcquireDispatcherLock ();
+
+ InsertedDriverEntry->Dependent = FALSE;
+ InsertedDriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);
+
+ CoreReleaseDispatcherLock ();
+
+ //
+ // Process After Dependency
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->After && DriverEntry->Dependent) {
+ if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
+ //
+ // Recursively process AFTER
+ //
+ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ }
+ }
+ }
+}
+
+
+BOOLEAN
+FvHasBeenProcessed (
+ IN EFI_HANDLE FvHandle
+ )
+/*++
+
+Routine Description:
+
+ Return TRUE if the Fv has been processed, FALSE if not.
+
+Arguments:
+
+ FvHandle - The handle of a FV that's being tested
+
+Returns:
+
+ TRUE - Fv protocol on FvHandle has been processed
+
+ FALSE - Fv protocol on FvHandle has not yet been processed
+
+--*/
+{
+ LIST_ENTRY *Link;
+ KNOWN_HANDLE *KnownHandle;
+
+ for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
+ KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
+ if (KnownHandle->Handle == FvHandle) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+VOID
+FvIsBeingProcesssed (
+ IN EFI_HANDLE FvHandle
+ )
+/*++
+
+Routine Description:
+
+ Remember that Fv protocol on FvHandle has had it's drivers placed on the
+ mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are
+ never removed/freed from the mFvHandleList.
+
+Arguments:
+
+ FvHandle - The handle of a FV that has been processed
+
+Returns:
+
+ None
+
+--*/
+{
+ KNOWN_HANDLE *KnownHandle;
+
+ KnownHandle = CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE));
+ ASSERT (KnownHandle != NULL);
+
+ KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
+ KnownHandle->Handle = FvHandle;
+ InsertTailList (&mFvHandleList, &KnownHandle->Link);
+}
+
+
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreFvToDevicePath (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Convert FvHandle and DriverName into an EFI device path
+
+Arguments:
+
+ Fv - Fv protocol, needed to read Depex info out of FLASH.
+
+ FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
+ PE image can be read out of the FV at a later time.
+
+ DriverName - Name of driver to add to mDiscoveredList.
+
+Returns:
+
+ Pointer to device path constructed from FvHandle and DriverName
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *FileNameDevicePath;
+
+ //
+ // Remember the device path of the FV
+ //
+ Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
+ if (EFI_ERROR (Status)) {
+ FileNameDevicePath = NULL;
+ } else {
+ //
+ // Build a device path to the file in the FV to pass into gBS->LoadImage
+ //
+ EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
+ mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
+ mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
+
+ FileNameDevicePath = CoreAppendDevicePath (
+ FvDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
+ );
+ }
+
+ return FileNameDevicePath;
+}
+
+
+
+EFI_STATUS
+CoreAddToDriverList (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,
+ and initilize any state variables. Read the Depex from the FV and store it
+ in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.
+ The Discovered list is never free'ed and contains booleans that represent the
+ other possible DXE driver states.
+
+Arguments:
+
+ Fv - Fv protocol, needed to read Depex info out of FLASH.
+
+ FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
+ PE image can be read out of the FV at a later time.
+
+ DriverName - Name of driver to add to mDiscoveredList.
+
+Returns:
+
+ EFI_SUCCESS - If driver was added to the mDiscoveredList.
+
+ EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName
+ may be active in the system at any one time.
+
+--*/
+{
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+
+ //
+ // Create the Driver Entry for the list. ZeroPool initializes lots of variables to
+ // NULL or FALSE.
+ //
+ DriverEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY));
+ ASSERT (DriverEntry != NULL);
+
+ DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE;
+ CopyMem (&DriverEntry->FileName, DriverName, sizeof (EFI_GUID));
+ DriverEntry->FvHandle = FvHandle;
+ DriverEntry->Fv = Fv;
+ DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName);
+
+ CoreGetDepexSectionAndPreProccess (DriverEntry);
+
+ CoreAcquireDispatcherLock ();
+
+ InsertTailList (&mDiscoveredList, &DriverEntry->Link);
+
+ CoreReleaseDispatcherLock ();
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+CoreProcessFvImageFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.
+
+Arguments:
+
+ Fv - The FIRMWARE_VOLUME protocol installed on the FV.
+ FvHandle - The handle which FVB protocol installed on.
+ DriverName - The driver guid specified.
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough memory or other resource.
+
+ EFI_VOLUME_CORRUPTED - Corrupted volume.
+
+ EFI_SUCCESS - Function successfully returned.
+
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SECTION_TYPE SectionType;
+ UINT32 AuthenticationStatus;
+ VOID *Buffer;
+ UINTN BufferSize;
+
+ //
+ // Read the first (and only the first) firmware volume section
+ //
+ SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
+ Buffer = NULL;
+ BufferSize = 0;
+ Status = Fv->ReadSection (
+ Fv,
+ DriverName,
+ SectionType,
+ 0,
+ &Buffer,
+ &BufferSize,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Produce a FVB protocol for the file
+ //
+ Status = ProduceFVBProtocolOnBuffer (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer,
+ (UINT64)BufferSize,
+ FvHandle,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status) && (Buffer != NULL)) {
+ //
+ // ReadSection or Produce FVB failed, Free data buffer
+ //
+ CoreFreePool (Buffer);
+
+ }
+
+ return Status;
+}
+
+
+VOID
+EFIAPI
+CoreFwVolEventProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Event notification that is fired every time a FV dispatch protocol is added.
+ More than one protocol may have been added when this event is fired, so you
+ must loop on CoreLocateHandle () to see how many protocols were added and
+ do the following to each FV:
+
+ If the Fv has already been processed, skip it. If the Fv has not been
+ processed then mark it as being processed, as we are about to process it.
+
+ Read the Fv and add any driver in the Fv to the mDiscoveredList.The
+ mDiscoveredList is never free'ed and contains variables that define
+ the other states the DXE driver transitions to..
+
+ While you are at it read the A Priori file into memory.
+ Place drivers in the A Priori list onto the mScheduledQueue.
+
+Arguments:
+
+ Event - The Event that is being processed, not used.
+
+ Context - Event Context, not used.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS GetNextFileStatus;
+ EFI_STATUS SecurityStatus;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
+ EFI_HANDLE FvHandle;
+ UINTN BufferSize;
+ EFI_GUID NameGuid;
+ UINTN Key;
+ EFI_FV_FILETYPE Type;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+ EFI_GUID *AprioriFile;
+ UINTN AprioriEntryCount;
+ UINTN Index;
+ LIST_ENTRY *Link;
+ UINT32 AuthenticationStatus;
+ UINTN SizeOfBuffer;
+
+
+ while (TRUE) {
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = CoreLocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mFwVolEventRegistration,
+ &BufferSize,
+ &FvHandle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If no more notification events exit
+ //
+ return;
+ }
+
+ if (FvHasBeenProcessed (FvHandle)) {
+ //
+ // This Fv has already been processed so lets skip it!
+ //
+ continue;
+ }
+
+ Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, (VOID **)&Fv);
+ if (EFI_ERROR (Status)) {
+ //
+ // If no dispatch protocol then skip, but do not marked as being processed as it
+ // may show up later.
+ //
+ continue;
+ }
+
+ //
+ // Since we are about to process this Fv mark it as processed.
+ //
+ FvIsBeingProcesssed (FvHandle);
+
+
+ Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Fv);
+ if (EFI_ERROR (Status)) {
+ //
+ // The Handle has a FirmwareVolumeDispatch protocol and should also contiain
+ // a FirmwareVolume protocol thus we should never get here.
+ //
+ ASSERT (FALSE);
+ continue;
+ }
+
+ Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
+ if (EFI_ERROR (Status)) {
+ //
+ // The Firmware volume doesn't have device path, can't be dispatched.
+ //
+ continue;
+ }
+
+ //
+ // Evaluate the authentication status of the Firmware Volume through
+ // Security Architectural Protocol
+ //
+ if (gSecurity != NULL) {
+ SecurityStatus = gSecurity->FileAuthenticationState (
+ gSecurity,
+ 0,
+ FvDevicePath
+ );
+ if (SecurityStatus != EFI_SUCCESS) {
+ //
+ // Security check failed. The firmware volume should not be used for any purpose.
+ //
+ continue;
+ }
+ }
+
+ //
+ // Discover Drivers in FV and add them to the Discovered Driver List.
+ // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
+ // EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core
+ // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb
+ //
+ for (Index = 0; Index < sizeof (mDxeFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {
+ //
+ // Initialize the search key
+ //
+ Key = 0;
+ do {
+ Type = mDxeFileTypes[Index];
+ GetNextFileStatus = Fv->GetNextFile (
+ Fv,
+ &Key,
+ &Type,
+ &NameGuid,
+ &Attributes,
+ &Size
+ );
+ if (!EFI_ERROR (GetNextFileStatus)) {
+ if (Type == EFI_FV_FILETYPE_DXE_CORE) {
+ //
+ // If this is the DXE core fill in it's DevicePath & DeviceHandle
+ //
+ if (gDxeCoreLoadedImage->FilePath == NULL) {
+ if (CompareGuid (&NameGuid, gDxeCoreFileName)) {
+ CopyGuid (&mFvDevicePath.File.NameGuid, &NameGuid);
+
+ gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath (
+ (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
+ );
+ gDxeCoreLoadedImage->DeviceHandle = FvHandle;
+ }
+ }
+ } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+ //
+ // Found a firmware volume image. Produce a firmware volume block
+ // protocol for it so it gets dispatched from. This is usually a
+ // capsule.
+ //
+ CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);
+ } else {
+ //
+ // Transition driver from Undiscovered to Discovered state
+ //
+ CoreAddToDriverList (Fv, FvHandle, &NameGuid);
+ }
+ }
+ } while (!EFI_ERROR (GetNextFileStatus));
+ }
+
+ //
+ // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
+ //
+ AprioriFile = NULL;
+ Status = Fv->ReadSection (
+ Fv,
+ &gAprioriGuid,
+ EFI_SECTION_RAW,
+ 0,
+ (VOID **)&AprioriFile,
+ &SizeOfBuffer,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
+ } else {
+ AprioriEntryCount = 0;
+ }
+
+ //
+ // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
+ // drivers not in the current FV and these must be skipped since the a priori list
+ // is only valid for the FV that it resided in.
+ //
+ CoreAcquireDispatcherLock ();
+
+ for (Index = 0; Index < AprioriEntryCount; Index++) {
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&
+ (FvHandle == DriverEntry->FvHandle)) {
+ DriverEntry->Dependent = FALSE;
+ DriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
+ break;
+ }
+ }
+ }
+
+ CoreReleaseDispatcherLock ();
+
+ //
+ // Free data allocated by Fv->ReadSection ()
+ //
+ CoreFreePool (AprioriFile);
+ }
+}
+
+
+VOID
+CoreInitializeDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the dispatcher. Initialize the notification function that runs when
+ a FV protocol is added to the system.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ mFwVolEvent = CoreCreateProtocolNotifyEvent (
+ &gEfiFirmwareVolumeProtocolGuid,
+ EFI_TPL_CALLBACK,
+ CoreFwVolEventProtocolNotify,
+ NULL,
+ &mFwVolEventRegistration,
+ TRUE
+ );
+}
+
+//
+// Function only used in debug buils
+//
+VOID
+CoreDisplayDiscoveredNotDispatched (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Traverse the discovered list for any drivers that were discovered but not loaded
+ because the dependency experessions evaluated to false
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->Dependent) {
+ DEBUG ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
+ }
+ }
+}
diff --git a/EdkModulePkg/Core/Dxe/Dispatcher/dependency.c b/EdkModulePkg/Core/Dxe/Dispatcher/dependency.c
new file mode 100644
index 0000000000..e6dc3282e6
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Dispatcher/dependency.c
@@ -0,0 +1,450 @@
+/*++
+
+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:
+
+ DXE 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 <DxeMain.h>
+
+//
+// Global stack used to evaluate dependency expressions
+//
+BOOLEAN *mDepexEvaluationStack = NULL;
+BOOLEAN *mDepexEvaluationStackEnd = NULL;
+BOOLEAN *mDepexEvaluationStackPointer = NULL;
+
+//
+// Worker functions
+//
+
+STATIC
+EFI_STATUS
+GrowDepexStack (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Grow size of the Depex stack
+
+Arguments:
+
+ Stack - Old stack on the way in and new stack on the way out
+
+ StackSize - New size of the stack
+
+Returns:
+
+ EFI_SUCCESS - Stack successfully growed.
+
+ EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack.
+
+
+
+--*/
+{
+ BOOLEAN *NewStack;
+ UINTN Size;
+
+ Size = DEPEX_STACK_SIZE_INCREMENT;
+ if (mDepexEvaluationStack != NULL) {
+ Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);
+ }
+
+ NewStack = CoreAllocateBootServicesPool (Size * sizeof (BOOLEAN));
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (mDepexEvaluationStack != NULL) {
+ //
+ // Copy to Old Stack to the New Stack
+ //
+ CopyMem (
+ NewStack,
+ mDepexEvaluationStack,
+ (mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (BOOLEAN)
+ );
+
+ //
+ // Free The Old Stack
+ //
+ CoreFreePool (mDepexEvaluationStack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);
+ mDepexEvaluationStack = NewStack;
+ mDepexEvaluationStackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+PushBool (
+ IN BOOLEAN Value
+ )
+/*++
+
+Routine Description:
+
+ Push an element onto the Boolean Stack
+
+Arguments:
+
+ Value - BOOLEAN to push.
+
+Returns:
+
+ EFI_SUCCESS - The value was pushed onto the stack.
+
+ EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowDepexStack ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ *mDepexEvaluationStackPointer = Value;
+ mDepexEvaluationStackPointer++;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+PopBool (
+ OUT BOOLEAN *Value
+ )
+/*++
+
+Routine Description:
+
+ Pop an element from the Boolean stack.
+
+Arguments:
+
+ Value - BOOLEAN to pop.
+
+Returns:
+
+ EFI_SUCCESS - The value was popped onto the stack.
+
+ EFI_ACCESS_DENIED - The pop operation underflowed the stack
+
+--*/
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ mDepexEvaluationStackPointer--;
+ *Value = *mDepexEvaluationStackPointer;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CorePreProcessDepex (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Preprocess dependency expression and update DriverEntry to reflect the
+ state of Before, After, and SOR dependencies. If DriverEntry->Before
+ or DriverEntry->After is set it will never be cleared. If SOR is set
+ it will be cleared by CoreSchedule(), and then the driver can be
+ dispatched.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ EFI_SUCCESS - It always works.
+
+--*/
+{
+ UINT8 *Iterator;
+
+ Iterator = DriverEntry->Depex;
+ if (*Iterator == EFI_DEP_SOR) {
+ DriverEntry->Unrequested = TRUE;
+ } else {
+ DriverEntry->Dependent = TRUE;
+ }
+
+ if (*Iterator == EFI_DEP_BEFORE) {
+ DriverEntry->Before = TRUE;
+ } else if (*Iterator == EFI_DEP_AFTER) {
+ DriverEntry->After = TRUE;
+ }
+
+ if (DriverEntry->Before || DriverEntry->After) {
+ CopyMem (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GUID));
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+BOOLEAN
+CoreIsSchedulable (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ This is the POSTFIX version of the dependency evaluator. This code does
+ not need to handle Before or After, as it is not valid to call this
+ routine in this case. The SOR is just ignored and is a nop in the grammer.
+
+ POSTFIX means all the math is done on top of the stack.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ TRUE - If driver is ready to run.
+
+ FALSE - If driver is not ready to run or some fatal error was found.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 *Iterator;
+ BOOLEAN Operator;
+ BOOLEAN Operator2;
+ EFI_GUID DriverGuid;
+ VOID *Interface;
+
+ if (DriverEntry->After || DriverEntry->Before) {
+ //
+ // If Before or After Depex skip as CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter ()
+ // processes them.
+ //
+ return FALSE;
+ }
+
+ if (DriverEntry->Depex == NULL) {
+ //
+ // A NULL Depex means treat the driver like an EFI 1.0 thing.
+ //
+ Status = CoreAllEfiServicesAvailable ();
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ //
+ // Clean out memory leaks in Depex Boolean stack. Leaks are only caused by
+ // incorrectly formed DEPEX expressions
+ //
+ mDepexEvaluationStackPointer = mDepexEvaluationStack;
+
+
+ Iterator = DriverEntry->Depex;
+
+ while (TRUE) {
+ //
+ // Check to see if we are attempting to fetch dependency expression instructions
+ // past the end of the dependency expression.
+ //
+ if (((UINTN)Iterator - (UINTN)DriverEntry->Depex) > DriverEntry->DepexSize) {
+ return FALSE;
+ }
+
+ //
+ // Look at the opcode of the dependency expression instruction.
+ //
+ switch (*Iterator) {
+ case EFI_DEP_BEFORE:
+ case EFI_DEP_AFTER:
+ //
+ // For a well-formed Dependency Expression, the code should never get here.
+ // The BEFORE and AFTER are processed prior to this routine's invocation.
+ // If the code flow arrives at this point, there was a BEFORE or AFTER
+ // that were not the first opcodes.
+ //
+ ASSERT (FALSE);
+ case EFI_DEP_SOR:
+ //
+ // These opcodes can only appear once as the first opcode. If it is found
+ // at any other location, then the dependency expression evaluates to FALSE
+ //
+ if (Iterator != DriverEntry->Depex) {
+ return FALSE;
+ }
+ //
+ // Otherwise, it is the first opcode and should be treated as a NOP.
+ //
+ break;
+
+ case EFI_DEP_PUSH:
+ //
+ // Push operator is followed by a GUID. Test to see if the GUID protocol
+ // is installed and push the boolean result on the stack.
+ //
+ CopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID));
+
+ Status = CoreLocateProtocol (&DriverGuid, NULL, &Interface);
+
+ if (EFI_ERROR (Status)) {
+ Status = PushBool (FALSE);
+ } else {
+ *Iterator = EFI_DEP_REPLACE_TRUE;
+ Status = PushBool (TRUE);
+ }
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Iterator += sizeof (EFI_GUID);
+ break;
+
+ case EFI_DEP_AND:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PopBool (&Operator2);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN)(Operator && Operator2));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_OR:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PopBool (&Operator2);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN)(Operator || Operator2));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_NOT:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN)(!Operator));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_TRUE:
+ Status = PushBool (TRUE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_FALSE:
+ Status = PushBool (FALSE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_END:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return Operator;
+
+ case EFI_DEP_REPLACE_TRUE:
+ Status = PushBool (TRUE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Iterator += sizeof (EFI_GUID);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ //
+ // Skip over the Dependency Op Code we just processed in the switch.
+ // The math is done out of order, but it should not matter. That is
+ // we may add in the sizeof (EFI_GUID) before we account for the OP Code.
+ // This is not an issue, since we just need the correct end result. You
+ // need to be careful using Iterator in the loop as it's intermediate value
+ // may be strange.
+ //
+ Iterator++;
+ }
+ return FALSE;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/DxeMain.h b/EdkModulePkg/Core/Dxe/DxeMain.h
new file mode 100644
index 0000000000..9a9ba683e7
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/DxeMain.h
@@ -0,0 +1,2539 @@
+/*++
+
+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:
+
+ DxeMain.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _DXE_MAIN_H_
+#define _DXE_MAIN_H_
+
+
+#include "DebugImageInfo.h"
+#include "Library.h"
+#include "FwVolBlock.h"
+#include "FwVolDriver.h"
+#include "gcd.h"
+#include "imem.h"
+#include "Image.h"
+#include "Exec.h"
+#include "hand.h"
+
+typedef struct {
+ EFI_GUID *ProtocolGuid;
+ VOID **Protocol;
+ EFI_EVENT Event;
+ VOID *Registration;
+ BOOLEAN Present;
+} ARCHITECTURAL_PROTOCOL_ENTRY;
+
+
+//
+// DXE Dispatcher Data structures
+//
+
+#define KNOWN_HANDLE_SIGNATURE EFI_SIGNATURE_32('k','n','o','w')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link; // mFvHandleList
+ EFI_HANDLE Handle;
+} KNOWN_HANDLE;
+
+
+#define EFI_CORE_DRIVER_ENTRY_SIGNATURE EFI_SIGNATURE_32('d','r','v','r')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link; // mDriverList
+
+ LIST_ENTRY ScheduledLink; // mScheduledQueue
+
+ EFI_HANDLE FvHandle;
+ EFI_GUID FileName;
+ EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+
+ VOID *Depex;
+ UINTN DepexSize;
+
+ BOOLEAN Before;
+ BOOLEAN After;
+ EFI_GUID BeforeAfterGuid;
+
+ BOOLEAN Dependent;
+ BOOLEAN Unrequested;
+ BOOLEAN Scheduled;
+ BOOLEAN Untrusted;
+ BOOLEAN Initialized;
+ BOOLEAN DepexProtocolError;
+
+ EFI_HANDLE ImageHandle;
+
+} EFI_CORE_DRIVER_ENTRY;
+
+//
+//The data structure of GCD memory map entry
+//
+#define EFI_GCD_MAP_SIGNATURE EFI_SIGNATURE_32('g','c','d','m')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 EndAddress;
+ UINT64 Capabilities;
+ UINT64 Attributes;
+ EFI_GCD_MEMORY_TYPE GcdMemoryType;
+ EFI_GCD_IO_TYPE GcdIoType;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE DeviceHandle;
+} EFI_GCD_MAP_ENTRY;
+
+//
+// DXE Core Global Variables
+//
+extern EFI_SYSTEM_TABLE *gST;
+extern EFI_BOOT_SERVICES *gBS;
+extern EFI_RUNTIME_SERVICES *gRT;
+extern EFI_DXE_SERVICES *gDS;
+extern EFI_HANDLE gDxeCoreImageHandle;
+
+extern EFI_DECOMPRESS_PROTOCOL gEfiDecompress;
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader;
+
+extern EFI_RUNTIME_ARCH_PROTOCOL *gRuntime;
+extern EFI_CPU_ARCH_PROTOCOL *gCpu;
+extern EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer;
+extern EFI_METRONOME_ARCH_PROTOCOL *gMetronome;
+extern EFI_TIMER_ARCH_PROTOCOL *gTimer;
+extern EFI_SECURITY_ARCH_PROTOCOL *gSecurity;
+extern EFI_BDS_ARCH_PROTOCOL *gBds;
+extern EFI_STATUS_CODE_PROTOCOL *gStatusCode;
+
+extern EFI_TPL gEfiCurrentTpl;
+
+extern EFI_GUID *gDxeCoreFileName;
+extern EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage;
+
+extern EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1];
+
+extern BOOLEAN gDispatcherRunning;
+
+//
+// Service Initialization Functions
+//
+
+
+VOID
+CoreInitializePool (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the pool.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreAddMemoryDescriptor (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 NumberOfPages,
+ IN UINT64 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the memory map and add descriptors to
+ the current descriptor list.
+
+ The first descriptor that is added must be general usable
+ memory as the addition allocates heap.
+
+Arguments:
+
+ Type - The type of memory to add
+
+ Start - The starting address in the memory range
+ Must be page aligned
+
+ NumberOfPages - The number of pages in the range
+
+ Attribute - Attributes of the memory to add
+
+Returns:
+
+ None. The range is added to the memory map
+
+--*/
+;
+
+VOID
+CoreReleaseGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Release memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+;
+
+VOID
+CoreAcquireGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Acquire memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+;
+
+EFI_STATUS
+CoreInitializeMemoryServices (
+ IN VOID **HobStart,
+ IN EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
+ IN UINT64 *MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map.
+
+Arguments:
+
+ HobStart - The start address of the HOB.
+
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+
+ MemoryLength - Length of memory region found to init DXE core.
+
+Returns:
+
+ EFI_SUCCESS - Memory services successfully initialized.
+
+--*/
+;
+
+
+EFI_STATUS
+CoreInitializeGcdServices (
+ IN VOID **HobStart,
+ IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map.
+
+Arguments:
+
+ HobStart - The start address of the HOB
+
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+
+ MemoryLength - Length of memory region found to init DXE core.
+
+
+Returns:
+
+ EFI_SUCCESS - GCD services successfully initialized.
+
+--*/
+;
+
+EFI_STATUS
+CoreInitializeEventServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes "event" support and populates parts of the System and Runtime Table.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Always return success
+
+--*/
+;
+
+EFI_STATUS
+CoreShutdownEventServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Register all runtime events to make sure they are still available after ExitBootService.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Always return success
+
+--*/
+;
+
+EFI_STATUS
+CoreInitializeImageServices (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Add the Image Services to EFI Boot Services Table and install the protocol
+ interfaces for this image.
+
+Arguments:
+
+ HobStart - The HOB to initialize
+
+Returns:
+
+ Status code.
+
+--*/
+;
+
+EFI_STATUS
+CoreShutdownImageServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Transfer control of runtime images to runtime service
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Function successfully returned
+
+--*/
+;
+
+VOID
+CoreNotifyOnArchProtocolInstallation (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Creates an event that is fired everytime a Protocol of a specific type is installed
+
+Arguments:
+ NONE
+
+Returns:
+ NONE
+
+--*/
+;
+
+EFI_STATUS
+CoreAllEfiServicesAvailable (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return TRUE if all AP services are availible.
+
+Arguments:
+ NONE
+
+Returns:
+ EFI_SUCCESS - All AP services are available
+ EFI_NOT_FOUND - At least one AP service is not available
+
+--*/
+;
+
+VOID
+CalculateEfiHdrCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Calcualte the 32-bit CRC in a EFI table using the service provided by the
+ gRuntime service.
+
+Arguments:
+
+ Hdr - Pointer to an EFI standard header
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+EFIAPI
+CoreTimerTick (
+ IN UINT64 Duration
+ )
+/*++
+
+Routine Description:
+
+ Called by the platform code to process a tick.
+
+Arguments:
+
+ Duration - The number of 100ns elasped since the last call to TimerTick
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreInitializeDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the dispatcher. Initialize the notification function that runs when
+ a FV protocol is added to the system.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+;
+
+BOOLEAN
+CoreIsSchedulable (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ This is the POSTFIX version of the dependency evaluator. This code does
+ not need to handle Before or After, as it is not valid to call this
+ routine in this case. The SOR is just ignored and is a nop in the grammer.
+
+ POSTFIX means all the math is done on top of the stack.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ TRUE - If driver is ready to run.
+
+ FALSE - If driver is not ready to run or some fatal error was found.
+
+--*/
+;
+
+EFI_STATUS
+CorePreProcessDepex (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Preprocess dependency expression and update DriverEntry to reflect the
+ state of Before, After, and SOR dependencies. If DriverEntry->Before
+ or DriverEntry->After is set it will never be cleared. If SOR is set
+ it will be cleared by CoreSchedule(), and then the driver can be
+ dispatched.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ EFI_SUCCESS - It always works.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreExitBootServices (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ EFI 1.0 API to terminate Boot Services
+
+Arguments:
+
+ ImageHandle - Handle that represents the identity of the calling image
+
+ MapKey -Key to the latest memory map.
+
+Returns:
+
+ EFI_SUCCESS - Boot Services terminated
+ EFI_INVALID_PARAMETER - MapKey is incorrect.
+
+--*/
+;
+
+EFI_STATUS
+CoreTerminateMemoryMap (
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ Make sure the memory map is following all the construction rules,
+ it is the last time to check memory map error before exit boot services.
+
+Arguments:
+
+ MapKey - Memory map key
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Memory map not consistent with construction rules.
+
+ EFI_SUCCESS - Valid memory map.
+
+--*/
+;
+
+VOID
+CoreNotifySignalList (
+ IN EFI_GUID *EventGroup
+ )
+/*++
+
+Routine Description:
+
+ Signals all events on the requested list
+
+Arguments:
+
+ SignalType - The list to signal
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreInstallConfigurationTable (
+ IN EFI_GUID *Guid,
+ IN VOID *Table
+ )
+/*++
+
+Routine Description:
+
+ Boot Service called to add, modify, or remove a system configuration table from
+ the EFI System Table.
+
+Arguments:
+
+ Guid: Pointer to the GUID for the entry to add, update, or remove
+ Table: Pointer to the configuration table for the entry to add, update, or
+ remove, may be NULL.
+
+Returns:
+
+ EFI_SUCCESS Guid, Table pair added, updated, or removed.
+ EFI_INVALID_PARAMETER Input GUID not valid.
+ EFI_NOT_FOUND Attempted to delete non-existant entry
+ EFI_OUT_OF_RESOURCES Not enough memory available
+
+--*/
+;
+
+
+EFI_TPL
+EFIAPI
+CoreRaiseTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Raise the task priority level to the new level.
+ High level is implemented by disabling processor interrupts.
+
+Arguments:
+
+ NewTpl - New task priority level
+
+Returns:
+
+ The previous task priority level
+
+--*/
+;
+
+
+VOID
+EFIAPI
+CoreRestoreTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Lowers the task priority to the previous value. If the new
+ priority unmasks events at a higher priority, they are dispatched.
+
+Arguments:
+
+ NewTpl - New, lower, task priority
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreStall (
+ IN UINTN Microseconds
+ )
+/*++
+
+Routine Description:
+
+ Introduces a fine-grained stall.
+
+Arguments:
+
+ Microseconds The number of microseconds to stall execution
+
+Returns:
+
+ EFI_SUCCESS - Execution was stalled for at least the requested amount
+ of microseconds.
+
+ EFI_NOT_AVAILABLE_YET - gMetronome is not available yet
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreSetWatchdogTimer (
+ IN UINTN Timeout,
+ IN UINT64 WatchdogCode,
+ IN UINTN DataSize,
+ IN CHAR16 *WatchdogData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Sets the system's watchdog timer.
+
+Arguments:
+
+ Timeout The number of seconds. Zero disables the timer.
+
+ ///////following three parameters are left for platform specific using
+
+ WatchdogCode The numberic code to log. 0x0 to 0xffff are firmware
+ DataSize Size of the optional data
+ WatchdogData Optional Null terminated unicode string followed by binary
+ data.
+
+Returns:
+
+ EFI_SUCCESS Timeout has been set
+ EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet
+ EFI_UNSUPPORTED System does not have a timer (currently not used)
+ EFI_DEVICE_ERROR Could not complete due to hardware error
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreInstallProtocolInterface (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
+ Calls the private one which contains a BOOLEAN parameter for notifications
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+Returns:
+
+ Status code
+
+--*/
+;
+
+EFI_STATUS
+CoreInstallProtocolInterfaceNotify (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface,
+ IN BOOLEAN Notify
+ )
+/*++
+
+Routine Description:
+
+ Installs a protocol interface into the boot services environment.
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+ Notify - Whether to notify the notification list for this protocol
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Protocol interface successfully installed
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreInstallMultipleProtocolInterfaces (
+ IN OUT EFI_HANDLE *Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Installs a list of protocol interface into the boot services environment.
+ This function calls InstallProtocolInterface() in a loop. If any error
+ occures all the protocols added by this function are removed. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to install the protocol handlers on,
+ or NULL if a new handle is to be allocated
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to InstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Handle is NULL.
+
+ EFI_SUCCESS - Protocol interfaces successfully installed.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreUninstallMultipleProtocolInterfaces (
+ IN EFI_HANDLE Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls a list of protocol interface in the boot services environment.
+ This function calls UnisatllProtocolInterface() in a loop. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to uninstall the protocol
+
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to UninstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ Status code
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreReinstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *OldInterface,
+ IN VOID *NewInterface
+ )
+/*++
+
+Routine Description:
+
+ Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
+
+Arguments:
+
+ UserHandle - Handle on which the interface is to be reinstalled
+ Protocol - The numeric ID of the interface
+ OldInterface - A pointer to the old interface
+ NewInterface - A pointer to the new interface
+
+
+Returns:
+
+ Status code.
+
+ On EFI_SUCCESS The protocol interface was installed
+ On EFI_NOT_FOUND The OldInterface on the handle was not found
+ On EFI_INVALID_PARAMETER One of the parameters has an invalid value
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreUninstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls all instances of a protocol:interfacer from a handle.
+ If the last protocol interface is remove from the handle, the
+ handle is freed.
+
+Arguments:
+
+ UserHandle - The handle to remove the protocol handler from
+
+ Protocol - The protocol, of protocol:interface, to remove
+
+ Interface - The interface, of protocol:interface, to remove
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Protocol interface successfully uninstalled.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreHandleProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Queries a handle to determine if it supports a specified protocol.
+
+Arguments:
+
+ UserHandle - The handle being queried.
+
+ Protocol - The published unique identifier of the protocol.
+
+ Interface - Supplies the address where a pointer to the corresponding Protocol
+ Interface is returned.
+
+Returns:
+
+ The requested protocol interface for the handle
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreOpenProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface OPTIONAL,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Locates the installed protocol handler for the handle, and
+ invokes it to obtain the protocol interface. Usage information
+ is registered in the protocol data base.
+
+Arguments:
+
+ UserHandle - The handle to obtain the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ Interface - The location to return the protocol interface
+
+ ImageHandle - The handle of the Image that is opening the protocol interface
+ specified by Protocol and Interface.
+
+ ControllerHandle - The controller handle that is requiring this interface.
+
+ Attributes - The open mode of the protocol interface specified by Handle
+ and Protocol.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Get the protocol interface.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreOpenProtocolInformation (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+ OUT UINTN *EntryCount
+ )
+/*++
+
+Routine Description:
+
+ Return information about Opened protocols in the system
+
+Arguments:
+
+ UserHandle - The handle to close the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ EntryBuffer - A pointer to a buffer of open protocol information in the form of
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+
+ EntryCount - Number of EntryBuffer entries
+
+Returns:
+
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreCloseProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle
+ )
+/*++
+
+Routine Description:
+
+ Close Protocol
+
+Arguments:
+
+ UserHandle - The handle to close the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ ImageHandle - The user of the protocol to close
+
+ ControllerHandle - The user of the protocol to close
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreProtocolsPerHandle (
+ IN EFI_HANDLE UserHandle,
+ OUT EFI_GUID ***ProtocolBuffer,
+ OUT UINTN *ProtocolBufferCount
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+ from pool.
+
+Arguments:
+
+ UserHandle - The handle from which to retrieve the list of protocol interface
+ GUIDs.
+
+ ProtocolBuffer - A pointer to the list of protocol interface GUID pointers that are
+ installed on Handle.
+
+ ProtocolBufferCount - A pointer to the number of GUID pointers present in
+ ProtocolBuffer.
+
+Returns:
+ EFI_SUCCESS - The list of protocol interface GUIDs installed on Handle was returned in
+ ProtocolBuffer. The number of protocol interface GUIDs was
+ returned in ProtocolBufferCount.
+ EFI_INVALID_PARAMETER - Handle is NULL.
+ EFI_INVALID_PARAMETER - Handle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ProtocolBuffer is NULL.
+ EFI_INVALID_PARAMETER - ProtocolBufferCount is NULL.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the results.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreRegisterProtocolNotify (
+ IN EFI_GUID *Protocol,
+ IN EFI_EVENT Event,
+ OUT VOID **Registration
+ )
+/*++
+
+Routine Description:
+
+ Add a new protocol notification record for the request protocol.
+
+Arguments:
+
+ Protocol - The requested protocol to add the notify registration
+
+ Event - The event to signal
+
+ Registration - Returns the registration record
+
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully returned the registration record that has been added
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateHandle (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HANDLE *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Locates the requested handle(s) and returns them in Buffer.
+
+Arguments:
+
+ SearchType - The type of search to perform to locate the handles
+
+ Protocol - The protocol to search for
+
+ SearchKey - Dependant on SearchType
+
+ BufferSize - On input the size of Buffer. On output the
+ size of data returned.
+
+ Buffer - The buffer to return the results in
+
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateDevicePath (
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT EFI_HANDLE *Device
+ )
+/*++
+
+Routine Description:
+
+ Locates the handle to a device on the device path that supports the specified protocol.
+
+Arguments:
+
+ Protocol - The protocol to search for.
+ FilePath - On input, a pointer to a pointer to the device path. On output, the device
+ path pointer is modified to point to the remaining part of the devicepath.
+ Device - A pointer to the returned device handle.
+
+Returns:
+
+ EFI_SUCCESS - The resulting handle was returned.
+ EFI_NOT_FOUND - No handles matched the search.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateHandleBuffer (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *NumberHandles,
+ OUT EFI_HANDLE **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Function returns an array of handles that support the requested protocol
+ in a buffer allocated from pool. This is a version of CoreLocateHandle()
+ that allocates a buffer for the caller.
+
+Arguments:
+
+ SearchType - Specifies which handle(s) are to be returned.
+ Protocol - Provides the protocol to search by.
+ This parameter is only valid for SearchType ByProtocol.
+ SearchKey - Supplies the search key depending on the SearchType.
+ NumberHandles - The number of handles returned in Buffer.
+ Buffer - A pointer to the buffer to return the requested array of
+ handles that support Protocol.
+
+Returns:
+
+ EFI_SUCCESS - The result array of handles was returned.
+ EFI_NOT_FOUND - No handles match the search.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Return the first Protocol Interface that matches the Protocol GUID. If
+ Registration is pasased in return a Protocol Instance that was just add
+ to the system. If Retistration is NULL return the first Protocol Interface
+ you find.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ Registration - Optional Registration Key returned from RegisterProtocolNotify()
+
+ Interface - Return the Protocol interface (instance).
+
+Returns:
+
+ EFI_SUCCESS - If a valid Interface is returned
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_NOT_FOUND - Protocol interface not found
+
+--*/
+;
+
+UINT64
+CoreGetHandleDatabaseKey (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ return handle database key.
+
+Arguments:
+
+ None
+
+Returns:
+
+ Handle database key.
+
+--*/
+;
+
+VOID
+CoreConnectHandlesByKey (
+ UINT64 Key
+ )
+/*++
+
+Routine Description:
+
+ Go connect any handles that were created or modified while a image executed.
+
+Arguments:
+
+ Key - The Key to show that the handle has been created/modified
+
+Returns:
+
+ None
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreConnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *DriverImageHandle OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
+ IN BOOLEAN Recursive
+ )
+/*++
+
+Routine Description:
+
+ Connects one or more drivers to a controller.
+
+Arguments:
+
+ ControllerHandle - Handle of the controller to be connected.
+
+ DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles.
+
+ RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the
+ controller specified by ControllerHandle.
+
+ Recursive - - Whether the function would be called recursively or not.
+
+Returns:
+
+ Status code.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreDisconnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE DriverImageHandle OPTIONAL,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Disonnects a controller from a driver
+
+Arguments:
+
+ ControllerHandle - ControllerHandle The handle of the controller from which driver(s)
+ are to be disconnected.
+ DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
+ ChildHandle - ChildHandle The handle of the child to destroy.
+
+Returns:
+
+ EFI_SUCCESS - One or more drivers were disconnected from the controller.
+ EFI_SUCCESS - On entry, no drivers are managing ControllerHandle.
+ EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle.
+ EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreAllocatePages (
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages from the memory map.
+
+Arguments:
+
+ Type - The type of allocation to perform
+
+ MemoryType - The type of memory to turn the allocated pages into
+
+ NumberOfPages - The number of pages to allocate
+
+ Memory - A pointer to receive the base allocated memory address
+
+Returns:
+
+ Status. On success, Memory is filled in with the base address allocated
+
+ EFI_INVALID_PARAMETER - Parameters violate checking rules defined in spec.
+
+ EFI_NOT_FOUND - Could not allocate pages match the requirement.
+
+ EFI_OUT_OF_RESOURCES - No enough pages to allocate.
+
+ EFI_SUCCESS - Pages successfully allocated.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreFreePages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Frees previous allocated pages.
+
+Arguments:
+
+ Memory - Base address of memory being freed
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the entry that covers the range
+
+ EFI_INVALID_PARAMETER - Address not aligned
+
+ EFI_SUCCESS -Pages successfully freed.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreGetMemoryMap (
+ IN OUT UINTN *MemoryMapSize,
+ IN OUT EFI_MEMORY_DESCRIPTOR *Desc,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion
+ )
+/*++
+
+Routine Description:
+
+ Returns the current memory map.
+
+Arguments:
+
+ MemoryMapSize - On input the buffer size of MemoryMap allocated by caller
+ On output the required buffer size to contain the memory map
+
+ Desc - The buffer to return the current memory map
+
+ MapKey - The address to return the current map key
+
+ DescriptorSize - The size in bytes for an individual EFI_MEMORY_DESCRIPTOR
+
+ DescriptorVersion - The version number associated with the EFI_MEMORY_DESCRIPTOR
+
+Returns:
+
+ EFI_SUCCESS The current memory map was returned successfully
+
+ EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small
+
+ EFI_INVALID_PARAMETER One of the parameters has an invalid value
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreAllocatePool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of a particular type.
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+ Buffer - The address to return a pointer to the allocated pool
+
+Returns:
+
+ EFI_INVALID_PARAMETER - PoolType not valid
+
+ EFI_OUT_OF_RESOURCES - Size exceeds max pool size or allocation failed.
+
+ EFI_SUCCESS - Pool successfully allocated.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreFreePool (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Frees pool.
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer is not a valid value.
+
+ EFI_SUCCESS - Pool successfully freed.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreLoadImage (
+ IN BOOLEAN BootPolicy,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image.
+
+Arguments:
+
+ BootPolicy - If TRUE, indicates that the request originates from the boot manager,
+ and that the boot manager is attempting to load FilePath as a boot selection.
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ ImageHandle - Pointer to the returned image handle that is created when the image
+ is successfully loaded.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreUnloadImage (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unload the specified image.
+
+Arguments:
+
+ ImageHandle - The specified image handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL.
+
+ EFI_UNSUPPORTED - Attempt to unload an unsupported image.
+
+ EFI_SUCCESS - Image successfully unloaded.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreStartImage (
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *ExitDataSize,
+ OUT CHAR16 **ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Transfer control to a loaded image's entry point.
+
+Arguments:
+
+ ImageHandle - Handle of image to be started.
+
+ ExitDataSize - Pointer of the size to ExitData
+
+ ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
+ Unicode string, optionally followed by additional binary data. The string
+ is a description that the caller may use to further indicate the reason for
+ the image¡¯s exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully transfer control to the image's entry point.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_STATUS Status,
+ IN UINTN ExitDataSize,
+ IN CHAR16 *ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Terminates the currently loaded EFI image and returns control to boot services.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the image. This parameter is passed to the image
+ on entry.
+ Status - The image¡¯s exit code.
+ ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
+ EFI_SUCCESS.
+ ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
+ optionally followed by additional binary data. The string is a
+ description that the caller may use to further indicate the reason for
+ the image¡¯s exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
+
+ EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
+
+ EFI_ACCESS_DENIED - Should never reach there.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreCreateEvent (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT EFI_EVENT *pEvent
+ )
+/*++
+
+Routine Description:
+
+ Creates a general-purpose event structure
+
+Arguments:
+
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the event’s notification function
+ NotifyContext - Pointer to the notification function’s context; corresponds to
+ parameter "Context" in the notification function
+ pEvent - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreCreateEventEx (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL
+ IN CONST VOID *NotifyContext, OPTIONAL
+ IN CONST EFI_GUID *EventGroup, OPTIONAL
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+ Creates a general-purpose event structure
+
+Arguments:
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the events notification function
+ NotifyContext - Pointer to the notification functions context; corresponds to
+ parameter "Context" in the notification function
+ EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent().
+ Event - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreSetTimer (
+ IN EFI_EVENT Event,
+ IN EFI_TIMER_DELAY Type,
+ IN UINT64 TriggerTime
+ )
+/*++
+
+Routine Description:
+
+ Sets the type of timer and the trigger time for a timer event.
+
+Arguments:
+
+ UserEvent - The timer event that is to be signaled at the specified time
+ Type - The type of time that is specified in TriggerTime
+ TriggerTime - The number of 100ns units until the timer expires
+
+Returns:
+
+ EFI_SUCCESS - The event has been set to be signaled at the requested time
+ EFI_INVALID_PARAMETER - Event or Type is not valid
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreSignalEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Signals the event. Queues the event to be notified if needed
+
+Arguments:
+
+ Event - The event to signal
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event was signaled.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreWaitForEvent (
+ IN UINTN NumberOfEvents,
+ IN EFI_EVENT *UserEvents,
+ OUT UINTN *UserIndex
+ )
+/*++
+
+Routine Description:
+
+ Stops execution until an event is signaled.
+
+Arguments:
+
+ NumberOfEvents - The number of events in the UserEvents array
+ UserEvents - An array of EFI_EVENT
+ UserIndex - Pointer to the index of the event which satisfied the wait condition
+
+Returns:
+
+ EFI_SUCCESS - The event indicated by Index was signaled.
+ EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or
+ Event was not a valid type
+ EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreCloseEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Closes an event and frees the event structure.
+
+Arguments:
+
+ UserEvent - Event to close
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event has been closed
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreCheckEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Check the status of an event
+
+Arguments:
+
+ UserEvent - The event to check
+
+Returns:
+
+ EFI_SUCCESS - The event is in the signaled state
+ EFI_NOT_READY - The event is not in the signaled state
+ EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL
+
+--*/
+;
+
+EFI_STATUS
+CoreAddMemorySpace (
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities
+ )
+/*++
+
+Routine Description:
+
+ Add a segment of memory space to GCD map and add all available pages in this segment
+ as memory descriptors.
+
+Arguments:
+
+ GcdMemoryType - Memory type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+ Capabilities - alterable attributes of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Merged this segment into GCD map.
+
+--*/
+;
+
+EFI_STATUS
+CoreAllocateMemorySpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocate memory space on GCD map.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdMemoryType - The desired memory type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - Memory space successfully allocated.
+
+--*/
+;
+
+EFI_STATUS
+CoreFreeMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Free a segment of memory space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+;
+
+EFI_STATUS
+CoreRemoveMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Remove a segment of memory space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Successfully a segment of memory space.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetMemorySpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Search all entries in GCD map which contains specified segment and build it to a descriptor.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully get memory space descriptor.
+
+--*/
+;
+
+EFI_STATUS
+CoreSetMemorySpaceAttributes (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Set memory space with specified attributes.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Length - Specified length
+
+ Attributes - Specified attributes
+
+Returns:
+
+ EFI_SUCCESS - Successfully set attribute of a segment of memory space.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetMemorySpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Transer all entries of GCD memory map into memory descriptors and pass to caller.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ MemorySpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get memory space map.
+
+--*/
+;
+
+EFI_STATUS
+CoreAddIoSpace (
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Add a segment of IO space to GCD map.
+
+Arguments:
+
+ GcdIoType - IO type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Merged this segment into GCD map.
+
+--*/
+;
+
+EFI_STATUS
+CoreAllocateIoSpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocate IO space on GCD map.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdIoType - The desired IO type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - IO space successfully allocated.
+
+--*/
+;
+
+EFI_STATUS
+CoreFreeIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Free a segment of IO space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+;
+
+EFI_STATUS
+CoreRemoveIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Remove a segment of IO space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Successfully removed a segment of IO space.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetIoSpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Search all entries in GCD map which contains specified segment and build it to a descriptor.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Descriptor is NULL.
+
+ EFI_SUCCESS - Successfully get the IO space descriptor.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetIoSpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Transer all entries of GCD IO map into IO descriptors and pass to caller.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ IoSpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get IO space map.
+
+--*/
+;
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This is the main Dispatcher for DXE and it exits when there are no more
+ drivers to run. Drain the mScheduledQueue and load and start a PE
+ image for each driver. Search the mDiscoveredList to see if any driver can
+ be placed on the mScheduledQueue. If no drivers are placed on the
+ mScheduledQueue exit the function. On exit it is assumed the Bds()
+ will be called, and when the Bds() exits the Dispatcher will be called
+ again.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ EFI_ALREADY_STARTED - The DXE Dispatcher is already running
+
+ EFI_NOT_FOUND - No DXE Drivers were dispatched
+
+ EFI_SUCCESS - One or more DXE Drivers were dispatched
+
+--*/
+;
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreSchedule (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Check every driver and locate a matching one. If the driver is found, the Unrequested
+ state flag is cleared.
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Dependent state.
+
+Returns:
+
+ EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared
+
+ EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set.
+
+--*/
+;
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreTrust (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Convert a driver from the Untrused back to the Scheduled state
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Scheduled state
+
+Returns:
+
+ EFI_SUCCESS - The file was found in the untrusted state, and it was promoted
+ to the trusted state.
+
+ EFI_NOT_FOUND - The file was not found in the untrusted state.
+
+--*/
+;
+
+BOOLEAN
+CoreGrowBuffer (
+ IN OUT EFI_STATUS *Status,
+ IN OUT VOID **Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Helper function called as part of the code needed
+ to allocate the proper sized buffer for various
+ EFI interfaces.
+
+Arguments:
+
+ Status - Current status
+
+ Buffer - Current allocated buffer, or NULL
+
+ BufferSize - Current buffer size needed
+
+Returns:
+
+ TRUE - if the buffer was reallocated and the caller
+ should try the API again.
+
+ FALSE - buffer could not be allocated and the caller
+ should not try the API again.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FwVolDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, and registers two notification functions. These notification
+ functions are responsible for building the FV stack dynamically.
+
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+
+Returns:
+ EFI_SUCCESS - Function successfully returned.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+InitializeSectionExtraction (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Entry point of the section extraction code. Initializes an instance of the
+ section extraction interface and installs it on a new handle.
+
+Arguments:
+ ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver
+ SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+Returns:
+ EFI_SUCCESS: Driver initialized successfully
+ EFI_OUT_OF_RESOURCES: Could not allocate needed resources
+
+--*/
+;
+
+EFI_STATUS
+CoreProcessFirmwareVolume (
+ IN VOID *FvHeader,
+ IN UINTN Size,
+ OUT EFI_HANDLE *FVProtocolHandle
+ )
+/*++
+
+Routine Description:
+ This DXE service routine is used to process a firmware volume. In
+ particular, it can be called by BDS to process a single firmware
+ volume found in a capsule.
+
+Arguments:
+ FvHeader - pointer to a firmware volume header
+ Size - the size of the buffer pointed to by FvHeader
+ FVProtocolHandle - the handle on which a firmware volume protocol
+ was produced for the firmware volume passed in.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - if an FVB could not be produced due to lack of
+ system resources
+ EFI_VOLUME_CORRUPTED - if the volume was corrupted
+ EFI_SUCCESS - a firmware volume protocol was produced for the
+ firmware volume
+
+--*/
+;
+
+//
+//Functions used during debug buils
+//
+VOID
+CoreDisplayMissingArchProtocols (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Displays Architectural protocols that were not loaded and are required for DXE core to function
+ Only used in Debug Builds
+
+ Arguments:
+ NONE
+
+ Returns:
+ NONE
+
+--*/;
+
+VOID
+CoreDisplayDiscoveredNotDispatched (
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ Traverse the discovered list for any drivers that were discovered but not loaded
+ because the dependency experessions evaluated to false
+
+ Arguments:
+
+ NONE
+
+ Returns:
+
+ NONE
+
+--*/;
+#endif
diff --git a/EdkModulePkg/Core/Dxe/DxeMain.mbd b/EdkModulePkg/Core/Dxe/DxeMain.mbd
new file mode 100644
index 0000000000..ec084b5c56
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/DxeMain.mbd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>DxeMain</BaseName>
+ <Guid>D6A2CB7F-6A18-4e2f-B43B-9920A733700A</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>BaseLib</Library>
+ <Library>BaseCacheMaintenanceLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>DxeCoreUefiDecompressLibFromHob</Library>
+ <Library>DxeCoreTianoDecompressLibFromHob</Library>
+ <Library>DxeCoreCustomDecompressLibFromHob</Library>
+ <Library>EdkDxePeCoffLoaderFromHobLib</Library>
+ <Library>DxeCoreHobLib</Library>
+ <Library>DxeCoreEntryPoint</Library>
+ <Library>BaseMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>BasePerformanceLibNull</Library>
+ </Libraries>
+ <BuildOptions ToolChain="MSFT">
+ <ImageEntryPoint>_ModuleEntryPoint</ImageEntryPoint>
+ <Option>C_PROJ_FLAGS = ${C_PROJ_FLAGS} /Ob0</Option>
+ </BuildOptions>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Core/Dxe/DxeMain.msa b/EdkModulePkg/Core/Dxe/DxeMain.msa
new file mode 100644
index 0000000000..42531812df
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/DxeMain.msa
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>DxeMain</BaseName>
+ <ModuleType>DXE_CORE</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>D6A2CB7F-6A18-4e2f-B43B-9920A733700A</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for DxeMain.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DxeCoreEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">TianoDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">CustomDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">CacheMaintenanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>DxeMain\DxeMain.c</Filename>
+ <Filename>DxeMain\DxeProtocolNotify.c</Filename>
+ <Filename>Dispatcher\Dispatcher.c</Filename>
+ <Filename>Dispatcher\Dependency.c</Filename>
+ <Filename>Event\ExecData.c</Filename>
+ <Filename>Event\Event.c</Filename>
+ <Filename>Event\Timer.c</Filename>
+ <Filename>Event\Tpl.c</Filename>
+ <Filename>FwVol\FwVol.c</Filename>
+ <Filename>FwVol\Ffs.c</Filename>
+ <Filename>FwVol\FwVolAttrib.c</Filename>
+ <Filename>FwVol\FwVolRead.c</Filename>
+ <Filename>FwVol\FwVolWrite.c</Filename>
+ <Filename>FwVolBlock\FwVolBlock.c</Filename>
+ <Filename>Mem\MemData.c</Filename>
+ <Filename>Mem\Page.c</Filename>
+ <Filename>Mem\Pool.c</Filename>
+ <Filename>Gcd\Gcd.c</Filename>
+ <Filename>Hand\Handle.c</Filename>
+ <Filename>Hand\Locate.c</Filename>
+ <Filename>Hand\Notify.c</Filename>
+ <Filename>Hand\DriverSupport.c</Filename>
+ <Filename>Library\Library.c</Filename>
+ <Filename>Misc\InstallConfigurationTable.c</Filename>
+ <Filename>Misc\SetWatchdogTimer.c</Filename>
+ <Filename>Misc\Stall.c</Filename>
+ <Filename>Misc\DebugImageInfo.c</Filename>
+ <Filename>Image\Image.c</Filename>
+ <Filename>Image\ImageFile.c</Filename>
+ <Filename>SectionExtraction\CoreSectionExtraction.c</Filename>
+ <Filename>DebugImageInfo.h</Filename>
+ <Filename>DebugMask.h</Filename>
+ <Filename>DxeMain.h</Filename>
+ <Filename>Exec.h</Filename>
+ <Filename>FwVolBlock.h</Filename>
+ <Filename>FwVolDriver.h</Filename>
+ <Filename>Gcd.h</Filename>
+ <Filename>Hand.h</Filename>
+ <Filename>Image.h</Filename>
+ <Filename>Imem.h</Filename>
+ <Filename>Library.h</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="SOMETIMES_CONSUMED">Ebc</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">LoadedImage</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">DevicePath</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Cpu</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">FirmwareVolume</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">FirmwareVolumeDispatch</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">FirmwareVolumeBlock</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">SectionExtraction</Protocol>
+ <Protocol Usage="SOMETIMES_CONSUMED">DriverBinding</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PlatformDriverOverride</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">BusSpecificDriverOverride</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Timer</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Metronome</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">MonotonicCounter</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">VariableWrite</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Bds</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Variable</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Security</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">WatchdogTimer</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Runtime</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">RealTimeClock</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Reset</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">LoadFile</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">SimpleFileSystem</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">LoadPeImage</Protocol>
+ </Protocols>
+ <Guids>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>MemoryTypeInformation</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>DxeServicesTable</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>HobList</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>DebugImageInfoTable</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>Apriori</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>FirmwareFileSystem</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>FileInfo</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>HobMemoryAllocModule</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>PeiPeCoffLoader</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>LoadPeImage</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>EventExitBootServices</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>EventVirtualAddressChange</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>EventMemoryMapChange</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>DxeMain</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+ <BuildOptions>
+ <Option>BUILD_TYPE=DXE_CORE</Option>
+ </BuildOptions>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Core/Dxe/DxeMain/DxeMain.c b/EdkModulePkg/Core/Dxe/DxeMain/DxeMain.c
new file mode 100644
index 0000000000..f98f0541ff
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/DxeMain/DxeMain.c
@@ -0,0 +1,1083 @@
+/*++
+
+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:
+
+ DxeMain.c
+
+Abstract:
+
+ DXE Core Main Entry Point
+
+--*/
+
+#include <DxeMain.h>
+
+VOID
+EFIAPI
+DxeMain (
+ IN VOID *HobStart
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg0 (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg1 (
+ UINTN Arg1
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg2 (
+ UINTN Arg1,
+ UINTN Arg2
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg3 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg4 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg5 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4,
+ UINTN Arg5
+ );
+
+EFI_STATUS
+CoreGetPeiProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ IN VOID **Interface
+ );
+
+EFI_STATUS
+DxeMainUefiDecompressGetInfo (
+ IN EFI_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize,
+ OUT UINT32 *ScratchSize
+ );
+
+EFI_STATUS
+EFIAPI
+DxeMainUefiDecompress (
+ IN EFI_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DestinationSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ );
+
+EFI_STATUS
+DxeMainTianoDecompressGetInfo (
+ IN EFI_TIANO_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize,
+ OUT UINT32 *ScratchSize
+ );
+
+EFI_STATUS
+EFIAPI
+DxeMainTianoDecompress (
+ IN EFI_TIANO_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DestinationSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ );
+
+EFI_STATUS
+DxeMainCustomDecompressGetInfo (
+ IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize,
+ OUT UINT32 *ScratchSize
+ );
+
+EFI_STATUS
+EFIAPI
+DxeMainCustomDecompress (
+ IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DestinationSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ );
+
+//
+// DXE Core Global Variables for Protocols from PEI
+//
+EFI_HANDLE mDecompressHandle = NULL;
+EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader = NULL;
+
+//
+// DXE Core globals for Architecture Protocols
+//
+EFI_SECURITY_ARCH_PROTOCOL *gSecurity = NULL;
+EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
+EFI_METRONOME_ARCH_PROTOCOL *gMetronome = NULL;
+EFI_TIMER_ARCH_PROTOCOL *gTimer = NULL;
+EFI_BDS_ARCH_PROTOCOL *gBds = NULL;
+EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer = NULL;
+EFI_RUNTIME_ARCH_PROTOCOL *gRuntime = NULL;
+
+//
+// BugBug: I'n not runtime, but is the PPI?
+//
+EFI_STATUS_CODE_PROTOCOL gStatusCodeInstance = {
+ NULL
+};
+
+EFI_STATUS_CODE_PROTOCOL *gStatusCode = &gStatusCodeInstance;
+
+
+//
+// DXE Core Global used to update core loaded image protocol handle
+//
+EFI_GUID *gDxeCoreFileName;
+EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage;
+
+
+
+//
+// DXE Core Module Variables
+//
+
+EFI_BOOT_SERVICES mBootServices = {
+ {
+ EFI_BOOT_SERVICES_SIGNATURE, // Signature
+ EFI_BOOT_SERVICES_REVISION, // Revision
+ sizeof (EFI_BOOT_SERVICES), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ (EFI_RAISE_TPL) CoreRaiseTpl, // RaiseTPL
+ (EFI_RESTORE_TPL) CoreRestoreTpl, // RestoreTPL
+ (EFI_ALLOCATE_PAGES) CoreAllocatePages, // AllocatePages
+ (EFI_FREE_PAGES) CoreFreePages, // FreePages
+ (EFI_GET_MEMORY_MAP) CoreGetMemoryMap, // GetMemoryMap
+ (EFI_ALLOCATE_POOL) CoreAllocatePool, // AllocatePool
+ (EFI_FREE_POOL) CoreFreePool, // FreePool
+ (EFI_CREATE_EVENT) CoreCreateEvent, // CreateEvent
+ (EFI_SET_TIMER) CoreSetTimer, // SetTimer
+ (EFI_WAIT_FOR_EVENT) CoreWaitForEvent, // WaitForEvent
+ (EFI_SIGNAL_EVENT) CoreSignalEvent, // SignalEvent
+ (EFI_CLOSE_EVENT) CoreCloseEvent, // CloseEvent
+ (EFI_CHECK_EVENT) CoreCheckEvent, // CheckEvent
+ (EFI_INSTALL_PROTOCOL_INTERFACE) CoreInstallProtocolInterface, // InstallProtocolInterface
+ (EFI_REINSTALL_PROTOCOL_INTERFACE) CoreReinstallProtocolInterface, // ReinstallProtocolInterface
+ (EFI_UNINSTALL_PROTOCOL_INTERFACE) CoreUninstallProtocolInterface, // UninstallProtocolInterface
+ (EFI_HANDLE_PROTOCOL) CoreHandleProtocol, // HandleProtocol
+ (VOID *) NULL, // Reserved
+ (EFI_REGISTER_PROTOCOL_NOTIFY) CoreRegisterProtocolNotify, // RegisterProtocolNotify
+ (EFI_LOCATE_HANDLE) CoreLocateHandle, // LocateHandle
+ (EFI_LOCATE_DEVICE_PATH) CoreLocateDevicePath, // LocateDevicePath
+ (EFI_INSTALL_CONFIGURATION_TABLE) CoreInstallConfigurationTable, // InstallConfigurationTable
+ (EFI_IMAGE_LOAD) CoreLoadImage, // LoadImage
+ (EFI_IMAGE_START) CoreStartImage, // StartImage
+ (EFI_EXIT) CoreExit, // Exit
+ (EFI_IMAGE_UNLOAD) CoreUnloadImage, // UnloadImage
+ (EFI_EXIT_BOOT_SERVICES) CoreExitBootServices, // ExitBootServices
+ (EFI_GET_NEXT_MONOTONIC_COUNT) CoreEfiNotAvailableYetArg1, // GetNextMonotonicCount
+ (EFI_STALL) CoreStall, // Stall
+ (EFI_SET_WATCHDOG_TIMER) CoreSetWatchdogTimer, // SetWatchdogTimer
+ (EFI_CONNECT_CONTROLLER) CoreConnectController, // ConnectController
+ (EFI_DISCONNECT_CONTROLLER) CoreDisconnectController, // DisconnectController
+ (EFI_OPEN_PROTOCOL) CoreOpenProtocol, // OpenProtocol
+ (EFI_CLOSE_PROTOCOL) CoreCloseProtocol, // CloseProtocol
+ (EFI_OPEN_PROTOCOL_INFORMATION) CoreOpenProtocolInformation, // OpenProtocolInformation
+ (EFI_PROTOCOLS_PER_HANDLE) CoreProtocolsPerHandle, // ProtocolsPerHandle
+ (EFI_LOCATE_HANDLE_BUFFER) CoreLocateHandleBuffer, // LocateHandleBuffer
+ (EFI_LOCATE_PROTOCOL) CoreLocateProtocol, // LocateProtocol
+ (EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreInstallMultipleProtocolInterfaces, // InstallMultipleProtocolInterfaces
+ (EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreUninstallMultipleProtocolInterfaces, // UninstallMultipleProtocolInterfaces
+ (EFI_CALCULATE_CRC32) CoreEfiNotAvailableYetArg3, // CalculateCrc32
+ (EFI_COPY_MEM) CopyMem, // CopyMem
+ (EFI_SET_MEM) SetMem // SetMem
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ ,
+ (EFI_CREATE_EVENT_EX) CoreCreateEventEx // CreateEventEx
+#endif
+};
+
+EFI_DXE_SERVICES mDxeServices = {
+ {
+ EFI_DXE_SERVICES_SIGNATURE, // Signature
+ EFI_DXE_SERVICES_REVISION, // Revision
+ sizeof (EFI_DXE_SERVICES), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ (EFI_ADD_MEMORY_SPACE) CoreAddMemorySpace, // AddMemorySpace
+ (EFI_ALLOCATE_MEMORY_SPACE) CoreAllocateMemorySpace, // AllocateMemorySpace
+ (EFI_FREE_MEMORY_SPACE) CoreFreeMemorySpace, // FreeMemorySpace
+ (EFI_REMOVE_MEMORY_SPACE) CoreRemoveMemorySpace, // RemoveMemorySpace
+ (EFI_GET_MEMORY_SPACE_DESCRIPTOR) CoreGetMemorySpaceDescriptor, // GetMemorySpaceDescriptor
+ (EFI_SET_MEMORY_SPACE_ATTRIBUTES) CoreSetMemorySpaceAttributes, // SetMemorySpaceAttributes
+ (EFI_GET_MEMORY_SPACE_MAP) CoreGetMemorySpaceMap, // GetMemorySpaceMap
+ (EFI_ADD_IO_SPACE) CoreAddIoSpace, // AddIoSpace
+ (EFI_ALLOCATE_IO_SPACE) CoreAllocateIoSpace, // AllocateIoSpace
+ (EFI_FREE_IO_SPACE) CoreFreeIoSpace, // FreeIoSpace
+ (EFI_REMOVE_IO_SPACE) CoreRemoveIoSpace, // RemoveIoSpace
+ (EFI_GET_IO_SPACE_DESCRIPTOR) CoreGetIoSpaceDescriptor, // GetIoSpaceDescriptor
+ (EFI_GET_IO_SPACE_MAP) CoreGetIoSpaceMap, // GetIoSpaceMap
+ (EFI_DISPATCH) CoreDispatcher, // Dispatch
+ (EFI_SCHEDULE) CoreSchedule, // Schedule
+ (EFI_TRUST) CoreTrust, // Trust
+ (EFI_PROCESS_FIRMWARE_VOLUME) CoreProcessFirmwareVolume, // ProcessFirmwareVolume
+};
+
+EFI_SYSTEM_TABLE mEfiSystemTableTemplate = {
+ {
+ EFI_SYSTEM_TABLE_SIGNATURE, // Signature
+ EFI_SYSTEM_TABLE_REVISION, // Revision
+ sizeof (EFI_SYSTEM_TABLE), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ NULL, // FirmwareVendor
+ 0, // FirmwareRevision
+ NULL, // ConsoleInHandle
+ NULL, // ConIn
+ NULL, // ConsoleOutHandle
+ NULL, // ConOut
+ NULL, // StandardErrorHandle
+ NULL, // StdErr
+ NULL, // RuntimeServices
+ &mBootServices, // BootServices
+ 0, // NumberOfConfigurationTableEntries
+ NULL // ConfigurationTable
+};
+
+EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate = {
+ {
+ EFI_RUNTIME_SERVICES_SIGNATURE, // Signature
+ EFI_RUNTIME_SERVICES_REVISION, // Revision
+ sizeof (EFI_RUNTIME_SERVICES), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ (EFI_GET_TIME) CoreEfiNotAvailableYetArg2, // GetTime
+ (EFI_SET_TIME) CoreEfiNotAvailableYetArg1, // SetTime
+ (EFI_GET_WAKEUP_TIME) CoreEfiNotAvailableYetArg3, // GetWakeupTime
+ (EFI_SET_WAKEUP_TIME) CoreEfiNotAvailableYetArg2, // SetWakeupTime
+ (EFI_SET_VIRTUAL_ADDRESS_MAP) CoreEfiNotAvailableYetArg4, // SetVirtualAddressMap
+ (EFI_CONVERT_POINTER) CoreEfiNotAvailableYetArg2, // ConvertPointer
+ (EFI_GET_VARIABLE) CoreEfiNotAvailableYetArg5, // GetVariable
+ (EFI_GET_NEXT_VARIABLE_NAME) CoreEfiNotAvailableYetArg3, // GetNextVariableName
+ (EFI_SET_VARIABLE) CoreEfiNotAvailableYetArg5, // SetVariable
+ (EFI_GET_NEXT_HIGH_MONO_COUNT) CoreEfiNotAvailableYetArg1, // GetNextHighMonotonicCount
+ (EFI_RESET_SYSTEM) CoreEfiNotAvailableYetArg4 // ResetSystem
+#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000))
+ ,
+ (TIANO_REPORT_STATUS_CODE) CoreEfiNotAvailableYetArg5 // ReportStatusCode
+#elif (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ ,
+ (EFI_UPDATE_CAPSULE) CoreEfiNotAvailableYetArg3, // UpdateCapsule
+ (EFI_QUERY_CAPSULE_CAPABILITIES) CoreEfiNotAvailableYetArg4, // QueryCapsuleCapabilities
+ (EFI_QUERY_VARIABLE_INFO) CoreEfiNotAvailableYetArg4 // QueryVariableInfo
+#endif
+};
+
+//
+// DXE Core Global Variables for the EFI System Table, Boot Services Table,
+// DXE Services Table, and Runtime Services Table
+//
+EFI_BOOT_SERVICES *gBS = &mBootServices;
+EFI_DXE_SERVICES *gDS = &mDxeServices;
+EFI_SYSTEM_TABLE *gST = NULL;
+
+//
+// For debug initialize gRT to template. gRT must be allocated from RT memory
+// but gRT is used for ASSERT () and DEBUG () type macros so lets give it
+// a value that will not cause debug infrastructure to crash early on.
+//
+EFI_RUNTIME_SERVICES *gRT = &mEfiRuntimeServicesTableTemplate;
+EFI_HANDLE gDxeCoreImageHandle = NULL;
+
+VOID *mHobStart;
+
+//
+// EFI Decompress Protocol
+//
+EFI_DECOMPRESS_PROTOCOL gEfiDecompress = {
+ DxeMainUefiDecompressGetInfo,
+ DxeMainUefiDecompress
+};
+
+//
+// Tiano Decompress Protocol
+//
+EFI_TIANO_DECOMPRESS_PROTOCOL gEfiTianoDecompress = {
+ DxeMainTianoDecompressGetInfo,
+ DxeMainTianoDecompress
+};
+
+//
+// Customized Decompress Protocol
+//
+EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL gEfiCustomizedDecompress = {
+ DxeMainCustomDecompressGetInfo,
+ DxeMainCustomDecompress
+};
+
+//
+// Main entry point to the DXE Core
+//
+VOID
+EFIAPI
+DxeMain (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Main entry point to DXE Core.
+
+Arguments:
+
+ HobStart - Pointer to the beginning of the HOB List from PEI
+
+Returns:
+
+ This function should never return
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS MemoryBaseAddress;
+ UINT64 MemoryLength;
+
+#ifdef EFI_DXE_PERFORMANCE
+ UINT64 Tick;
+
+ GetTimerValue (&Tick);
+#endif
+
+ mHobStart = HobStart;
+
+ //
+ // Initialize Memory Services
+ //
+ CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
+
+ //
+ // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData
+ // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table
+ //
+ gST = CoreAllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate);
+ ASSERT (gST != NULL);
+
+ gRT = CoreAllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
+ ASSERT (gRT != NULL);
+
+ gST->RuntimeServices = gRT;
+
+ //
+ // Start the Image Services.
+ //
+ Status = CoreInitializeImageServices (HobStart);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Call constructor for all libraries
+ //
+ ProcessLibraryConstructorList (gDxeCoreImageHandle, gST);
+
+ //
+ // Initialize the Global Coherency Domain Services
+ //
+ Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the DXE Services Table into the EFI System Tables's Configuration Table
+ //
+ Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDS);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the HOB List into the EFI System Tables's Configuration Table
+ //
+ Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Memory Type Information Table into the EFI System Tables's Configuration Table
+ //
+ Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the ReportStatusCode with PEI version, if availible
+ //
+ CoreGetPeiProtocol (&gEfiStatusCodeRuntimeProtocolGuid, (VOID **)&gStatusCode->ReportStatusCode);
+#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000))
+ gRT->ReportStatusCode = gStatusCode->ReportStatusCode;
+#endif
+
+ //
+ // Report Status Code here for DXE_ENTRY_POINT once it is available
+ //
+ CoreReportProgressCode ((EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT));
+
+ //
+ // Create the aligned system table pointer structure that is used by external
+ // debuggers to locate the system table... Also, install debug image info
+ // configuration table.
+ //
+ CoreInitializeDebugImageInfoTable ();
+ CoreNewDebugImageInfoEntry (
+ EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
+ gDxeCoreLoadedImage,
+ gDxeCoreImageHandle
+ );
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "HOBLIST address in DXE = 0x%08x\n", HobStart));
+
+ //
+ // Initialize the Event Services
+ //
+ Status = CoreInitializeEventServices ();
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Get the Protocols that were passed in from PEI to DXE through GUIDed HOBs
+ //
+ // These Protocols are not architectural. This implementation is sharing code between
+ // PEI and DXE in order to save FLASH space. These Protocols could also be implemented
+ // as part of the DXE Core. However, that would also require the DXE Core to be ported
+ // each time a different CPU is used, a different Decompression algorithm is used, or a
+ // different Image type is used. By placing these Protocols in PEI, the DXE Core remains
+ // generic, and only PEI and the Arch Protocols need to be ported from Platform to Platform,
+ // and from CPU to CPU.
+ //
+
+ //
+ // Publish the EFI, Tiano, and Custom Decompress protocols for use by other DXE components
+ //
+ Status = CoreInstallMultipleProtocolInterfaces (
+ &mDecompressHandle,
+ &gEfiDecompressProtocolGuid, &gEfiDecompress,
+ &gEfiTianoDecompressProtocolGuid, &gEfiTianoDecompress,
+ &gEfiCustomizedDecompressProtocolGuid, &gEfiCustomizedDecompress,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ gEfiPeiPeCoffLoader = GetPeCoffLoaderProtocol ();
+ ASSERT (gEfiPeiPeCoffLoader != NULL);
+
+ //
+ // Register for the GUIDs of the Architectural Protocols, so the rest of the
+ // EFI Boot Services and EFI Runtime Services tables can be filled in.
+ //
+ CoreNotifyOnArchProtocolInstallation ();
+
+ //
+ // Produce Firmware Volume Protocols, one for each FV in the HOB list.
+ //
+ Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = FwVolDriverInit (gDxeCoreImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Produce the Section Extraction Protocol
+ //
+ Status = InitializeSectionExtraction (gDxeCoreImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the DXE Dispatcher
+ //
+ PERF_START (0,"CoreInitializeDispatcher", "DxeMain", 0) ;
+ CoreInitializeDispatcher ();
+ PERF_END (0,"CoreInitializeDispatcher", "DxeMain", 0) ;
+
+ //
+ // Invoke the DXE Dispatcher
+ //
+ PERF_START (0, "CoreDispatcher", "DxeMain", 0);
+ CoreDispatcher ();
+ PERF_END (0, "CoreDispatcher", "DxeMain", 0);
+
+ //
+ // Display Architectural protocols that were not loaded if this is DEBUG build
+ //
+ DEBUG_CODE (
+ CoreDisplayMissingArchProtocols ();
+ );
+
+ //
+ // Assert if the Architectural Protocols are not present.
+ //
+ ASSERT_EFI_ERROR (CoreAllEfiServicesAvailable ());
+
+ //
+ // Report Status code before transfer control to BDS
+ //
+ CoreReportProgressCode ((EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT));
+ //
+ // Display any drivers that were not dispatched because dependency expression
+ // evaluated to false if this is a debug build
+ //
+ DEBUG_CODE (
+ CoreDisplayDiscoveredNotDispatched ();
+ );
+
+ //
+ // Transfer control to the BDS Architectural Protocol
+ //
+ gBds->Entry (gBds);
+
+ //
+ // BDS should never return
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg0 (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The CpuBreakpoint () is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg1 (
+ UINTN Arg1
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The CpuBreakpoint () is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg2 (
+ UINTN Arg1,
+ UINTN Arg2
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The CpuBreakpoint () is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg3 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+ Arg3 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The CpuBreakpoint () is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg4 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+ Arg3 - Undefined
+
+ Arg4 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The CpuBreakpoint () is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg5 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4,
+ UINTN Arg5
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+ Arg3 - Undefined
+
+ Arg4 - Undefined
+
+ Arg5 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The CpuBreakpoint () is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+
+EFI_STATUS
+CoreGetPeiProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ IN VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Searches for a Protocol Interface passed from PEI through a HOB
+
+Arguments:
+
+ ProtocolGuid - The Protocol GUID to search for in the HOB List
+
+ Interface - A pointer to the interface for the Protocol GUID
+
+Returns:
+
+ EFI_SUCCESS - The Protocol GUID was found and its interface is returned in Interface
+
+ EFI_NOT_FOUND - The Protocol GUID was not found in the HOB List
+
+--*/
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ VOID *Buffer;
+
+ GuidHob = GetNextGuidHob (ProtocolGuid, mHobStart);
+ if (GuidHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Buffer = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (Buffer != NULL);
+
+ *Interface = (VOID *)(*(UINTN *)(Buffer));
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+CalculateEfiHdrCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Calcualte the 32-bit CRC in a EFI table using the service provided by the
+ gRuntime service.
+
+Arguments:
+
+ Hdr - Pointer to an EFI standard header
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT32 Crc;
+
+ Hdr->CRC32 = 0;
+
+ //
+ // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
+ // Crc will come back as zero if we set it to zero here
+ //
+ Crc = 0;
+ gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);
+ Hdr->CRC32 = Crc;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreExitBootServices (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ EFI 1.0 API to terminate Boot Services
+
+Arguments:
+
+ ImageHandle - Handle that represents the identity of the calling image
+
+ MapKey -Key to the latest memory map.
+
+Returns:
+
+ EFI_SUCCESS - Boot Services terminated
+ EFI_INVALID_PARAMETER - MapKey is incorrect.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Terminate memory services if the MapKey matches
+ //
+ Status = CoreTerminateMemoryMap (MapKey);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify other drivers that we are exiting boot services.
+ //
+ CoreNotifySignalList (&gEfiEventExitBootServicesGuid);
+
+ //
+ // Disable Timer
+ //
+ gTimer->SetTimerPeriod (gTimer, 0);
+
+ //
+ // Disable CPU Interrupts
+ //
+ gCpu->DisableInterrupt (gCpu);
+
+ //
+ // Register Runtime events with the Runtime Architectural Protocol
+ //
+ CoreShutdownEventServices ();
+
+ //
+ // Register Runtime images with the Runtime Architectural Protocol
+ //
+ CoreShutdownImageServices ();
+
+ //
+ // Report that ExitBootServices() has been called
+ //
+ // We are using gEfiDxeServicesTableGuid as the caller ID for Dxe Core
+ //
+ CoreReportProgressCode ((EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES));
+
+ //
+ // Clear the non-runtime values of the EFI System Table
+ //
+ gST->BootServices = NULL;
+ gST->ConIn = NULL;
+ gST->ConsoleInHandle = NULL;
+ gST->ConOut = NULL;
+ gST->ConsoleOutHandle = NULL;
+ gST->StdErr = NULL;
+ gST->StandardErrorHandle = NULL;
+
+ //
+ // Recompute the 32-bit CRC of the EFI System Table
+ //
+ CalculateEfiHdrCrc (&gST->Hdr);
+
+ //
+ // Zero out the Boot Service Table
+ //
+ SetMem (gBS, sizeof (EFI_BOOT_SERVICES), 0);
+ gBS = NULL;
+
+ return Status;
+}
+
+EFI_STATUS
+DxeMainUefiDecompressGetInfo (
+ IN EFI_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize,
+ OUT UINT32 *ScratchSize
+ )
+{
+ return UefiDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize);
+}
+
+EFI_STATUS
+EFIAPI
+DxeMainUefiDecompress (
+ IN EFI_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DestinationSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TestDestinationSize;
+ UINT32 TestScratchSize;
+
+ Status = UefiDecompressGetInfo (Source, SourceSize, &TestDestinationSize, &TestScratchSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ScratchSize < TestScratchSize || DestinationSize < TestDestinationSize) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ return UefiDecompress (Source, Destination, Scratch);
+}
+
+EFI_STATUS
+DxeMainTianoDecompressGetInfo (
+ IN EFI_TIANO_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize,
+ OUT UINT32 *ScratchSize
+ )
+{
+ return TianoDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize);
+}
+
+EFI_STATUS
+EFIAPI
+DxeMainTianoDecompress (
+ IN EFI_TIANO_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DestinationSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TestDestinationSize;
+ UINT32 TestScratchSize;
+
+ Status = TianoDecompressGetInfo (Source, SourceSize, &TestDestinationSize, &TestScratchSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ScratchSize < TestScratchSize || DestinationSize < TestDestinationSize) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ return TianoDecompress (Source, Destination, Scratch);
+}
+
+EFI_STATUS
+DxeMainCustomDecompressGetInfo (
+ IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize,
+ OUT UINT32 *ScratchSize
+ )
+{
+ return CustomDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize);
+}
+
+EFI_STATUS
+EFIAPI
+DxeMainCustomDecompress (
+ IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This,
+ IN VOID *Source,
+ IN UINT32 SourceSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DestinationSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TestDestinationSize;
+ UINT32 TestScratchSize;
+
+ Status = CustomDecompressGetInfo (Source, SourceSize, &TestDestinationSize, &TestScratchSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ScratchSize < TestScratchSize || DestinationSize < TestDestinationSize) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ return CustomDecompress (Source, Destination, Scratch);
+}
+
diff --git a/EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c b/EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
new file mode 100644
index 0000000000..7e49423fb4
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
@@ -0,0 +1,266 @@
+/*++
+
+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:
+
+ DxeProtocolNotify.c
+
+Abstract:
+
+ This file deals with Architecture Protocol (AP) registration in
+ the Dxe Core. The mArchProtocols[] array represents a list of
+ events that represent the Architectural Protocols.
+
+--*/
+
+#include <DxeMain.h>
+
+
+//
+// DXE Core Global Variables for all of the Architectural Protocols.
+// If a protocol is installed mArchProtocols[].Present will be TRUE.
+//
+// CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
+// and mArchProtocols[].Registration as it creates events for every array
+// entry.
+//
+
+ARCHITECTURAL_PROTOCOL_ENTRY mArchProtocols[] = {
+ { &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE },
+ { &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE },
+ { &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE },
+ { &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE },
+ { &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE },
+ { &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
+ { &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE },
+ { &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+// { &gEfiStatusCodeRuntimeProtocolGuid, (VOID **)&gStatusCode, NULL, NULL, FALSE },
+ { &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { NULL, (VOID **)NULL, NULL, NULL, FALSE }
+};
+
+
+EFI_STATUS
+CoreAllEfiServicesAvailable (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return TRUE if all AP services are availible.
+
+Arguments:
+ NONE
+
+Returns:
+ EFI_SUCCESS - All AP services are available
+ EFI_NOT_FOUND - At least one AP service is not available
+
+--*/
+{
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+ if (!Entry->Present) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+GenericArchProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+ Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
+ This notify function is registered for every architectural protocol. This handler
+ updates mArchProtocol[] array entry with protocol instance data and sets it's
+ present flag to TRUE. If any constructor is required it is executed. The EFI
+ System Table headers are updated.
+
+Arguments:
+
+ Event - The Event that is being processed, not used.
+
+ Context - Event Context, not used.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+ VOID *Protocol;
+ BOOLEAN Found;
+
+ Found = FALSE;
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+
+ Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Found = TRUE;
+ Entry->Present = TRUE;
+
+ //
+ // Update protocol global variable if one exists. Entry->Protocol points to a global variable
+ // if one exists in the DXE core for this Architectural Protocol
+ //
+ if (Entry->Protocol != NULL) {
+ *(Entry->Protocol) = Protocol;
+ }
+
+ if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
+ //
+ // Register the Core timer tick handler with the Timer AP
+ //
+ gTimer->RegisterHandler (gTimer, CoreTimerTick);
+ }
+
+ if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
+ //
+ // When runtime architectural protocol is available, updates CRC32 in the Debug Table
+ //
+ CoreUpdateDebugTableCrc32 ();
+ }
+ }
+
+ //
+ // It's over kill to do them all every time, but it saves a lot of code.
+ //
+ if (Found) {
+ CalculateEfiHdrCrc (&gRT->Hdr);
+ CalculateEfiHdrCrc (&gBS->Hdr);
+ CalculateEfiHdrCrc (&gST->Hdr);
+ CalculateEfiHdrCrc (&gDS->Hdr);
+ }
+}
+
+
+
+VOID
+CoreNotifyOnArchProtocolInstallation (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Creates an event that is fired everytime a Protocol of a specific type is installed
+
+Arguments:
+ NONE
+
+Returns:
+ NONE
+
+--*/
+{
+ EFI_STATUS Status;
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+
+ //
+ // Create the event
+ //
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ GenericArchProtocolNotify,
+ NULL,
+ &Entry->Event
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register for protocol notifactions on this event
+ //
+ Status = CoreRegisterProtocolNotify (
+ Entry->ProtocolGuid,
+ Entry->Event,
+ &Entry->Registration
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ }
+}
+
+//
+// Following is needed to display missing architectural protocols in debug builds
+//
+typedef struct {
+ EFI_GUID *ProtocolGuid;
+ CHAR16 *GuidString;
+} GUID_TO_STRING_PROTOCOL_ENTRY;
+
+static const GUID_TO_STRING_PROTOCOL_ENTRY MissingProtocols[] = {
+ { &gEfiSecurityArchProtocolGuid, (CHAR16 *)L"Security" },
+ { &gEfiCpuArchProtocolGuid, (CHAR16 *)L"CPU" },
+ { &gEfiMetronomeArchProtocolGuid, (CHAR16 *)L"Metronome" },
+ { &gEfiTimerArchProtocolGuid, (CHAR16 *)L"Timer" },
+ { &gEfiBdsArchProtocolGuid, (CHAR16 *)L"Bds" },
+ { &gEfiWatchdogTimerArchProtocolGuid, (CHAR16 *)L"Watchdog Timer" },
+ { &gEfiRuntimeArchProtocolGuid, (CHAR16 *)L"Runtime" },
+ { &gEfiVariableArchProtocolGuid, (CHAR16 *)L"Variable" },
+ { &gEfiVariableWriteArchProtocolGuid, (CHAR16 *)L"Variable Write" },
+ { &gEfiMonotonicCounterArchProtocolGuid, (CHAR16 *)L"Monotonic Counter" },
+ { &gEfiResetArchProtocolGuid, (CHAR16 *)L"Reset" },
+// { &gEfiStatusCodeRuntimeProtocolGuid, (CHAR16 *)L"Status Code" },
+ { &gEfiRealTimeClockArchProtocolGuid, (CHAR16 *)L"Real Time Clock" }
+};
+
+VOID
+CoreDisplayMissingArchProtocols (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Displays Architectural protocols that were not loaded and are required for DXE core to function
+ Only used in Debug Builds
+
+Arguments:
+ NONE
+
+Returns:
+ NONE
+
+--*/
+{
+ const GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry;
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+ if (!Entry->Present) {
+ MissingEntry = MissingProtocols;
+ for (MissingEntry = MissingProtocols; TRUE ; MissingEntry++) {
+ if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
+ DEBUG ((EFI_D_ERROR, "\n%s Arch Protocol not present!!\n", MissingEntry->GuidString));
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/EdkModulePkg/Core/Dxe/Event/event.c b/EdkModulePkg/Core/Dxe/Event/event.c
new file mode 100644
index 0000000000..e8391419ab
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Event/event.c
@@ -0,0 +1,862 @@
+/*++
+
+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:
+
+ event.c
+
+Abstract:
+
+ EFI Event support
+
+--*/
+
+
+#include <DxeMain.h>
+
+//
+// Enumerate the valid types
+//
+UINT32 mEventTable[] = {
+ //
+ // 0x80000200 Timer event with a notification function that is
+ // queue when the event is signaled with SignalEvent()
+ //
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ //
+ // 0x80000000 Timer event without a notification function. It can be
+ // signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().
+ //
+ EFI_EVENT_TIMER,
+ //
+ // 0x00000100 Generic event with a notification function that
+ // can be waited on with CheckEvent() or WaitForEvent()
+ //
+ EFI_EVENT_NOTIFY_WAIT,
+ //
+ // 0x00000200 Generic event with a notification function that
+ // is queue when the event is signaled with SignalEvent()
+ //
+ EFI_EVENT_NOTIFY_SIGNAL,
+ //
+ // 0x00000201 ExitBootServicesEvent.
+ //
+ EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ //
+ // 0x60000202 SetVirtualAddressMapEvent.
+ //
+ EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+ //
+ // 0x00000203 ReadyToBootEvent.
+ //
+ EFI_EVENT_SIGNAL_READY_TO_BOOT,
+ //
+ // 0x00000204 LegacyBootEvent.
+ //
+ EFI_EVENT_SIGNAL_LEGACY_BOOT,
+ //
+ // 0x00000603 Signal all ReadyToBootEvents.
+ //
+ EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_READY_TO_BOOT,
+ //
+ // 0x00000604 Signal all LegacyBootEvents.
+ //
+ EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_LEGACY_BOOT,
+#endif
+
+ //
+ // 0x00000000 Generic event without a notification function.
+ // It can be signaled with SignalEvent() and checked with CheckEvent()
+ // or WaitForEvent().
+ //
+ 0x00000000,
+ //
+ // 0x80000100 Timer event with a notification function that can be
+ // waited on with CheckEvent() or WaitForEvent()
+ //
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_WAIT,
+};
+
+
+VOID
+CoreAcquireEventLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by acquiring the lock on gEventQueueLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreAcquireLock (&gEventQueueLock);
+}
+
+
+VOID
+CoreReleaseEventLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing the lock on gEventQueueLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&gEventQueueLock);
+}
+
+
+EFI_STATUS
+CoreInitializeEventServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes "event" support and populates parts of the System and Runtime Table.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Always return success
+
+--*/
+{
+ UINTN Index;
+
+ for (Index=0; Index <= EFI_TPL_HIGH_LEVEL; Index++) {
+ InitializeListHead (&gEventQueue[Index]);
+ }
+
+ CoreInitializeTimer ();
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CoreShutdownEventServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Register all runtime events to make sure they are still available after ExitBootService.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Always return success.
+
+--*/
+{
+ LIST_ENTRY *Link;
+ IEVENT *Event;
+
+ //
+ // The Runtime AP is required for the core to function!
+ //
+ ASSERT (gRuntime != NULL);
+
+ for (Link = mRuntimeEventList.ForwardLink; Link != &mRuntimeEventList; Link = Link->ForwardLink) {
+ Event = CR (Link, IEVENT, RuntimeLink, EVENT_SIGNATURE);
+ gRuntime->RegisterEvent (
+ gRuntime,
+ Event->Type,
+ Event->NotifyTpl,
+ Event->NotifyFunction,
+ Event->NotifyContext,
+ (VOID **)Event
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+CoreDispatchEventNotifies (
+ IN EFI_TPL Priority
+ )
+/*++
+
+Routine Description:
+
+ Dispatches all pending events.
+
+Arguments:
+
+ Priority - The task priority level of event notifications to dispatch
+
+Returns:
+
+ None
+
+--*/
+{
+ IEVENT *Event;
+ LIST_ENTRY *Head;
+
+ CoreAcquireEventLock ();
+ ASSERT (gEventQueueLock.OwnerTpl == Priority);
+ Head = &gEventQueue[Priority];
+
+ //
+ // Dispatch all the pending notifications
+ //
+ while (!IsListEmpty (Head)) {
+
+ Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);
+ RemoveEntryList (&Event->NotifyLink);
+
+ Event->NotifyLink.ForwardLink = NULL;
+
+ //
+ // Only clear the SIGNAL status if it is a SIGNAL type event.
+ // WAIT type events are only cleared in CheckEvent()
+ //
+ if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
+ Event->SignalCount = 0;
+ }
+
+ CoreReleaseEventLock ();
+
+ //
+ // Notify this event
+ //
+ ASSERT (Event->NotifyFunction != NULL);
+ Event->NotifyFunction (Event, Event->NotifyContext);
+
+ //
+ // Check for next pending event
+ //
+ CoreAcquireEventLock ();
+ }
+
+ gEventPending &= ~(1 << Priority);
+ CoreReleaseEventLock ();
+}
+
+
+VOID
+STATIC
+CoreNotifyEvent (
+ IN IEVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ Queues the event's notification function to fire
+
+Arguments:
+
+ Event - The Event to notify
+
+Returns:
+
+ None
+
+--*/
+{
+
+ //
+ // Event database must be locked
+ //
+ ASSERT_LOCKED (&gEventQueueLock);
+
+ //
+ // If the event is queued somewhere, remove it
+ //
+
+ if (Event->NotifyLink.ForwardLink != NULL) {
+ RemoveEntryList (&Event->NotifyLink);
+ Event->NotifyLink.ForwardLink = NULL;
+ }
+
+ //
+ // Queue the event to the pending notification list
+ //
+
+ InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);
+ gEventPending |= (UINTN)(1 << Event->NotifyTpl);
+}
+
+
+
+VOID
+CoreNotifySignalList (
+ IN EFI_GUID *EventGroup
+ )
+/*++
+
+Routine Description:
+ Signals all events in the EventGroup
+
+Arguments:
+ EventGroup - The list to signal
+
+Returns:
+
+ None
+
+--*/
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Head;
+ IEVENT *Event;
+
+ CoreAcquireEventLock ();
+
+ Head = &gEventSignalQueue;
+ for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
+ Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);
+ if (CompareGuid (&Event->EventGroup, EventGroup)) {
+ CoreNotifyEvent (Event);
+ }
+ }
+
+ CoreReleaseEventLock ();
+}
+
+
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+
+static
+VOID
+EFIAPI
+EventNofitySignalAllNullEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // This null event is a size efficent way to enusre that
+ // EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.
+ // EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into
+ // CreateEventEx() and this function is used to make the
+ // old error checking in CreateEvent() for Tiano extensions
+ // function.
+ //
+ return;
+}
+
+#endif
+
+
+
+
+EFI_STATUS
+EFIAPI
+CoreCreateEvent (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL
+ IN VOID *NotifyContext, OPTIONAL
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+ Creates a general-purpose event structure
+
+Arguments:
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the events notification function
+ NotifyContext - Pointer to the notification functions context; corresponds to
+ parameter "Context" in the notification function
+ Event - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+{
+ EFI_GUID *GuidPtr;
+ EFI_EVENT_NOTIFY Function;
+
+ GuidPtr = NULL;
+ Function = NotifyFunction;
+
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+ //
+ // Clear EFI_EVENT_NOFITY_SIGNAL_ALL (Tiano extension) as all events in the
+ // EventGroup now have this property. So we need to filter it out.
+ //
+ if (Type & EFI_EVENT_NOTIFY_SIGNAL_ALL) {
+ Type &= ~EFI_EVENT_NOTIFY_SIGNAL_ALL;
+ Function = EventNofitySignalAllNullEvent;
+ }
+
+ //
+ // Map the Tiano extensions Events to CreateEventEx form
+ //
+ if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) {
+ GuidPtr = &gEfiEventReadToBootGuid;
+ } else if (Type == EFI_EVENT_SIGNAL_LEGACY_BOOT) {
+ GuidPtr = &gEfiEventLegacyBootGuid
+ }
+#endif
+
+ //
+ // Convert EFI 1.10 Events to thier UEFI 2.0 CreateEventEx mapping
+ //
+ if (Type == EVENT_SIGNAL_EXIT_BOOT_SERVICES) {
+ GuidPtr = &gEfiEventExitBootServicesGuid;
+ } else if (Type == EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
+ GuidPtr = &gEfiEventVirtualAddressChangeGuid;
+ }
+
+ return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event);
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreCreateEventEx (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL
+ IN CONST VOID *NotifyContext, OPTIONAL
+ IN CONST EFI_GUID *EventGroup, OPTIONAL
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+ Creates a general-purpose event structure
+
+Arguments:
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the events notification function
+ NotifyContext - Pointer to the notification functions context; corresponds to
+ parameter "Context" in the notification function
+ EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent().
+ Event - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+{
+ EFI_STATUS Status;
+ IEVENT *IEvent;
+ INTN Index;
+
+
+ if ((Event == NULL) || (NotifyTpl == EFI_TPL_APPLICATION)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to make sure no reserved flags are set
+ //
+ Status = EFI_INVALID_PARAMETER;
+ for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
+ if (Type == mEventTable[Index]) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ if(EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If it's a notify type of event, check its parameters
+ //
+ if ((Type & (EFI_EVENT_NOTIFY_WAIT | EFI_EVENT_NOTIFY_SIGNAL))) {
+ //
+ // Check for an invalid NotifyFunction or NotifyTpl
+ //
+ if ((NotifyFunction == NULL) ||
+ (NotifyTpl < EFI_TPL_APPLICATION) ||
+ (NotifyTpl >= EFI_TPL_HIGH_LEVEL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ } else {
+ //
+ // No notification needed, zero ignored values
+ //
+ NotifyTpl = 0;
+ NotifyFunction = NULL;
+ NotifyContext = NULL;
+ }
+
+ //
+ // Allcoate and initialize a new event structure.
+ //
+ Status = CoreAllocatePool (
+ (Type & EFI_EVENT_RUNTIME) ? EfiRuntimeServicesData: EfiBootServicesData,
+ sizeof (IEVENT),
+ (VOID **)&IEvent
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetMem (IEvent, sizeof (IEVENT), 0);
+
+ IEvent->Signature = EVENT_SIGNATURE;
+ IEvent->Type = Type;
+
+ IEvent->NotifyTpl = NotifyTpl;
+ IEvent->NotifyFunction = NotifyFunction;
+ IEvent->NotifyContext = (VOID *)NotifyContext;
+ if (EventGroup != NULL) {
+ CopyGuid (&IEvent->EventGroup, EventGroup);
+ IEvent->ExFlag = TRUE;
+ }
+
+ *Event = IEvent;
+
+ if (Type & EFI_EVENT_RUNTIME) {
+ //
+ // Keep a list of all RT events so we can tell the RT AP.
+ //
+ InsertTailList (&mRuntimeEventList, &IEvent->RuntimeLink);
+ }
+
+ CoreAcquireEventLock ();
+
+ if ((Type & EFI_EVENT_NOTIFY_SIGNAL) != 0x00000000) {
+ //
+ // The Event's NotifyFunction must be queued whenever the event is signaled
+ //
+ InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);
+ }
+
+ CoreReleaseEventLock ();
+
+ //
+ // Done
+ //
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreSignalEvent (
+ IN EFI_EVENT UserEvent
+ )
+/*++
+
+Routine Description:
+
+ Signals the event. Queues the event to be notified if needed
+
+Arguments:
+
+ UserEvent - The event to signal
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event was signaled.
+
+--*/
+{
+ IEVENT *Event;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireEventLock ();
+
+ //
+ // If the event is not already signalled, do so
+ //
+
+ if (Event->SignalCount == 0x00000000) {
+ Event->SignalCount++;
+
+ //
+ // If signalling type is a notify function, queue it
+ //
+ if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
+ if (Event->ExFlag) {
+ //
+ // The CreateEventEx() style requires all members of the Event Group
+ // to be signaled.
+ //
+ CoreReleaseEventLock ();
+ CoreNotifySignalList (&Event->EventGroup);
+ CoreAcquireEventLock ();
+ } else {
+ CoreNotifyEvent (Event);
+ }
+ }
+ }
+
+ CoreReleaseEventLock ();
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreCheckEvent (
+ IN EFI_EVENT UserEvent
+ )
+/*++
+
+Routine Description:
+
+ Check the status of an event
+
+Arguments:
+
+ UserEvent - The event to check
+
+Returns:
+
+ EFI_SUCCESS - The event is in the signaled state
+ EFI_NOT_READY - The event is not in the signaled state
+ EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL
+
+--*/
+
+{
+ IEVENT *Event;
+ EFI_STATUS Status;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_READY;
+
+ if (!Event->SignalCount && (Event->Type & EFI_EVENT_NOTIFY_WAIT)) {
+
+ //
+ // Queue the wait notify function
+ //
+
+ CoreAcquireEventLock ();
+ if (!Event->SignalCount) {
+ CoreNotifyEvent (Event);
+ }
+ CoreReleaseEventLock ();
+ }
+
+ //
+ // If the even looks signalled, get the lock and clear it
+ //
+
+ if (Event->SignalCount) {
+ CoreAcquireEventLock ();
+
+ if (Event->SignalCount) {
+ Event->SignalCount = 0;
+ Status = EFI_SUCCESS;
+ }
+
+ CoreReleaseEventLock ();
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreWaitForEvent (
+ IN UINTN NumberOfEvents,
+ IN EFI_EVENT *UserEvents,
+ OUT UINTN *UserIndex
+ )
+/*++
+
+Routine Description:
+
+ Stops execution until an event is signaled.
+
+Arguments:
+
+ NumberOfEvents - The number of events in the UserEvents array
+ UserEvents - An array of EFI_EVENT
+ UserIndex - Pointer to the index of the event which satisfied the wait condition
+
+Returns:
+
+ EFI_SUCCESS - The event indicated by Index was signaled.
+ EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or
+ Event was not a valid type
+ EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION
+
+--*/
+
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ //
+ // Can only WaitForEvent at TPL_APPLICATION
+ //
+ if (gEfiCurrentTpl != EFI_TPL_APPLICATION) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for(;;) {
+
+ for(Index = 0; Index < NumberOfEvents; Index++) {
+
+ Status = CoreCheckEvent (UserEvents[Index]);
+
+ //
+ // provide index of event that caused problem
+ //
+ if (Status != EFI_NOT_READY) {
+ *UserIndex = Index;
+ return Status;
+ }
+ }
+
+ //
+ // This was the location of the Idle loop callback in EFI 1.x reference
+ // code. We don't have that concept in this base at this point.
+ //
+ }
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreCloseEvent (
+ IN EFI_EVENT UserEvent
+ )
+/*++
+
+Routine Description:
+
+ Closes an event and frees the event structure.
+
+Arguments:
+
+ UserEvent - Event to close
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event has been closed
+
+--*/
+
+{
+ EFI_STATUS Status;
+ IEVENT *Event;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If it's a timer event, make sure it's not pending
+ //
+ if (Event->Type & EFI_EVENT_TIMER) {
+ CoreSetTimer (Event, TimerCancel, 0);
+ }
+
+ CoreAcquireEventLock ();
+
+ //
+ // If the event is queued somewhere, remove it
+ //
+
+ if (Event->RuntimeLink.ForwardLink != NULL) {
+ RemoveEntryList (&Event->RuntimeLink);
+ }
+
+ if (Event->NotifyLink.ForwardLink != NULL) {
+ RemoveEntryList (&Event->NotifyLink);
+ }
+
+ if (Event->SignalLink.ForwardLink != NULL) {
+ RemoveEntryList (&Event->SignalLink);
+ }
+
+ CoreReleaseEventLock ();
+
+ //
+ // If the event is registered on a protocol notify, then remove it from the protocol database
+ //
+ CoreUnregisterProtocolNotify (Event);
+
+ Status = CoreFreePool (Event);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/EdkModulePkg/Core/Dxe/Event/execdata.c b/EdkModulePkg/Core/Dxe/Event/execdata.c
new file mode 100644
index 0000000000..e7a11c2400
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Event/execdata.c
@@ -0,0 +1,55 @@
+/*++
+
+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:
+
+ execdata.c
+
+Abstract:
+
+
+
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+
+//
+// gTpl - Task priority level
+//
+EFI_TPL gEfiCurrentTpl = EFI_TPL_APPLICATION;
+
+
+//
+// gEventQueueLock - Protects the event queus
+//
+EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
+
+//
+// gEventQueue - A list of event's to notify for each priority level
+// gEventPending - A bitmask of the EventQueues that are pending
+//
+LIST_ENTRY gEventQueue[EFI_TPL_HIGH_LEVEL + 1];
+UINTN gEventPending = 0;
+
+
+//
+// gEventSignalQueue - A list of events to signal based on EventGroup type
+//
+LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue);
+
+//
+// LIST of runtime events that need to be fired by RT AP.
+//
+LIST_ENTRY mRuntimeEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeEventList);
diff --git a/EdkModulePkg/Core/Dxe/Event/timer.c b/EdkModulePkg/Core/Dxe/Event/timer.c
new file mode 100644
index 0000000000..8d7932f837
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Event/timer.c
@@ -0,0 +1,386 @@
+/*++
+
+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:
+
+ timer.c
+
+Abstract:
+
+ EFI Event support
+
+Revision History
+
+--*/
+
+
+#include <DxeMain.h>
+
+//
+// Internal prototypes
+//
+STATIC
+UINT64
+CoreCurrentSystemTime (
+ VOID
+ );
+
+VOID
+EFIAPI
+CoreCheckTimers (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+STATIC
+VOID
+CoreInsertEventTimer (
+ IN IEVENT *Event
+ );
+
+//
+// Internal data
+//
+
+static LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList);
+static EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL - 1);
+static EFI_EVENT mEfiCheckTimerEvent;
+
+static EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
+static UINT64 mEfiSystemTime = 0;
+
+//
+// Timer functions
+//
+
+VOID
+CoreInitializeTimer (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes timer support
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_HIGH_LEVEL - 1,
+ CoreCheckTimers,
+ NULL,
+ &mEfiCheckTimerEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+STATIC
+UINT64
+CoreCurrentSystemTime (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Returns the current system time
+
+Arguments:
+
+ None
+
+Returns:
+
+ Returns the current system time
+
+--*/
+{
+ UINT64 SystemTime;
+
+ CoreAcquireLock (&mEfiSystemTimeLock);
+ SystemTime = mEfiSystemTime;
+ CoreReleaseLock (&mEfiSystemTimeLock);
+ return SystemTime;
+}
+
+VOID
+EFIAPI
+CoreTimerTick (
+ IN UINT64 Duration
+ )
+/*++
+
+Routine Description:
+
+ Called by the platform code to process a tick.
+
+Arguments:
+
+ Duration - The number of 100ns elasped since the last call to TimerTick
+
+Returns:
+
+ None
+
+--*/
+{
+ IEVENT *Event;
+
+ //
+ // Check runtiem flag in case there are ticks while exiting boot services
+ //
+
+ CoreAcquireLock (&mEfiSystemTimeLock);
+
+ //
+ // Update the system time
+ //
+
+ mEfiSystemTime += Duration;
+
+ //
+ // If the head of the list is expired, fire the timer event
+ // to process it
+ //
+
+ if (!IsListEmpty (&mEfiTimerList)) {
+ Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
+
+ if (Event->u.Timer.TriggerTime <= mEfiSystemTime) {
+ CoreSignalEvent (mEfiCheckTimerEvent);
+ }
+ }
+
+ CoreReleaseLock (&mEfiSystemTimeLock);
+}
+
+VOID
+EFIAPI
+CoreCheckTimers (
+ IN EFI_EVENT CheckEvent,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Checks the sorted timer list against the current system time.
+ Signals any expired event timer.
+
+Arguments:
+
+ CheckEvent - Not used
+
+ Context - Not used
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 SystemTime;
+ IEVENT *Event;
+
+ //
+ // Check the timer database for expired timers
+ //
+
+ CoreAcquireLock (&mEfiTimerLock);
+ SystemTime = CoreCurrentSystemTime ();
+
+ while (!IsListEmpty (&mEfiTimerList)) {
+ Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
+
+ //
+ // If this timer is not expired, then we're done
+ //
+
+ if (Event->u.Timer.TriggerTime > SystemTime) {
+ break;
+ }
+
+ //
+ // Remove this timer from the timer queue
+ //
+
+ RemoveEntryList (&Event->u.Timer.Link);
+ Event->u.Timer.Link.ForwardLink = NULL;
+
+ //
+ // Signal it
+ //
+ CoreSignalEvent (Event);
+
+ //
+ // If this is a periodic timer, set it
+ //
+ if (Event->u.Timer.Period) {
+
+ //
+ // Compute the timers new trigger time
+ //
+
+ Event->u.Timer.TriggerTime = Event->u.Timer.TriggerTime + Event->u.Timer.Period;
+
+ //
+ // If that's before now, then reset the timer to start from now
+ //
+ if (Event->u.Timer.TriggerTime <= SystemTime) {
+ Event->u.Timer.TriggerTime = SystemTime;
+ CoreSignalEvent (mEfiCheckTimerEvent);
+ }
+
+ //
+ // Add the timer
+ //
+
+ CoreInsertEventTimer (Event);
+ }
+ }
+
+ CoreReleaseLock (&mEfiTimerLock);
+}
+
+STATIC
+VOID
+CoreInsertEventTimer (
+ IN IEVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ Inserts the timer event
+
+Arguments:
+
+ Event - Points to the internal structure of timer event to be installed
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 TriggerTime;
+ LIST_ENTRY *Link;
+ IEVENT *Event2;
+
+ ASSERT_LOCKED (&mEfiTimerLock);
+
+ //
+ // Get the timer's trigger time
+ //
+
+ TriggerTime = Event->u.Timer.TriggerTime;
+
+ //
+ // Insert the timer into the timer database in assending sorted order
+ //
+
+ for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) {
+ Event2 = CR (Link, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
+
+ if (Event2->u.Timer.TriggerTime > TriggerTime) {
+ break;
+ }
+ }
+
+ InsertTailList (Link, &Event->u.Timer.Link);
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreSetTimer (
+ IN EFI_EVENT UserEvent,
+ IN EFI_TIMER_DELAY Type,
+ IN UINT64 TriggerTime
+ )
+/*++
+
+Routine Description:
+
+ Sets the type of timer and the trigger time for a timer event.
+
+Arguments:
+
+ UserEvent - The timer event that is to be signaled at the specified time
+ Type - The type of time that is specified in TriggerTime
+ TriggerTime - The number of 100ns units until the timer expires
+
+Returns:
+
+ EFI_SUCCESS - The event has been set to be signaled at the requested time
+ EFI_INVALID_PARAMETER - Event or Type is not valid
+
+--*/
+{
+ IEVENT *Event;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Type < 0 || Type > TimerRelative || !(Event->Type & EFI_EVENT_TIMER)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireLock (&mEfiTimerLock);
+
+ //
+ // If the timer is queued to the timer database, remove it
+ //
+
+ if (Event->u.Timer.Link.ForwardLink != NULL) {
+ RemoveEntryList (&Event->u.Timer.Link);
+ Event->u.Timer.Link.ForwardLink = NULL;
+ }
+
+ Event->u.Timer.TriggerTime = 0;
+ Event->u.Timer.Period = 0;
+
+ if (Type != TimerCancel) {
+
+ if (Type == TimerPeriodic) {
+ Event->u.Timer.Period = TriggerTime;
+ }
+
+ Event->u.Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
+ CoreInsertEventTimer (Event);
+
+ if (TriggerTime == 0) {
+ CoreSignalEvent (mEfiCheckTimerEvent);
+ }
+ }
+
+ CoreReleaseLock (&mEfiTimerLock);
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Dxe/Event/tpl.c b/EdkModulePkg/Core/Dxe/Event/tpl.c
new file mode 100644
index 0000000000..ae851638af
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Event/tpl.c
@@ -0,0 +1,198 @@
+/*++
+
+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:
+
+ tpl.c
+
+Abstract:
+
+ Task priority function
+
+--*/
+
+#include <DxeMain.h>
+
+STATIC
+VOID
+CoreSetInterruptState (
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ Set Interrupt State
+
+Arguments:
+
+ Enable - The state of enable or disable interrupt
+
+Returns:
+
+ None
+
+--*/
+
+{
+ if (gCpu != NULL) {
+ if (Enable) {
+ gCpu->EnableInterrupt(gCpu);
+ } else {
+ gCpu->DisableInterrupt(gCpu);
+ }
+ }
+}
+
+//
+// Return the highest set bit
+//
+UINTN
+CoreHighestSetBit (
+ IN UINTN Number
+ )
+/*++
+
+Routine Description:
+
+ Return the highest set bit
+
+Arguments:
+
+ Number - The value to check
+
+Returns:
+
+ Bit position of the highest set bit
+
+--*/
+{
+ UINTN msb;
+
+ msb = 31;
+ while ((msb > 0) && ((Number & (UINTN)(1 << msb)) == 0)) {
+ msb--;
+ }
+
+ return msb;
+}
+
+
+
+EFI_TPL
+EFIAPI
+CoreRaiseTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Raise the task priority level to the new level.
+ High level is implemented by disabling processor interrupts.
+
+Arguments:
+
+ NewTpl - New task priority level
+
+Returns:
+
+ The previous task priority level
+
+--*/
+{
+ EFI_TPL OldTpl;
+
+ OldTpl = gEfiCurrentTpl;
+ ASSERT (OldTpl <= NewTpl);
+ ASSERT (VALID_TPL (NewTpl));
+
+ //
+ // If raising to high level, disable interrupts
+ //
+ if (NewTpl >= EFI_TPL_HIGH_LEVEL && OldTpl < EFI_TPL_HIGH_LEVEL) {
+ CoreSetInterruptState (FALSE);
+ }
+
+ //
+ // Set the new value
+ //
+ gEfiCurrentTpl = NewTpl;
+
+ return OldTpl;
+}
+
+
+
+VOID
+EFIAPI
+CoreRestoreTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Lowers the task priority to the previous value. If the new
+ priority unmasks events at a higher priority, they are dispatched.
+
+Arguments:
+
+ NewTpl - New, lower, task priority
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_TPL OldTpl;
+
+ OldTpl = gEfiCurrentTpl;
+ ASSERT (NewTpl <= OldTpl);
+ ASSERT (VALID_TPL (NewTpl));
+
+ //
+ // If lowering below HIGH_LEVEL, make sure
+ // interrupts are enabled
+ //
+
+ if (OldTpl >= EFI_TPL_HIGH_LEVEL && NewTpl < EFI_TPL_HIGH_LEVEL) {
+ gEfiCurrentTpl = EFI_TPL_HIGH_LEVEL;
+ }
+
+ //
+ // Dispatch any pending events
+ //
+
+ while ((-2 << NewTpl) & gEventPending) {
+ gEfiCurrentTpl = CoreHighestSetBit (gEventPending);
+ if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) {
+ CoreSetInterruptState (TRUE);
+ }
+ CoreDispatchEventNotifies (gEfiCurrentTpl);
+ }
+
+ //
+ // Set the new value
+ //
+
+ gEfiCurrentTpl = NewTpl;
+
+ //
+ // If lowering below HIGH_LEVEL, make sure
+ // interrupts are enabled
+ //
+ if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) {
+ CoreSetInterruptState (TRUE);
+ }
+
+}
diff --git a/EdkModulePkg/Core/Dxe/FwVol/Ffs.c b/EdkModulePkg/Core/Dxe/FwVol/Ffs.c
new file mode 100644
index 0000000000..6f7d353e05
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVol/Ffs.c
@@ -0,0 +1,266 @@
+/*++
+
+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:
+
+ Ffs.c
+
+Abstract:
+
+ FFS file access utilities.
+
+--*/
+
+
+#include <DxeMain.h>
+
+#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *)((UINTN)(Address)))
+
+
+EFI_FFS_FILE_STATE
+GetFileState (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Get the FFS file state by checking the highest bit set in the header's state field
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header
+
+Returns:
+ FFS File state
+
+--*/
+{
+ EFI_FFS_FILE_STATE FileState;
+ UINT8 HighestBit;
+
+ FileState = FfsHeader->State;
+
+ if (ErasePolarity != 0) {
+ FileState = (EFI_FFS_FILE_STATE)~FileState;
+ }
+
+ HighestBit = 0x80;
+ while (HighestBit != 0 && ((HighestBit & FileState) == 0)) {
+ HighestBit >>= 1;
+ }
+
+ return (EFI_FFS_FILE_STATE)HighestBit;
+}
+
+
+BOOLEAN
+IsBufferErased (
+ IN UINT8 ErasePolarity,
+ IN VOID *InBuffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+ Check if a block of buffer is erased
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ InBuffer - The buffer to be checked
+ BufferSize - Size of the buffer in bytes
+
+Returns:
+ TRUE - The block of buffer is erased
+ FALSE - The block of buffer is not erased
+
+--*/
+{
+ UINTN Count;
+ UINT8 EraseByte;
+ UINT8 *Buffer;
+
+ if(ErasePolarity == 1) {
+ EraseByte = 0xFF;
+ } else {
+ EraseByte = 0;
+ }
+
+ Buffer = InBuffer;
+ for (Count = 0; Count < BufferSize; Count++) {
+ if (Buffer[Count] != EraseByte) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN
+VerifyFvHeaderChecksum (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+ Verify checksum of the firmware volume header
+
+Arguments:
+ FvHeader - Points to the firmware volume header to be checked
+
+Returns:
+ TRUE - Checksum verification passed
+ FALSE - Checksum verification failed
+
+--*/
+{
+ UINT32 Index;
+ UINT32 HeaderLength;
+ UINT16 Checksum;
+ UINT16 *ptr;
+
+ HeaderLength = FvHeader->HeaderLength;
+ ptr = (UINT16 *)FvHeader;
+ Checksum = 0;
+
+ for (Index = 0; Index < HeaderLength / sizeof (UINT16); Index++) {
+ Checksum = (UINT16)(Checksum + ptr[Index]);
+ }
+
+ if (Checksum == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+VerifyHeaderChecksum (
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Verify checksum of the FFS file header
+
+Arguments:
+ FfsHeader - Points to the FFS file header to be checked
+
+Returns:
+ TRUE - Checksum verification passed
+ FALSE - Checksum verification failed
+
+--*/
+{
+ UINT32 Index;
+ UINT8 *ptr;
+ UINT8 HeaderChecksum;
+
+ ptr = (UINT8 *)FfsHeader;
+ HeaderChecksum = 0;
+ for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
+ HeaderChecksum = (UINT8)(HeaderChecksum + ptr[Index]);
+ }
+
+ HeaderChecksum = HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File;
+
+ if (HeaderChecksum == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+IsValidFfsHeader (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT EFI_FFS_FILE_STATE *FileState
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file header
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header to be checked
+ FileState - FFS file state to be returned
+
+Returns:
+ TRUE - Valid FFS file header
+ FALSE - Invalid FFS file header
+
+--*/
+{
+ *FileState = GetFileState (ErasePolarity, FfsHeader);
+
+ switch (*FileState) {
+ case EFI_FILE_HEADER_VALID:
+ case EFI_FILE_DATA_VALID:
+ case EFI_FILE_MARKED_FOR_UPDATE:
+ case EFI_FILE_DELETED:
+ //
+ // Here we need to verify header checksum
+ //
+ return VerifyHeaderChecksum (FfsHeader);
+
+ case EFI_FILE_HEADER_CONSTRUCTION:
+ case EFI_FILE_HEADER_INVALID:
+ default:
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+IsValidFfsFile (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file.
+ Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file to be checked
+
+Returns:
+ TRUE - Valid FFS file
+ FALSE - Invalid FFS file
+
+--*/
+{
+ EFI_FFS_FILE_STATE FileState;
+
+ FileState = GetFileState (ErasePolarity, FfsHeader);
+ switch (FileState) {
+
+ case EFI_FILE_DELETED:
+ case EFI_FILE_DATA_VALID:
+ case EFI_FILE_MARKED_FOR_UPDATE:
+ //
+ // Some other vliadation like file content checksum might be done here.
+ // For performance issue, Tiano only do FileState check.
+ //
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVol.c b/EdkModulePkg/Core/Dxe/FwVol/FwVol.c
new file mode 100644
index 0000000000..d8137d79c6
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVol/FwVol.c
@@ -0,0 +1,553 @@
+/*++
+
+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:
+
+ Firmware File System driver that produce Firmware Volume protocol.
+ Layers on top of Firmware Block protocol to produce a file abstraction
+ of FV based files.
+
+--*/
+
+#include <DxeMain.h>
+
+#define KEYSIZE sizeof (UINTN)
+
+//
+// Protocol notify related globals
+//
+VOID *gEfiFwVolBlockNotifyReg;
+EFI_EVENT gEfiFwVolBlockEvent;
+
+FV_DEVICE mFvDevice = {
+ FV_DEVICE_SIGNATURE,
+ NULL,
+ NULL,
+ {
+ FvGetVolumeAttributes,
+ FvSetVolumeAttributes,
+ FvReadFile,
+ FvReadFileSection,
+ FvWriteFile,
+ FvGetNextFile,
+ KEYSIZE
+ },
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ { NULL, NULL },
+ 0
+};
+
+
+//
+// FFS helper functions
+//
+
+EFI_STATUS
+GetFwVolHeader (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
+ )
+/*++
+
+Routine Description:
+ given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
+ copy the volume header into it.
+
+Arguments:
+ Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
+ header
+ FwVolHeader - Pointer to pointer to allocated buffer in which the volume
+ header is returned.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
+ EFI_SUCCESS - Successfully read volume header to the allocated buffer.
+
+--*/
+
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER TempFvh;
+ UINTN FvhLength;
+ UINT8 *Buffer;
+
+
+ //
+ //Determine the real length of FV header
+ //
+ FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
+ Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh);
+
+ //
+ // Allocate a buffer for the caller
+ //
+ *FwVolHeader = CoreAllocateBootServicesPool (TempFvh.HeaderLength);
+ if (*FwVolHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy the standard header into the buffer
+ //
+ CopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
+
+ //
+ // Read the rest of the header
+ //
+ FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);
+ Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);
+ Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer);
+ if (EFI_ERROR (Status)) {
+ //
+ // Read failed so free buffer
+ //
+ CoreFreePool (*FwVolHeader);
+ }
+
+ return Status;
+}
+
+
+STATIC
+VOID
+FreeFvDeviceResource (
+ IN FV_DEVICE *FvDevice
+ )
+/*++
+
+Routine Description:
+ Free FvDevice resource when error happens
+
+Arguments:
+ FvDevice - pointer to the FvDevice to be freed.
+
+Returns:
+ None.
+
+--*/
+{
+ FFS_FILE_LIST_ENTRY *FfsFileEntry;
+ LIST_ENTRY *NextEntry;
+
+ //
+ // Free File List Entry
+ //
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink;
+ while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {
+ NextEntry = (&FfsFileEntry->Link)->ForwardLink;
+
+ if (FfsFileEntry->StreamHandle != 0) {
+ //
+ // Close stream and free resources from SEP
+ //
+ FfsFileEntry->Sep->CloseSectionStream (FfsFileEntry->Sep, FfsFileEntry->StreamHandle);
+ }
+
+ CoreFreePool (FfsFileEntry);
+
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *)NextEntry;
+ }
+
+
+ //
+ // Free the cache
+ //
+ CoreFreePool (FvDevice->CachedFv);
+
+ //
+ // Free Volume Header
+ //
+ CoreFreePool (FvDevice->FwVolHeader);
+
+ return;
+}
+
+
+EFI_STATUS
+FvCheck (
+ IN OUT FV_DEVICE *FvDevice
+ )
+/*++
+
+Routine Description:
+ Check if a FV is consistent and allocate cache
+
+Arguments:
+ FvDevice - pointer to the FvDevice to be checked.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
+ EFI_SUCCESS - FV is consistent and cache is allocated.
+ EFI_VOLUME_CORRUPTED - File system is corrupted.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FVB_ATTRIBUTES FvbAttributes;
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ FFS_FILE_LIST_ENTRY *FfsFileEntry;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINT8 *CacheLocation;
+ UINTN LbaOffset;
+ UINTN Index;
+ EFI_LBA LbaIndex;
+ UINTN Size;
+ UINTN FileLength;
+ EFI_FFS_FILE_STATE FileState;
+ UINT8 *TopFvAddress;
+ UINTN TestLength;
+
+
+ Fvb = FvDevice->Fvb;
+ FwVolHeader = FvDevice->FwVolHeader;
+
+ Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Size is the size of the FV minus the head. We have already allocated
+ // the header to check to make sure the volume is valid
+ //
+ Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);
+ FvDevice->CachedFv = CoreAllocateZeroBootServicesPool (Size);
+ if (FvDevice->CachedFv == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Remember a pointer to the end fo the CachedFv
+ //
+ FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;
+
+ //
+ // Copy FV minus header into memory using the block map we have all ready
+ // read into memory.
+ //
+ BlockMap = FwVolHeader->FvBlockMap;
+ CacheLocation = FvDevice->CachedFv;
+ LbaIndex = 0;
+ LbaOffset = FwVolHeader->HeaderLength;
+ while ((BlockMap->NumBlocks != 0) || (BlockMap->BlockLength != 0)) {
+
+ for (Index = 0; Index < BlockMap->NumBlocks; Index ++) {
+
+ Size = BlockMap->BlockLength;
+ if (Index == 0) {
+ //
+ // Cache does not include FV Header
+ //
+ Size -= LbaOffset;
+ }
+ Status = Fvb->Read (Fvb,
+ LbaIndex,
+ LbaOffset,
+ &Size,
+ CacheLocation
+ );
+ //
+ // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->BlockLength
+ //
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // After we skip Fv Header always read from start of block
+ //
+ LbaOffset = 0;
+
+ LbaIndex++;
+ CacheLocation += Size;
+ }
+ BlockMap++;
+ }
+
+ //
+ // Scan to check the free space & File list
+ //
+ if (FvbAttributes & EFI_FVB_ERASE_POLARITY) {
+ FvDevice->ErasePolarity = 1;
+ } else {
+ FvDevice->ErasePolarity = 0;
+ }
+
+
+ //
+ // go through the whole FV cache, check the consistence of the FV.
+ // Make a linked list off all the Ffs file headers
+ //
+ Status = EFI_SUCCESS;
+ InitializeListHead (&FvDevice->FfsFileListHeader);
+
+ //
+ // Build FFS list
+ //
+ FfsHeader = (EFI_FFS_FILE_HEADER *)FvDevice->CachedFv;
+ TopFvAddress = FvDevice->EndOfCachedFv;
+ while ((UINT8 *)FfsHeader < TopFvAddress) {
+
+ TestLength = TopFvAddress - ((UINT8 *)FfsHeader);
+ if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
+ TestLength = sizeof (EFI_FFS_FILE_HEADER);
+ }
+
+ if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) {
+ //
+ // We have found the free space so we are done!
+ //
+ goto Done;
+ }
+
+ if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) {
+ if ((FileState == EFI_FILE_HEADER_INVALID) ||
+ (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
+ FfsHeader++;
+
+ continue;
+
+ } else {
+ //
+ // File system is corrputed
+ //
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Done;
+ }
+ }
+
+ if (!IsValidFfsFile (FvDevice->ErasePolarity, FfsHeader)) {
+ //
+ // File system is corrupted
+ //
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Done;
+ }
+
+ //
+ // Size[3] is a three byte array, read 4 bytes and throw one away
+ //
+ FileLength = *(UINT32 *)&FfsHeader->Size[0] & 0x00FFFFFF;
+
+ FileState = GetFileState (FvDevice->ErasePolarity, FfsHeader);
+
+ //
+ // check for non-deleted file
+ //
+ if (FileState != EFI_FILE_DELETED) {
+ //
+ // Create a FFS list entry for each non-deleted file
+ //
+ FfsFileEntry = CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY));
+ if (FfsFileEntry == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ FfsFileEntry->FfsHeader = FfsHeader;
+ InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
+ }
+
+ FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FfsHeader) + FileLength);
+
+ //
+ // Adjust pointer to the next 8-byte aligned boundry.
+ //
+ FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07);
+
+ }
+
+Done:
+ if (EFI_ERROR (Status)) {
+ FreeFvDeviceResource (FvDevice);
+ }
+
+ return Status;
+}
+
+
+STATIC
+VOID
+EFIAPI
+NotifyFwVolBlock (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+ This notification function is invoked when an instance of the
+ EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
+ EFI_FIRMWARE_VOLUME_PROTOCOL on the same handle. This is the function where
+ the actual initialization of the EFI_FIRMWARE_VOLUME_PROTOCOL is done.
+
+Arguments:
+ Event - The event that occured
+ Context - For EFI compatiblity. Not used.
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ FV_DEVICE *FvDevice;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ //
+ // Examine all new handles
+ //
+ for (;;) {
+ //
+ // Get the next handle
+ //
+ BufferSize = sizeof (Handle);
+ Status = CoreLocateHandle (
+ ByRegisterNotify,
+ NULL,
+ gEfiFwVolBlockNotifyReg,
+ &BufferSize,
+ &Handle
+ );
+
+ //
+ // If not found, we're done
+ //
+ if (EFI_NOT_FOUND == Status) {
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Get the FirmwareVolumeBlock protocol on that handle
+ //
+ Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Make sure the Fv Header is O.K.
+ //
+ Status = GetFwVolHeader (Fvb, &FwVolHeader);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ if (!VerifyFvHeaderChecksum (FwVolHeader)) {
+ CoreFreePool (FwVolHeader);
+ continue;
+ }
+
+
+ //
+ // Check to see that the file system is indeed formatted in a way we can
+ // understand it...
+ //
+ if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystemGuid)) {
+ continue;
+ }
+
+ //
+ // Check if there is an FV protocol already installed in that handle
+ //
+ Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Fv);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update Fv to use a new Fvb
+ //
+ FvDevice = _CR (Fv, FV_DEVICE, Fv);
+ if (FvDevice->Signature == FV_DEVICE_SIGNATURE) {
+ //
+ // Only write into our device structure if it's our device structure
+ //
+ FvDevice->Fvb = Fvb;
+ }
+
+ } else {
+ //
+ // No FwVol protocol on the handle so create a new one
+ //
+ FvDevice = CoreAllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);
+ if (FvDevice == NULL) {
+ return;
+ }
+
+ FvDevice->Fvb = Fvb;
+ FvDevice->Handle = Handle;
+ FvDevice->FwVolHeader = FwVolHeader;
+ FvDevice->Fv.ParentHandle = Fvb->ParentHandle;
+
+ //
+ // Install an New FV protocol on the existing handle
+ //
+ Status = CoreInstallProtocolInterface (
+ &Handle,
+ &gEfiFirmwareVolumeProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &FvDevice->Fv
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, and registers two notification functions. These notification
+ functions are responsible for building the FV stack dynamically.
+
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+
+Returns:
+ EFI_SUCCESS - Function successfully returned.
+
+--*/
+{
+ gEfiFwVolBlockEvent = CoreCreateProtocolNotifyEvent (
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ EFI_TPL_CALLBACK,
+ NotifyFwVolBlock,
+ NULL,
+ &gEfiFwVolBlockNotifyReg,
+ TRUE
+ );
+ return EFI_SUCCESS;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVolAttrib.c b/EdkModulePkg/Core/Dxe/FwVol/FwVolAttrib.c
new file mode 100644
index 0000000000..8a44653282
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVol/FwVolAttrib.c
@@ -0,0 +1,99 @@
+/*++
+
+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:
+
+ FwVolAttrib.c
+
+Abstract:
+
+ Implements get/set firmware volume attributes
+
+--*/
+
+#include <DxeMain.h>
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully got volume attributes
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FVB_ATTRIBUTES FvbAttributes;
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+ Fvb = FvDevice->Fvb;
+
+ if (FvDevice->CachedFv == NULL) {
+ Status = FvCheck (FvDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // First get the Firmware Volume Block Attributes
+ //
+ Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes);
+
+ //
+ // Mask out Fvb bits that are not defined in FV
+ //
+ FvbAttributes &= 0xfffff0ff;
+
+ *Attributes = (EFI_FV_ATTRIBUTES)FvbAttributes;
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Sets current attributes for volume
+
+Arguments:
+ This - Calling context
+ Attributes - At input, contains attributes to be set. At output contains
+ new value of FV
+
+Returns:
+ EFI_UNSUPPORTED - Could not be set.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVolRead.c b/EdkModulePkg/Core/Dxe/FwVol/FwVolRead.c
new file mode 100644
index 0000000000..ff2fcb8023
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVol/FwVolRead.c
@@ -0,0 +1,516 @@
+/*++
+
+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:
+
+ FwVolRead.c
+
+Abstract:
+
+ Implements read firmware file
+
+--*/
+
+#include <DxeMain.h>
+
+/*++
+
+Required Alignment Alignment Value in FFS Alignment Value in
+(bytes) Attributes Field Firmware Volume Interfaces
+1 0 0
+2 0 1
+4 0 2
+8 0 3
+16 1 4
+128 2 7
+512 3 9
+1 KB 4 10
+4 KB 5 12
+32 KB 6 15
+64 KB 7 16
+
+--*/
+
+UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};
+
+
+STATIC
+EFI_FV_FILE_ATTRIBUTES
+FfsAttributes2FvFileAttributes (
+ IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
+ )
+/*++
+
+ Routine Description:
+ Convert the FFS File Attributes to FV File Attributes
+
+ Arguments:
+ FfsAttributes - The attributes of UINT8 type.
+
+ Returns:
+ The attributes of EFI_FV_FILE_ATTRIBUTES
+
+--*/
+{
+ FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
+ ASSERT (FfsAttributes < 8);
+
+ return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes];
+}
+
+
+EFI_STATUS
+EFIAPI
+FvGetNextFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT VOID *Key,
+ IN OUT EFI_FV_FILETYPE *FileType,
+ OUT EFI_GUID *NameGuid,
+ OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
+ OUT UINTN *Size
+ )
+/*++
+
+Routine Description:
+ Given the input key, search for the next matching file in the volume.
+
+Arguments:
+ This - Indicates the calling context.
+ FileType - FileType is a pointer to a caller allocated
+ EFI_FV_FILETYPE. The GetNextFile() API can filter it's
+ search for files based on the value of *FileType input.
+ A *FileType input of 0 causes GetNextFile() to search for
+ files of all types. If a file is found, the file's type
+ is returned in *FileType. *FileType is not modified if
+ no file is found.
+ Key - Key is a pointer to a caller allocated buffer that
+ contains implementation specific data that is used to
+ track where to begin the search for the next file.
+ The size of the buffer must be at least This->KeySize
+ bytes long. To reinitialize the search and begin from
+ the beginning of the firmware volume, the entire buffer
+ must be cleared to zero. Other than clearing the buffer
+ to initiate a new search, the caller must not modify the
+ data in the buffer between calls to GetNextFile().
+ NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
+ If a file is found, the file's name is returned in
+ *NameGuid. *NameGuid is not modified if no file is
+ found.
+ Attributes - Attributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
+ attributes are returned in *Attributes. *Attributes is
+ not modified if no file is found.
+ Size - Size is a pointer to a caller allocated UINTN.
+ If a file is found, the file's size is returned in *Size.
+ *Size is not modified if no file is found.
+
+Returns:
+ EFI_SUCCESS - Successfully find the file.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Fv could not read.
+ EFI_NOT_FOUND - No matching file found.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FV_ATTRIBUTES FvAttributes;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ UINTN *KeyValue;
+ LIST_ENTRY *Link;
+ FFS_FILE_LIST_ENTRY *FfsFileEntry;
+ UINTN FileLength;
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+ Status = FvGetVolumeAttributes (This, &FvAttributes);
+ if (EFI_ERROR (Status)){
+ return Status;
+ }
+
+ //
+ // Check if read operation is enabled
+ //
+ if ((FvAttributes & EFI_FV_READ_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+ //
+ // File type needs to be in 0 - 0x0B
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ KeyValue = (UINTN *)Key;
+ for (;;) {
+ if (*KeyValue == 0) {
+ //
+ // Search for 1st matching file
+ //
+ Link = &FvDevice->FfsFileListHeader;
+ } else {
+ //
+ // Key is pointer to FFsFileEntry, so get next one
+ //
+ Link = (LIST_ENTRY *)(*KeyValue);
+ }
+
+ if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
+ //
+ // Next is end of list so we did not find data
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;
+
+ //
+ // remember the key
+ //
+ *KeyValue = (UINTN)FfsFileEntry;
+
+ if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
+ //
+ // we ignore pad files
+ //
+ continue;
+ }
+
+ if (*FileType == 0) {
+ //
+ // Process all file types so we have a match
+ //
+ break;
+ }
+
+ if (*FileType == FfsFileHeader->Type) {
+ //
+ // Found a matching file type
+ //
+ break;
+ }
+
+ }
+
+ //
+ // Return FileType, NameGuid, and Attributes
+ //
+ *FileType = FfsFileHeader->Type;
+ CopyMem (NameGuid, &FfsFileHeader->Name, sizeof (EFI_GUID));
+ *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
+
+ //
+ // Read four bytes out of the 3 byte array and throw out extra data
+ //
+ FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF;
+
+ //
+ // we need to substract the header size
+ //
+ *Size = FileLength - sizeof(EFI_FFS_FILE_HEADER);
+
+ if (FfsFileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ //
+ // If tail is present substract it's size;
+ //
+ *Size -= sizeof(EFI_FFS_FILE_TAIL);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvReadFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_FV_FILETYPE *FoundType,
+ OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Locates a file in the firmware volume and
+ copies it to the supplied buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ Buffer - Buffer is a pointer to pointer to a buffer in
+ which the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated
+ UINTN. On input *BufferSize indicates the size
+ in bytes of the memory region pointed to by
+ Buffer. On output, *BufferSize contains the number
+ of bytes required to read the file.
+ FoundType - FoundType is a pointer to a caller allocated
+ EFI_FV_FILETYPE that on successful return from Read()
+ contains the type of file read. This output reflects
+ the file type irrespective of the value of the
+ SectionType input.
+ FileAttributes - FileAttributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. On successful return from
+ Read(), *FileAttributes contains the attributes of
+ the file read.
+ AuthenticationStatus - AuthenticationStatus is a pointer to a caller
+ allocated UINTN in which the authentication status
+ is returned.
+Returns:
+ EFI_SUCCESS - Successfully read to memory buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_GUID SearchNameGuid;
+ EFI_FV_FILETYPE LocalFoundType;
+ EFI_FV_FILE_ATTRIBUTES LocalAttributes;
+ UINTN FileSize;
+ UINT8 *SrcPtr;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINTN InputBufferSize;
+
+ if (NULL == NameGuid) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+
+ //
+ // Keep looking until we find the matching NameGuid.
+ // The Key is really an FfsFileEntry
+ //
+ FvDevice->LastKey = 0;
+ do {
+ LocalFoundType = 0;
+ Status = FvGetNextFile (
+ This,
+ &FvDevice->LastKey,
+ &LocalFoundType,
+ &SearchNameGuid,
+ &LocalAttributes,
+ &FileSize
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ } while (!CompareGuid (&SearchNameGuid, NameGuid));
+
+ //
+ // Get a pointer to the header
+ //
+ FfsHeader = FvDevice->LastKey->FfsHeader;
+
+ //
+ // Remember callers buffer size
+ //
+ InputBufferSize = *BufferSize;
+
+ //
+ // Calculate return values
+ //
+ *FoundType = FfsHeader->Type;
+ *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
+ *AuthenticationStatus = 0;
+ *BufferSize = FileSize;
+
+ if (Buffer == NULL) {
+ //
+ // If Buffer is NULL, we only want to get the information colected so far
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip over file header
+ //
+ SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
+
+ Status = EFI_SUCCESS;
+ if (*Buffer == NULL) {
+ //
+ // Caller passed in a pointer so allocate buffer for them
+ //
+ *Buffer = CoreAllocateBootServicesPool (FileSize);
+ if (*Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else if (FileSize > InputBufferSize) {
+ //
+ // Callers buffer was not big enough
+ //
+ Status = EFI_WARN_BUFFER_TOO_SMALL;
+ FileSize = InputBufferSize;
+ }
+
+ //
+ // Copy data into callers buffer
+ //
+ CopyMem (*Buffer, SrcPtr, FileSize);
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvReadFileSection (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN SectionInstance,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+ Routine Description:
+ Locates a section in a given FFS File and
+ copies it to the supplied buffer (not including section header).
+
+ Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ SectionType - Indicates the section type to return.
+ SectionInstance - Indicates which instance of sections with a type of
+ SectionType to return.
+ Buffer - Buffer is a pointer to pointer to a buffer in which
+ the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated UINTN.
+ AuthenticationStatus -AuthenticationStatus is a pointer to a caller
+ allocated UINT32 in which the authentication status
+ is returned.
+
+ Returns:
+ EFI_SUCCESS - Successfully read the file section into buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Section not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINTN FileSize;
+ UINT8 *FileBuffer;
+ EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
+ FFS_FILE_LIST_ENTRY *FfsEntry;
+
+ if (NULL == NameGuid || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+ //
+ // Read the whole file into buffer
+ //
+ FileBuffer = NULL;
+ Status = FvReadFile (
+ This,
+ NameGuid,
+ (VOID **)&FileBuffer,
+ &FileSize,
+ &FileType,
+ &FileAttributes,
+ AuthenticationStatus
+ );
+ //
+ // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.
+ //
+ FfsEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->LastKey;
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check to see that the file actually HAS sections before we go any further.
+ //
+ if (FileType == EFI_FV_FILETYPE_RAW) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Use FfsEntry to cache Section Extraction Protocol Inforomation
+ //
+ if (FfsEntry->StreamHandle == 0) {
+ //
+ // Located the protocol
+ //
+ Status = CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid, NULL, (VOID **)&Sep);
+ //
+ // Section Extraction Protocol is part of Dxe Core so this should never fail
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Sep->OpenSectionStream (
+ Sep,
+ FileSize,
+ FileBuffer,
+ &FfsEntry->StreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ FfsEntry->Sep = Sep;
+ } else {
+ //
+ // Get cached copy of Sep
+ //
+ Sep = FfsEntry->Sep;
+ }
+
+ //
+ // If SectionType == 0 We need the whole section stream
+ //
+ Status = Sep->GetSection (
+ Sep,
+ FfsEntry->StreamHandle,
+ (SectionType == 0) ? NULL : &SectionType,
+ NULL,
+ (SectionType == 0) ? 0 : SectionInstance,
+ Buffer,
+ BufferSize,
+ AuthenticationStatus
+ );
+
+ //
+ // Close of stream defered to close of FfsHeader list to allow SEP to cache data
+ //
+
+Done:
+ CoreFreePool (FileBuffer);
+
+ return Status;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVolWrite.c b/EdkModulePkg/Core/Dxe/FwVol/FwVolWrite.c
new file mode 100644
index 0000000000..4368fe534e
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVol/FwVolWrite.c
@@ -0,0 +1,60 @@
+/*++
+
+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:
+
+ FwVolWrite.c
+
+Abstract:
+
+ Implements write firmware file
+
+--*/
+
+#include <DxeMain.h>
+
+
+EFI_STATUS
+EFIAPI
+FvWriteFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN UINT32 NumberOfFiles,
+ IN EFI_FV_WRITE_POLICY WritePolicy,
+ IN EFI_FV_WRITE_FILE_DATA *FileData
+ )
+/*++
+
+ Routine Description:
+ Writes one or more files to the firmware volume.
+
+ Arguments:
+ This - Indicates the calling context.
+ NumberOfFiles - Number of files.
+ WritePolicy - WritePolicy indicates the level of reliability for
+ the write in the event of a power failure or other
+ system failure during the write operation.
+ FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
+ Each element of FileData[] represents a file to be written.
+
+ Returns:
+ EFI_SUCCESS - Files successfully written to firmware volume
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_WRITE_PROTECTED - Write protected.
+ EFI_NOT_FOUND - Not found.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_UNSUPPORTED - This function not supported.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/FwVolBlock.h b/EdkModulePkg/Core/Dxe/FwVolBlock.h
new file mode 100644
index 0000000000..2e76242184
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVolBlock.h
@@ -0,0 +1,324 @@
+/*++
+
+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:
+
+ FwVolBlock.h
+
+Abstract:
+
+ Firmware Volume Block protocol.. Consumes FV hobs and creates
+ appropriate block protocols.
+
+ Also consumes NT_NON_MM_FV envinronment variable and produces appropriate
+ block protocols fro them also... (this is TBD)
+
+--*/
+
+#ifndef _FWVOL_BLOCK_H_
+#define _FWVOL_BLOCK_H_
+
+
+#define FVB_DEVICE_SIGNATURE EFI_SIGNATURE_32('_','F','V','B')
+
+typedef struct {
+ UINTN Base;
+ UINTN Length;
+} LBA_CACHE;
+
+typedef struct {
+ MEMMAP_DEVICE_PATH MemMapDevPath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;
+} FV_DEVICE_PATH;
+
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ FV_DEVICE_PATH DevicePath;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance;
+ UINTN NumBlocks;
+ LBA_CACHE *LbaCache;
+ UINT32 FvbAttributes;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+} EFI_FW_VOL_BLOCK_DEVICE;
+
+#define FVB_DEVICE_FROM_THIS(a) \
+ CR(a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)
+
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
+ produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+Returns:
+ EFI_SUCCESS - Successfully initialized firmware volume block driver.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves Volume attributes. No polarity translations are done.
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockSetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Modifies the current settings of the firmware volume according to the input parameter.
+
+Arguments:
+ This - Calling context
+ Attributes - input buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+ EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as
+ declared in the firmware volume header.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockEraseBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ )
+/*++
+
+Routine Description:
+ The EraseBlock() function erases one or more blocks as denoted by the
+variable argument list. The entire parameter list of blocks must be verified
+prior to erasing any blocks. If a block is requested that does not exist
+within the associated firmware volume (it has a larger index than the last
+block of the firmware volume), the EraseBlock() function must return
+EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
+
+Arguments:
+ This - Calling context
+ ... - Starting LBA followed by Number of Lba to erase. a -1 to terminate
+ the list.
+
+Returns:
+ EFI_SUCCESS - The erase request was successfully completed.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be
+ written. The firmware device may have been partially erased.
+ EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do
+ EFI_UNSUPPORTED - Not supported.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockReadBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Read the specified number of bytes from the block to the input buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to read.
+ Offset - Offset into the block at which to begin reading.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually read.
+ Buffer - Pinter to a caller-allocated buffer that contains the destine
+ for the read.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was read successfully.
+ EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary.
+ EFI_ACCESS_DENIED - Access denied.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockWriteBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Writes the specified number of bytes from the input buffer to the block.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to write to.
+ Offset - Offset into the block at which to begin writing.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually written.
+ Buffer - Pinter to a caller-allocated buffer that contains the source
+ for the write.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was written successfully.
+ EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output,
+ NumBytes contains the total number of bytes actually written.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetPhysicalAddress (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+/*++
+
+Routine Description:
+ Get Fvb's base address.
+
+Arguments:
+ This - Indicates the calling context.
+ Address - Fvb device base address.
+
+Returns:
+ EFI_SUCCESS - Successfully got Fvb's base address.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetBlockSize (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+ Retrieves the size in bytes of a specific block within a firmware volume.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - Indicates the block for which to return the size.
+ BlockSize - Pointer to a caller-allocated UINTN in which the size of the
+ block is returned.
+ NumberOfBlocks - Pointer to a caller-allocated UINTN in which the number of
+ consecutive blocks starting with Lba is returned. All blocks
+ in this range have a size of BlockSize.
+Returns:
+ EFI_SUCCESS - The firmware volume base address is returned.
+ EFI_INVALID_PARAMETER - The requested LBA is out of range.
+--*/
+;
+EFI_STATUS
+FwVolBlockDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
+ produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+Returns:
+ Status code
+
+--*/
+;
+
+EFI_STATUS
+ProduceFVBProtocolOnBuffer (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_HANDLE ParentHandle,
+ OUT EFI_HANDLE *FvProtocolHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+ This routine produces a firmware volume block protocol on a given
+ buffer.
+
+Arguments:
+ BaseAddress - base address of the firmware volume image
+ Length - length of the firmware volume image
+ ParentHandle - handle of parent firmware volume, if this
+ image came from an FV image file in another
+ firmware volume (ala capsules)
+ FvProtocolHandle - Firmware volume block protocol produced.
+
+Returns:
+ EFI_VOLUME_CORRUPTED - Volume corrupted.
+ EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
+ EFI_SUCCESS - Successfully produced a FVB protocol on given buffer.
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c b/EdkModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
new file mode 100644
index 0000000000..49f197f811
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
@@ -0,0 +1,598 @@
+/*++
+
+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:
+
+ FwVolBlock.c
+
+Abstract:
+
+ Firmware Volume Block protocol.. Consumes FV hobs and creates
+ appropriate block protocols.
+
+ Also consumes NT_NON_MM_FV envinronment variable and produces appropriate
+ block protocols fro them also... (this is TBD)
+
+--*/
+
+#include <DxeMain.h>
+
+
+EFI_FW_VOL_BLOCK_DEVICE mFwVolBlock = {
+ FVB_DEVICE_SIGNATURE,
+ NULL,
+ {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_MEMMAP_DP,
+ { (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) }
+ },
+ EfiMemoryMappedIO,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { END_DEVICE_PATH_LENGTH, 0 }
+ },
+ },
+ {
+ FwVolBlockGetAttributes,
+ (EFI_FVB_SET_ATTRIBUTES)FwVolBlockSetAttributes,
+ FwVolBlockGetPhysicalAddress,
+ FwVolBlockGetBlockSize,
+ FwVolBlockReadBlock,
+ (EFI_FVB_WRITE)FwVolBlockWriteBlock,
+ (EFI_FVB_ERASE_BLOCKS)FwVolBlockEraseBlock,
+ NULL
+ },
+ 0,
+ NULL,
+ 0,
+ 0
+};
+
+
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves Volume attributes. No polarity translations are done.
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ //
+ // Since we are read only, it's safe to get attributes data from our in-memory copy.
+ //
+ *Attributes = FvbDevice->FvbAttributes;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockSetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Modifies the current settings of the firmware volume according to the input parameter.
+
+Arguments:
+ This - Calling context
+ Attributes - input buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+ EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as
+ declared in the firmware volume header.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockEraseBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ )
+/*++
+
+Routine Description:
+ The EraseBlock() function erases one or more blocks as denoted by the
+variable argument list. The entire parameter list of blocks must be verified
+prior to erasing any blocks. If a block is requested that does not exist
+within the associated firmware volume (it has a larger index than the last
+block of the firmware volume), the EraseBlock() function must return
+EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
+
+Arguments:
+ This - Calling context
+ ... - Starting LBA followed by Number of Lba to erase. a -1 to terminate
+ the list.
+
+Returns:
+ EFI_SUCCESS - The erase request was successfully completed.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be
+ written. The firmware device may have been partially erased.
+ EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do
+ EFI_UNSUPPORTED - Not supported.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockReadBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Read the specified number of bytes from the block to the input buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to read.
+ Offset - Offset into the block at which to begin reading.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually read.
+ Buffer - Pinter to a caller-allocated buffer that contains the destine
+ for the read.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was read successfully.
+ EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary.
+ EFI_ACCESS_DENIED - Access denied.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read.
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINT8 *LbaOffset;
+ UINTN LbaStart;
+ UINTN NumOfBytesRead;
+ UINTN LbaIndex;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ //
+ // Check if This FW can be read
+ //
+ if ((FvbDevice->FvbAttributes & EFI_FVB_READ_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ LbaIndex = (UINTN)Lba;
+ if (LbaIndex >= FvbDevice->NumBlocks) {
+ //
+ // Invalid Lba, read nothing.
+ //
+ *NumBytes = 0;
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Offset > FvbDevice->LbaCache[LbaIndex].Length) {
+ //
+ // all exceed boundry, read nothing.
+ //
+ *NumBytes = 0;
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumOfBytesRead = *NumBytes;
+ if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) {
+ //
+ // partial exceed boundry, read data from current postion to end.
+ //
+ NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset;
+ }
+
+ LbaStart = FvbDevice->LbaCache[LbaIndex].Base;
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
+ LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset;
+
+ //
+ // Perform read operation
+ //
+ CopyMem (Buffer, LbaOffset, NumOfBytesRead);
+
+ if (NumOfBytesRead == *NumBytes) {
+ return EFI_SUCCESS;
+ }
+
+ *NumBytes = NumOfBytesRead;
+ return EFI_BAD_BUFFER_SIZE;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockWriteBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Writes the specified number of bytes from the input buffer to the block.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to write to.
+ Offset - Offset into the block at which to begin writing.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually written.
+ Buffer - Pinter to a caller-allocated buffer that contains the source
+ for the write.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was written successfully.
+ EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output,
+ NumBytes contains the total number of bytes actually written.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetPhysicalAddress (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+/*++
+
+Routine Description:
+ Get Fvb's base address.
+
+Arguments:
+ This - Indicates the calling context.
+ Address - Fvb device base address.
+
+Returns:
+ EFI_SUCCESS - Successfully got Fvb's base address.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ if (FvbDevice->FvbAttributes & EFI_FVB_MEMORY_MAPPED) {
+ *Address = FvbDevice->BaseAddress;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetBlockSize (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+ Retrieves the size in bytes of a specific block within a firmware volume.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - Indicates the block for which to return the size.
+ BlockSize - Pointer to a caller-allocated UINTN in which the size of the
+ block is returned.
+ NumberOfBlocks - Pointer to a caller-allocated UINTN in which the number of
+ consecutive blocks starting with Lba is returned. All blocks
+ in this range have a size of BlockSize.
+Returns:
+ EFI_SUCCESS - The firmware volume base address is returned.
+ EFI_INVALID_PARAMETER - The requested LBA is out of range.
+--*/
+{
+ UINTN TotalBlocks;
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ //
+ // Do parameter checking
+ //
+ if (Lba >= FvbDevice->NumBlocks) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
+
+ PtrBlockMapEntry = FwVolHeader->FvBlockMap;
+
+ //
+ // Search the block map for the given block
+ //
+ TotalBlocks = 0;
+ while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->BlockLength !=0 )) {
+ TotalBlocks += PtrBlockMapEntry->NumBlocks;
+ if (Lba < TotalBlocks) {
+ //
+ // We find the range
+ //
+ break;
+ }
+
+ PtrBlockMapEntry++;
+ }
+
+ *BlockSize = PtrBlockMapEntry->BlockLength;
+ *NumberOfBlocks = TotalBlocks - (UINTN)Lba;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+ProduceFVBProtocolOnBuffer (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_HANDLE ParentHandle,
+ OUT EFI_HANDLE *FvProtocol OPTIONAL
+ )
+/*++
+
+Routine Description:
+ This routine produces a firmware volume block protocol on a given
+ buffer.
+
+Arguments:
+ BaseAddress - base address of the firmware volume image
+ Length - length of the firmware volume image
+ ParentHandle - handle of parent firmware volume, if this
+ image came from an FV image file in another
+ firmware volume (ala capsules)
+ FvProtocol - Firmware volume block protocol produced.
+
+Returns:
+ EFI_VOLUME_CORRUPTED - Volume corrupted.
+ EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
+ EFI_SUCCESS - Successfully produced a FVB protocol on given buffer.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDev;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINTN BlockIndex;
+ UINTN BlockIndex2;
+ UINTN LinearOffset;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
+ //
+ // Validate FV Header, if not as expected, return
+ //
+ if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+ //
+ // Allocate EFI_FW_VOL_BLOCK_DEVICE
+ //
+ FvbDev = CoreAllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);
+ if (FvbDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FvbDev->BaseAddress = BaseAddress;
+ FvbDev->FvbAttributes = FwVolHeader->Attributes;
+ FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle;
+
+ //
+ // Init the block caching fields of the device
+ // First, count the number of blocks
+ //
+ FvbDev->NumBlocks = 0;
+ for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
+ PtrBlockMapEntry->NumBlocks != 0;
+ PtrBlockMapEntry++) {
+ FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks;
+ }
+ //
+ // Second, allocate the cache
+ //
+ FvbDev->LbaCache = CoreAllocateBootServicesPool (FvbDev->NumBlocks * sizeof (LBA_CACHE));
+ if (FvbDev->LbaCache == NULL) {
+ CoreFreePool (FvbDev);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Last, fill in the cache with the linear address of the blocks
+ //
+ BlockIndex = 0;
+ LinearOffset = 0;
+ for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
+ PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
+ for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
+ FvbDev->LbaCache[BlockIndex].Base = LinearOffset;
+ FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->BlockLength;
+ LinearOffset += PtrBlockMapEntry->BlockLength;
+ BlockIndex++;
+ }
+ }
+
+ //
+ // Set up the devicepath
+ //
+ FvbDev->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;
+ FvbDev->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1;
+
+ //
+ //
+ // Attach FvVolBlock Protocol to new handle
+ //
+ Status = CoreInstallMultipleProtocolInterfaces (
+ &FvbDev->Handle,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &FvbDev->FwVolBlockInstance,
+ &gEfiDevicePathProtocolGuid, &FvbDev->DevicePath,
+ &gEfiFirmwareVolumeDispatchProtocolGuid, NULL,
+ NULL
+ );
+
+ //
+ // If they want the handle back, set it.
+ //
+ if (FvProtocol != NULL) {
+ *FvProtocol = FvbDev->Handle;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
+ produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+Returns:
+ EFI_SUCCESS - Successfully initialized firmware volume block driver.
+--*/
+{
+ EFI_PEI_HOB_POINTERS FvHob;
+ //
+ // Core Needs Firmware Volumes to function
+ //
+ FvHob.Raw = GetHobList ();
+ while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) {
+ //
+ // Produce an FVB protocol for it
+ //
+ ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, NULL);
+ FvHob.Raw = GET_NEXT_HOB (FvHob);
+ }
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CoreProcessFirmwareVolume (
+ IN VOID *FvHeader,
+ IN UINTN Size,
+ OUT EFI_HANDLE *FVProtocolHandle
+ )
+/*++
+
+Routine Description:
+ This DXE service routine is used to process a firmware volume. In
+ particular, it can be called by BDS to process a single firmware
+ volume found in a capsule.
+
+Arguments:
+ FvHeader - pointer to a firmware volume header
+ Size - the size of the buffer pointed to by FvHeader
+ FVProtocolHandle - the handle on which a firmware volume protocol
+ was produced for the firmware volume passed in.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - if an FVB could not be produced due to lack of
+ system resources
+ EFI_VOLUME_CORRUPTED - if the volume was corrupted
+ EFI_SUCCESS - a firmware volume protocol was produced for the
+ firmware volume
+
+--*/
+{
+ VOID *Ptr;
+ EFI_STATUS Status;
+
+ *FVProtocolHandle = NULL;
+ Status = ProduceFVBProtocolOnBuffer (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
+ (UINT64)Size,
+ NULL,
+ FVProtocolHandle
+ );
+ //
+ // Since in our implementation we use register-protocol-notify to put a
+ // FV protocol on the FVB protocol handle, we can't directly verify that
+ // the FV protocol was produced. Therefore here we will check the handle
+ // and make sure an FV protocol is on it. This indicates that all went
+ // well. Otherwise we have to assume that the volume was corrupted
+ // somehow.
+ //
+ if (!EFI_ERROR(Status)) {
+ Ptr = NULL;
+ Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Ptr);
+ if (EFI_ERROR(Status) || (Ptr == NULL)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+ return EFI_SUCCESS;
+ }
+ return Status;
+}
+
+
diff --git a/EdkModulePkg/Core/Dxe/FwVolDriver.h b/EdkModulePkg/Core/Dxe/FwVolDriver.h
new file mode 100644
index 0000000000..fb4e0d5bb2
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/FwVolDriver.h
@@ -0,0 +1,466 @@
+/*++
+
+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:
+
+ FwVolDriver.h
+
+Abstract:
+
+ Firmware File System protocol. Layers on top of Firmware
+ Block protocol to produce a file abstraction of FV based files.
+
+--*/
+
+#ifndef __FWVOL_H
+#define __FWVOL_H
+
+
+//
+// Used to track all non-deleted files
+//
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINTN StreamHandle;
+ EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
+} FFS_FILE_LIST_ENTRY;
+
+typedef struct {
+ UINTN Signature;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_HANDLE Handle;
+ EFI_FIRMWARE_VOLUME_PROTOCOL Fv;
+
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINT8 *CachedFv;
+ UINT8 *EndOfCachedFv;
+
+ FFS_FILE_LIST_ENTRY *LastKey;
+
+ LIST_ENTRY FfsFileListHeader;
+
+ UINT8 ErasePolarity;
+} FV_DEVICE;
+
+#define FV_DEVICE_FROM_THIS(a) CR(a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE)
+
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully got volume attributes
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Sets current attributes for volume
+
+Arguments:
+ This - Calling context
+ Attributes - At input, contains attributes to be set. At output contains
+ new value of FV
+
+Returns:
+ EFI_UNSUPPORTED - Could not be set.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvGetNextFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT VOID *Key,
+ IN OUT EFI_FV_FILETYPE *FileType,
+ OUT EFI_GUID *NameGuid,
+ OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
+ OUT UINTN *Size
+ )
+/*++
+
+Routine Description:
+ Given the input key, search for the next matching file in the volume.
+
+Arguments:
+ This - Indicates the calling context.
+ FileType - FileType is a pointer to a caller allocated
+ EFI_FV_FILETYPE. The GetNextFile() API can filter it's
+ search for files based on the value of *FileType input.
+ A *FileType input of 0 causes GetNextFile() to search for
+ files of all types. If a file is found, the file's type
+ is returned in *FileType. *FileType is not modified if
+ no file is found.
+ Key - Key is a pointer to a caller allocated buffer that
+ contains implementation specific data that is used to
+ track where to begin the search for the next file.
+ The size of the buffer must be at least This->KeySize
+ bytes long. To reinitialize the search and begin from
+ the beginning of the firmware volume, the entire buffer
+ must be cleared to zero. Other than clearing the buffer
+ to initiate a new search, the caller must not modify the
+ data in the buffer between calls to GetNextFile().
+ NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
+ If a file is found, the file's name is returned in
+ *NameGuid. *NameGuid is not modified if no file is
+ found.
+ Attributes - Attributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
+ attributes are returned in *Attributes. *Attributes is
+ not modified if no file is found.
+ Size - Size is a pointer to a caller allocated UINTN.
+ If a file is found, the file's size is returned in *Size.
+ *Size is not modified if no file is found.
+
+Returns:
+ EFI_SUCCESS - Successfully find the file.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Fv could not read.
+ EFI_NOT_FOUND - No matching file found.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FvReadFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_FV_FILETYPE *FoundType,
+ OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Locates a file in the firmware volume and
+ copies it to the supplied buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ Buffer - Buffer is a pointer to pointer to a buffer in
+ which the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated
+ UINTN. On input *BufferSize indicates the size
+ in bytes of the memory region pointed to by
+ Buffer. On output, *BufferSize contains the number
+ of bytes required to read the file.
+ FoundType - FoundType is a pointer to a caller allocated
+ EFI_FV_FILETYPE that on successful return from Read()
+ contains the type of file read. This output reflects
+ the file type irrespective of the value of the
+ SectionType input.
+ FileAttributes - FileAttributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. On successful return from
+ Read(), *FileAttributes contains the attributes of
+ the file read.
+ AuthenticationStatus - AuthenticationStatus is a pointer to a caller
+ allocated UINTN in which the authentication status
+ is returned.
+Returns:
+ EFI_SUCCESS - Successfully read to memory buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvReadFileSection (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN SectionInstance,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+ Routine Description:
+ Locates a section in a given FFS File and
+ copies it to the supplied buffer (not including section header).
+
+ Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ SectionType - Indicates the section type to return.
+ SectionInstance - Indicates which instance of sections with a type of
+ SectionType to return.
+ Buffer - Buffer is a pointer to pointer to a buffer in which
+ the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated UINTN.
+ AuthenticationStatus -AuthenticationStatus is a pointer to a caller
+ allocated UINT32 in which the authentication status
+ is returned.
+
+ Returns:
+ EFI_SUCCESS - Successfully read the file section into buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Section not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvWriteFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN UINT32 NumberOfFiles,
+ IN EFI_FV_WRITE_POLICY WritePolicy,
+ IN EFI_FV_WRITE_FILE_DATA *FileData
+ )
+/*++
+
+ Routine Description:
+ Writes one or more files to the firmware volume.
+
+ Arguments:
+ This - Indicates the calling context.
+ WritePolicy - WritePolicy indicates the level of reliability for
+ the write in the event of a power failure or other
+ system failure during the write operation.
+ FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
+ Each element of FileData[] represents a file to be written.
+
+ Returns:
+ EFI_SUCCESS - Files successfully written to firmware volume
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_WRITE_PROTECTED - Write protected.
+ EFI_NOT_FOUND - Not found.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_UNSUPPORTED - This function not supported.
+
+--*/
+;
+
+
+
+//
+//Internal functions
+//
+typedef enum {
+ EfiCheckSumUint8 = 0,
+ EfiCheckSumUint16 = 1,
+ EfiCheckSumUint32 = 2,
+ EfiCheckSumUint64 = 3,
+ EfiCheckSumMaximum = 4
+} EFI_CHECKSUM_TYPE;
+
+
+BOOLEAN
+IsBufferErased (
+ IN UINT8 ErasePolarity,
+ IN VOID *Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+ Check if a block of buffer is erased
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ Buffer - The buffer to be checked
+ BufferSize - Size of the buffer in bytes
+
+Returns:
+ TRUE - The block of buffer is erased
+ FALSE - The block of buffer is not erased
+
+--*/
+;
+
+EFI_FFS_FILE_STATE
+GetFileState (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Get the FFS file state by checking the highest bit set in the header's state field
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header
+
+Returns:
+ FFS File state
+
+--*/
+;
+
+VOID
+SetFileState (
+ IN UINT8 State,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Set the FFS file state.
+
+Arguments:
+ State - The state to be set.
+ FfsHeader - Points to the FFS file header
+
+Returns:
+ None.
+
+--*/
+;
+
+BOOLEAN
+VerifyFvHeaderChecksum (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+ Verify checksum of the firmware volume header
+
+Arguments:
+ FvHeader - Points to the firmware volume header to be checked
+
+Returns:
+ TRUE - Checksum verification passed
+ FALSE - Checksum verification failed
+
+--*/
+;
+
+BOOLEAN
+IsValidFfsHeader (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT EFI_FFS_FILE_STATE *FileState
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file header
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header to be checked
+ FileState - FFS file state to be returned
+
+Returns:
+ TRUE - Valid FFS file header
+ FALSE - Invalid FFS file header
+
+--*/
+;
+
+BOOLEAN
+IsValidFfsFile (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file.
+ Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file to be checked
+
+Returns:
+ TRUE - Valid FFS file
+ FALSE - Invalid FFS file
+
+--*/
+;
+
+EFI_STATUS
+GetFwVolHeader (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
+ )
+/*++
+
+Routine Description:
+ given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
+ copy the volume header into it.
+
+Arguments:
+ Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
+ header
+ FwVolHeader - Pointer to pointer to allocated buffer in which the volume
+ header is returned.
+
+Returns:
+ Status code.
+
+--*/
+;
+
+
+EFI_STATUS
+FvCheck (
+ IN OUT FV_DEVICE *FvDevice
+ )
+/*++
+
+Routine Description:
+ Check if a FV is consistent and allocate cache
+
+Arguments:
+ FvDevice - pointer to the FvDevice to be checked.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_SUCCESS - FV is consistent and cache is allocated.
+ EFI_VOLUME_CORRUPTED - File system is corrupted.
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Core/Dxe/Gcd/gcd.c b/EdkModulePkg/Core/Dxe/Gcd/gcd.c
new file mode 100644
index 0000000000..73037edb24
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Gcd/gcd.c
@@ -0,0 +1,2481 @@
+/*++
+
+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:
+
+ gcd.c
+
+Abstract:
+ The file contains the GCD related services in the EFI Boot Services Table.
+ The GCD services are used to manage the memory and I/O regions that
+ are accessible to the CPU that is executing the DXE core.
+
+--*/
+
+#include <DxeMain.h>
+
+#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
+
+#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO )
+
+#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED )
+
+#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
+
+#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
+
+#define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
+
+//
+// Module Variables
+//
+EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap);
+LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap);
+
+EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = {
+ EFI_GCD_MAP_SIGNATURE,
+ { NULL, NULL },
+ 0,
+ 0,
+ 0,
+ 0,
+ EfiGcdMemoryTypeNonExistent,
+ 0,
+ NULL,
+ NULL
+};
+
+EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = {
+ EFI_GCD_MAP_SIGNATURE,
+ { NULL, NULL },
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ EfiGcdIoTypeNonExistent,
+ NULL,
+ NULL
+};
+
+GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {
+ { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED, EFI_MEMORY_RP, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED, EFI_MEMORY_WP, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED, EFI_MEMORY_XP, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE },
+ { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE },
+ { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },
+ { 0, 0, FALSE }
+};
+
+VOID
+CoreAcquireGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Acquire memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreAcquireLock (&mGcdMemorySpaceLock);
+}
+
+
+VOID
+CoreReleaseGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Release memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreReleaseLock (&mGcdMemorySpaceLock);
+}
+
+
+
+VOID
+CoreAcquireGcdIoLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Acquire memory lock on mGcdIoSpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreAcquireLock (&mGcdIoSpaceLock);
+}
+
+
+VOID
+CoreReleaseGcdIoLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Release memory lock on mGcdIoSpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreReleaseLock (&mGcdIoSpaceLock);
+}
+
+
+
+//
+// GCD Initialization Worker Functions
+//
+UINT64
+AlignValue (
+ IN UINT64 Value,
+ IN UINTN Alignment,
+ IN BOOLEAN RoundUp
+ )
+/*++
+
+Routine Description:
+
+ Aligns a value to the specified boundary.
+
+Arguments:
+
+ Value - 64 bit value to align
+ Alignment - Log base 2 of the boundary to align Value to
+ RoundUp - TRUE if Value is to be rounded up to the nearest aligned boundary.
+ FALSE is Value is to be rounded down to the nearest aligned boundary.
+
+Returns:
+
+ A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
+
+--*/
+{
+ UINT64 AlignmentMask;
+
+ AlignmentMask = LShiftU64 (1, Alignment) - 1;
+ if (RoundUp) {
+ Value += AlignmentMask;
+ }
+ return Value & (~AlignmentMask);
+}
+
+UINT64
+PageAlignAddress (
+ IN UINT64 Value
+ )
+/*++
+
+Routine Description:
+
+ Aligns address to the page boundary.
+
+Arguments:
+
+ Value - 64 bit address to align
+
+Returns:
+
+ A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
+
+--*/
+{
+ return AlignValue (Value, EFI_PAGE_SHIFT, TRUE);
+}
+
+UINT64
+PageAlignLength (
+ IN UINT64 Value
+ )
+/*++
+
+Routine Description:
+
+ Aligns length to the page boundary.
+
+Arguments:
+
+ Value - 64 bit length to align
+
+Returns:
+
+ A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
+
+--*/
+{
+ return AlignValue (Value, EFI_PAGE_SHIFT, FALSE);
+}
+
+//
+// GCD Memory Space Worker Functions
+//
+EFI_STATUS
+CoreAllocateGcdMapEntry (
+ IN OUT EFI_GCD_MAP_ENTRY **TopEntry,
+ IN OUT EFI_GCD_MAP_ENTRY **BottomEntry
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool for two entries.
+
+Arguments:
+
+ TopEntry - An entry of GCD map
+ BottomEntry - An entry of GCD map
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
+ EFI_SUCCESS - Both entries successfully allocated.
+
+--*/
+{
+ *TopEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));
+ if (*TopEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *BottomEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));
+ if (*BottomEntry == NULL) {
+ CoreFreePool (*TopEntry);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreInsertGcdMapEntry (
+ IN LIST_ENTRY *Link,
+ IN EFI_GCD_MAP_ENTRY *Entry,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_GCD_MAP_ENTRY *TopEntry,
+ IN EFI_GCD_MAP_ENTRY *BottomEntry
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Inserts a new descriptor into a sorted list
+
+Arguments:
+
+ Link - The linked list to insert the range BaseAddress and Length into
+
+ Entry - A pointer to the entry that is inserted
+
+ BaseAddress - The base address of the new range
+
+ Length - The length of the new range in bytes
+
+ TopEntry - Top pad entry to insert if needed.
+
+ BottomEntry - Bottom pad entry to insert if needed.
+
+Returns:
+
+ EFI_SUCCESS - The new range was inserted into the linked list
+
+--*/
+{
+ ASSERT (Length != 0);
+ ASSERT (TopEntry->Signature == 0);
+ ASSERT (BottomEntry->Signature == 0);
+
+ if (BaseAddress > Entry->BaseAddress) {
+ CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
+ Entry->BaseAddress = BaseAddress;
+ BottomEntry->EndAddress = BaseAddress - 1;
+ InsertTailList (Link, &BottomEntry->Link);
+ }
+
+ if ((BaseAddress + Length - 1) < Entry->EndAddress) {
+ CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
+ TopEntry->BaseAddress = BaseAddress + Length;
+ Entry->EndAddress = BaseAddress + Length - 1;
+ InsertHeadList (Link, &TopEntry->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreMergeGcdMapEntry (
+ IN LIST_ENTRY *Link,
+ IN BOOLEAN Forward,
+ IN LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Merge the Gcd region specified by Link and its adjacent entry
+
+Arguments:
+
+ Link - Specify the entry to be merged (with its adjacent entry).
+
+ Forward - Direction (forward or backward).
+
+ Map - Boundary.
+
+Returns:
+
+ EFI_SUCCESS - Successfully returned.
+
+ EFI_UNSUPPORTED - These adjacent regions could not merge.
+
+--*/
+{
+ LIST_ENTRY *AdjacentLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *AdjacentEntry;
+
+ //
+ // Get adjacent entry
+ //
+ if (Forward) {
+ AdjacentLink = Link->ForwardLink;
+ } else {
+ AdjacentLink = Link->BackLink;
+ }
+
+ //
+ // If AdjacentLink is the head of the list, then no merge can be performed
+ //
+ if (AdjacentLink == Map) {
+ return EFI_SUCCESS;
+ }
+
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ if (Entry->Capabilities != AdjacentEntry->Capabilities) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->Attributes != AdjacentEntry->Attributes) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->GcdIoType != AdjacentEntry->GcdIoType) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->ImageHandle != AdjacentEntry->ImageHandle) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Forward) {
+ Entry->EndAddress = AdjacentEntry->EndAddress;
+ } else {
+ Entry->BaseAddress = AdjacentEntry->BaseAddress;
+ }
+ RemoveEntryList (AdjacentLink);
+ CoreFreePool (AdjacentEntry);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreCleanupGcdMapEntry (
+ IN EFI_GCD_MAP_ENTRY *TopEntry,
+ IN EFI_GCD_MAP_ENTRY *BottomEntry,
+ IN LIST_ENTRY *StartLink,
+ IN LIST_ENTRY *EndLink,
+ IN LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Merge adjacent entries on total chain.
+
+Arguments:
+
+ TopEntry - Top entry of GCD map.
+
+ BottomEntry - Bottom entry of GCD map.
+
+ StartLink - Start link of the list for this loop.
+
+ EndLink - End link of the list for this loop.
+
+ Map - Boundary.
+
+Returns:
+
+ EFI_SUCCESS - GCD map successfully cleaned up.
+
+--*/
+{
+ LIST_ENTRY *Link;
+
+ if (TopEntry->Signature == 0) {
+ CoreFreePool (TopEntry);
+ }
+ if (BottomEntry->Signature == 0) {
+ CoreFreePool (BottomEntry);
+ }
+
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ CoreMergeGcdMapEntry (Link, FALSE, Map);
+ Link = Link->ForwardLink;
+ }
+ CoreMergeGcdMapEntry (EndLink, TRUE, Map);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreSearchGcdMapEntry (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT LIST_ENTRY **StartLink,
+ OUT LIST_ENTRY **EndLink,
+ IN LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Search a segment of memory space in GCD map. The result is a range of GCD entry list.
+
+Arguments:
+
+ BaseAddress - The start address of the segment.
+
+ Length - The length of the segment.
+
+ StartLink - The first GCD entry involves this segment of memory space.
+
+ EndLink - The first GCD entry involves this segment of memory space.
+
+ Map - Points to the start entry to search.
+
+Returns:
+
+ EFI_SUCCESS - Successfully found the entry.
+
+ EFI_NOT_FOUND - Not found.
+
+--*/
+{
+ LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ ASSERT (Length != 0);
+
+ *StartLink = NULL;
+ *EndLink = NULL;
+
+ Link = Map->ForwardLink;
+ while (Link != Map) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) {
+ *StartLink = Link;
+ }
+ if (*StartLink != NULL) {
+ if ((BaseAddress + Length - 1) >= Entry->BaseAddress &&
+ (BaseAddress + Length - 1) <= Entry->EndAddress ) {
+ *EndLink = Link;
+ return EFI_SUCCESS;
+ }
+ }
+ Link = Link->ForwardLink;
+ }
+ return EFI_NOT_FOUND;
+}
+
+UINTN
+CoreCountGcdMapEntry (
+ IN LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Count the amount of GCD map entries.
+
+Arguments:
+
+ Map - Points to the start entry to do the count loop.
+
+Returns:
+
+ The count.
+
+--*/
+{
+ UINTN Count;
+ LIST_ENTRY *Link;
+
+ Count = 0;
+ Link = Map->ForwardLink;
+ while (Link != Map) {
+ Count++;
+ Link = Link->ForwardLink;
+ }
+ return Count;
+}
+
+
+
+UINT64
+ConverToCpuArchAttributes (
+ UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Return the memory attribute specified by Attributes
+
+Arguments:
+
+ Attributes - A num with some attribute bits on.
+
+Returns:
+
+ The enum value of memory attribute.
+
+--*/
+{
+ if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) {
+ return EFI_MEMORY_UC;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) {
+ return EFI_MEMORY_WC;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) {
+ return EFI_MEMORY_WT;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) {
+ return EFI_MEMORY_WB;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) {
+ return EFI_MEMORY_WP;
+ }
+
+ return INVALID_CPU_ARCH_ATTRIBUTES;
+
+}
+
+
+EFI_STATUS
+CoreConvertSpace (
+ IN UINTN Operation,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
+
+Arguments:
+
+ Operation - The type of the operation
+
+ GcdMemoryType - Additional information for the operation
+
+ GcdIoType - Additional information for the operation
+
+ BaseAddress - Start address of the segment
+
+ Length - length of the segment
+
+ Capabilities - The alterable attributes of a newly added entry
+
+ Attributes - The attributes needs to be set
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Length is 0 or address (length) not aligned when setting attribute.
+
+ EFI_SUCCESS - Action successfully done.
+
+ EFI_UNSUPPORTED - Could not find the proper descriptor on this segment or
+ set an upsupported attribute.
+
+ EFI_ACCESS_DENIED - Operate on an space non-exist or is used for an image.
+
+ EFI_NOT_FOUND - Free a non-using space or remove a non-exist space, and so on.
+
+ EFI_OUT_OF_RESOURCES - No buffer could be allocated.
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Map;
+ LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *TopEntry;
+ EFI_GCD_MAP_ENTRY *BottomEntry;
+ LIST_ENTRY *StartLink;
+ LIST_ENTRY *EndLink;
+
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ UINT64 CpuArchAttributes;
+
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Map = NULL;
+ if (Operation & GCD_MEMORY_SPACE_OPERATION) {
+ CoreAcquireGcdMemoryLock ();
+ Map = &mGcdMemorySpaceMap;
+ }
+ if (Operation & GCD_IO_SPACE_OPERATION) {
+ CoreAcquireGcdIoLock ();
+ Map = &mGcdIoSpaceMap;
+ }
+
+ //
+ // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
+ //
+ Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+
+ goto Done;
+ }
+
+ //
+ // Verify that the list of descriptors are unallocated non-existent memory.
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ switch (Operation) {
+ //
+ // Add operations
+ //
+ case GCD_ADD_MEMORY_OPERATION:
+ if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent ||
+ Entry->ImageHandle != NULL ) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ case GCD_ADD_IO_OPERATION:
+ if (Entry->GcdIoType != EfiGcdIoTypeNonExistent ||
+ Entry->ImageHandle != NULL ) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ //
+ // Free operations
+ //
+ case GCD_FREE_MEMORY_OPERATION:
+ case GCD_FREE_IO_OPERATION:
+ if (Entry->ImageHandle == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ break;
+ //
+ // Remove operations
+ //
+ case GCD_REMOVE_MEMORY_OPERATION:
+ if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ if (Entry->ImageHandle != NULL) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ case GCD_REMOVE_IO_OPERATION:
+ if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ if (Entry->ImageHandle != NULL) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ //
+ // Set attribute operations
+ //
+ case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
+ if (Attributes & EFI_MEMORY_RUNTIME) {
+ if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+
+ goto Done;
+ }
+ }
+ if ((Entry->Capabilities & Attributes) != Attributes) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ break;
+ }
+ Link = Link->ForwardLink;
+ }
+
+ //
+ // Allocate work space to perform this operation
+ //
+ Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ //
+ //
+ if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
+ //
+ // Call CPU Arch Protocol to attempt to set attributes on the range
+ //
+ CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
+ if ( CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES ) {
+ Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ Status = CpuArch->SetMemoryAttributes (
+ CpuArch,
+ BaseAddress,
+ Length,
+ CpuArchAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ }
+
+ //
+ // Convert/Insert the list of descriptors from StartLink to EndLink
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry);
+ switch (Operation) {
+ //
+ // Add operations
+ //
+ case GCD_ADD_MEMORY_OPERATION:
+ Entry->GcdMemoryType = GcdMemoryType;
+ if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
+ Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO;
+ } else {
+ Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME;
+ }
+ break;
+ case GCD_ADD_IO_OPERATION:
+ Entry->GcdIoType = GcdIoType;
+ break;
+ //
+ // Free operations
+ //
+ case GCD_FREE_MEMORY_OPERATION:
+ case GCD_FREE_IO_OPERATION:
+ Entry->ImageHandle = NULL;
+ Entry->DeviceHandle = NULL;
+ break;
+ //
+ // Remove operations
+ //
+ case GCD_REMOVE_MEMORY_OPERATION:
+ Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;
+ Entry->Capabilities = 0;
+ break;
+ case GCD_REMOVE_IO_OPERATION:
+ Entry->GcdIoType = EfiGcdIoTypeNonExistent;
+ break;
+ //
+ // Set attribute operations
+ //
+ case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
+ Entry->Attributes = Attributes;
+ break;
+ }
+ Link = Link->ForwardLink;
+ }
+
+ //
+ // Cleanup
+ //
+ Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
+
+Done:
+ if (Operation & GCD_MEMORY_SPACE_OPERATION) {
+ CoreReleaseGcdMemoryLock ();
+ }
+ if (Operation & GCD_IO_SPACE_OPERATION) {
+ CoreReleaseGcdIoLock ();
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+CoreAllocateSpaceCheckEntry (
+ IN UINTN Operation,
+ IN EFI_GCD_MAP_ENTRY *Entry,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_GCD_IO_TYPE GcdIoType
+ )
+/*++
+
+Routine Description:
+
+ Check whether an entry could be used to allocate space.
+
+Arguments:
+
+ Operation - Allocate memory or IO
+
+ Entry - The entry to be tested
+
+ GcdMemoryType - The desired memory type
+
+ GcdIoType - The desired IO type
+
+Returns:
+
+ EFI_NOT_FOUND - The memory type does not match or there's an image handle on the entry.
+
+ EFI_UNSUPPORTED - The operation unsupported.
+
+ EFI_SUCCESS - It's ok for this entry to be used to allocate space.
+
+--*/
+{
+ if (Entry->ImageHandle != NULL) {
+ return EFI_NOT_FOUND;
+ }
+ switch (Operation) {
+ case GCD_ALLOCATE_MEMORY_OPERATION:
+ if (Entry->GcdMemoryType != GcdMemoryType) {
+ return EFI_NOT_FOUND;
+ }
+ break;
+ case GCD_ALLOCATE_IO_OPERATION:
+ if (Entry->GcdIoType != GcdIoType) {
+ return EFI_NOT_FOUND;
+ }
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreAllocateSpace (
+ IN UINTN Operation,
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocate space on specified address and length.
+
+Arguments:
+
+ Operation - The type of operation (memory or IO)
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdMemoryType - The desired memory type
+
+ GcdIoType - The desired IO type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor for the desired space exists.
+
+ EFI_SUCCESS - Space successfully allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS AlignmentMask;
+ EFI_PHYSICAL_ADDRESS MaxAddress;
+ LIST_ENTRY *Map;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *SubLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *TopEntry;
+ EFI_GCD_MAP_ENTRY *BottomEntry;
+ LIST_ENTRY *StartLink;
+ LIST_ENTRY *EndLink;
+ BOOLEAN Found;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (GcdAllocateType < 0 || GcdAllocateType >= EfiGcdMaxAllocateType) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (GcdMemoryType < 0 || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (GcdIoType < 0 || GcdIoType >= EfiGcdIoTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (BaseAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Alignment >= 64) {
+ return EFI_NOT_FOUND;
+ }
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Map = NULL;
+ if (Operation & GCD_MEMORY_SPACE_OPERATION) {
+ CoreAcquireGcdMemoryLock ();
+ Map = &mGcdMemorySpaceMap;
+ }
+ if (Operation & GCD_IO_SPACE_OPERATION) {
+ CoreAcquireGcdIoLock ();
+ Map = &mGcdIoSpaceMap;
+ }
+
+ Found = FALSE;
+ StartLink = NULL;
+ EndLink = NULL;
+ //
+ // Compute alignment bit mask
+ //
+ AlignmentMask = LShiftU64 (1, Alignment) - 1;
+
+ if (GcdAllocateType == EfiGcdAllocateAddress) {
+ //
+ // Verify that the BaseAddress passed in is aligned correctly
+ //
+ if ((*BaseAddress & AlignmentMask) != 0) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
+ //
+ Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ Link = Link->ForwardLink;
+ Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+ Found = TRUE;
+ } else {
+
+ Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ //
+ // Compute the maximum address to use in the search algorithm
+ //
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp ||
+ GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) {
+ MaxAddress = *BaseAddress - 1;
+ } else {
+ MaxAddress = Entry->EndAddress;
+ }
+
+ //
+ // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
+ //
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
+ GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {
+ Link = Map->BackLink;
+ } else {
+ Link = Map->ForwardLink;
+ }
+ while (Link != Map) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
+ GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {
+ Link = Link->BackLink;
+ } else {
+ Link = Link->ForwardLink;
+ }
+
+ Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
+ GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {
+ if ((Entry->BaseAddress + Length) > MaxAddress) {
+ continue;
+ }
+ if (Length > (Entry->EndAddress + 1)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ if (Entry->EndAddress > MaxAddress) {
+ *BaseAddress = MaxAddress;
+ } else {
+ *BaseAddress = Entry->EndAddress;
+ }
+ *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask);
+ } else {
+ *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask);
+ if ((*BaseAddress + Length - 1) > MaxAddress) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ //
+ // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
+ //
+ Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ Link = StartLink;
+ //
+ // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
+ //
+ Found = TRUE;
+ SubLink = StartLink;
+ while (SubLink != EndLink->ForwardLink) {
+ Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
+ if (EFI_ERROR (Status)) {
+ Link = SubLink;
+ Found = FALSE;
+ break;
+ }
+ SubLink = SubLink->ForwardLink;
+ }
+ if (Found) {
+ break;
+ }
+ }
+ }
+ if (!Found) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Allocate work space to perform this operation
+ //
+ Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Convert/Insert the list of descriptors from StartLink to EndLink
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry);
+ Entry->ImageHandle = ImageHandle;
+ Entry->DeviceHandle = DeviceHandle;
+ Link = Link->ForwardLink;
+ }
+
+ //
+ // Cleanup
+ //
+ Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
+
+Done:
+ if (Operation & GCD_MEMORY_SPACE_OPERATION) {
+ CoreReleaseGcdMemoryLock ();
+ }
+ if (Operation & GCD_IO_SPACE_OPERATION) {
+ CoreReleaseGcdIoLock ();
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+CoreInternalAddMemorySpace (
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities
+ )
+/*++
+
+Routine Description:
+
+ Add a segment of memory to GCD map.
+
+Arguments:
+
+ GcdMemoryType - Memory type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+ Capabilities - alterable attributes of the segment.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameters.
+
+ EFI_SUCCESS - Successfully add a segment of memory space.
+
+--*/
+{
+ //
+ // Make sure parameters are valid
+ //
+ if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, 0, BaseAddress, Length, Capabilities, 0);
+}
+
+//
+// GCD Core Services
+//
+EFI_STATUS
+CoreAllocateMemorySpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocates nonexistent memory, reserved memory, system memory, or memorymapped
+I/O resources from the global coherency domain of the processor.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdMemoryType - The desired memory type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - Memory space successfully allocated.
+
+--*/
+{
+ return CoreAllocateSpace (
+ GCD_ALLOCATE_MEMORY_OPERATION,
+ GcdAllocateType,
+ GcdMemoryType,
+ 0,
+ Alignment,
+ Length,
+ BaseAddress,
+ ImageHandle,
+ DeviceHandle
+ );
+}
+
+EFI_STATUS
+CoreAddMemorySpace (
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities
+ )
+/*++
+
+Routine Description:
+
+ Adds reserved memory, system memory, or memory-mapped I/O resources to the
+global coherency domain of the processor.
+
+Arguments:
+
+ GcdMemoryType - Memory type of the memory space.
+
+ BaseAddress - Base address of the memory space.
+
+ Length - Length of the memory space.
+
+ Capabilities - alterable attributes of the memory space.
+
+Returns:
+
+ EFI_SUCCESS - Merged this memory space into GCD map.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PageBaseAddress;
+ UINT64 PageLength;
+
+ Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);
+
+ if (!EFI_ERROR (Status) && GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
+
+ PageBaseAddress = PageAlignLength (BaseAddress);
+ PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);
+
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ GcdMemoryType,
+ EFI_PAGE_SHIFT,
+ PageLength,
+ &PageBaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ PageBaseAddress,
+ RShiftU64 (PageLength, EFI_PAGE_SHIFT),
+ Capabilities
+ );
+ } else {
+ for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) {
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ GcdMemoryType,
+ EFI_PAGE_SHIFT,
+ EFI_PAGE_SIZE,
+ &PageBaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ PageBaseAddress,
+ 1,
+ Capabilities
+ );
+ }
+ }
+ }
+ }
+ return Status;
+}
+
+EFI_STATUS
+CoreFreeMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Frees nonexistent memory, reserved memory, system memory, or memory-mapped
+I/O resources from the global coherency domain of the processor.
+
+Arguments:
+
+ BaseAddress - Base address of the memory space.
+
+ Length - Length of the memory space.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+{
+ return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+EFI_STATUS
+CoreRemoveMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Removes reserved memory, system memory, or memory-mapped I/O resources from
+the global coherency domain of the processor.
+
+Arguments:
+
+ BaseAddress - Base address of the memory space.
+
+ Length - Length of the memory space.
+
+Returns:
+
+ EFI_SUCCESS - Successfully remove a segment of memory space.
+
+--*/
+{
+ return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+VOID
+BuildMemoryDescriptor (
+ IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,
+ IN EFI_GCD_MAP_ENTRY *Entry
+ )
+/*++
+
+Routine Description:
+
+ Build a memory descriptor according to an entry.
+
+Arguments:
+
+ Descriptor - The descriptor to be built
+
+ Entry - According to this entry
+
+Returns:
+
+ None
+
+--*/
+{
+ Descriptor->BaseAddress = Entry->BaseAddress;
+ Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
+ Descriptor->Capabilities = Entry->Capabilities;
+ Descriptor->Attributes = Entry->Attributes;
+ Descriptor->GcdMemoryType = Entry->GcdMemoryType;
+ Descriptor->ImageHandle = Entry->ImageHandle;
+ Descriptor->DeviceHandle = Entry->DeviceHandle;
+}
+
+EFI_STATUS
+CoreGetMemorySpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the descriptor for a memory region containing a specified address.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully get memory space descriptor.
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *StartLink;
+ LIST_ENTRY *EndLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdMemoryLock ();
+
+ //
+ // Search for the list of descriptors that contain BaseAddress
+ //
+ Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // Copy the contents of the found descriptor into Descriptor
+ //
+ Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildMemoryDescriptor (Descriptor, Entry);
+ }
+
+ CoreReleaseGcdMemoryLock ();
+
+ return Status;
+}
+
+EFI_STATUS
+CoreSetMemorySpaceAttributes (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Modifies the attributes for a memory region in the global coherency domain of the
+processor.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Length - Specified length
+
+ Attributes - Specified attributes
+
+Returns:
+
+ EFI_SUCCESS - Successfully set attribute of a segment of memory space.
+
+--*/
+{
+ return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, Attributes);
+}
+
+EFI_STATUS
+CoreGetMemorySpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Returns a map of the memory resources in the global coherency domain of the
+processor.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ MemorySpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get memory space map.
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (NumberOfDescriptors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (MemorySpaceMap == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdMemoryLock ();
+
+ //
+ // Count the number of descriptors
+ //
+ *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);
+
+ //
+ // Allocate the MemorySpaceMap
+ //
+ *MemorySpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
+ if (*MemorySpaceMap == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Fill in the MemorySpaceMap
+ //
+ Descriptor = *MemorySpaceMap;
+ Link = mGcdMemorySpaceMap.ForwardLink;
+ while (Link != &mGcdMemorySpaceMap) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildMemoryDescriptor (Descriptor, Entry);
+ Descriptor++;
+ Link = Link->ForwardLink;
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseGcdMemoryLock ();
+ return Status;
+}
+
+EFI_STATUS
+CoreAddIoSpace (
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Adds reserved I/O or I/O resources to the global coherency domain of the processor.
+
+Arguments:
+
+ GcdIoType - IO type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Merged this segment into GCD map.
+ EFI_INVALID_PARAMETER - Parameter not valid
+
+--*/
+{
+ //
+ // Make sure parameters are valid
+ //
+ if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return CoreConvertSpace (GCD_ADD_IO_OPERATION, 0, GcdIoType, BaseAddress, Length, 0, 0);
+}
+
+EFI_STATUS
+CoreAllocateIoSpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
+domain of the processor.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdIoType - The desired IO type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - IO space successfully allocated.
+
+--*/
+{
+ return CoreAllocateSpace (
+ GCD_ALLOCATE_IO_OPERATION,
+ GcdAllocateType,
+ 0,
+ GcdIoType,
+ Alignment,
+ Length,
+ BaseAddress,
+ ImageHandle,
+ DeviceHandle
+ );
+}
+
+EFI_STATUS
+CoreFreeIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
+domain of the processor.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+{
+ return CoreConvertSpace (GCD_FREE_IO_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+EFI_STATUS
+CoreRemoveIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Removes reserved I/O or I/O resources from the global coherency domain of the
+processor.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Successfully removed a segment of IO space.
+
+--*/
+{
+ return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+VOID
+BuildIoDescriptor (
+ IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,
+ IN EFI_GCD_MAP_ENTRY *Entry
+ )
+/*++
+
+Routine Description:
+
+ Build a IO descriptor according to an entry.
+
+Arguments:
+
+ Descriptor - The descriptor to be built
+
+ Entry - According to this entry
+
+Returns:
+
+ None
+
+--*/
+{
+ Descriptor->BaseAddress = Entry->BaseAddress;
+ Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
+ Descriptor->GcdIoType = Entry->GcdIoType;
+ Descriptor->ImageHandle = Entry->ImageHandle;
+ Descriptor->DeviceHandle = Entry->DeviceHandle;
+}
+
+EFI_STATUS
+CoreGetIoSpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the descriptor for an I/O region containing a specified address.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Descriptor is NULL.
+
+ EFI_SUCCESS - Successfully get the IO space descriptor.
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *StartLink;
+ LIST_ENTRY *EndLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdIoLock ();
+
+ //
+ // Search for the list of descriptors that contain BaseAddress
+ //
+ Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // Copy the contents of the found descriptor into Descriptor
+ //
+ Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildIoDescriptor (Descriptor, Entry);
+ }
+
+ CoreReleaseGcdIoLock ();
+
+ return Status;
+}
+
+EFI_STATUS
+CoreGetIoSpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Returns a map of the I/O resources in the global coherency domain of the processor.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ IoSpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get IO space map.
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (NumberOfDescriptors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (IoSpaceMap == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdIoLock ();
+
+ //
+ // Count the number of descriptors
+ //
+ *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap);
+
+ //
+ // Allocate the IoSpaceMap
+ //
+ *IoSpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));
+ if (*IoSpaceMap == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Fill in the IoSpaceMap
+ //
+ Descriptor = *IoSpaceMap;
+ Link = mGcdIoSpaceMap.ForwardLink;
+ while (Link != &mGcdIoSpaceMap) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildIoDescriptor (Descriptor, Entry);
+ Descriptor++;
+ Link = Link->ForwardLink;
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseGcdIoLock ();
+ return Status;
+}
+
+UINT64
+CoreConvertResourceDescriptorHobAttributesToCapabilities (
+ EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
+ capabilities mask
+
+Arguments:
+
+ GcdMemoryType - Type of resource in the GCD memory map.
+ Attributes - The attribute mask in the Resource Descriptor HOB.
+
+Returns:
+
+ The capabilities mask for an EFI Memory Descriptor.
+
+--*/
+{
+ UINT64 Capabilities;
+ GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;
+
+ //
+ // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
+ //
+ for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {
+ if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) {
+ if (Attributes & Conversion->Attribute) {
+ Capabilities |= Conversion->Capability;
+ }
+ }
+ }
+
+ return Capabilities;
+}
+
+EFI_STATUS
+CoreInitializeMemoryServices (
+ IN VOID **HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
+ OUT UINT64 *MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map.
+
+Arguments:
+
+ HobStart - The start address of the HOB.
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+ MemoryLength - Length of memory region found to init DXE core.
+
+Returns:
+
+ EFI_SUCCESS - Memory services successfully initialized.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;
+ UINTN DataSize;
+ BOOLEAN Found;
+ EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINT64 Attributes;
+ UINT64 Capabilities;
+ EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;
+ UINT64 MaxMemoryLength;
+ UINT64 MaxMemoryAttributes;
+ EFI_PHYSICAL_ADDRESS MaxAddress;
+ EFI_PHYSICAL_ADDRESS HighAddress;
+ EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ //
+ // Point at the first HOB. This must be the PHIT HOB.
+ //
+ Hob.Raw = *HobStart;
+ ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
+
+ //
+ // Initialize the spin locks and maps in the memory services.
+ // Also fill in the memory services into the EFI Boot Services Table
+ //
+ CoreInitializePool ();
+
+ //
+ // Initialize Local Variables
+ //
+ PhitResourceHob = NULL;
+ MaxResourceHob = NULL;
+ ResourceHob = NULL;
+ BaseAddress = 0;
+ Length = 0;
+ Attributes = 0;
+ MaxMemoryBaseAddress = 0;
+ MaxMemoryLength = 0;
+ MaxMemoryAttributes = 0;
+
+ //
+ // Cache the PHIT HOB for later use
+ //
+ PhitHob = Hob.HandoffInformationTable;
+
+ //
+ // See if a Memory Type Information HOB is available
+ //
+ GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
+ if (GuidHob != NULL) {
+ EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
+ DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+ if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize < EfiMaxMemoryType * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {
+ CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
+ }
+ }
+
+ //
+ // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
+ //
+ Length = 0;
+ Found = FALSE;
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+
+ ResourceHob = Hob.ResourceDescriptor;
+
+ if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
+ (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES ) {
+
+ if (PhitHob->EfiFreeMemoryBottom >= ResourceHob->PhysicalStart &&
+ PhitHob->EfiFreeMemoryTop <= (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) ) {
+
+ //
+ // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
+ //
+ PhitResourceHob = ResourceHob;
+ Found = TRUE;
+
+ Attributes = PhitResourceHob->ResourceAttribute;
+ BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
+ Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
+ if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
+ BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
+ Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
+ if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
+ BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
+ Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
+ //
+ ASSERT (Found);
+
+ //
+ // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
+ // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
+ // The max address must be within the physically addressible range for the processor.
+ //
+ MaxMemoryLength = 0;
+ MaxAddress = EFI_MAX_ADDRESS;
+ do {
+ HighAddress = 0;
+ Found = FALSE;
+ //
+ // Search for a tested memory region that is below MaxAddress
+ //
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+
+ //
+ // See if this is a resource descriptor HOB that does not contain the PHIT.
+ //
+ if (Hob.ResourceDescriptor != PhitResourceHob && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+
+ ResourceHob = Hob.ResourceDescriptor;
+ //
+ // See if this resource descrior HOB describes tested system memory below MaxAddress
+ //
+ if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
+ (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES &&
+ ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MaxAddress ) {
+
+ //
+ // See if this is the highest tested system memory region below MaxAddress
+ //
+ if (ResourceHob->PhysicalStart > HighAddress) {
+
+ MaxResourceHob = ResourceHob;
+ HighAddress = MaxResourceHob->PhysicalStart;
+ Found = TRUE;
+ }
+ }
+ }
+ }
+ if (Found) {
+ //
+ // Compute the size of the tested memory region below MaxAddrees
+ //
+ MaxMemoryBaseAddress = PageAlignAddress (MaxResourceHob->PhysicalStart);
+ MaxMemoryLength = PageAlignLength (MaxResourceHob->PhysicalStart + MaxResourceHob->ResourceLength - MaxMemoryBaseAddress);
+ MaxMemoryAttributes = MaxResourceHob->ResourceAttribute;
+ }
+ MaxAddress = ResourceHob->PhysicalStart;
+ } while (Found && MaxMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE);
+
+ //
+ //
+ //
+ if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||
+ (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE) ) {
+ BaseAddress = MaxMemoryBaseAddress;
+ Length = MaxMemoryLength;
+ Attributes = MaxMemoryAttributes;
+ }
+
+ //
+ // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
+ //
+ ASSERT (Length >= MINIMUM_INITIAL_MEMORY_SIZE);
+
+ //
+ // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
+ //
+ Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
+
+ //
+ // Declare the very first memory region, so the EFI Memory Services are available.
+ //
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ BaseAddress,
+ RShiftU64 (Length, EFI_PAGE_SHIFT),
+ Capabilities
+ );
+
+ *MemoryBaseAddress = BaseAddress;
+ *MemoryLength = Length;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreInitializeGcdServices (
+ IN VOID **HobStart,
+ IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map.
+
+Arguments:
+
+ HobStart - The start address of the HOB
+
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+
+ MemoryLength - Length of memory region found to init DXE core.
+
+
+Returns:
+
+ EFI_SUCCESS - GCD services successfully initialized.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ VOID *NewHobList;
+ EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
+ UINT8 SizeOfMemorySpace;
+ UINT8 SizeOfIoSpace;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ EFI_STATUS Status;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MEMORY_TYPE GcdMemoryType;
+ EFI_GCD_IO_TYPE GcdIoType;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
+ UINTN NumberOfDescriptors;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINTN Index;
+ UINT64 Capabilities;
+ EFI_HOB_CPU * CpuHob;
+ //
+ // Cache the PHIT HOB for later use
+ //
+ PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);
+
+ //
+ // Get the number of address lines in the I/O and Memory space for the CPU
+ //
+ CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ ASSERT (CpuHob != NULL);
+ SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;
+ SizeOfIoSpace = CpuHob->SizeOfIoSpace;
+
+ //
+ // Initialize the GCD Memory Space Map
+ //
+ Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
+ ASSERT (Entry != NULL);
+
+ Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;
+
+ InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);
+
+ //
+ // Initialize the GCD I/O Space Map
+ //
+ Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);
+ ASSERT (Entry != NULL);
+
+ Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;
+
+ InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);
+
+ //
+ // Walk the HOB list and add all resource descriptors to the GCD
+ //
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+
+ GcdMemoryType = EfiGcdMemoryTypeNonExistent;
+ GcdIoType = EfiGcdIoTypeNonExistent;
+
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+
+ ResourceHob = Hob.ResourceDescriptor;
+
+ switch (ResourceHob->ResourceType) {
+ case EFI_RESOURCE_SYSTEM_MEMORY:
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
+ GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
+ }
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
+ GcdMemoryType = EfiGcdMemoryTypeReserved;
+ }
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
+ GcdMemoryType = EfiGcdMemoryTypeReserved;
+ }
+ break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO:
+ case EFI_RESOURCE_FIRMWARE_DEVICE:
+ GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;
+ break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
+ case EFI_RESOURCE_MEMORY_RESERVED:
+ GcdMemoryType = EfiGcdMemoryTypeReserved;
+ break;
+ case EFI_RESOURCE_IO:
+ GcdIoType = EfiGcdIoTypeIo;
+ break;
+ case EFI_RESOURCE_IO_RESERVED:
+ GcdIoType = EfiGcdIoTypeReserved;
+ break;
+ }
+
+ if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {
+
+ //
+ // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
+ //
+ Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (
+ GcdMemoryType,
+ ResourceHob->ResourceAttribute
+ );
+
+ Status = CoreInternalAddMemorySpace (
+ GcdMemoryType,
+ ResourceHob->PhysicalStart,
+ ResourceHob->ResourceLength,
+ Capabilities
+ );
+ }
+
+ if (GcdIoType != EfiGcdIoTypeNonExistent) {
+ Status = CoreAddIoSpace (
+ GcdIoType,
+ ResourceHob->PhysicalStart,
+ ResourceHob->ResourceLength
+ );
+ }
+ }
+ }
+
+ //
+ // Allocate first memory region from the GCD by the DXE core
+ //
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeSystemMemory,
+ 0,
+ MemoryLength,
+ &MemoryBaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+
+ //
+ // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
+ // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
+ //
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ MemoryHob = Hob.MemoryAllocation;
+ BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeSystemMemory,
+ 0,
+ MemoryHob->AllocDescriptor.MemoryLength,
+ &BaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = CoreGetMemorySpaceDescriptor (MemoryHob->AllocDescriptor.MemoryBaseAddress, &Descriptor);
+ if (!EFI_ERROR (Status)) {
+ CoreAddMemoryDescriptor (
+ MemoryHob->AllocDescriptor.MemoryType,
+ MemoryHob->AllocDescriptor.MemoryBaseAddress,
+ RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),
+ Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)
+ );
+ }
+ }
+ }
+
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
+ FirmwareVolumeHob = Hob.FirmwareVolume;
+ BaseAddress = FirmwareVolumeHob->BaseAddress;
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 0,
+ FirmwareVolumeHob->Length,
+ &BaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+ }
+ }
+
+ //
+ // Relocate HOB List to an allocated pool buffer.
+ //
+ NewHobList = CoreAllocateCopyPool (
+ (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),
+ *HobStart
+ );
+ ASSERT (NewHobList != NULL);
+
+ *HobStart = NewHobList;
+
+ //
+ // Add and allocate the remaining unallocated system memory to the memory services.
+ //
+ Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
+ if (MemorySpaceMap[Index].ImageHandle == NULL) {
+ BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);
+ Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ BaseAddress,
+ RShiftU64 (Length, EFI_PAGE_SHIFT),
+ MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)
+ );
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeSystemMemory,
+ 0,
+ Length,
+ &BaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+ }
+ }
+ }
+ CoreFreePool (MemorySpaceMap);
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Dxe/Hand/DriverSupport.c b/EdkModulePkg/Core/Dxe/Hand/DriverSupport.c
new file mode 100644
index 0000000000..aa601fba08
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Hand/DriverSupport.c
@@ -0,0 +1,848 @@
+/*++
+
+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:
+
+ DriverSupport.c
+
+Abstract:
+
+ EFI Driver Support Protocol
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+
+
+STATIC
+EFI_STATUS
+GetHandleFromDriverBinding (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,
+ OUT EFI_HANDLE *Handle
+ );
+
+
+//
+// Driver Support Function Prototypes
+//
+STATIC
+EFI_STATUS
+CoreConnectSingleController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *DriverImageHandle OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+//
+// Driver Support Functions
+//
+
+
+EFI_STATUS
+EFIAPI
+CoreConnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *DriverImageHandle OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
+ IN BOOLEAN Recursive
+ )
+/*++
+
+Routine Description:
+
+ Connects one or more drivers to a controller.
+
+Arguments:
+
+ ControllerHandle - Handle of the controller to be connected.
+
+ DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles.
+
+ RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the
+ controller specified by ControllerHandle.
+
+ Recursive - Whether the function would be called recursively or not.
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *ProtLink;
+ OPEN_PROTOCOL_DATA *OpenData;
+ EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath;
+
+ //
+ // Make sure ControllerHandle is valid
+ //
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Handle = ControllerHandle;
+
+ //
+ // Connect all drivers to ControllerHandle
+ //
+ AlignedRemainingDevicePath = NULL;
+ if (RemainingDevicePath != NULL) {
+ AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
+ }
+ ReturnStatus = CoreConnectSingleController (
+ ControllerHandle,
+ DriverImageHandle,
+ AlignedRemainingDevicePath
+ );
+ if (AlignedRemainingDevicePath != NULL) {
+ CoreFreePool (AlignedRemainingDevicePath);
+ }
+
+ //
+ // If not recursive, then just return after connecting drivers to ControllerHandle
+ //
+ if (!Recursive) {
+ return ReturnStatus;
+ }
+
+ //
+ // If recursive, then connect all drivers to all of ControllerHandle's children
+ //
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ CoreReleaseProtocolLock ();
+ Status = CoreConnectController (
+ OpenData->ControllerHandle,
+ NULL,
+ NULL,
+ TRUE
+ );
+ CoreAcquireProtocolLock ();
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+
+ return ReturnStatus;
+}
+
+VOID
+AddSortedDriverBindingProtocol (
+ IN EFI_HANDLE DriverBindingHandle,
+ IN OUT UINTN *NumberOfSortedDriverBindingProtocols,
+ IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,
+ IN UINTN DriverBindingHandleCount,
+ IN OUT EFI_HANDLE *DriverBindingHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ Add Driver Binding Protocols from Context Driver Image Handles to sorted
+ Driver Binding Protocol list.
+
+Arguments:
+
+ DriverBindingHandle - Handle of the driver binding protocol.
+
+ NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols
+
+ SortedDriverBindingProtocols - The sorted protocol list.
+
+ DriverBindingHandleCount - Driver Binding Handle Count.
+
+ DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ UINTN Index;
+
+ //
+ // Make sure the DriverBindingHandle is valid
+ //
+ Status = CoreValidateHandle (DriverBindingHandle);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Retrieve the Driver Binding Protocol from DriverBindingHandle
+ //
+ Status = CoreHandleProtocol(
+ DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **)&DriverBinding
+ );
+ //
+ // If DriverBindingHandle does not support the Driver Binding Protocol then return
+ //
+ if (EFI_ERROR (Status) || DriverBinding == NULL) {
+ return;
+ }
+
+ //
+ // See if DriverBinding is already in the sorted list
+ //
+ for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols; Index++) {
+ if (DriverBinding == SortedDriverBindingProtocols[Index]) {
+ return;
+ }
+ }
+
+ //
+ // Add DriverBinding to the end of the list
+ //
+ SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
+ *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
+
+ //
+ // Mark the cooresponding handle in DriverBindingHandleBuffer as used
+ //
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
+ DriverBindingHandleBuffer[Index] = NULL;
+ }
+ }
+}
+
+STATIC
+EFI_STATUS
+CoreConnectSingleController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Connects a controller to a driver.
+
+Arguments:
+
+ ControllerHandle - Handle of the controller to be connected.
+ ContextDriverImageHandles - DriverImageHandle A pointer to an ordered list of driver image handles.
+ RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child
+ of the controller specified by ControllerHandle.
+
+Returns:
+
+ EFI_SUCCESS - One or more drivers were connected to ControllerHandle.
+ EFI_OUT_OF_RESOURCES - No enough system resources to complete the request.
+ EFI_NOT_FOUND - No drivers were connected to ControllerHandle.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_HANDLE DriverImageHandle;
+ UINTN PlatformDriverOverrideHandleCount;
+ EFI_HANDLE *PlatformDriverOverrideHandleBuffer;
+ EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride;
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ UINTN NumberOfSortedDriverBindingProtocols;
+ EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;
+ UINT32 HighestVersion;
+ UINTN HighestIndex;
+ UINTN SortIndex;
+ BOOLEAN OneStarted;
+ BOOLEAN DriverFound;
+ EFI_HANDLE DriverBindingHandle;
+
+ //
+ // DriverBindingHandle is used for performance measurement, initialize it here just in case.
+ //
+ DriverBindingHandle = NULL;
+ //
+ // Initialize local variables
+ //
+ DriverBindingHandleCount = 0;
+ DriverBindingHandleBuffer = NULL;
+ PlatformDriverOverrideHandleCount = 0;
+ PlatformDriverOverrideHandleBuffer = NULL;
+ NumberOfSortedDriverBindingProtocols = 0;
+ SortedDriverBindingProtocols = NULL;
+
+ //
+ // Get list of all Driver Binding Protocol Instances
+ //
+ Status = CoreLocateHandleBuffer (
+ ByProtocol,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
+ //
+ SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
+ if (SortedDriverBindingProtocols == NULL) {
+ CoreFreePool (DriverBindingHandleBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Add Driver Binding Protocols from Context Driver Image Handles first
+ //
+ if (ContextDriverImageHandles != NULL) {
+ for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
+ AddSortedDriverBindingProtocol (
+ ContextDriverImageHandles[Index],
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer
+ );
+ }
+ }
+
+ //
+ // Add the Platform Driver Override Protocol drivers for ControllerHandle next
+ //
+ Status = CoreLocateProtocol (
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ NULL,
+ (VOID **)&PlatformDriverOverride
+ );
+ if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
+ DriverImageHandle = NULL;
+ do {
+ Status = PlatformDriverOverride->GetDriver (
+ PlatformDriverOverride,
+ ControllerHandle,
+ &DriverImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ AddSortedDriverBindingProtocol (
+ DriverImageHandle,
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer
+ );
+ }
+ } while (!EFI_ERROR (Status));
+ }
+
+ //
+ // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
+ //
+ Status = CoreHandleProtocol(
+ ControllerHandle,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ (VOID **)&BusSpecificDriverOverride
+ );
+ if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
+ DriverImageHandle = NULL;
+ do {
+ Status = BusSpecificDriverOverride->GetDriver (
+ BusSpecificDriverOverride,
+ &DriverImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ AddSortedDriverBindingProtocol (
+ DriverImageHandle,
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer
+ );
+ }
+ } while (!EFI_ERROR (Status));
+ }
+
+ //
+ // Then add all the remaining Driver Binding Protocols
+ //
+ SortIndex = NumberOfSortedDriverBindingProtocols;
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ AddSortedDriverBindingProtocol (
+ DriverBindingHandleBuffer[Index],
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer
+ );
+ }
+
+ //
+ // Free the Driver Binding Handle Buffer
+ //
+ CoreFreePool (DriverBindingHandleBuffer);
+
+ //
+ // Sort the remaining DriverBinding Protocol based on their Version field from
+ // highest to lowest.
+ //
+ for ( ; SortIndex < DriverBindingHandleCount; SortIndex++) {
+ HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
+ HighestIndex = SortIndex;
+ for (Index = SortIndex + 1; Index < DriverBindingHandleCount; Index++) {
+ if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
+ HighestVersion = SortedDriverBindingProtocols[Index]->Version;
+ HighestIndex = Index;
+ }
+ }
+ if (SortIndex != HighestIndex) {
+ DriverBinding = SortedDriverBindingProtocols[SortIndex];
+ SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
+ SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
+ }
+ }
+
+ //
+ // Loop until no more drivers can be started on ControllerHandle
+ //
+ OneStarted = FALSE;
+ do {
+
+ //
+ // Loop through the sorted Driver Binding Protocol Instances in order, and see if
+ // any of the Driver Binding Protocols support the controller specified by
+ // ControllerHandle.
+ //
+ DriverBinding = NULL;
+ DriverFound = FALSE;
+ for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
+ if (SortedDriverBindingProtocols[Index] != NULL) {
+ DriverBinding = SortedDriverBindingProtocols[Index];
+ Status = DriverBinding->Supported(
+ DriverBinding,
+ ControllerHandle,
+ RemainingDevicePath
+ );
+ if (!EFI_ERROR (Status)) {
+ SortedDriverBindingProtocols[Index] = NULL;
+ DriverFound = TRUE;
+
+ //
+ // A driver was found that supports ControllerHandle, so attempt to start the driver
+ // on ControllerHandle.
+ //
+ PERF_CODE_BEGIN ();
+ GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle);
+ PERF_CODE_END ();
+
+ PERF_START (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
+ Status = DriverBinding->Start (
+ DriverBinding,
+ ControllerHandle,
+ RemainingDevicePath
+ );
+ PERF_END (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // The driver was successfully started on ControllerHandle, so set a flag
+ //
+ OneStarted = TRUE;
+ }
+ }
+ }
+ }
+ } while (DriverFound);
+
+ //
+ // Free any buffers that were allocated with AllocatePool()
+ //
+ CoreFreePool (SortedDriverBindingProtocols);
+
+ //
+ // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
+ //
+ if (OneStarted) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
+ //
+ if (RemainingDevicePath != NULL) {
+ if (IsDevicePathEnd (RemainingDevicePath)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
+ //
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreDisconnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE DriverImageHandle OPTIONAL,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Disonnects a controller from a driver
+
+Arguments:
+
+ ControllerHandle - ControllerHandle The handle of the controller from which driver(s)
+ are to be disconnected.
+ DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
+ ChildHandle - ChildHandle The handle of the child to destroy.
+
+Returns:
+
+ EFI_SUCCESS - One or more drivers were disconnected from the controller.
+ EFI_SUCCESS - On entry, no drivers are managing ControllerHandle.
+ EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle.
+ EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error.
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ EFI_HANDLE *DriverImageHandleBuffer;
+ EFI_HANDLE *ChildBuffer;
+ UINTN Index;
+ UINTN HandleIndex;
+ UINTN DriverImageHandleCount;
+ UINTN ChildrenToStop;
+ UINTN ChildBufferCount;
+ UINTN StopCount;
+ BOOLEAN Duplicate;
+ BOOLEAN ChildHandleValid;
+ BOOLEAN DriverImageHandleValid;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *ProtLink;
+ OPEN_PROTOCOL_DATA *OpenData;
+ PROTOCOL_INTERFACE *Prot;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+
+ //
+ // Make sure ControllerHandle is valid
+ //
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Make sure ChildHandle is valid if it is not NULL
+ //
+ if (ChildHandle != NULL) {
+ Status = CoreValidateHandle (ChildHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Handle = ControllerHandle;
+
+ //
+ // Get list of drivers that are currently managing ControllerHandle
+ //
+ DriverImageHandleBuffer = NULL;
+ DriverImageHandleCount = 1;
+
+ if (DriverImageHandle == NULL) {
+ //
+ // Look at each protocol interface for a match
+ //
+ DriverImageHandleCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ DriverImageHandleCount++;
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+
+ //
+ // If there are no drivers managing this controller, then return EFI_SUCCESS
+ //
+ if (DriverImageHandleCount == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
+ if (DriverImageHandleBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ DriverImageHandleCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ Duplicate = FALSE;
+ for (Index = 0; Index< DriverImageHandleCount; Index++) {
+ if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
+ Duplicate = TRUE;
+ break;
+ }
+ }
+ if (!Duplicate) {
+ DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
+ DriverImageHandleCount++;
+ }
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+ }
+
+ StopCount = 0;
+ for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
+
+ if (DriverImageHandleBuffer != NULL) {
+ DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
+ }
+
+ //
+ // Get the Driver Binding Protocol of the driver that is managing this controller
+ //
+ Status = CoreHandleProtocol (
+ DriverImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **)&DriverBinding
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Look at each protocol interface for a match
+ //
+ DriverImageHandleValid = FALSE;
+ ChildBufferCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->AgentHandle == DriverImageHandle) {
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ ChildBufferCount++;
+ }
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ DriverImageHandleValid = TRUE;
+ }
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+
+ if (DriverImageHandleValid) {
+ ChildHandleValid = FALSE;
+ ChildBuffer = NULL;
+ if (ChildBufferCount != 0) {
+ ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);
+ if (ChildBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ChildBufferCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->AgentHandle == DriverImageHandle) &&
+ ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
+ Duplicate = FALSE;
+ for (Index = 0; Index < ChildBufferCount; Index++) {
+ if (ChildBuffer[Index] == OpenData->ControllerHandle) {
+ Duplicate = TRUE;
+ break;
+ }
+ }
+ if (!Duplicate) {
+ ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
+ if (ChildHandle == ChildBuffer[ChildBufferCount]) {
+ ChildHandleValid = TRUE;
+ }
+ ChildBufferCount++;
+ }
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+ }
+
+ if (ChildHandle == NULL || ChildHandleValid) {
+ ChildrenToStop = 0;
+ Status = EFI_SUCCESS;
+ if (ChildBufferCount > 0) {
+ if (ChildHandle != NULL) {
+ ChildrenToStop = 1;
+ Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
+ } else {
+ ChildrenToStop = ChildBufferCount;
+ Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
+ }
+ }
+ if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
+ Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
+ }
+ if (!EFI_ERROR (Status)) {
+ StopCount++;
+ }
+ }
+
+ if (ChildBuffer != NULL) {
+ CoreFreePool (ChildBuffer);
+ }
+ }
+ }
+
+ if (StopCount > 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+
+Done:
+
+ if (DriverImageHandleBuffer != NULL) {
+ CoreFreePool (DriverImageHandleBuffer);
+ }
+
+ return Status;
+}
+
+
+
+STATIC
+EFI_STATUS
+GetHandleFromDriverBinding (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,
+ OUT EFI_HANDLE *Handle
+ )
+/*++
+
+Routine Description:
+
+ Locate the driver binding handle which a specified driver binding protocol installed on.
+
+Arguments:
+
+ DriverBindingNeed - The specified driver binding protocol.
+
+ Handle - The driver binding handle which the protocol installed on.
+
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the handle.
+
+ EFI_SUCCESS - Successfully find the associated driver binding handle.
+
+--*/
+ {
+ EFI_STATUS Status ;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ UINTN Index;
+
+ DriverBindingHandleCount = 0;
+ DriverBindingHandleBuffer = NULL;
+ *Handle = NULL_HANDLE;
+ Status = CoreLocateHandleBuffer (
+ ByProtocol,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) {
+ Status = CoreOpenProtocol(
+ DriverBindingHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **)&DriverBinding,
+ gDxeCoreImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (!EFI_ERROR (Status) && DriverBinding != NULL) {
+
+ if ( DriverBinding == DriverBindingNeed ) {
+ *Handle = DriverBindingHandleBuffer[Index];
+ CoreFreePool (DriverBindingHandleBuffer);
+ return EFI_SUCCESS ;
+ }
+ }
+ }
+
+ CoreFreePool (DriverBindingHandleBuffer);
+ return EFI_NOT_FOUND ;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/Hand/Notify.c b/EdkModulePkg/Core/Dxe/Hand/Notify.c
new file mode 100644
index 0000000000..f48fee76cb
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Hand/Notify.c
@@ -0,0 +1,333 @@
+/*++
+
+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:
+
+ notify.c
+
+Abstract:
+
+ EFI notify infrastructure
+
+
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+VOID
+CoreNotifyProtocolEntry (
+ IN PROTOCOL_ENTRY *ProtEntry
+ )
+/*++
+
+Routine Description:
+
+ Signal event for every protocol in protocol entry.
+
+Arguments:
+
+ ProtEntry - Protocol entry
+
+Returns:
+
+--*/
+{
+ PROTOCOL_NOTIFY *ProtNotify;
+ LIST_ENTRY *Link;
+
+ ASSERT_LOCKED (&gProtocolDatabaseLock);
+
+ for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+ ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+ CoreSignalEvent (ProtNotify->Event);
+ }
+}
+
+
+PROTOCOL_INTERFACE *
+CoreRemoveInterfaceFromProtocol (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Removes Protocol from the protocol list (but not the handle list).
+
+Arguments:
+
+ Handle - The handle to remove protocol on.
+
+ Protocol - GUID of the protocol to be moved
+
+ Interface - The interface of the protocol
+
+Returns:
+
+ Protocol Entry
+
+--*/
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_NOTIFY *ProtNotify;
+ PROTOCOL_ENTRY *ProtEntry;
+ LIST_ENTRY *Link;
+
+ ASSERT_LOCKED (&gProtocolDatabaseLock);
+
+ Prot = CoreFindProtocolInterface (Handle, Protocol, Interface);
+ if (Prot != NULL) {
+
+ ProtEntry = Prot->Protocol;
+
+ //
+ // If there's a protocol notify location pointing to this entry, back it up one
+ //
+
+ for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+ ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+
+ if (ProtNotify->Position == &Prot->ByProtocol) {
+ ProtNotify->Position = Prot->ByProtocol.BackLink;
+ }
+ }
+
+ //
+ // Remove the protocol interface entry
+ //
+
+ RemoveEntryList (&Prot->ByProtocol);
+ }
+
+ return Prot;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreRegisterProtocolNotify (
+ IN EFI_GUID *Protocol,
+ IN EFI_EVENT Event,
+ OUT VOID **Registration
+ )
+/*++
+
+Routine Description:
+
+ Add a new protocol notification record for the request protocol.
+
+Arguments:
+
+ Protocol - The requested protocol to add the notify registration
+
+ Event - The event to signal
+
+ Registration - Returns the registration record
+
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully returned the registration record that has been added
+
+--*/
+{
+ PROTOCOL_ENTRY *ProtEntry;
+ PROTOCOL_NOTIFY *ProtNotify;
+ EFI_STATUS Status;
+
+ if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireProtocolLock ();
+
+ ProtNotify = NULL;
+
+ //
+ // Get the protocol entry to add the notification too
+ //
+
+ ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
+ if (ProtEntry != NULL) {
+
+ //
+ // Allocate a new notification record
+ //
+
+ ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY));
+
+ if (ProtNotify != NULL) {
+
+ ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
+ ProtNotify->Protocol = ProtEntry;
+ ProtNotify->Event = Event;
+ //
+ // start at the begining
+ //
+ ProtNotify->Position = &ProtEntry->Protocols;
+
+ InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+
+ //
+ // Done. If we have a protocol notify entry, then return it.
+ // Otherwise, we must have run out of resources trying to add one
+ //
+
+ Status = EFI_OUT_OF_RESOURCES;
+ if (ProtNotify != NULL) {
+ *Registration = ProtNotify;
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreReinstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *OldInterface,
+ IN VOID *NewInterface
+ )
+/*++
+
+Routine Description:
+
+ Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
+
+Arguments:
+
+ UserHandle - Handle on which the interface is to be reinstalled
+ Protocol - The numeric ID of the interface
+ OldInterface - A pointer to the old interface
+ NewInterface - A pointer to the new interface
+
+
+Returns:
+
+ Status code.
+
+ On EFI_SUCCESS The protocol interface was installed
+ On EFI_NOT_FOUND The OldInterface on the handle was not found
+ On EFI_INVALID_PARAMETER One of the parameters has an invalid value
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Handle = (IHANDLE *) UserHandle;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+ //
+ Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
+ if (Prot == NULL) {
+ CoreReleaseProtocolLock ();
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
+ //
+ Status = CoreDisconnectControllersUsingProtocolInterface (
+ UserHandle,
+ Prot
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // One or more drivers refused to release, so return the error
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+ }
+
+ //
+ // Remove the protocol interface from the protocol
+ //
+ Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
+
+ if (Prot == NULL) {
+ CoreReleaseProtocolLock ();
+ return EFI_NOT_FOUND;
+ }
+
+ ProtEntry = Prot->Protocol;
+
+ //
+ // Update the interface on the protocol
+ //
+ Prot->Interface = NewInterface;
+
+ //
+ // Add this protocol interface to the tail of the
+ // protocol entry
+ //
+ InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
+
+ //
+ // Update the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Release the lock and connect all drivers to UserHandle
+ //
+ CoreReleaseProtocolLock ();
+ Status = CoreConnectController (
+ UserHandle,
+ NULL,
+ NULL,
+ TRUE
+ );
+ CoreAcquireProtocolLock ();
+
+ //
+ // Notify the notification list for this protocol
+ //
+ CoreNotifyProtocolEntry (ProtEntry);
+
+ CoreReleaseProtocolLock ();
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Dxe/Hand/handle.c b/EdkModulePkg/Core/Dxe/Hand/handle.c
new file mode 100644
index 0000000000..2edfdeb78b
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Hand/handle.c
@@ -0,0 +1,1699 @@
+/*++
+
+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:
+
+ handle.c
+
+Abstract:
+
+ EFI handle & protocol handling
+
+
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+
+//
+// mProtocolDatabase - A list of all protocols in the system. (simple list for now)
+// gHandleList - A list of all the handles in the system
+// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
+// gHandleDatabaseKey - The Key to show that the handle has been created/modified
+//
+static LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
+LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
+EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+UINT64 gHandleDatabaseKey = 0;
+
+
+VOID
+CoreAcquireProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acquire lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreAcquireLock (&gProtocolDatabaseLock);
+}
+
+
+VOID
+CoreReleaseProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Release lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&gProtocolDatabaseLock);
+}
+
+
+EFI_STATUS
+CoreValidateHandle (
+ IN EFI_HANDLE UserHandle
+ )
+/*++
+
+Routine Description:
+
+ Check whether a handle is a valid EFI_HANDLE
+
+Arguments:
+
+ UserHandle - The handle to check
+
+Returns:
+
+ EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE.
+
+ EFI_SUCCESS - The handle is valid EFI_HANDLE.
+
+--*/
+{
+ IHANDLE *Handle;
+
+ Handle = (IHANDLE *)UserHandle;
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+
+PROTOCOL_ENTRY *
+CoreFindProtocolEntry (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN Create
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol entry for the requested protocol.
+
+ The gProtocolDatabaseLock must be owned
+
+Arguments:
+
+ Protocol - The ID of the protocol
+
+ Create - Create a new entry if not found
+
+Returns:
+
+ Protocol entry
+
+--*/
+{
+ LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *Item;
+ PROTOCOL_ENTRY *ProtEntry;
+
+ ASSERT_LOCKED(&gProtocolDatabaseLock);
+
+ //
+ // Search the database for the matching GUID
+ //
+
+ ProtEntry = NULL;
+ for (Link = mProtocolDatabase.ForwardLink;
+ Link != &mProtocolDatabase;
+ Link = Link->ForwardLink) {
+
+ Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
+ if (CompareGuid (&Item->ProtocolID, Protocol)) {
+
+ //
+ // This is the protocol entry
+ //
+
+ ProtEntry = Item;
+ break;
+ }
+ }
+
+ //
+ // If the protocol entry was not found and Create is TRUE, then
+ // allocate a new entry
+ //
+ if ((ProtEntry == NULL) && Create) {
+ ProtEntry = CoreAllocateBootServicesPool (sizeof(PROTOCOL_ENTRY));
+
+ if (ProtEntry != NULL) {
+ //
+ // Initialize new protocol entry structure
+ //
+ ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
+ CopyMem ((VOID *)&ProtEntry->ProtocolID, Protocol, sizeof (EFI_GUID));
+ InitializeListHead (&ProtEntry->Protocols);
+ InitializeListHead (&ProtEntry->Notify);
+
+ //
+ // Add it to protocol database
+ //
+ InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
+ }
+ }
+
+ return ProtEntry;
+}
+
+
+PROTOCOL_INTERFACE *
+CoreFindProtocolInterface (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol instance for the requested handle and protocol.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ Handle - The handle to search the protocol on
+
+ Protocol - GUID of the protocol
+
+ Interface - The interface for the protocol being searched
+
+Returns:
+
+ Protocol instance (NULL: Not found)
+
+--*/
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+ LIST_ENTRY *Link;
+
+ ASSERT_LOCKED(&gProtocolDatabaseLock);
+ Prot = NULL;
+
+ //
+ // Lookup the protocol entry for this protocol ID
+ //
+
+ ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
+ if (ProtEntry != NULL) {
+
+ //
+ // Look at each protocol interface for any matches
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
+
+ //
+ // If this protocol interface matches, remove it
+ //
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
+ break;
+ }
+
+ Prot = NULL;
+ }
+ }
+
+ return Prot;
+}
+
+STATIC
+EFI_STATUS
+CoreUnregisterProtocolNotifyEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Removes an event from a register protocol notify list on a protocol.
+
+Arguments:
+
+ Event - The event to search for in the protocol database.
+
+Returns:
+
+ EFI_SUCCESS if the event was found and removed.
+ EFI_NOT_FOUND if the event was not found in the protocl database.
+
+--*/
+{
+ LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *ProtEntry;
+ LIST_ENTRY *NotifyLink;
+ PROTOCOL_NOTIFY *ProtNotify;
+
+ CoreAcquireProtocolLock ();
+
+ for ( Link = mProtocolDatabase.ForwardLink;
+ Link != &mProtocolDatabase;
+ Link = Link->ForwardLink) {
+
+ ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
+
+ for ( NotifyLink = ProtEntry->Notify.ForwardLink;
+ NotifyLink != &ProtEntry->Notify;
+ NotifyLink = NotifyLink->ForwardLink) {
+
+ ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+
+ if (ProtNotify->Event == Event) {
+ RemoveEntryList(&ProtNotify->Link);
+ CoreFreePool(ProtNotify);
+ CoreReleaseProtocolLock ();
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+CoreUnregisterProtocolNotify (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Removes all the events in the protocol database that match Event.
+
+Arguments:
+
+ Event - The event to search for in the protocol database.
+
+Returns:
+
+ EFI_SUCCESS when done searching the entire database.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ do {
+ Status = CoreUnregisterProtocolNotifyEvent (Event);
+ } while (!EFI_ERROR (Status));
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreInstallProtocolInterface (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
+ Calls the private one which contains a BOOLEAN parameter for notifications
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+Returns:
+
+ Status code
+
+--*/
+{
+ return CoreInstallProtocolInterfaceNotify (
+ UserHandle,
+ Protocol,
+ InterfaceType,
+ Interface,
+ TRUE
+ );
+}
+
+EFI_STATUS
+CoreInstallProtocolInterfaceNotify (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface,
+ IN BOOLEAN Notify
+ )
+/*++
+
+Routine Description:
+
+ Installs a protocol interface into the boot services environment.
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+ Notify - indicates whether notify the notification list
+ for this protocol
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Protocol interface successfully installed
+
+--*/
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+ IHANDLE *Handle;
+ EFI_STATUS Status;
+ VOID *ExistingInterface;
+
+ //
+ // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
+ // Also added check for invalid UserHandle and Protocol pointers.
+ //
+ if (UserHandle == NULL || Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterfaceType != EFI_NATIVE_INTERFACE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Print debug message
+ //
+ DEBUG((EFI_D_ERROR | EFI_D_INFO, "InstallProtocolInterface: %g %x\n", Protocol, Interface));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ Prot = NULL;
+ Handle = NULL;
+
+ ASSERT (NULL != gBS);
+
+ if (*UserHandle != NULL_HANDLE) {
+ Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
+ if (!EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Lookup the Protocol Entry for the requested protocol
+ //
+ ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
+ if (ProtEntry == NULL) {
+ goto Done;
+ }
+
+ //
+ // Allocate a new protocol interface structure
+ //
+ Prot = CoreAllocateZeroBootServicesPool (sizeof(PROTOCOL_INTERFACE));
+ if (Prot == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // If caller didn't supply a handle, allocate a new one
+ //
+ Handle = (IHANDLE *)*UserHandle;
+ if (Handle == NULL) {
+ Handle = CoreAllocateZeroBootServicesPool (sizeof(IHANDLE));
+ if (Handle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Initialize new handler structure
+ //
+ Handle->Signature = EFI_HANDLE_SIGNATURE;
+ InitializeListHead (&Handle->Protocols);
+
+ //
+ // Initialize the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Add this handle to the list global list of all handles
+ // in the system
+ //
+ InsertTailList (&gHandleList, &Handle->AllHandles);
+ }
+
+ Status = CoreValidateHandle (Handle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Each interface that is added must be unique
+ //
+ ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
+
+ //
+ // Initialize the protocol interface structure
+ //
+ Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
+ Prot->Handle = Handle;
+ Prot->Protocol = ProtEntry;
+ Prot->Interface = Interface;
+
+ //
+ // Initalize OpenProtocol Data base
+ //
+ InitializeListHead (&Prot->OpenList);
+ Prot->OpenListCount = 0;
+
+ //
+ // Add this protocol interface to the head of the supported
+ // protocol list for this handle
+ //
+ InsertHeadList (&Handle->Protocols, &Prot->Link);
+
+ //
+ // Add this protocol interface to the tail of the
+ // protocol entry
+ //
+ InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
+
+ //
+ // Notify the notification list for this protocol
+ //
+ if (Notify) {
+ CoreNotifyProtocolEntry (ProtEntry);
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ //
+ // Done, unlock the database and return
+ //
+ CoreReleaseProtocolLock ();
+ if (!EFI_ERROR (Status)) {
+ //
+ // Return the new handle back to the caller
+ //
+ *UserHandle = Handle;
+ } else {
+ //
+ // There was an error, clean up
+ //
+ if (Prot != NULL) {
+ CoreFreePool (Prot);
+ }
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreInstallMultipleProtocolInterfaces (
+ IN OUT EFI_HANDLE *Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Installs a list of protocol interface into the boot services environment.
+ This function calls InstallProtocolInterface() in a loop. If any error
+ occures all the protocols added by this function are removed. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to install the protocol handlers on,
+ or NULL if a new handle is to be allocated
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to InstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Handle is NULL.
+
+ EFI_SUCCESS - Protocol interfaces successfully installed.
+
+--*/
+{
+ VA_LIST args;
+ EFI_STATUS Status;
+ EFI_GUID *Protocol;
+ VOID *Interface;
+ EFI_TPL OldTpl;
+ UINTN Index;
+ EFI_HANDLE OldHandle;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Syncronize with notifcations.
+ //
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+ OldHandle = *Handle;
+
+ //
+ // Check for duplicate device path and install the protocol interfaces
+ //
+ VA_START (args, Handle);
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ //
+ // If protocol is NULL, then it's the end of the list
+ //
+ Protocol = VA_ARG (args, EFI_GUID *);
+ if (Protocol == NULL) {
+ break;
+ }
+
+ Interface = VA_ARG (args, VOID *);
+
+ //
+ // Make sure you are installing on top a device path that has already been added.
+ //
+ if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
+ DeviceHandle = NULL;
+ DevicePath = Interface;
+ Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
+ if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {
+ Status = EFI_ALREADY_STARTED;
+ continue;
+ }
+ }
+
+ //
+ // Install it
+ //
+ Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
+ }
+
+ //
+ // If there was an error, remove all the interfaces that were installed without any errors
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset the va_arg back to the first argument.
+ //
+ VA_START (args, Handle);
+ for (; Index > 1; Index--) {
+ Protocol = VA_ARG (args, EFI_GUID *);
+ Interface = VA_ARG (args, VOID *);
+ CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
+ }
+ *Handle = OldHandle;
+ }
+
+ //
+ // Done
+ //
+ CoreRestoreTpl (OldTpl);
+ return Status;
+}
+
+EFI_STATUS
+CoreDisconnectControllersUsingProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN PROTOCOL_INTERFACE *Prot
+ )
+/*++
+
+Routine Description:
+
+ Attempts to disconnect all drivers that are using the protocol interface being queried.
+ If failed, reconnect all drivers disconnected.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ UserHandle - The handle on which the protocol is installed
+ Prot - The protocol to disconnect drivers from
+
+Returns:
+
+ EFI_SUCCESS - Drivers using the protocol interface are all disconnected
+ EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN ItemFound;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Attempt to disconnect all drivers from this protocol interface
+ //
+ do {
+ ItemFound = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink;
+ (Link != &Prot->OpenList) && !ItemFound;
+ Link = Link->ForwardLink ) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ ItemFound = TRUE;
+ CoreReleaseProtocolLock ();
+ Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+ CoreAcquireProtocolLock ();
+ if (EFI_ERROR (Status)) {
+ ItemFound = FALSE;
+ break;
+ }
+ }
+ }
+ } while (ItemFound);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
+ //
+ do {
+ ItemFound = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink;
+ (Link != &Prot->OpenList) && !ItemFound;
+ Link = Link->ForwardLink ) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->Attributes &
+ (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {
+ ItemFound = TRUE;
+ RemoveEntryList (&OpenData->Link);
+ Prot->OpenListCount--;
+ CoreFreePool (OpenData);
+ }
+ }
+ } while (ItemFound);
+ }
+
+ //
+ // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
+ //
+ if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
+ CoreReleaseProtocolLock ();
+ CoreConnectController (UserHandle, NULL, NULL, TRUE);
+ CoreAcquireProtocolLock ();
+ Status = EFI_ACCESS_DENIED;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreUninstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls all instances of a protocol:interfacer from a handle.
+ If the last protocol interface is remove from the handle, the
+ handle is freed.
+
+Arguments:
+
+ UserHandle - The handle to remove the protocol handler from
+
+ Protocol - The protocol, of protocol:interface, to remove
+
+ Interface - The interface, of protocol:interface, to remove
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Protocol interface successfully uninstalled.
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+
+ //
+ // Check that Protocol is valid
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check that UserHandle is a valid handle
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+ //
+ Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
+ if (Prot == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
+ //
+ Status = CoreDisconnectControllersUsingProtocolInterface (
+ UserHandle,
+ Prot
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // One or more drivers refused to release, so return the error
+ //
+ goto Done;
+ }
+
+ //
+ // Remove the protocol interface from the protocol
+ //
+ Status = EFI_NOT_FOUND;
+ Handle = (IHANDLE *)UserHandle;
+ Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
+
+ if (Prot != NULL) {
+ //
+ // Update the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Remove the protocol interface from the handle
+ //
+ RemoveEntryList (&Prot->Link);
+
+ //
+ // Free the memory
+ //
+ Prot->Signature = 0;
+ CoreFreePool (Prot);
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // If there are no more handlers for the handle, free the handle
+ //
+ if (IsListEmpty (&Handle->Protocols)) {
+ Handle->Signature = 0;
+ RemoveEntryList (&Handle->AllHandles);
+ CoreFreePool (Handle);
+ }
+
+Done:
+ //
+ // Done, unlock the database and return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreUninstallMultipleProtocolInterfaces (
+ IN EFI_HANDLE Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls a list of protocol interface in the boot services environment.
+ This function calls UnisatllProtocolInterface() in a loop. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to uninstall the protocol
+
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to UninstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ Status code
+
+--*/
+{
+ EFI_STATUS Status;
+ VA_LIST args;
+ EFI_GUID *Protocol;
+ VOID *Interface;
+ UINTN Index;
+
+ VA_START (args, Handle);
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ //
+ // If protocol is NULL, then it's the end of the list
+ //
+ Protocol = VA_ARG (args, EFI_GUID *);
+ if (Protocol == NULL) {
+ break;
+ }
+
+ Interface = VA_ARG (args, VOID *);
+
+ //
+ // Uninstall it
+ //
+ Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
+ }
+
+ //
+ // If there was an error, add all the interfaces that were
+ // uninstalled without any errors
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset the va_arg back to the first argument.
+ //
+ VA_START (args, Handle);
+ for (; Index > 1; Index--) {
+ Protocol = VA_ARG(args, EFI_GUID *);
+ Interface = VA_ARG(args, VOID *);
+ CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
+ }
+ }
+
+ return Status;
+}
+
+PROTOCOL_INTERFACE *
+CoreGetProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol
+ )
+/*++
+
+Routine Description:
+
+ Locate a certain GUID protocol interface in a Handle's protocols.
+
+Arguments:
+
+ UserHandle - The handle to obtain the protocol interface on
+
+ Protocol - The GUID of the protocol
+
+Returns:
+
+ The requested protocol interface for the handle
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_ENTRY *ProtEntry;
+ PROTOCOL_INTERFACE *Prot;
+ IHANDLE *Handle;
+ LIST_ENTRY *Link;
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Handle = (IHANDLE *)UserHandle;
+
+ //
+ // Look at each protocol interface for a match
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ ProtEntry = Prot->Protocol;
+ if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
+ return Prot;
+ }
+ }
+ return NULL;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreHandleProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Queries a handle to determine if it supports a specified protocol.
+
+Arguments:
+
+ UserHandle - The handle being queried.
+
+ Protocol - The published unique identifier of the protocol.
+
+ Interface - Supplies the address where a pointer to the corresponding Protocol
+ Interface is returned.
+
+Returns:
+
+ The requested protocol interface for the handle
+
+--*/
+{
+ return CoreOpenProtocol (
+ UserHandle,
+ Protocol,
+ Interface,
+ gDxeCoreImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreOpenProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface OPTIONAL,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Locates the installed protocol handler for the handle, and
+ invokes it to obtain the protocol interface. Usage information
+ is registered in the protocol data base.
+
+Arguments:
+
+ UserHandle - The handle to obtain the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ Interface - The location to return the protocol interface
+
+ ImageHandle - The handle of the Image that is opening the protocol interface
+ specified by Protocol and Interface.
+
+ ControllerHandle - The controller handle that is requiring this interface.
+
+ Attributes - The open mode of the protocol interface specified by Handle
+ and Protocol.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Get the protocol interface.
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *Prot;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+ BOOLEAN ByDriver;
+ BOOLEAN Exclusive;
+ BOOLEAN Disconnect;
+ BOOLEAN ExactMatch;
+
+ //
+ // Check for invalid Protocol
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check for invalid Interface
+ //
+ if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+ if (Interface == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ *Interface = NULL;
+ }
+ }
+
+ //
+ // Check for invalid UserHandle
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check for invalid Attributes
+ //
+ switch (Attributes) {
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (UserHandle == ControllerHandle) {
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER :
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Prot = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (Prot == NULL) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ //
+ // This is the protocol interface entry for this protocol
+ //
+ if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+ *Interface = Prot->Interface;
+ }
+ Status = EFI_SUCCESS;
+
+ ByDriver = FALSE;
+ Exclusive = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
+ (OpenData->Attributes == Attributes) &&
+ (OpenData->ControllerHandle == ControllerHandle));
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ ByDriver = TRUE;
+ if (ExactMatch) {
+ Status = EFI_ALREADY_STARTED;
+ goto Done;
+ }
+ }
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
+ Exclusive = TRUE;
+ } else if (ExactMatch) {
+ OpenData->OpenCount++;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ //
+ // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
+ // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
+ // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
+ // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
+ //
+
+ switch (Attributes) {
+ case EFI_OPEN_PROTOCOL_BY_DRIVER :
+ if (Exclusive || ByDriver) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ if (Exclusive) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ if (ByDriver) {
+ do {
+ Disconnect = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ Disconnect = TRUE;
+ CoreReleaseProtocolLock ();
+ Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+ CoreAcquireProtocolLock ();
+ if (EFI_ERROR (Status)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ }
+ }
+ } while (Disconnect);
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
+ break;
+ }
+
+ if (ImageHandle == NULL) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ //
+ // Create new entry
+ //
+ OpenData = CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA));
+ if (OpenData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
+ OpenData->AgentHandle = ImageHandle;
+ OpenData->ControllerHandle = ControllerHandle;
+ OpenData->Attributes = Attributes;
+ OpenData->OpenCount = 1;
+ InsertTailList (&Prot->OpenList, &OpenData->Link);
+ Prot->OpenListCount++;
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ //
+ // Done. Release the database lock are return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreCloseProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_HANDLE AgentHandle,
+ IN EFI_HANDLE ControllerHandle
+ )
+/*++
+
+Routine Description:
+
+ Closes a protocol on a handle that was opened using OpenProtocol().
+
+Arguments:
+
+ UserHandle - The handle for the protocol interface that was previously opened
+ with OpenProtocol(), and is now being closed.
+ Protocol - The published unique identifier of the protocol. It is the caller¡¯s
+ responsibility to pass in a valid GUID.
+ AgentHandle - The handle of the agent that is closing the protocol interface.
+ ControllerHandle - If the agent that opened a protocol is a driver that follows the
+ EFI Driver Model, then this parameter is the controller handle
+ that required the protocol interface. If the agent does not follow
+ the EFI Driver Model, then this parameter is optional and may be NULL.
+
+Returns:
+
+ EFI_SUCCESS - The protocol instance was closed.
+ EFI_INVALID_PARAMETER - Handle, AgentHandle or ControllerHandle is not a valid EFI_HANDLE.
+ EFI_NOT_FOUND - Can not find the specified protocol or AgentHandle.
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *ProtocolInterface;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+
+ //
+ // Check for invalid parameters
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = CoreValidateHandle (AgentHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (ControllerHandle != NULL_HANDLE) {
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Status = EFI_NOT_FOUND;
+ ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (ProtocolInterface == NULL) {
+ goto Done;
+ }
+
+ //
+ // Walk the Open data base looking for AgentHandle
+ //
+ Link = ProtocolInterface->OpenList.ForwardLink;
+ while (Link != &ProtocolInterface->OpenList) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ Link = Link->ForwardLink;
+ if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
+ RemoveEntryList (&OpenData->Link);
+ ProtocolInterface->OpenListCount--;
+ CoreFreePool (OpenData);
+ Status = EFI_SUCCESS;
+ }
+ }
+
+Done:
+ //
+ // Done. Release the database lock and return.
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreOpenProtocolInformation (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+ OUT UINTN *EntryCount
+ )
+/*++
+
+Routine Description:
+
+ Return information about Opened protocols in the system
+
+Arguments:
+
+ UserHandle - The handle to close the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ EntryBuffer - A pointer to a buffer of open protocol information in the form of
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+
+ EntryCount - Number of EntryBuffer entries
+
+Returns:
+
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *ProtocolInterface;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
+ UINTN Count;
+ UINTN Size;
+
+ *EntryBuffer = NULL;
+ *EntryCount = 0;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Status = EFI_NOT_FOUND;
+ ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (ProtocolInterface == NULL) {
+ goto Done;
+ }
+
+ //
+ // Count the number of Open Entries
+ //
+ for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
+ (Link != &ProtocolInterface->OpenList) ;
+ Link = Link->ForwardLink ) {
+ Count++;
+ }
+
+ ASSERT (Count == ProtocolInterface->OpenListCount);
+
+ if (Count == 0) {
+ Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
+ } else {
+ Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
+ }
+
+ Buffer = CoreAllocateBootServicesPool (Size);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = EFI_SUCCESS;
+ for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
+ (Link != &ProtocolInterface->OpenList);
+ Link = Link->ForwardLink, Count++ ) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+
+ Buffer[Count].AgentHandle = OpenData->AgentHandle;
+ Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
+ Buffer[Count].Attributes = OpenData->Attributes;
+ Buffer[Count].OpenCount = OpenData->OpenCount;
+ }
+
+ *EntryBuffer = Buffer;
+ *EntryCount = Count;
+
+Done:
+ //
+ // Done. Release the database lock are return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreProtocolsPerHandle (
+ IN EFI_HANDLE UserHandle,
+ OUT EFI_GUID ***ProtocolBuffer,
+ OUT UINTN *ProtocolBufferCount
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+ from pool.
+
+Arguments:
+
+ UserHandle - The handle from which to retrieve the list of protocol interface
+ GUIDs.
+
+ ProtocolBuffer - A pointer to the list of protocol interface GUID pointers that are
+ installed on Handle.
+
+ ProtocolBufferCount - A pointer to the number of GUID pointers present in
+ ProtocolBuffer.
+
+Returns:
+ EFI_SUCCESS - The list of protocol interface GUIDs installed on Handle was returned in
+ ProtocolBuffer. The number of protocol interface GUIDs was
+ returned in ProtocolBufferCount.
+ EFI_INVALID_PARAMETER - Handle is NULL.
+ EFI_INVALID_PARAMETER - Handle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ProtocolBuffer is NULL.
+ EFI_INVALID_PARAMETER - ProtocolBufferCount is NULL.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the results.
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ LIST_ENTRY *Link;
+ UINTN ProtocolCount;
+ EFI_GUID **Buffer;
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Handle = (IHANDLE *)UserHandle;
+
+ if (ProtocolBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ProtocolBufferCount == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ProtocolBufferCount = 0;
+
+ ProtocolCount = 0;
+
+ CoreAcquireProtocolLock ();
+
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ ProtocolCount++;
+ }
+
+ //
+ // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
+ //
+ if (ProtocolCount == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Buffer = CoreAllocateBootServicesPool (sizeof (EFI_GUID *) * ProtocolCount);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *ProtocolBuffer = Buffer;
+ *ProtocolBufferCount = ProtocolCount;
+
+ for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
+ Link != &Handle->Protocols;
+ Link = Link->ForwardLink, ProtocolCount++) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+UINT64
+CoreGetHandleDatabaseKey (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ return handle database key.
+
+Arguments:
+
+ None
+
+Returns:
+
+ Handle database key.
+
+--*/
+{
+ return gHandleDatabaseKey;
+}
+
+
+VOID
+CoreConnectHandlesByKey (
+ UINT64 Key
+ )
+/*++
+
+Routine Description:
+
+ Go connect any handles that were created or modified while a image executed.
+
+Arguments:
+
+ Key - The Key to show that the handle has been created/modified
+
+Returns:
+
+ None
+--*/
+{
+ UINTN Count;
+ LIST_ENTRY *Link;
+ EFI_HANDLE *HandleBuffer;
+ IHANDLE *Handle;
+ UINTN Index;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ if (Handle->Key > Key) {
+ Count++;
+ }
+ }
+
+ HandleBuffer = CoreAllocateBootServicesPool (Count * sizeof (EFI_HANDLE));
+ if (HandleBuffer == NULL) {
+ CoreReleaseProtocolLock ();
+ return;
+ }
+
+ for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ if (Handle->Key > Key) {
+ HandleBuffer[Count++] = Handle;
+ }
+ }
+
+ //
+ // Unlock the protocol database
+ //
+ CoreReleaseProtocolLock ();
+
+ //
+ // Connect all handles whose Key value is greater than Key
+ //
+ for (Index = 0; Index < Count; Index++) {
+ CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ CoreFreePool(HandleBuffer);
+}
diff --git a/EdkModulePkg/Core/Dxe/Hand/locate.c b/EdkModulePkg/Core/Dxe/Hand/locate.c
new file mode 100644
index 0000000000..faa4255c7e
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Hand/locate.c
@@ -0,0 +1,737 @@
+/*++
+
+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:
+
+ locate.c
+
+Abstract:
+
+ Locate handle functions
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+//
+// ProtocolRequest - Last LocateHandle request ID
+//
+UINTN mEfiLocateHandleRequest = 0;
+
+//
+// Internal prototypes
+//
+
+typedef struct {
+ EFI_GUID *Protocol;
+ VOID *SearchKey;
+ LIST_ENTRY *Position;
+ PROTOCOL_ENTRY *ProtEntry;
+} LOCATE_POSITION;
+
+typedef
+IHANDLE *
+(* CORE_GET_NEXT) (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+STATIC
+IHANDLE *
+CoreGetNextLocateAllHandles (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByRegisterNotify (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByProtocol (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+//
+//
+//
+
+
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateHandle (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HANDLE *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Locates the requested handle(s) and returns them in Buffer.
+
+Arguments:
+
+ SearchType - The type of search to perform to locate the handles
+
+ Protocol - The protocol to search for
+
+ SearchKey - Dependant on SearchType
+
+ BufferSize - On input the size of Buffer. On output the
+ size of data returned.
+
+ Buffer - The buffer to return the results in
+
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOCATE_POSITION Position;
+ PROTOCOL_NOTIFY *ProtNotify;
+ CORE_GET_NEXT GetNext;
+ UINTN ResultSize;
+ IHANDLE *Handle;
+ IHANDLE **ResultBuffer;
+ VOID *Interface;
+
+ if (BufferSize == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ if ((*BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GetNext = NULL;
+ //
+ // Set initial position
+ //
+
+ Position.Protocol = Protocol;
+ Position.SearchKey = SearchKey;
+ Position.Position = &gHandleList;
+
+ ResultSize = 0;
+ ResultBuffer = (IHANDLE **) Buffer;
+ Status = EFI_SUCCESS;
+
+ //
+ // Lock the protocol database
+ //
+
+ CoreAcquireProtocolLock ();
+
+ //
+ // Get the search function based on type
+ //
+ switch (SearchType) {
+ case AllHandles:
+ GetNext = CoreGetNextLocateAllHandles;
+ break;
+
+ case ByRegisterNotify:
+ //
+ // Must have SearchKey for locate ByRegisterNotify
+ //
+ if (SearchKey == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ GetNext = CoreGetNextLocateByRegisterNotify;
+ break;
+
+ case ByProtocol:
+ GetNext = CoreGetNextLocateByProtocol;
+ if (Protocol == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ //
+ // Look up the protocol entry and set the head pointer
+ //
+ Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
+ if (Position.ProtEntry == NULL) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ Position.Position = &Position.ProtEntry->Protocols;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (EFI_ERROR(Status)) {
+ CoreReleaseProtocolLock ();
+ return Status;
+ }
+
+ //
+ // Enumerate out the matching handles
+ //
+ mEfiLocateHandleRequest += 1;
+ for (; ;) {
+ //
+ // Get the next handle. If no more handles, stop
+ //
+ Handle = GetNext (&Position, &Interface);
+ if (NULL == Handle) {
+ break;
+ }
+
+ //
+ // Increase the resulting buffer size, and if this handle
+ // fits return it
+ //
+ ResultSize += sizeof(Handle);
+ if (ResultSize <= *BufferSize) {
+ *ResultBuffer = Handle;
+ ResultBuffer += 1;
+ }
+ }
+
+ //
+ // If the result is a zero length buffer, then there were no
+ // matching handles
+ //
+ if (ResultSize == 0) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // Return the resulting buffer size. If it's larger than what
+ // was passed, then set the error code
+ //
+ if (ResultSize > *BufferSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *BufferSize = ResultSize;
+
+ if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
+ //
+ // If this is a search by register notify and a handle was
+ // returned, update the register notification position
+ //
+ ProtNotify = SearchKey;
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+STATIC
+IHANDLE *
+CoreGetNextLocateAllHandles (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Routine to get the next Handle, when you are searching for all handles.
+
+Arguments:
+
+ Position - Information about which Handle to seach for.
+
+ Interface - Return the interface structure for the matching protocol.
+
+Returns:
+ IHANDLE - An IHANDLE is returned if the next Position is not the end of the
+ list. A NULL_HANDLE is returned if it's the end of the list.
+
+--*/
+{
+ IHANDLE *Handle;
+
+ //
+ // Next handle
+ //
+ Position->Position = Position->Position->ForwardLink;
+
+ //
+ // If not at the end of the list, get the handle
+ //
+ Handle = NULL_HANDLE;
+ *Interface = NULL;
+ if (Position->Position != &gHandleList) {
+ Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ }
+
+ return Handle;
+}
+
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByRegisterNotify (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Routine to get the next Handle, when you are searching for register protocol
+ notifies.
+
+Arguments:
+
+ Position - Information about which Handle to seach for.
+
+ Interface - Return the interface structure for the matching protocol.
+
+Returns:
+ IHANDLE - An IHANDLE is returned if the next Position is not the end of the
+ list. A NULL_HANDLE is returned if it's the end of the list.
+
+--*/
+{
+ IHANDLE *Handle;
+ PROTOCOL_NOTIFY *ProtNotify;
+ PROTOCOL_INTERFACE *Prot;
+ LIST_ENTRY *Link;
+
+ Handle = NULL_HANDLE;
+ *Interface = NULL;
+ ProtNotify = Position->SearchKey;
+
+ //
+ // If this is the first request, get the next handle
+ //
+ if (ProtNotify != NULL) {
+ ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
+ Position->SearchKey = NULL;
+
+ //
+ // If not at the end of the list, get the next handle
+ //
+ Link = ProtNotify->Position->ForwardLink;
+ if (Link != &ProtNotify->Protocol->Protocols) {
+ Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+ Handle = (IHANDLE *) Prot->Handle;
+ *Interface = Prot->Interface;
+ }
+ }
+
+ return Handle;
+}
+
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByProtocol (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Routine to get the next Handle, when you are searching for a given protocol.
+
+Arguments:
+
+ Position - Information about which Handle to seach for.
+
+ Interface - Return the interface structure for the matching protocol.
+
+Returns:
+ IHANDLE - An IHANDLE is returned if the next Position is not the end of the
+ list. A NULL_HANDLE is returned if it's the end of the list.
+
+--*/
+{
+ IHANDLE *Handle;
+ LIST_ENTRY *Link;
+ PROTOCOL_INTERFACE *Prot;
+
+ Handle = NULL_HANDLE;
+ *Interface = NULL;
+ for (; ;) {
+ //
+ // Next entry
+ //
+ Link = Position->Position->ForwardLink;
+ Position->Position = Link;
+
+ //
+ // If not at the end, return the handle
+ //
+ if (Link == &Position->ProtEntry->Protocols) {
+ Handle = NULL_HANDLE;
+ break;
+ }
+
+ //
+ // Get the handle
+ //
+ Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+ Handle = (IHANDLE *) Prot->Handle;
+ *Interface = Prot->Interface;
+
+ //
+ // If this handle has not been returned this request, then
+ // return it now
+ //
+ if (Handle->LocateRequest != mEfiLocateHandleRequest) {
+ Handle->LocateRequest = mEfiLocateHandleRequest;
+ break;
+ }
+ }
+
+ return Handle;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateDevicePath (
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ OUT EFI_HANDLE *Device
+ )
+/*++
+
+Routine Description:
+
+ Locates the handle to a device on the device path that best matches the specified protocol.
+
+Arguments:
+
+ Protocol - The protocol to search for.
+ DevicePath - On input, a pointer to a pointer to the device path. On output, the device
+ path pointer is modified to point to the remaining part of the devicepath.
+ Device - A pointer to the returned device handle.
+
+Returns:
+
+ EFI_SUCCESS - The resulting handle was returned.
+ EFI_NOT_FOUND - No handles matched the search.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+
+--*/
+{
+ INTN SourceSize;
+ INTN Size;
+ INTN BestMatch;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *SourcePath;
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
+
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DevicePath == NULL) || (*DevicePath == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Device == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Device = NULL_HANDLE;
+ SourcePath = *DevicePath;
+ SourceSize = CoreDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
+
+ //
+ // The source path can only have 1 instance
+ //
+ if (CoreIsDevicePathMultiInstance (SourcePath)) {
+ DEBUG((EFI_D_ERROR, "LocateDevicePath: Device path has too many instances\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get a list of all handles that support the requested protocol
+ //
+ Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);
+ if (EFI_ERROR (Status) || HandleCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ BestMatch = -1;
+ for(Index = 0; Index < HandleCount; Index += 1) {
+ Handle = Handles[Index];
+ Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);
+ if (EFI_ERROR (Status)) {
+ //
+ // If this handle doesn't support device path, then skip it
+ //
+ continue;
+ }
+
+ //
+ // Check if DevicePath is first part of SourcePath
+ //
+ Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
+ if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {
+ //
+ // If the size is equal to the best match, then we
+ // have a duplice device path for 2 different device
+ // handles
+ //
+ ASSERT (Size != BestMatch);
+
+ //
+ // We've got a match, see if it's the best match so far
+ //
+ if (Size > BestMatch) {
+ BestMatch = Size;
+ *Device = Handle;
+ }
+ }
+ }
+
+ CoreFreePool (Handles);
+
+ //
+ // If there wasn't any match, then no parts of the device path was found.
+ // Which is strange since there is likely a "root level" device path in the system.
+ //
+ if (BestMatch == -1) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Return the remaining part of the device path
+ //
+ *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Return the first Protocol Interface that matches the Protocol GUID. If
+ Registration is pasased in return a Protocol Instance that was just add
+ to the system. If Retistration is NULL return the first Protocol Interface
+ you find.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ Registration - Optional Registration Key returned from RegisterProtocolNotify()
+
+ Interface - Return the Protocol interface (instance).
+
+Returns:
+
+ EFI_SUCCESS - If a valid Interface is returned
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_NOT_FOUND - Protocol interface not found
+
+--*/
+{
+ EFI_STATUS Status;
+ LOCATE_POSITION Position;
+ PROTOCOL_NOTIFY *ProtNotify;
+ IHANDLE *Handle;
+
+ if (Interface == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Protocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Interface = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // Set initial position
+ //
+ Position.Protocol = Protocol;
+ Position.SearchKey = Registration;
+ Position.Position = &gHandleList;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ mEfiLocateHandleRequest += 1;
+
+ if (NULL == Registration) {
+ //
+ // Look up the protocol entry and set the head pointer
+ //
+ Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
+ if (Position.ProtEntry == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ Position.Position = &Position.ProtEntry->Protocols;
+
+ Handle = CoreGetNextLocateByProtocol (&Position, Interface);
+ } else {
+ Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);
+ }
+
+ if (NULL == Handle) {
+ Status = EFI_NOT_FOUND;
+ } else if (NULL != Registration) {
+ //
+ // If this is a search by register notify and a handle was
+ // returned, update the register notification position
+ //
+ ProtNotify = Registration;
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;
+ }
+
+Done:
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreLocateHandleBuffer (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *NumberHandles,
+ OUT EFI_HANDLE **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Function returns an array of handles that support the requested protocol
+ in a buffer allocated from pool. This is a version of CoreLocateHandle()
+ that allocates a buffer for the caller.
+
+Arguments:
+
+ SearchType - Specifies which handle(s) are to be returned.
+ Protocol - Provides the protocol to search by.
+ This parameter is only valid for SearchType ByProtocol.
+ SearchKey - Supplies the search key depending on the SearchType.
+ NumberHandles - The number of handles returned in Buffer.
+ Buffer - A pointer to the buffer to return the requested array of
+ handles that support Protocol.
+
+Returns:
+
+ EFI_SUCCESS - The result array of handles was returned.
+ EFI_NOT_FOUND - No handles match the search.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+
+ if (NumberHandles == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BufferSize = 0;
+ *NumberHandles = 0;
+ *Buffer = NULL;
+ Status = CoreLocateHandle (
+ SearchType,
+ Protocol,
+ SearchKey,
+ &BufferSize,
+ *Buffer
+ );
+ //
+ // LocateHandleBuffer() returns incorrect status code if SearchType is
+ // invalid.
+ //
+ // Add code to correctly handle expected errors from CoreLocateHandle().
+ //
+ if (EFI_ERROR(Status)) {
+ switch (Status) {
+ case EFI_BUFFER_TOO_SMALL:
+ break;
+ case EFI_INVALID_PARAMETER:
+ return Status;
+ default:
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ *Buffer = CoreAllocateBootServicesPool (BufferSize);
+ if (*Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = CoreLocateHandle (
+ SearchType,
+ Protocol,
+ SearchKey,
+ &BufferSize,
+ *Buffer
+ );
+
+ *NumberHandles = BufferSize/sizeof(EFI_HANDLE);
+ if (EFI_ERROR(Status)) {
+ *NumberHandles = 0;
+ }
+
+ return Status;
+}
+
+
diff --git a/EdkModulePkg/Core/Dxe/Image.h b/EdkModulePkg/Core/Dxe/Image.h
new file mode 100644
index 0000000000..067d42d4b5
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Image.h
@@ -0,0 +1,380 @@
+/*++
+
+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:
+
+ Image.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+
+#ifndef _IMAGE_H_
+#define _IMAGE_H_
+
+
+
+#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','d','r','i')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle; // Image handle
+ UINTN Type; // Image type
+
+ BOOLEAN Started; // If entrypoint has been called
+
+ EFI_IMAGE_ENTRY_POINT EntryPoint; // The image's entry point
+ EFI_LOADED_IMAGE_PROTOCOL Info; // loaded image protocol
+
+ EFI_PHYSICAL_ADDRESS ImageBasePage; // Location in memory
+ UINTN NumberOfPages; // Number of pages
+
+ CHAR8 *FixupData; // Original fixup data
+
+ EFI_TPL Tpl; // Tpl of started image
+ EFI_STATUS Status; // Status returned by started image
+
+ UINTN ExitDataSize; // Size of ExitData from started image
+ VOID *ExitData; // Pointer to exit data from started image
+ BASE_LIBRARY_JUMP_BUFFER *JumpContext; // Pointer to buffer for context save/retore
+ UINT16 Machine; // Machine type from PE image
+
+ EFI_EBC_PROTOCOL *Ebc; // EBC Protocol pointer
+
+ BOOLEAN RuntimeFixupValid; // True if RT image needs fixup
+ VOID *RuntimeFixup; // Copy of fixup data;
+ LIST_ENTRY Link; // List of RT LOADED_IMAGE_PRIVATE_DATA
+
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; // PeCoffLoader ImageContext
+
+} LOADED_IMAGE_PRIVATE_DATA;
+
+#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
+
+
+
+#define LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','p','e','i')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle; // Image handle
+ EFI_PE32_IMAGE_PROTOCOL Pe32Image;
+} LOAD_PE32_IMAGE_PRIVATE_DATA;
+
+#define LOAD_PE32_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, LOAD_PE32_IMAGE_PRIVATE_DATA, Pe32Image, LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE)
+
+
+
+//
+// Private Data Types
+//
+#define IMAGE_FILE_HANDLE_SIGNATURE EFI_SIGNATURE_32('i','m','g','f')
+typedef struct {
+ UINTN Signature;
+ BOOLEAN FreeBuffer;
+ VOID *Source;
+ UINTN SourceSize;
+} IMAGE_FILE_HANDLE;
+
+
+//
+// Abstractions for reading image contents
+//
+
+EFI_STATUS
+CoreOpenImageFile (
+ IN BOOLEAN BootPolicy,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ OUT EFI_HANDLE *DeviceHandle,
+ IN IMAGE_FILE_HANDLE *ImageFileHandle,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+
+ Opens a file for (simple) reading. The simple read abstraction
+ will access the file either from a memory copy, from a file
+ system interface, or from the load file interface.
+
+Arguments:
+
+ BootPolicy - Policy for Open Image File.
+ SourceBuffer - Pointer to the memory location containing copy
+ of the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ FilePath - The specific file path from which the image is loaded
+ DeviceHandle - Pointer to the return device handle.
+ ImageFileHandle - Pointer to the image file handle.
+ AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
+
+Returns:
+
+ A handle to access the file
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreReadImageFile (
+ IN VOID *UserHandle,
+ IN UINTN Offset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Read image file (specified by UserHandle) into user specified buffer with specified offset
+ and length.
+
+Arguments:
+
+ UserHandle - Image file handle
+
+ Offset - Offset to the source file
+
+ ReadSize - For input, pointer of size to read;
+ For output, pointer of size actually read.
+
+ Buffer - Buffer to write into
+
+Returns:
+
+ EFI_SUCCESS - Successfully read the specified part of file into buffer.
+
+--*/
+;
+
+VOID
+EFIAPI
+CoreCloseImageFile (
+ IN IMAGE_FILE_HANDLE *ImageFileHandle
+ )
+/*++
+
+Routine Description:
+
+ A function out of date, should be removed.
+
+Arguments:
+
+ ImageFileHandle - Handle of the file to close
+
+Returns:
+
+ None
+
+--*/
+;
+
+//
+// Image processing worker functions
+//
+EFI_STATUS
+CoreDevicePathToInterface (
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT VOID **Interface,
+ OUT EFI_HANDLE *Handle
+ )
+/*++
+
+Routine Description:
+
+ Search a handle to a device on a specified device path that supports a specified protocol,
+ interface of that protocol on that handle is another output.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ FilePath - The specified device path
+
+ Interface - Interface of the protocol on the handle
+
+ Handle - The handle to the device on the specified device path that supports the protocol.
+
+Returns:
+
+ Status code.
+
+--*/
+;
+
+EFI_STATUS
+CoreLoadPeImage (
+ IN VOID *Pe32Handle,
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Loads, relocates, and invokes a PE/COFF image
+
+Arguments:
+
+ Pe32Handle - The handle of PE32 image
+ Image - PE image to be loaded
+ DstBuffer - The buffer to store the image
+ EntryPoint - A pointer to the entry point
+ Attribute - The bit mask of attributes to set for the load PE image
+
+Returns:
+
+ EFI_SUCCESS - The file was loaded, relocated, and invoked
+
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_BUFFER_TOO_SMALL - Buffer for image is too small
+
+--*/
+;
+
+LOADED_IMAGE_PRIVATE_DATA *
+CoreLoadedImageInfo (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+CoreUnloadAndCloseImage (
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN BOOLEAN FreePage
+ )
+/*++
+
+Routine Description:
+
+ Unloads EFI image from memory.
+
+Arguments:
+
+ Image - EFI image
+ FreePage - Free allocated pages
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+//
+// Exported Image functions
+//
+
+EFI_STATUS
+EFIAPI
+CoreLoadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT UINTN *NumberOfPages OPTIONAL,
+ OUT EFI_HANDLE *ImageHandle,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image with extended parameters.
+
+Arguments:
+
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ DstBuffer - The buffer to store the image.
+ NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
+ For output, specifies the actual space size needed.
+ ImageHandle - Image handle for output.
+ EntryPoint - Image entry point for output.
+ Attribute - The bit mask of attributes to set for the load PE image.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CoreUnloadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unload the specified image.
+
+Arguments:
+
+ This - Indicates the calling context.
+
+ ImageHandle - The specified image handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL.
+
+ EFI_UNSUPPORTED - Attempt to unload an unsupported image.
+
+ EFI_SUCCESS - Image successfully unloaded.
+
+--*/
+;
+#endif
diff --git a/EdkModulePkg/Core/Dxe/Image/Image.c b/EdkModulePkg/Core/Dxe/Image/Image.c
new file mode 100644
index 0000000000..c818cc2131
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Image/Image.c
@@ -0,0 +1,1377 @@
+/*++
+
+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:
+
+ Image.c
+
+Abstract:
+
+ Core image handling services
+
+--*/
+
+#include <DxeMain.h>
+//
+// Module Globals
+//
+
+//
+// LIST of runtime images that need to be relocated.
+//
+LIST_ENTRY mRuntimeImageList = INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeImageList);
+
+LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;
+
+LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {
+ LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,
+ NULL,
+ {
+ CoreLoadImageEx,
+ CoreUnloadImageEx
+ }
+};
+
+
+//
+// This code is needed to build the Image handle for the DXE Core
+//
+LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {
+ LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature
+ NULL, // Image handle
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type
+ TRUE, // If entrypoint has been called
+ NULL, // EntryPoint
+ {
+ EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision
+ NULL, // Parent handle
+ NULL, // System handle
+
+ NULL, // Device handle
+ NULL, // File path
+ NULL, // Reserved
+
+ 0, // LoadOptionsSize
+ NULL, // LoadOptions
+
+ NULL, // ImageBase
+ 0, // ImageSize
+ EfiBootServicesCode, // ImageCodeType
+ EfiBootServicesData // ImageDataType
+ },
+ (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage
+ 0, // NumberOfPages
+ NULL, // FixupData
+ 0, // Tpl
+ EFI_SUCCESS, // Status
+ 0, // ExitDataSize
+ NULL, // ExitData
+ NULL, // JumpContext
+ 0, // Machine
+ NULL, // Ebc
+ FALSE, // RuntimeFixupValid
+ NULL, // RuntimeFixup
+ { NULL, NULL }, // Link
+};
+
+
+EFI_STATUS
+CoreInitializeImageServices (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Add the Image Services to EFI Boot Services Table and install the protocol
+ interfaces for this image.
+
+Arguments:
+
+ HobStart - The HOB to initialize
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+ EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;
+ UINT64 DxeCoreImageLength;
+ VOID *DxeCoreEntryPoint;
+ EFI_PEI_HOB_POINTERS DxeCoreHob;
+ //
+ // Searching for image hob
+ //
+ DxeCoreHob.Raw = HobStart;
+ while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
+ if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
+ //
+ // Find Dxe Core HOB
+ //
+ break;
+ }
+ DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
+ }
+ ASSERT (DxeCoreHob.Raw != NULL);
+
+ DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
+ DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
+ DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;
+ gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;
+ //
+ // Initialize the fields for an internal driver
+ //
+ Image = &mCorePrivateImage;
+
+ Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
+ Image->ImageBasePage = DxeCoreImageBaseAddress;
+ Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));
+ Image->Tpl = gEfiCurrentTpl;
+ Image->Info.SystemTable = gST;
+ Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;
+ Image->Info.ImageSize = DxeCoreImageLength;
+
+ //
+ // Install the protocol interfaces for this image
+ //
+ Status = CoreInstallProtocolInterface (
+ &Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Image->Info
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mCurrentImage = Image;
+
+ //
+ // Fill in DXE globals
+ //
+ gDxeCoreImageHandle = Image->Handle;
+ gDxeCoreLoadedImage = &Image->Info;
+
+ //
+ // Export DXE Core PE Loader functionality
+ //
+ return CoreInstallProtocolInterface (
+ &mLoadPe32PrivateData.Handle,
+ &gEfiLoadPeImageProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mLoadPe32PrivateData.Pe32Image
+ );
+}
+
+
+EFI_STATUS
+CoreShutdownImageServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Transfer control of runtime images to runtime service
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Function successfully returned
+
+--*/
+{
+ LIST_ENTRY *Link;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+
+ //
+ // The Runtime AP is required for the core to function!
+ //
+ ASSERT (gRuntime != NULL);
+
+ for (Link = mRuntimeImageList.ForwardLink; Link != &mRuntimeImageList; Link = Link->ForwardLink) {
+ Image = CR (Link, LOADED_IMAGE_PRIVATE_DATA, Link, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE);
+ if (Image->RuntimeFixupValid) {
+ gRuntime->RegisterImage (
+ gRuntime,
+ (UINT64)(UINTN)(Image->Info.ImageBase),
+ (EFI_SIZE_TO_PAGES ((UINTN)Image->Info.ImageSize)),
+ Image->RuntimeFixup
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+CoreLoadPeImage (
+ IN VOID *Pe32Handle,
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Loads, relocates, and invokes a PE/COFF image
+
+Arguments:
+
+ Pe32Handle - The handle of PE32 image
+ Image - PE image to be loaded
+ DstBuffer - The buffer to store the image
+ EntryPoint - A pointer to the entry point
+ Attribute - The bit mask of attributes to set for the load PE image
+
+Returns:
+
+ EFI_SUCCESS - The file was loaded, relocated, and invoked
+
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_BUFFER_TOO_SMALL - Buffer for image is too small
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Size;
+
+ ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));
+
+ Image->ImageContext.Handle = Pe32Handle;
+ Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;
+
+ //
+ // Get information about the image being loaded
+ //
+ Status = gEfiPeiPeCoffLoader->GetImageInfo (gEfiPeiPeCoffLoader, &Image->ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate memory of the correct memory type aligned on the required image boundry
+ //
+
+ if (DstBuffer == 0) {
+ //
+ // Allocate Destination Buffer as caller did not pass it in
+ //
+
+ if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
+ Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
+ } else {
+ Size = (UINTN)Image->ImageContext.ImageSize;
+ }
+
+ Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
+
+ //
+ // If the image relocations have not been stripped, then load at any address.
+ // Otherwise load at the address at which it was linked.
+ //
+ Status = CoreAllocatePages (
+ (Image->ImageContext.RelocationsStripped) ? AllocateAddress : AllocateAnyPages,
+ Image->ImageContext.ImageCodeMemoryType,
+ Image->NumberOfPages,
+ &Image->ImageContext.ImageAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Image->ImageBasePage = Image->ImageContext.ImageAddress;
+
+ } else {
+ //
+ // Caller provided the destination buffer
+ //
+
+ if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
+ //
+ // If the image relocations were stripped, and the caller provided a
+ // destination buffer address that does not match the address that the
+ // image is linked at, then the image cannot be loaded.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Image->NumberOfPages != 0 &&
+ Image->NumberOfPages <
+ (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {
+ Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
+ Image->ImageContext.ImageAddress = DstBuffer;
+ Image->ImageBasePage = Image->ImageContext.ImageAddress;
+ }
+
+ Image->ImageContext.ImageAddress =
+ (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
+ ~((UINTN)Image->ImageContext.SectionAlignment - 1);
+
+ //
+ // Load the image from the file into the allocated memory
+ //
+ Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If this is a Runtime Driver, then allocate memory for the FixupData that
+ // is used to relocate the image when SetVirtualAddressMap() is called. The
+ // relocation is done by the Runtime AP.
+ //
+ if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
+ if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+ Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
+ if (Image->ImageContext.FixupData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Make a list off all the RT images so we can let the RT AP know about them
+ //
+ Image->RuntimeFixupValid = TRUE;
+ Image->RuntimeFixup = Image->ImageContext.FixupData;
+ InsertTailList (&mRuntimeImageList, &Image->Link);
+ }
+ }
+
+ //
+ // Relocate the image in memory
+ //
+ Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Flush the Instruction Cache
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);
+
+ //
+ // Copy the machine type from the context to the image private data. This
+ // is needed during image unload to know if we should call an EBC protocol
+ // to unload the image.
+ //
+ Image->Machine = Image->ImageContext.Machine;
+
+ //
+ // Get the image entry point. If it's an EBC image, then call into the
+ // interpreter to create a thunk for the entry point and use the returned
+ // value for the entry point.
+ //
+ Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
+ if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
+ //
+ // Locate the EBC interpreter protocol
+ //
+ Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ //
+ // Register a callback for flushing the instruction cache so that created
+ // thunks can be flushed.
+ //
+ Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ //
+ // Create a thunk for the image's entry point. This will be the new
+ // entry point for the image.
+ //
+ Status = Image->Ebc->CreateThunk (
+ Image->Ebc,
+ Image->Handle,
+ (VOID *)(UINTN)Image->ImageContext.EntryPoint,
+ (VOID **)&Image->EntryPoint
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Fill in the image information for the Loaded Image Protocol
+ //
+ Image->Type = Image->ImageContext.ImageType;
+ Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
+ Image->Info.ImageSize = Image->ImageContext.ImageSize;
+ Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType;
+ Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType;
+
+ //
+ // Fill in the entry point of the image if it is available
+ //
+ if (EntryPoint != NULL) {
+ *EntryPoint = Image->ImageContext.EntryPoint;
+ }
+
+ //
+ // Print the load address and the PDB file name if it is available
+ //
+
+ DEBUG_CODE (
+ {
+ UINTN Index;
+ UINTN StartIndex;
+ CHAR8 EfiFileName[256];
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.EntryPoint));
+ if (Image->ImageContext.PdbPointer != NULL) {
+ StartIndex = 0;
+ for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
+ if (Image->ImageContext.PdbPointer[Index] == '\\') {
+ StartIndex = Index + 1;
+ }
+ }
+ //
+ // Copy the PDB file name to our temporary string, and replace .pdb with .efi
+ //
+ for (Index = 0; Index < sizeof (EfiFileName); Index++) {
+ EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
+ if (EfiFileName[Index] == 0) {
+ EfiFileName[Index] = '.';
+ }
+ if (EfiFileName[Index] == '.') {
+ EfiFileName[Index + 1] = 'e';
+ EfiFileName[Index + 2] = 'f';
+ EfiFileName[Index + 3] = 'i';
+ EfiFileName[Index + 4] = 0;
+ break;
+ }
+ }
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
+ }
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
+ }
+ );
+
+ return EFI_SUCCESS;
+
+Done:
+ //
+ // Free memory
+ //
+ CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
+ return Status;
+}
+
+
+LOADED_IMAGE_PRIVATE_DATA *
+CoreLoadedImageInfo (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Get the image's private data from its handle.
+
+Arguments:
+
+ ImageHandle - The image handle
+
+Returns:
+
+ Return the image private data associated with ImageHandle.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+
+ Status = CoreHandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ if (!EFI_ERROR (Status)) {
+ Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
+ } else {
+ DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));
+ Image = NULL;
+ }
+
+ return Image;
+}
+
+
+EFI_STATUS
+CoreLoadImageCommon (
+ IN BOOLEAN BootPolicy,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ IN OUT UINTN *NumberOfPages OPTIONAL,
+ OUT EFI_HANDLE *ImageHandle,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image.
+
+Arguments:
+
+ BootPolicy - If TRUE, indicates that the request originates from the boot manager,
+ and that the boot manager is attempting to load FilePath as a boot selection.
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ DstBuffer - The buffer to store the image
+ NumberOfPages - If not NULL, a pointer to the image's page number, if this number
+ is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
+ the required number.
+ ImageHandle - Pointer to the returned image handle that is created when the image
+ is successfully loaded.
+ EntryPoint - A pointer to the entry point
+ Attribute - The bit mask of attributes to set for the load PE image
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_BUFFER_TOO_SMALL - The buffer is too small
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+{
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+ LOADED_IMAGE_PRIVATE_DATA *ParentImage;
+ IMAGE_FILE_HANDLE FHand;
+ EFI_STATUS Status;
+ EFI_STATUS SecurityStatus;
+ EFI_HANDLE DeviceHandle;
+ UINT32 AuthenticationStatus;
+ EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;
+ EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
+ UINTN FilePathSize;
+
+
+ ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY);
+ ParentImage = NULL;
+
+ //
+ // The caller must pass in a valid ParentImageHandle
+ //
+ if (ImageHandle == NULL || ParentImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentImage = CoreLoadedImageInfo (ParentImageHandle);
+ if (ParentImage == NULL) {
+ DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get simple read access to the source file
+ //
+ OriginalFilePath = FilePath;
+ Status = CoreOpenImageFile (
+ BootPolicy,
+ SourceBuffer,
+ SourceSize,
+ FilePath,
+ &DeviceHandle,
+ &FHand,
+ &AuthenticationStatus
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ Image = NULL;
+ goto Done;
+ } else if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the Authentication Status through the Security Architectural Protocol
+ //
+ if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
+ SecurityStatus = gSecurity->FileAuthenticationState (
+ gSecurity,
+ AuthenticationStatus,
+ OriginalFilePath
+ );
+ if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
+ Status = SecurityStatus;
+ Image = NULL;
+ goto Done;
+ }
+ }
+
+
+ //
+ // Allocate a new image structure
+ //
+ Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
+ //
+ Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
+ if (!EFI_ERROR (Status)) {
+ FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
+ FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );
+ }
+
+ //
+ // Initialize the fields for an internal driver
+ //
+ Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
+ Image->Info.SystemTable = gST;
+ Image->Info.DeviceHandle = DeviceHandle;
+ Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
+ Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);
+ Image->Info.ParentHandle = ParentImageHandle;
+
+ if (NumberOfPages != NULL) {
+ Image->NumberOfPages = *NumberOfPages ;
+ } else {
+ Image->NumberOfPages = 0 ;
+ }
+
+ //
+ // Install the protocol interfaces for this image
+ // don't fire notifications yet
+ //
+ Status = CoreInstallProtocolInterfaceNotify (
+ &Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Image->Info,
+ FALSE
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Load the image. If EntryPoint is Null, it will not be set.
+ //
+ Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute);
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
+ if (NumberOfPages != NULL) {
+ *NumberOfPages = Image->NumberOfPages;
+ }
+ }
+ goto Done;
+ }
+
+ //
+ // Register the image in the Debug Image Info Table if the attribute is set
+ //
+ if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {
+ CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
+ }
+
+ //
+ //Reinstall loaded image protocol to fire any notifications
+ //
+ Status = CoreReinstallProtocolInterface (
+ Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ &Image->Info,
+ &Image->Info
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+
+ //
+ // Success. Return the image handle
+ //
+ *ImageHandle = Image->Handle;
+
+Done:
+ //
+ // All done accessing the source file
+ // If we allocated the Source buffer, free it
+ //
+ if (FHand.FreeBuffer) {
+ CoreFreePool (FHand.Source);
+ }
+
+ //
+ // There was an error. If there's an Image structure, free it
+ //
+ if (EFI_ERROR (Status)) {
+ if (Image != NULL) {
+ CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
+ *ImageHandle = NULL;
+ }
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreLoadImage (
+ IN BOOLEAN BootPolicy,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image.
+
+Arguments:
+
+ BootPolicy - If TRUE, indicates that the request originates from the boot manager,
+ and that the boot manager is attempting to load FilePath as a boot selection.
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ ImageHandle - Pointer to the returned image handle that is created when the image
+ is successfully loaded.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+{
+ EFI_STATUS Status;
+
+ PERF_START (NULL, "LoadImage", NULL, 0);
+
+ Status = CoreLoadImageCommon (
+ BootPolicy,
+ ParentImageHandle,
+ FilePath,
+ SourceBuffer,
+ SourceSize,
+ (EFI_PHYSICAL_ADDRESS)NULL,
+ NULL,
+ ImageHandle,
+ NULL,
+ EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
+ );
+
+ PERF_END (NULL, "LoadImage", NULL, 0);
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreLoadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT UINTN *NumberOfPages OPTIONAL,
+ OUT EFI_HANDLE *ImageHandle,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image with extended parameters.
+
+Arguments:
+
+ This - Calling context
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ DstBuffer - The buffer to store the image.
+ NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
+ For output, specifies the actual space size needed.
+ ImageHandle - Image handle for output.
+ EntryPoint - Image entry point for output.
+ Attribute - The bit mask of attributes to set for the load PE image.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+{
+ return CoreLoadImageCommon (
+ TRUE,
+ ParentImageHandle,
+ FilePath,
+ SourceBuffer,
+ SourceSize,
+ DstBuffer,
+ NumberOfPages,
+ ImageHandle,
+ EntryPoint,
+ Attribute
+ );
+}
+
+
+
+
+EFI_STATUS
+EFIAPI
+CoreStartImage (
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *ExitDataSize,
+ OUT CHAR16 **ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Transfer control to a loaded image's entry point.
+
+Arguments:
+
+ ImageHandle - Handle of image to be started.
+
+ ExitDataSize - Pointer of the size to ExitData
+
+ ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
+ Unicode string, optionally followed by additional binary data. The string
+ is a description that the caller may use to further indicate the reason for
+ the image¡¯s exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully transfer control to the image's entry point.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+ LOADED_IMAGE_PRIVATE_DATA *LastImage;
+ UINT64 HandleDatabaseKey;
+ UINTN SetJumpFlag;
+
+ Image = CoreLoadedImageInfo (ImageHandle);
+ if (Image == NULL_HANDLE || Image->Started) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Don't profile Objects or invalid start requests
+ //
+ PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);
+
+ if (sizeof (UINTN) == 4 && Image->Machine == EFI_IMAGE_MACHINE_X64) {
+ return EFI_UNSUPPORTED;
+ } else if (sizeof (UINTN) == 8 && Image->Machine == EFI_IMAGE_MACHINE_IA32) {
+ return EFI_UNSUPPORTED;
+ } else {
+ //
+ // For orther possible cases
+ //
+ }
+
+ //
+ // Push the current start image context, and
+ // link the current image to the head. This is the
+ // only image that can call Exit()
+ //
+ HandleDatabaseKey = CoreGetHandleDatabaseKey();
+ LastImage = mCurrentImage;
+ mCurrentImage = Image;
+ Image->Tpl = gEfiCurrentTpl;
+
+ //
+ // Set long jump for Exit() support
+ //
+ Image->JumpContext = CoreAllocateBootServicesPool (sizeof (*Image->JumpContext));
+ if (Image->JumpContext == NULL) {
+ PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetJumpFlag = SetJump (Image->JumpContext);
+ //
+ // The initial call to SetJump() must always return 0.
+ // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
+ //
+ if (!SetJumpFlag) {
+ //
+ // Call the image's entry point
+ //
+ Image->Started = TRUE;
+ Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
+
+ //
+ // Add some debug information if the image returned with error.
+ // This make the user aware and check if the driver image have already released
+ // all the resource in this situation.
+ //
+ DEBUG_CODE (
+ if (EFI_ERROR (Image->Status)) {
+ DEBUG ((EFI_D_ERROR, "Error: Image at %08X start failed: %x\n", Image->Info.ImageBase, Image->Status));
+ }
+ );
+
+ //
+ // If the image returns, exit it through Exit()
+ //
+ CoreExit (ImageHandle, Image->Status, 0, NULL);
+ }
+
+ //
+ // Image has completed. Verify the tpl is the same
+ //
+ ASSERT (Image->Tpl == gEfiCurrentTpl);
+ CoreRestoreTpl (Image->Tpl);
+
+ CoreFreePool (Image->JumpContext);
+
+ //
+ // Pop the current start image context
+ //
+ mCurrentImage = LastImage;
+
+ //
+ // Go connect any handles that were created or modified while the image executed.
+ //
+ CoreConnectHandlesByKey (HandleDatabaseKey);
+
+ //
+ // Handle the image's returned ExitData
+ //
+ DEBUG_CODE (
+ if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
+
+ DEBUG (
+ (EFI_D_LOAD,
+ "StartImage: ExitDataSize %d, ExitData %x",
+ Image->ExitDataSize,
+ Image->ExitData)
+ );
+ if (Image->ExitData != NULL) {
+ DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));
+ }
+ DEBUG ((EFI_D_LOAD, "\n"));
+ }
+ );
+
+ //
+ // Return the exit data to the caller
+ //
+ if (ExitData != NULL && ExitDataSize != NULL) {
+ *ExitDataSize = Image->ExitDataSize;
+ *ExitData = Image->ExitData;
+ } else {
+ //
+ // Caller doesn't want the exit data, free it
+ //
+ CoreFreePool (Image->ExitData);
+ Image->ExitData = NULL;
+ }
+
+ //
+ // Save the Status because Image will get destroyed if it is unloaded.
+ //
+ Status = Image->Status;
+
+ //
+ // If the image returned an error, or if the image is an application
+ // unload it
+ //
+ if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
+ CoreUnloadAndCloseImage (Image, TRUE);
+ }
+
+ //
+ // Done
+ //
+ PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
+ return Status;
+}
+
+
+VOID
+CoreUnloadAndCloseImage (
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN BOOLEAN FreePage
+ )
+/*++
+
+Routine Description:
+
+ Unloads EFI image from memory.
+
+Arguments:
+
+ Image - EFI image
+ FreePage - Free allocated pages
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleIndex;
+ EFI_GUID **ProtocolGuidArray;
+ UINTN ArrayCount;
+ UINTN ProtocolIndex;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
+ UINTN OpenInfoCount;
+ UINTN OpenInfoIndex;
+
+ if (Image->Ebc != NULL) {
+ //
+ // If EBC protocol exists we must perform cleanups for this image.
+ //
+ Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
+ }
+
+ //
+ // Unload image, free Image->ImageContext->ModHandle
+ //
+ gEfiPeiPeCoffLoader->UnloadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
+
+ //
+ // Free our references to the image handle
+ //
+ if (Image->Handle != NULL_HANDLE) {
+
+ Status = CoreLocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ Status = CoreProtocolsPerHandle (
+ HandleBuffer[HandleIndex],
+ &ProtocolGuidArray,
+ &ArrayCount
+ );
+ if (!EFI_ERROR (Status)) {
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+ Status = CoreOpenProtocolInformation (
+ HandleBuffer[HandleIndex],
+ ProtocolGuidArray[ProtocolIndex],
+ &OpenInfo,
+ &OpenInfoCount
+ );
+ if (!EFI_ERROR (Status)) {
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
+ Status = CoreCloseProtocol (
+ HandleBuffer[HandleIndex],
+ ProtocolGuidArray[ProtocolIndex],
+ Image->Handle,
+ OpenInfo[OpenInfoIndex].ControllerHandle
+ );
+ }
+ }
+ if (OpenInfo != NULL) {
+ CoreFreePool(OpenInfo);
+ }
+ }
+ }
+ if (ProtocolGuidArray != NULL) {
+ CoreFreePool(ProtocolGuidArray);
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ CoreFreePool (HandleBuffer);
+ }
+ }
+
+ CoreRemoveDebugImageInfoEntry (Image->Handle);
+
+ Status = CoreUninstallProtocolInterface (
+ Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ &Image->Info
+ );
+ }
+
+ if (Image->RuntimeFixupValid) {
+ //
+ // Remove the Image from the Runtime Image list as we are about to Free it!
+ //
+ RemoveEntryList (&Image->Link);
+ }
+
+ //
+ // Free the Image from memory
+ //
+ if ((Image->ImageBasePage != 0) && FreePage) {
+ CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
+ }
+
+ //
+ // Done with the Image structure
+ //
+ if (Image->Info.FilePath != NULL) {
+ CoreFreePool (Image->Info.FilePath);
+ }
+
+ if (Image->FixupData != NULL) {
+ CoreFreePool (Image->FixupData);
+ }
+
+ CoreFreePool (Image);
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_STATUS Status,
+ IN UINTN ExitDataSize,
+ IN CHAR16 *ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Terminates the currently loaded EFI image and returns control to boot services.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the image. This parameter is passed to the image
+ on entry.
+ Status - The image¡¯s exit code.
+ ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
+ EFI_SUCCESS.
+ ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
+ optionally followed by additional binary data. The string is a
+ description that the caller may use to further indicate the reason for
+ the image¡¯s exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
+
+ EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
+
+ EFI_ACCESS_DENIED - Should never reach there.
+
+ EFI_OUT_OF_RESOURCES - Could not allocate pool
+
+--*/
+{
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+
+ Image = CoreLoadedImageInfo (ImageHandle);
+ if (Image == NULL_HANDLE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!Image->Started) {
+ //
+ // The image has not been started so just free its resources
+ //
+ CoreUnloadAndCloseImage (Image, TRUE);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Image has been started, verify this image can exit
+ //
+ if (Image != mCurrentImage) {
+ DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set status
+ //
+ Image->Status = Status;
+
+ //
+ // If there's ExitData info, move it
+ //
+ if (ExitData != NULL) {
+ Image->ExitDataSize = ExitDataSize;
+ Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);
+ if (Image->ExitData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
+ }
+
+ //
+ // return to StartImage
+ //
+ LongJump (Image->JumpContext, (UINTN)-1);
+
+ //
+ // If we return from LongJump, then it is an error
+ //
+ ASSERT (FALSE);
+ return EFI_ACCESS_DENIED;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreUnloadImage (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unloads an image.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the image to be unloaded.
+
+Returns:
+
+ EFI_SUCCESS - The image has been unloaded.
+ EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
+ EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+
+ Image = CoreLoadedImageInfo (ImageHandle);
+ if (Image == NULL ) {
+ //
+ // The image handle is not valid
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Image->Started) {
+ //
+ // The image has been started, request it to unload.
+ //
+ Status = EFI_UNSUPPORTED;
+ if (Image->Info.Unload != NULL) {
+ Status = Image->Info.Unload (ImageHandle);
+ }
+
+ } else {
+ //
+ // This Image hasn't been started, thus it can be unloaded
+ //
+ Status = EFI_SUCCESS;
+ }
+
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // if the Image was not started or Unloaded O.K. then clean up
+ //
+ CoreUnloadAndCloseImage (Image, TRUE);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreUnloadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unload the specified image.
+
+Arguments:
+
+ This - Indicates the calling context.
+
+ ImageHandle - The specified image handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL.
+
+ EFI_UNSUPPORTED - Attempt to unload an unsupported image.
+
+ EFI_SUCCESS - Image successfully unloaded.
+
+--*/
+{
+ return CoreUnloadImage (ImageHandle);
+}
diff --git a/EdkModulePkg/Core/Dxe/Image/ImageFile.c b/EdkModulePkg/Core/Dxe/Image/ImageFile.c
new file mode 100644
index 0000000000..999cd694ad
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Image/ImageFile.c
@@ -0,0 +1,569 @@
+/*++
+
+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:
+
+ ImageFile.c
+
+
+Abstract:
+
+
+
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+
+VOID
+CoreDevicePathToFileName (
+ IN FILEPATH_DEVICE_PATH *FilePath,
+ OUT CHAR16 **String
+ );
+
+
+
+EFI_STATUS
+CoreOpenImageFile (
+ IN BOOLEAN BootPolicy,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ OUT EFI_HANDLE *DeviceHandle,
+ IN IMAGE_FILE_HANDLE *ImageFileHandle,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+
+ Opens a file for (simple) reading. The simple read abstraction
+ will access the file either from a memory copy, from a file
+ system interface, or from the load file interface.
+
+Arguments:
+
+ BootPolicy - Policy for Open Image File.
+ SourceBuffer - Pointer to the memory location containing copy
+ of the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ FilePath - The specific file path from which the image is loaded
+ DeviceHandle - Pointer to the return device handle.
+ ImageFileHandle - Pointer to the image file handle.
+ AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
+
+Returns:
+
+ EFI_SUCCESS - Image file successfully opened.
+
+ EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0.
+
+ EFI_INVALID_PARAMETER - File path is not valid.
+
+ EFI_NOT_FOUND - File not found.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TempFilePath;
+ FILEPATH_DEVICE_PATH *FilePathNode;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
+ EFI_FILE_HANDLE FileHandle;
+ EFI_FILE_HANDLE LastHandle;
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+ EFI_SECTION_TYPE SectionType;
+ UINT8 *Pe32Buffer;
+ UINTN Pe32BufferSize;
+ EFI_FV_FILETYPE Type;
+ EFI_FV_FILE_ATTRIBUTES Attrib;
+ EFI_FILE_INFO *FileInfo;
+ UINTN FileInfoSize;
+ EFI_GUID *NameGuid;
+
+ *AuthenticationStatus = 0;
+ ZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE));
+ ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE;
+
+ //
+ // If the caller passed a copy of the file, then just use it
+ //
+ if (SourceBuffer != NULL) {
+ ImageFileHandle->Source = SourceBuffer;
+ ImageFileHandle->SourceSize = SourceSize;
+ *DeviceHandle = NULL;
+ if (SourceSize > 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_LOAD_ERROR;
+ }
+ goto Done;
+ }
+
+ //
+ // Make sure FilePath is valid
+ //
+ if (FilePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if it's in a Firmware Volume
+ //
+ FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiFirmwareVolumeProtocolGuid,
+ (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode,
+ (VOID*)&FwVol,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // For FwVol File system there is only a single file name that is a GUID.
+ //
+ NameGuid = EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode);
+ if (NameGuid != NULL) {
+
+ SectionType = EFI_SECTION_PE32;
+ Pe32Buffer = NULL;
+ Status = FwVol->ReadSection (
+ FwVol,
+ NameGuid,
+ SectionType,
+ 0,
+ (VOID **)&Pe32Buffer,
+ &Pe32BufferSize,
+ AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Try a raw file, since a PE32 SECTION does not exist
+ //
+ if (Pe32Buffer != NULL) {
+ CoreFreePool (Pe32Buffer);
+ *AuthenticationStatus = 0;
+ }
+ Pe32Buffer = NULL;
+ Status = FwVol->ReadFile (
+ FwVol,
+ NameGuid,
+ (VOID **)&Pe32Buffer,
+ &Pe32BufferSize,
+ &Type,
+ &Attrib,
+ AuthenticationStatus
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // One of the reads passed so we are done
+ //
+ ImageFileHandle->Source = Pe32Buffer;
+ ImageFileHandle->SourceSize = Pe32BufferSize;
+ ImageFileHandle->FreeBuffer = TRUE;
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // Attempt to access the file via a file system interface
+ //
+ FilePathNode = (FILEPATH_DEVICE_PATH *) FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiSimpleFileSystemProtocolGuid,
+ (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode,
+ (VOID*)&Volume,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Open the Volume to get the File System handle
+ //
+ Status = Volume->OpenVolume (Volume, &FileHandle);
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
+ // directory information and filename can be seperate. The goal is to inch
+ // our way down each device path node and close the previous node
+ //
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {
+ if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Exit loop on Error
+ //
+ break;
+ }
+
+ LastHandle = FileHandle;
+ FileHandle = NULL;
+ Status = LastHandle->Open (
+ LastHandle,
+ &FileHandle,
+ FilePathNode->PathName,
+ EFI_FILE_MODE_READ,
+ 0
+ );
+
+ //
+ // Close the previous node
+ //
+ LastHandle->Close (LastHandle);
+
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // We have found the file. Now we need to read it. Before we can read the file we need to
+ // figure out how big the file is.
+ //
+ FileInfo = NULL;
+ FileInfoSize = sizeof (EFI_FILE_INFO);
+ while (CoreGrowBuffer (&Status, (VOID **)&FileInfo, FileInfoSize)) {
+ //
+ // Automatically allocate buffer of the correct size and make the call
+ //
+ Status = FileHandle->GetInfo (
+ FileHandle,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo
+ );
+ }
+ if (!EFI_ERROR (Status)) {
+ //
+ // Allocate space for the file
+ //
+ ImageFileHandle->Source = CoreAllocateBootServicesPool ((UINTN)FileInfo->FileSize);
+ if (ImageFileHandle->Source != NULL) {
+ //
+ // Read the file into the buffer we allocated
+ //
+ ImageFileHandle->SourceSize = (UINTN)FileInfo->FileSize;
+ ImageFileHandle->FreeBuffer = TRUE;
+ Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source);
+
+ //
+ // Close the file since we are done
+ //
+ FileHandle->Close (FileHandle);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+
+ goto Done;
+ }
+ }
+ }
+ }
+
+
+ //
+ // Try LoadFile style
+ //
+
+ TempFilePath = FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiLoadFileProtocolGuid,
+ &TempFilePath,
+ (VOID*)&LoadFile,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Call LoadFile with the correct buffer size
+ //
+ while (CoreGrowBuffer (&Status, (VOID **)&ImageFileHandle->Source, ImageFileHandle->SourceSize)) {
+ Status = LoadFile->LoadFile (
+ LoadFile,
+ TempFilePath,
+ BootPolicy,
+ &ImageFileHandle->SourceSize,
+ ImageFileHandle->Source
+ );
+ //
+ // If success or other error happens, stop loop
+ //
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ break;
+ }
+ }
+
+ if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {
+ ImageFileHandle->FreeBuffer = TRUE;
+ goto Done;
+ }
+ }
+
+ //
+ // Nothing else to try
+ //
+ DEBUG ((EFI_D_LOAD|EFI_D_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n"));
+ Status = EFI_NOT_FOUND;
+
+Done:
+
+ //
+ // If the file was not accessed, clean up
+ //
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ if (ImageFileHandle->FreeBuffer) {
+ //
+ // Free the source buffer if we allocated it
+ //
+ CoreFreePool (ImageFileHandle->Source);
+ }
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreReadImageFile (
+ IN VOID *UserHandle,
+ IN UINTN Offset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Read image file (specified by UserHandle) into user specified buffer with specified offset
+ and length.
+
+Arguments:
+
+ UserHandle - Image file handle
+
+ Offset - Offset to the source file
+
+ ReadSize - For input, pointer of size to read;
+ For output, pointer of size actually read.
+
+ Buffer - Buffer to write into
+
+Returns:
+
+ EFI_SUCCESS - Successfully read the specified part of file into buffer.
+
+--*/
+{
+ UINTN EndPosition;
+ IMAGE_FILE_HANDLE *FHand;
+
+ FHand = (IMAGE_FILE_HANDLE *)UserHandle;
+ ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);
+
+ //
+ // Move data from our local copy of the file
+ //
+ EndPosition = Offset + *ReadSize;
+ if (EndPosition > FHand->SourceSize) {
+ *ReadSize = (UINT32)(FHand->SourceSize - Offset);
+ }
+ if (Offset >= FHand->SourceSize) {
+ *ReadSize = 0;
+ }
+
+ CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreDevicePathToInterface (
+ IN EFI_GUID *Protocol,
+ IN EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT VOID **Interface,
+ OUT EFI_HANDLE *Handle
+ )
+/*++
+
+Routine Description:
+
+ Search a handle to a device on a specified device path that supports a specified protocol,
+ interface of that protocol on that handle is another output.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ FilePath - The specified device path
+
+ Interface - Interface of the protocol on the handle
+
+ Handle - The handle to the device on the specified device path that supports the protocol.
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = CoreLocateDevicePath (Protocol, FilePath, Handle);
+ if (!EFI_ERROR (Status)) {
+ Status = CoreHandleProtocol (*Handle, Protocol, Interface);
+ }
+ return Status;
+}
+
+
+VOID
+CoreDevicePathToFileName (
+ IN FILEPATH_DEVICE_PATH *FilePath,
+ OUT CHAR16 **String
+ )
+/*++
+
+Routine Description:
+
+ Transfer a device's full path a string.
+
+Arguments:
+
+ FilePath - Device path
+
+ String - The string represent the device's full path
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN StringSize;
+ FILEPATH_DEVICE_PATH *FilePathNode;
+ CHAR16 *Str;
+
+ *String = NULL;
+ StringSize = 0;
+ FilePathNode = FilePath;
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {
+
+ //
+ // For filesystem access each node should be a filepath component
+ //
+ if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
+
+ return;
+ }
+
+ StringSize += StrLen (FilePathNode->PathName);
+
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
+ }
+
+ *String = CoreAllocateBootServicesPool (StringSize);
+ if (*String == NULL) {
+ return;
+ }
+
+ FilePathNode = FilePath;
+ Str = *String;
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {
+ StrCat (Str, FilePathNode->PathName);
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
+ }
+}
+
+
+BOOLEAN
+CoreGrowBuffer (
+ IN OUT EFI_STATUS *Status,
+ IN OUT VOID **Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Helper function called as part of the code needed
+ to allocate the proper sized buffer for various
+ EFI interfaces.
+
+Arguments:
+
+ Status - Current status
+
+ Buffer - Current allocated buffer, or NULL
+
+ BufferSize - Current buffer size needed
+
+Returns:
+
+ TRUE - if the buffer was reallocated and the caller
+ should try the API again.
+
+ FALSE - buffer could not be allocated and the caller
+ should not try the API again.
+
+--*/
+{
+ BOOLEAN TryAgain;
+
+ TryAgain = FALSE;
+ //
+ // If this is an initial request, buffer will be null with a new buffer size
+ //
+ if (*Buffer == NULL) {
+ *Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (BufferSize == 0) {
+ return TRUE;
+ }
+
+ //
+ // If the status code is "buffer too small", resize the buffer
+ //
+
+ if (*Status == EFI_BUFFER_TOO_SMALL) {
+ if (*Buffer != NULL) {
+ CoreFreePool (*Buffer);
+ }
+
+ *Buffer = CoreAllocateBootServicesPool (BufferSize);
+ if (*Buffer != NULL) {
+ TryAgain = TRUE;
+ } else {
+ *Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // If there's an error, free the buffer
+ //
+ if ((!TryAgain) && (EFI_ERROR (*Status)) && (*Buffer)) {
+ CoreFreePool (*Buffer);
+ *Buffer = NULL;
+ }
+
+ return TryAgain;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/Library.h b/EdkModulePkg/Core/Dxe/Library.h
new file mode 100644
index 0000000000..5e33da5285
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Library.h
@@ -0,0 +1,407 @@
+/*++
+
+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:
+
+ Library.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _DXE_LIBRARY_H_
+#define _DXE_LIBRARY_H_
+
+
+VOID
+CoreReportProgressCode (
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreReportProgressCodeSpecific (
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid,
+ with a handle as additional information.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+ Handle - Additional information.
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreAcquireLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Raising to the task priority level of the mutual exclusion
+ lock, and then acquires ownership of the lock.
+
+Arguments:
+
+ Lock - The lock to acquire
+
+Returns:
+
+ Lock owned
+
+--*/
+;
+
+EFI_STATUS
+CoreAcquireLockOrFail (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Initialize a basic mutual exclusion lock. Each lock
+ provides mutual exclusion access at it's task priority
+ level. Since there is no-premption (at any TPL) or
+ multiprocessor support, acquiring the lock only consists
+ of raising to the locks TPL.
+
+Arguments:
+
+ Lock - The EFI_LOCK structure to initialize
+
+Returns:
+
+ EFI_SUCCESS - Lock Owned.
+ EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned.
+
+--*/
+;
+
+VOID
+CoreReleaseLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Releases ownership of the mutual exclusion lock, and
+ restores the previous task priority level.
+
+Arguments:
+
+ Lock - The lock to release
+
+Returns:
+
+ Lock unowned
+
+--*/
+;
+
+//
+// Device Path functions
+//
+
+UINTN
+CoreDevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+
+ Calculate the size of a whole device path.
+
+Arguments:
+
+ DevicePath - The pointer to the device path data.
+
+Returns:
+
+ Size of device path data structure..
+
+--*/
+;
+
+BOOLEAN
+CoreIsDevicePathMultiInstance (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Return TRUE is this is a multi instance device path.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+
+Returns:
+ TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
+ instance.
+
+--*/
+;
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreDuplicateDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Duplicate a new device path data structure from the old one.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+Returns:
+ A pointer to the new allocated device path data.
+ Caller must free the memory used by DevicePath if it is no longer needed.
+
+--*/
+;
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreAppendDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *Src1,
+ IN EFI_DEVICE_PATH_PROTOCOL *Node
+ )
+/*++
+
+Routine Description:
+ Function is used to append a Src1 and Src2 together.
+
+Arguments:
+ Src1 - A pointer to a device path data structure.
+
+ Node - A pointer to a device path data structure.
+
+Returns:
+
+ A pointer to the new device path is returned.
+ NULL is returned if space for the new device path could not be allocated from pool.
+ It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
+
+--*/
+;
+
+VOID *
+CoreAllocateBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+VOID *
+CoreAllocateZeroBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetConfigTable (
+ IN EFI_GUID *Guid,
+ IN OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+
+ Find a config table by name in system table's ConfigurationTable.
+
+Arguments:
+
+ Guid - The table name to look for
+
+ Table - Pointer of the config table
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable.
+
+ EFI_SUCCESS - Table successfully found.
+
+--*/
+;
+
+VOID *
+CoreAllocateRuntimeCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+VOID *
+CoreAllocateRuntimePool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+VOID *
+CoreAllocateCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+EFI_EVENT
+CoreCreateProtocolNotifyEvent (
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT VOID **Registration,
+ IN BOOLEAN SignalFlag
+ )
+/*++
+
+Routine Description:
+
+ Create a protocol notification event and return it.
+
+Arguments:
+
+ ProtocolGuid - Protocol to register notification event on.
+
+ NotifyTpl - Maximum TPL to signal the NotifyFunction.
+
+ NotifyFuncition - EFI notification routine.
+
+ NotifyContext - Context passed into Event when it is created.
+
+ Registration - Registration key returned from RegisterProtocolNotify().
+
+ SignalFlag - Boolean value to decide whether kick the event after register or not.
+
+Returns:
+
+ The EFI_EVENT that has been registered to be signaled when a ProtocolGuid
+ is added to the system.
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Core/Dxe/Library/Library.c b/EdkModulePkg/Core/Dxe/Library/Library.c
new file mode 100644
index 0000000000..74d873e3f8
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Library/Library.c
@@ -0,0 +1,613 @@
+/*++
+
+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:
+
+ Library.c
+
+Abstract:
+
+ DXE Core library services.
+
+--*/
+
+#include <DxeMain.h>
+
+UINTN mErrorLevel = EFI_D_ERROR | EFI_D_LOAD;
+
+EFI_DEVICE_HANDLE_EXTENDED_DATA mStatusCodeData = {
+ {
+ sizeof (EFI_STATUS_CODE_DATA),
+ 0,
+ EFI_STATUS_CODE_SPECIFIC_DATA_GUID
+ },
+ NULL
+};
+
+VOID
+CoreReportProgressCodeSpecific (
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid,
+ with a handle as additional information.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+ Handle - Additional information.
+
+Returns:
+
+ None
+
+--*/
+{
+ mStatusCodeData.DataHeader.Size = sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA);
+ mStatusCodeData.Handle = Handle;
+
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ EFI_PROGRESS_CODE,
+ Value,
+ 0,
+ &gEfiDxeServicesTableGuid,
+ (EFI_STATUS_CODE_DATA *) &mStatusCodeData
+ );
+ }
+}
+
+VOID
+CoreReportProgressCode (
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+Returns:
+
+ None
+
+--*/
+{
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ EFI_PROGRESS_CODE,
+ Value,
+ 0,
+ &gEfiDxeServicesTableGuid,
+ NULL
+ );
+ }
+}
+
+
+VOID *
+CoreAllocateBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ CoreAllocatePool (EfiBootServicesData, AllocationSize, &Memory);
+ return Memory;
+}
+
+
+VOID *
+CoreAllocateZeroBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ Memory = CoreAllocateBootServicesPool (AllocationSize);
+ SetMem (Memory, (Memory == NULL) ? 0 : AllocationSize, 0);
+ return Memory;
+}
+
+
+VOID *
+CoreAllocateCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ Memory = CoreAllocateBootServicesPool (AllocationSize);
+ CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);
+
+ return Memory;
+}
+
+
+
+VOID *
+CoreAllocateRuntimePool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ CoreAllocatePool (EfiRuntimeServicesData, AllocationSize, &Memory);
+ return Memory;
+}
+
+VOID *
+CoreAllocateRuntimeCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+
+{
+ VOID *Memory;
+
+ Memory = CoreAllocateRuntimePool (AllocationSize);
+ CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);
+
+ return Memory;
+}
+
+
+
+//
+// Lock Stuff
+//
+
+
+
+EFI_STATUS
+CoreAcquireLockOrFail (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Initialize a basic mutual exclusion lock. Each lock
+ provides mutual exclusion access at it's task priority
+ level. Since there is no-premption (at any TPL) or
+ multiprocessor support, acquiring the lock only consists
+ of raising to the locks TPL.
+
+Arguments:
+
+ Lock - The EFI_LOCK structure to initialize
+
+Returns:
+
+ EFI_SUCCESS - Lock Owned.
+ EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned.
+
+--*/
+{
+ ASSERT (Lock != NULL);
+ ASSERT (Lock->Lock != EfiLockUninitialized);
+
+ if (Lock->Lock == EfiLockAcquired) {
+ //
+ // Lock is already owned, so bail out
+ //
+ return EFI_ACCESS_DENIED;
+ }
+
+ Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);
+
+ Lock->Lock = EfiLockAcquired;
+ return EFI_SUCCESS;
+}
+
+
+VOID
+CoreAcquireLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Raising to the task priority level of the mutual exclusion
+ lock, and then acquires ownership of the lock.
+
+Arguments:
+
+ Lock - The lock to acquire
+
+Returns:
+
+ Lock owned
+
+--*/
+{
+ ASSERT (Lock != NULL);
+ ASSERT (Lock->Lock == EfiLockReleased);
+
+ Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);
+ Lock->Lock = EfiLockAcquired;
+}
+
+
+VOID
+CoreReleaseLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Releases ownership of the mutual exclusion lock, and
+ restores the previous task priority level.
+
+Arguments:
+
+ Lock - The lock to release
+
+Returns:
+
+ Lock unowned
+
+--*/
+{
+ EFI_TPL Tpl;
+
+ ASSERT (Lock != NULL);
+ ASSERT (Lock->Lock == EfiLockAcquired);
+
+ Tpl = Lock->OwnerTpl;
+
+ Lock->Lock = EfiLockReleased;
+
+ CoreRestoreTpl (Tpl);
+}
+
+
+UINTN
+CoreDevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+
+ Calculate the size of a whole device path.
+
+Arguments:
+
+ DevicePath - The pointer to the device path data.
+
+Returns:
+
+ Size of device path data structure..
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *Start;
+
+ if (DevicePath == NULL) {
+ return 0;
+ }
+
+ //
+ // Search for the end of the device path structure
+ //
+ Start = DevicePath;
+ while (!EfiIsDevicePathEnd (DevicePath)) {
+ DevicePath = EfiNextDevicePathNode (DevicePath);
+ }
+
+ //
+ // Compute the size and add back in the size of the end device path structure
+ //
+ return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL);
+}
+
+
+BOOLEAN
+CoreIsDevicePathMultiInstance (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Return TRUE is this is a multi instance device path.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+
+Returns:
+ TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
+ instance.
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+
+ if (DevicePath == NULL) {
+ return FALSE;
+ }
+
+ Node = DevicePath;
+ while (!EfiIsDevicePathEnd (Node)) {
+ if (EfiIsDevicePathEndInstance (Node)) {
+ return TRUE;
+ }
+ Node = EfiNextDevicePathNode (Node);
+ }
+ return FALSE;
+}
+
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreDuplicateDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Duplicate a new device path data structure from the old one.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+Returns:
+ A pointer to the new allocated device path data.
+ Caller must free the memory used by DevicePath if it is no longer needed.
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ UINTN Size;
+
+ if (DevicePath == NULL) {
+ return NULL;
+ }
+
+ //
+ // Compute the size
+ //
+ Size = CoreDevicePathSize (DevicePath);
+
+ //
+ // Allocate space for duplicate device path
+ //
+ NewDevicePath = CoreAllocateCopyPool (Size, DevicePath);
+
+ return NewDevicePath;
+}
+
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreAppendDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *Src1,
+ IN EFI_DEVICE_PATH_PROTOCOL *Src2
+ )
+/*++
+
+Routine Description:
+ Function is used to append a Src1 and Src2 together.
+
+Arguments:
+ Src1 - A pointer to a device path data structure.
+
+ Src2 - A pointer to a device path data structure.
+
+Returns:
+
+ A pointer to the new device path is returned.
+ NULL is returned if space for the new device path could not be allocated from pool.
+ It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
+
+--*/
+{
+ UINTN Size;
+ UINTN Size1;
+ UINTN Size2;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath;
+
+ if (Src1 == NULL && Src2 == NULL) {
+ return NULL;
+ }
+
+ //
+ // Allocate space for the combined device path. It only has one end node of
+ // length EFI_DEVICE_PATH_PROTOCOL
+ //
+ Size1 = CoreDevicePathSize (Src1);
+ Size2 = CoreDevicePathSize (Src2);
+ Size = Size1 + Size2 - sizeof(EFI_DEVICE_PATH_PROTOCOL);
+
+ NewDevicePath = CoreAllocateCopyPool (Size, Src1);
+ if (NewDevicePath != NULL) {
+
+ //
+ // Over write Src1 EndNode and do the copy
+ //
+ SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath + (Size1 - sizeof(EFI_DEVICE_PATH_PROTOCOL)));
+ CopyMem (SecondDevicePath, Src2, Size2);
+ }
+
+ return NewDevicePath;
+}
+
+
+
+EFI_EVENT
+CoreCreateProtocolNotifyEvent (
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT VOID **Registration,
+ IN BOOLEAN SignalFlag
+ )
+/*++
+
+Routine Description:
+
+ Create a protocol notification event and return it.
+
+Arguments:
+
+ ProtocolGuid - Protocol to register notification event on.
+
+ NotifyTpl - Maximum TPL to signal the NotifyFunction.
+
+ NotifyFuncition - EFI notification routine.
+
+ NotifyContext - Context passed into Event when it is created.
+
+ Registration - Registration key returned from RegisterProtocolNotify().
+
+ SignalFlag - Boolean value to decide whether kick the event after register or not.
+
+Returns:
+
+ The EFI_EVENT that has been registered to be signaled when a ProtocolGuid
+ is added to the system.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ //
+ // Create the event
+ //
+
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ NotifyTpl,
+ NotifyFunction,
+ NotifyContext,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for protocol notifactions on this event
+ //
+
+ Status = CoreRegisterProtocolNotify (
+ ProtocolGuid,
+ Event,
+ Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (SignalFlag) {
+ //
+ // Kick the event so we will perform an initial pass of
+ // current installed drivers
+ //
+ CoreSignalEvent (Event);
+ }
+
+ return Event;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/Mem/Page.c b/EdkModulePkg/Core/Dxe/Mem/Page.c
new file mode 100644
index 0000000000..e65b0283c6
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Mem/Page.c
@@ -0,0 +1,1589 @@
+/*++
+
+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:
+
+ page.c
+
+Abstract:
+
+ EFI Memory page management
+
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE)
+
+//
+// Entry for tracking the memory regions for each memory type to help cooalese like memory types
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_PHYSICAL_ADDRESS MaximumAddress;
+ UINT64 CurrentNumberOfPages;
+ UINTN InformationIndex;
+} EFI_MEMORY_TYPE_STAISTICS;
+
+//
+// MemoryMap - The current memory map
+//
+UINTN mMemoryMapKey = 0;
+
+//
+// mMapStack - space to use as temp storage to build new map descriptors
+// mMapDepth - depth of new descriptor stack
+//
+
+#define MAX_MAP_DEPTH 6
+UINTN mMapDepth = 0;
+MEMORY_MAP mMapStack[MAX_MAP_DEPTH];
+UINTN mFreeMapStack = 0;
+
+BOOLEAN mMemoryTypeInformationInitialized = FALSE;
+
+EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiReservedMemoryType
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiLoaderCode
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiLoaderData
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiBootServicesCode
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiBootServicesData
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiRuntimeServicesCode
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiRuntimeServicesData
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiConventionalMemory
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiUnusableMemory
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiACPIReclaimMemory
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiACPIMemoryNVS
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiMemoryMappedIO
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiMemoryMappedIOPortSpace
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiPalCode
+ { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType } // EfiMaxMemoryType
+};
+
+EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = EFI_MAX_ADDRESS;
+
+EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
+ { EfiReservedMemoryType, 0 },
+ { EfiLoaderCode, 0 },
+ { EfiLoaderData, 0 },
+ { EfiBootServicesCode, 0 },
+ { EfiBootServicesData, 0 },
+ { EfiRuntimeServicesCode, 0 },
+ { EfiRuntimeServicesData, 0 },
+ { EfiConventionalMemory, 0 },
+ { EfiUnusableMemory, 0 },
+ { EfiACPIReclaimMemory, 0 },
+ { EfiACPIMemoryNVS, 0 },
+ { EfiMemoryMappedIO, 0 },
+ { EfiMemoryMappedIOPortSpace, 0 },
+ { EfiPalCode, 0 },
+ { EfiMaxMemoryType, 0 }
+};
+
+//
+// Internal prototypes
+//
+VOID
+PromoteMemoryResource (
+ VOID
+);
+
+STATIC
+VOID
+CoreAddRange (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End,
+ IN UINT64 Attribute
+ );
+
+STATIC
+VOID
+CoreFreeMemoryMapStack (
+ VOID
+ );
+
+STATIC
+EFI_STATUS
+CoreConvertPages (
+ IN UINT64 Start,
+ IN UINT64 NumberOfPages,
+ IN EFI_MEMORY_TYPE NewType
+ );
+
+STATIC
+VOID
+RemoveMemoryMapEntry (
+ MEMORY_MAP *Entry
+ );
+
+VOID
+CoreAcquireMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by gaining lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreAcquireLock (&gMemoryLock);
+}
+
+
+VOID
+CoreReleaseMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&gMemoryLock);
+}
+
+VOID
+PromoteMemoryResource (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "Promote the memory resource\n"));
+
+ CoreAcquireGcdMemoryLock ();
+
+ Link = mGcdMemorySpaceMap.ForwardLink;
+ while (Link != &mGcdMemorySpaceMap) {
+
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ if (Entry->GcdMemoryType == EfiGcdMemoryTypeReserved &&
+ Entry->EndAddress < EFI_MAX_ADDRESS &&
+ (Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
+ (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) {
+ //
+ // Update the GCD map
+ //
+ Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
+ Entry->Capabilities |= EFI_MEMORY_TESTED;
+ Entry->ImageHandle = gDxeCoreImageHandle;
+ Entry->DeviceHandle = NULL;
+
+ //
+ // Add to allocable system memory resource
+ //
+
+ CoreAddRange (
+ EfiConventionalMemory,
+ Entry->BaseAddress,
+ Entry->EndAddress,
+ Entry->Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)
+ );
+ CoreFreeMemoryMapStack ();
+
+ }
+
+ Link = Link->ForwardLink;
+ }
+
+ CoreReleaseGcdMemoryLock ();
+
+ return;
+}
+
+VOID
+CoreAddMemoryDescriptor (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 NumberOfPages,
+ IN UINT64 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the memory map and add descriptors to
+ the current descriptor list.
+
+ The first descriptor that is added must be general usable
+ memory as the addition allocates heap.
+
+Arguments:
+
+ Type - The type of memory to add
+
+ Start - The starting address in the memory range
+ Must be page aligned
+
+ NumberOfPages - The number of pages in the range
+
+ Attribute - Attributes of the memory to add
+
+Returns:
+
+ None. The range is added to the memory map
+
+--*/
+{
+ EFI_PHYSICAL_ADDRESS End;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN FreeIndex;
+
+ if ((Start & EFI_PAGE_MASK) != 0) {
+ return;
+ }
+
+ if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) {
+ return;
+ }
+
+ CoreAcquireMemoryLock ();
+ End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
+ CoreAddRange (Type, Start, End, Attribute);
+ CoreFreeMemoryMapStack ();
+ CoreReleaseMemoryLock ();
+
+ //
+ // Check to see if the statistics for the different memory types have already been established
+ //
+ if (mMemoryTypeInformationInitialized) {
+ return;
+ }
+
+ //
+ // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
+ //
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = gMemoryTypeInformation[Index].Type;
+ if (Type < 0 || Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
+ //
+ // Allocate pages for the current memory type from the top of available memory
+ //
+ Status = CoreAllocatePages (
+ AllocateAnyPages,
+ Type,
+ gMemoryTypeInformation[Index].NumberOfPages,
+ &mMemoryTypeStatistics[Type].BaseAddress
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If an error occurs allocating the pages for the current memory type, then
+ // free all the pages allocates for the previous memory types and return. This
+ // operation with be retied when/if more memory is added to the system
+ //
+ for (FreeIndex = 0; FreeIndex < Index; FreeIndex++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = gMemoryTypeInformation[FreeIndex].Type;
+ if (Type < 0 || Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ if (gMemoryTypeInformation[FreeIndex].NumberOfPages != 0) {
+ CoreFreePages (
+ mMemoryTypeStatistics[Type].BaseAddress,
+ gMemoryTypeInformation[FreeIndex].NumberOfPages
+ );
+ mMemoryTypeStatistics[Type].BaseAddress = 0;
+ mMemoryTypeStatistics[Type].MaximumAddress = EFI_MAX_ADDRESS;
+ }
+ }
+ return;
+ }
+
+ //
+ // Compute the address at the top of the current statistics
+ //
+ mMemoryTypeStatistics[Type].MaximumAddress =
+ mMemoryTypeStatistics[Type].BaseAddress +
+ LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT) - 1;
+
+ //
+ // If the current base address is the lowest address so far, then update the default
+ // maximum address
+ //
+ if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) {
+ mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1;
+ }
+ }
+ }
+
+ //
+ // There was enough system memory for all the the memory types were allocated. So,
+ // those memory areas can be freed for future allocations, and all future memory
+ // allocations can occur within their respective bins
+ //
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = gMemoryTypeInformation[Index].Type;
+ if (Type < 0 || Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
+ CoreFreePages (
+ mMemoryTypeStatistics[Type].BaseAddress,
+ gMemoryTypeInformation[Index].NumberOfPages
+ );
+ gMemoryTypeInformation[Index].NumberOfPages = 0;
+ }
+ }
+
+ //
+ // If the number of pages reserved for a memory type is 0, then all allocations for that type
+ // should be in the default range.
+ //
+ for (Type = 0; Type < EfiMaxMemoryType; Type++) {
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) {
+ mMemoryTypeStatistics[Type].InformationIndex = Index;
+ }
+ }
+ mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0;
+ if (mMemoryTypeStatistics[Type].MaximumAddress == EFI_MAX_ADDRESS) {
+ mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress;
+ }
+ }
+
+ mMemoryTypeInformationInitialized = TRUE;
+}
+
+
+STATIC
+VOID
+CoreAddRange (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End,
+ IN UINT64 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Adds a ranges to the memory map.
+ The range must not already exist in the map.
+
+Arguments:
+
+ Type - The type of memory range to add
+
+ Start - The starting address in the memory range
+ Must be paged aligned
+
+ End - The last address in the range
+ Must be the last byte of a page
+
+ Attribute - The attributes of the memory range to add
+
+Returns:
+
+ None. The range is added to the memory map
+
+--*/
+{
+ LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+
+ ASSERT ((Start & EFI_PAGE_MASK) == 0);
+ ASSERT (End > Start) ;
+
+ ASSERT_LOCKED (&gMemoryLock);
+
+ DEBUG ((EFI_D_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type));
+
+ //
+ // Memory map being altered so updated key
+ //
+ mMemoryMapKey += 1;
+
+ //
+ // UEFI 2.0 added an event group for notificaiton on memory map changes.
+ // So we need to signal this Event Group every time the memory map changes.
+ // If we are in EFI 1.10 compatability mode no event groups will be
+ // found and nothing will happen we we call this function. These events
+ // will get signaled but since a lock is held around the call to this
+ // function the notificaiton events will only be called after this funciton
+ // returns and the lock is released.
+ //
+ CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid);
+
+ //
+ // Look for adjoining memory descriptor
+ //
+
+ // Two memory descriptors can only be merged if they have the same Type
+ // and the same Attribute
+ //
+
+ Link = gMemoryMap.ForwardLink;
+ while (Link != &gMemoryMap) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ Link = Link->ForwardLink;
+
+ if (Entry->Type != Type) {
+ continue;
+ }
+
+ if (Entry->Attribute != Attribute) {
+ continue;
+ }
+
+ if (Entry->End + 1 == Start) {
+
+ Start = Entry->Start;
+ RemoveMemoryMapEntry (Entry);
+
+ } else if (Entry->Start == End + 1) {
+
+ End = Entry->End;
+ RemoveMemoryMapEntry (Entry);
+ }
+ }
+
+ //
+ // Add descriptor
+ //
+
+ mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
+ mMapStack[mMapDepth].FromPool = FALSE;
+ mMapStack[mMapDepth].Type = Type;
+ mMapStack[mMapDepth].Start = Start;
+ mMapStack[mMapDepth].End = End;
+ mMapStack[mMapDepth].VirtualStart = 0;
+ mMapStack[mMapDepth].Attribute = Attribute;
+ InsertTailList (&gMemoryMap, &mMapStack[mMapDepth].Link);
+
+ mMapDepth += 1;
+ ASSERT (mMapDepth < MAX_MAP_DEPTH);
+
+ return ;
+}
+
+STATIC
+VOID
+CoreFreeMemoryMapStack (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Moves any memory descriptors that are on the
+ temporary descriptor stack to heap.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ MEMORY_MAP *Entry;
+ MEMORY_MAP *Entry2;
+ LIST_ENTRY *Link2;
+
+ ASSERT_LOCKED (&gMemoryLock);
+
+ //
+ // If already freeing the map stack, then return
+ //
+ if (mFreeMapStack) {
+ return ;
+ }
+
+ //
+ // Move the temporary memory descriptor stack into pool
+ //
+ mFreeMapStack += 1;
+
+ while (mMapDepth) {
+
+ //
+ // Allocate memory for a entry
+ //
+ Entry = CoreAllocatePoolI (EfiRuntimeServicesData, sizeof(MEMORY_MAP));
+
+ ASSERT (Entry);
+
+ //
+ // Update to proper entry
+ //
+ mMapDepth -= 1;
+
+ if (mMapStack[mMapDepth].Link.ForwardLink != NULL) {
+
+ //
+ // Move this entry to general pool
+ //
+ RemoveEntryList (&mMapStack[mMapDepth].Link);
+ mMapStack[mMapDepth].Link.ForwardLink = NULL;
+
+ CopyMem (Entry , &mMapStack[mMapDepth], sizeof (MEMORY_MAP));
+ Entry->FromPool = TRUE;
+
+ //
+ // Find insertion location
+ //
+ for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) {
+ Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ if (Entry2->FromPool && Entry2->Start > Entry->Start) {
+ break;
+ }
+ }
+
+ InsertTailList (Link2, &Entry->Link);
+
+ } else {
+
+ //
+ // It was removed, don't move it
+ //
+ CoreFreePoolI (Entry);
+
+ }
+ }
+
+ mFreeMapStack -= 1;
+}
+
+STATIC
+VOID
+RemoveMemoryMapEntry (
+ MEMORY_MAP *Entry
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Removes a descriptor entry.
+
+Arguments:
+
+ Entry - The entry to remove
+
+Returns:
+
+ None
+
+--*/
+{
+ RemoveEntryList (&Entry->Link);
+ Entry->Link.ForwardLink = NULL;
+
+ if (Entry->FromPool) {
+ CoreFreePoolI (Entry);
+ }
+}
+
+
+STATIC
+EFI_STATUS
+CoreConvertPages (
+ IN UINT64 Start,
+ IN UINT64 NumberOfPages,
+ IN EFI_MEMORY_TYPE NewType
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Converts a memory range to the specified type.
+ The range must exist in the memory map.
+
+Arguments:
+
+ Start - The first address of the range
+ Must be page aligned
+
+ NumberOfPages - The number of pages to convert
+
+ NewType - The new type for the memory range
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_NOT_FOUND - Could not find a descriptor cover the specified range
+ or convertion not allowed.
+
+ EFI_SUCCESS - Successfully converts the memory range to the specified type.
+
+--*/
+{
+
+ UINT64 NumberOfBytes;
+ UINT64 End;
+ UINT64 RangeEnd;
+ UINT64 Attribute;
+ LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+
+ Entry = NULL;
+ NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
+ End = Start + NumberOfBytes - 1;
+
+ ASSERT (NumberOfPages);
+ ASSERT ((Start & EFI_PAGE_MASK) == 0);
+ ASSERT (End > Start) ;
+ ASSERT_LOCKED (&gMemoryLock);
+
+ if (NumberOfPages == 0 || (Start & EFI_PAGE_MASK ) || (Start > (Start + NumberOfBytes))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Convert the entire range
+ //
+
+ while (Start < End) {
+
+ //
+ // Find the entry that the covers the range
+ //
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+
+ if (Entry->Start <= Start && Entry->End > Start) {
+ break;
+ }
+ }
+
+ if (Link == &gMemoryMap) {
+ DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "ConvertPages: failed to find range %lx - %lx\n", Start, End));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Convert range to the end, or to the end of the descriptor
+ // if that's all we've got
+ //
+ RangeEnd = End;
+ if (Entry->End < End) {
+ RangeEnd = Entry->End;
+ }
+
+ DEBUG ((EFI_D_PAGE, "ConvertRange: %lx-%lx to %d\n", Start, RangeEnd, NewType));
+
+ //
+ // Debug code - verify conversion is allowed
+ //
+ if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) {
+ DEBUG ((EFI_D_ERROR , "ConvertPages: Incompatible memory types\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Update counters for the number of pages allocated to each memory type
+ //
+ if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {
+ if (Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress &&
+ Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) {
+ if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {
+ mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;
+ } else {
+ mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfPages;
+ }
+ }
+ }
+
+ if (NewType >= 0 && NewType < EfiMaxMemoryType) {
+ if (Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) {
+ mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;
+ if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages >
+ gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {
+ gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;
+ }
+ }
+ }
+
+ //
+ // Pull range out of descriptor
+ //
+ if (Entry->Start == Start) {
+
+ //
+ // Clip start
+ //
+ Entry->Start = RangeEnd + 1;
+
+ } else if (Entry->End == RangeEnd) {
+
+ //
+ // Clip end
+ //
+ Entry->End = Start - 1;
+
+ } else {
+
+ //
+ // Pull it out of the center, clip current
+ //
+
+ //
+ // Add a new one
+ //
+ mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
+ mMapStack[mMapDepth].FromPool = FALSE;
+ mMapStack[mMapDepth].Type = Entry->Type;
+ mMapStack[mMapDepth].Start = RangeEnd+1;
+ mMapStack[mMapDepth].End = Entry->End;
+
+ //
+ // Inherit Attribute from the Memory Descriptor that is being clipped
+ //
+ mMapStack[mMapDepth].Attribute = Entry->Attribute;
+
+ Entry->End = Start - 1;
+ ASSERT (Entry->Start < Entry->End);
+
+ Entry = &mMapStack[mMapDepth];
+ InsertTailList (&gMemoryMap, &Entry->Link);
+
+ mMapDepth += 1;
+ ASSERT (mMapDepth < MAX_MAP_DEPTH);
+ }
+
+ //
+ // The new range inherits the same Attribute as the Entry
+ //it is being cut out of
+ //
+ Attribute = Entry->Attribute;
+
+ //
+ // If the descriptor is empty, then remove it from the map
+ //
+ if (Entry->Start == Entry->End + 1) {
+ RemoveMemoryMapEntry (Entry);
+ Entry = NULL;
+ }
+
+ //
+ // Add our new range in
+ //
+ CoreAddRange (NewType, Start, RangeEnd, Attribute);
+
+ //
+ // Move any map descriptor stack to general pool
+ //
+ CoreFreeMemoryMapStack ();
+
+ //
+ // Bump the starting address, and convert the next range
+ //
+ Start = RangeEnd + 1;
+ }
+
+ //
+ // Converted the whole range, done
+ //
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+UINT64
+CoreFindFreePagesI (
+ IN UINT64 MaxAddress,
+ IN UINT64 NumberOfPages,
+ IN EFI_MEMORY_TYPE NewType,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Finds a consecutive free page range below
+ the requested address.
+
+Arguments:
+
+ MaxAddress - The address that the range must be below
+
+ NumberOfPages - Number of pages needed
+
+ NewType - The type of memory the range is going to be turned into
+
+ Alignment - Bits to align with
+
+Returns:
+
+ The base address of the range, or 0 if the range was not found
+
+--*/
+{
+ UINT64 NumberOfBytes;
+ UINT64 Target;
+ UINT64 DescStart;
+ UINT64 DescEnd;
+ UINT64 DescNumberOfBytes;
+ LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+
+ if ((MaxAddress < EFI_PAGE_MASK) ||(NumberOfPages == 0)) {
+ return 0;
+ }
+
+ if ((MaxAddress & EFI_PAGE_MASK) != EFI_PAGE_MASK) {
+
+ //
+ // If MaxAddress is not aligned to the end of a page
+ //
+
+ //
+ // Change MaxAddress to be 1 page lower
+ //
+ MaxAddress -= (EFI_PAGE_MASK + 1);
+
+ //
+ // Set MaxAddress to a page boundary
+ //
+ MaxAddress &= ~EFI_PAGE_MASK;
+
+ //
+ // Set MaxAddress to end of the page
+ //
+ MaxAddress |= EFI_PAGE_MASK;
+ }
+
+ NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
+ Target = 0;
+
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+
+ //
+ // If it's not a free entry, don't bother with it
+ //
+ if (Entry->Type != EfiConventionalMemory) {
+ continue;
+ }
+
+ DescStart = Entry->Start;
+ DescEnd = Entry->End;
+
+ //
+ // If desc is past max allowed address, skip it
+ //
+ if (DescStart >= MaxAddress) {
+ continue;
+ }
+
+ //
+ // If desc ends past max allowed address, clip the end
+ //
+ if (DescEnd >= MaxAddress) {
+ DescEnd = MaxAddress;
+ }
+
+ DescEnd = ((DescEnd + 1) & (~(Alignment - 1))) - 1;
+
+ //
+ // Compute the number of bytes we can used from this
+ // descriptor, and see it's enough to satisfy the request
+ //
+ DescNumberOfBytes = DescEnd - DescStart + 1;
+
+ if (DescNumberOfBytes >= NumberOfBytes) {
+
+ //
+ // If this is the best match so far remember it
+ //
+ if (DescEnd > Target) {
+ Target = DescEnd;
+ }
+ }
+ }
+
+ //
+ // If this is a grow down, adjust target to be the allocation base
+ //
+ Target -= NumberOfBytes - 1;
+
+ //
+ // If we didn't find a match, return 0
+ //
+ if ((Target & EFI_PAGE_MASK) != 0) {
+ return 0;
+ }
+
+ return Target;
+}
+
+STATIC
+UINT64
+FindFreePages (
+ IN UINT64 MaxAddress,
+ IN UINT64 NoPages,
+ IN EFI_MEMORY_TYPE NewType,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Finds a consecutive free page range below
+ the requested address
+
+Arguments:
+
+ MaxAddress - The address that the range must be below
+
+ NoPages - Number of pages needed
+
+ NewType - The type of memory the range is going to be turned into
+
+ Alignment - Bits to align with
+
+Returns:
+
+ The base address of the range, or 0 if the range was not found.
+
+--*/
+{
+ UINT64 NewMaxAddress;
+ UINT64 Start;
+
+ NewMaxAddress = MaxAddress;
+
+ if (NewType >= 0 && NewType < EfiMaxMemoryType && NewMaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {
+ NewMaxAddress = mMemoryTypeStatistics[NewType].MaximumAddress;
+ } else {
+ if (NewMaxAddress > mDefaultMaximumAddress) {
+ NewMaxAddress = mDefaultMaximumAddress;
+ }
+ }
+
+ Start = CoreFindFreePagesI (NewMaxAddress, NoPages, NewType, Alignment);
+ if (!Start) {
+ Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
+ if (!Start) {
+ //
+ // Here means there may be no enough memory to use, so try to go through
+ // all the memory descript to promote the untested memory directly
+ //
+ PromoteMemoryResource ();
+
+ //
+ // Allocate memory again after the memory resource re-arranged
+ //
+ Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
+ }
+ }
+
+ return Start;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreAllocatePages (
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages from the memory map.
+
+Arguments:
+
+ Type - The type of allocation to perform
+
+ MemoryType - The type of memory to turn the allocated pages into
+
+ NumberOfPages - The number of pages to allocate
+
+ Memory - A pointer to receive the base allocated memory address
+
+Returns:
+
+ Status. On success, Memory is filled in with the base address allocated
+
+ EFI_INVALID_PARAMETER - Parameters violate checking rules defined in spec.
+
+ EFI_NOT_FOUND - Could not allocate pages match the requirement.
+
+ EFI_OUT_OF_RESOURCES - No enough pages to allocate.
+
+ EFI_SUCCESS - Pages successfully allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 Start;
+ UINT64 MaxAddress;
+ UINTN Alignment;
+
+ if (Type < AllocateAnyPages || Type >= (UINTN) MaxAllocateType) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MemoryType >= EfiMaxMemoryType && MemoryType <= 0x7fffffff) ||
+ MemoryType == EfiConventionalMemory) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
+
+ if (MemoryType == EfiACPIReclaimMemory ||
+ MemoryType == EfiACPIMemoryNVS ||
+ MemoryType == EfiRuntimeServicesCode ||
+ MemoryType == EfiRuntimeServicesData) {
+
+ Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
+ }
+
+ if (Type == AllocateAddress) {
+ if ((*Memory & (Alignment - 1)) != 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
+ NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
+
+ //
+ // If this is for below a particular address, then
+ //
+ Start = *Memory;
+
+ //
+ // The max address is the max natively addressable address for the processor
+ //
+ MaxAddress = EFI_MAX_ADDRESS;
+
+ if (Type == AllocateMaxAddress) {
+ MaxAddress = Start;
+ }
+
+ CoreAcquireMemoryLock ();
+
+ //
+ // If not a specific address, then find an address to allocate
+ //
+ if (Type != AllocateAddress) {
+ Start = FindFreePages (MaxAddress, NumberOfPages, MemoryType, Alignment);
+ if (Start == 0) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ }
+
+ //
+ // Convert pages from FreeMemory to the requested type
+ //
+ Status = CoreConvertPages (Start, NumberOfPages, MemoryType);
+
+Done:
+ CoreReleaseMemoryLock ();
+
+ if (!EFI_ERROR (Status)) {
+ *Memory = Start;
+ }
+
+ return Status;
+}
+
+
+
+
+EFI_STATUS
+EFIAPI
+CoreFreePages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Frees previous allocated pages.
+
+Arguments:
+
+ Memory - Base address of memory being freed
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the entry that covers the range
+
+ EFI_INVALID_PARAMETER - Address not aligned
+
+ EFI_SUCCESS -Pages successfully freed.
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+ UINTN Alignment;
+
+ //
+ // Free the range
+ //
+ CoreAcquireMemoryLock ();
+
+ //
+ // Find the entry that the covers the range
+ //
+ Entry = NULL;
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ if (Entry->Start <= Memory && Entry->End > Memory) {
+ break;
+ }
+ }
+ if (Link == &gMemoryMap) {
+ CoreReleaseMemoryLock ();
+ return EFI_NOT_FOUND;
+ }
+
+ Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
+
+ if (Entry->Type == EfiACPIReclaimMemory ||
+ Entry->Type == EfiACPIMemoryNVS ||
+ Entry->Type == EfiRuntimeServicesCode ||
+ Entry->Type == EfiRuntimeServicesData) {
+
+ Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
+
+ }
+
+ if ((Memory & (Alignment - 1)) != 0) {
+ CoreReleaseMemoryLock ();
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
+ NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
+
+ Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
+
+ CoreReleaseMemoryLock ();
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Destroy the contents
+ //
+ if (Memory < EFI_MAX_ADDRESS) {
+ DEBUG_CLEAR_MEMORY ((VOID *)(UINTN)Memory, NumberOfPages << EFI_PAGE_SHIFT);
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreGetMemoryMap (
+ IN OUT UINTN *MemoryMapSize,
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion
+ )
+/*++
+
+Routine Description:
+
+ This function returns a copy of the current memory map. The map is an array of
+ memory descriptors, each of which describes a contiguous block of memory.
+
+Arguments:
+
+ MemoryMapSize - A pointer to the size, in bytes, of the MemoryMap buffer. On
+ input, this is the size of the buffer allocated by the caller.
+ On output, it is the size of the buffer returned by the firmware
+ if the buffer was large enough, or the size of the buffer needed
+ to contain the map if the buffer was too small.
+ MemoryMap - A pointer to the buffer in which firmware places the current memory map.
+ MapKey - A pointer to the location in which firmware returns the key for the
+ current memory map.
+ DescriptorSize - A pointer to the location in which firmware returns the size, in
+ bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+ DescriptorVersion - A pointer to the location in which firmware returns the version
+ number associated with the EFI_MEMORY_DESCRIPTOR.
+
+Returns:
+
+ EFI_SUCCESS - The memory map was returned in the MemoryMap buffer.
+ EFI_BUFFER_TOO_SMALL - The MemoryMap buffer was too small. The current buffer size
+ needed to hold the memory map is returned in MemoryMapSize.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN BufferSize;
+ UINTN NumberOfRuntimeEntries;
+ LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+ EFI_GCD_MAP_ENTRY *GcdMapEntry;
+
+ //
+ // Make sure the parameters are valid
+ //
+ if (MemoryMapSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdMemoryLock ();
+
+ //
+ // Count the number of Reserved and MMIO entries that are marked for runtime use
+ //
+ NumberOfRuntimeEntries = 0;
+ for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
+ GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
+ (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
+ if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
+ NumberOfRuntimeEntries++;
+ }
+ }
+ }
+
+ Size = sizeof (EFI_MEMORY_DESCRIPTOR);
+
+ //
+ // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
+ // prevent people from having pointer math bugs in their code.
+ // now you have to use *DescriptorSize to make things work.
+ //
+ Size += sizeof(UINT64) - (Size % sizeof (UINT64));
+
+ if (DescriptorSize != NULL) {
+ *DescriptorSize = Size;
+ }
+
+ if (DescriptorVersion != NULL) {
+ *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
+ }
+
+ CoreAcquireMemoryLock ();
+
+ //
+ // Compute the buffer size needed to fit the entire map
+ //
+ BufferSize = Size * NumberOfRuntimeEntries;
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ BufferSize += Size;
+ }
+
+ if (*MemoryMapSize < BufferSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ if (MemoryMap == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Build the map
+ //
+ ZeroMem (MemoryMap, Size);
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ ASSERT (Entry->VirtualStart == 0);
+
+ MemoryMap->Type = Entry->Type;
+ MemoryMap->PhysicalStart = Entry->Start;
+ MemoryMap->VirtualStart = Entry->VirtualStart;
+ MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
+
+ switch (Entry->Type) {
+ case EfiRuntimeServicesCode:
+ case EfiRuntimeServicesData:
+ case EfiPalCode:
+ MemoryMap->Attribute = Entry->Attribute | EFI_MEMORY_RUNTIME;
+ break;
+
+ default:
+ MemoryMap->Attribute = Entry->Attribute;
+ break;
+ }
+
+ MemoryMap = NextMemoryDescriptor (MemoryMap, Size);
+ }
+
+ for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
+ GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
+ (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
+ if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
+
+ MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;
+ MemoryMap->VirtualStart = 0;
+ MemoryMap->NumberOfPages = MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);
+ MemoryMap->Attribute = GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO;
+
+ if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) {
+ MemoryMap->Type = EfiReservedMemoryType;
+ } else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
+ if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) {
+ MemoryMap->Type = EfiMemoryMappedIOPortSpace;
+ } else {
+ MemoryMap->Type = EfiMemoryMappedIO;
+ }
+ }
+
+ MemoryMap = NextMemoryDescriptor (MemoryMap, Size);
+ }
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ CoreReleaseMemoryLock ();
+
+ CoreReleaseGcdMemoryLock ();
+
+ //
+ // Update the map key finally
+ //
+ if (MapKey != NULL) {
+ *MapKey = mMemoryMapKey;
+ }
+
+ *MemoryMapSize = BufferSize;
+
+ return Status;
+}
+
+VOID *
+CoreAllocatePoolPages (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN NumberOfPages,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Used by the pool functions to allocate pages
+ to back pool allocation requests.
+
+Arguments:
+
+ PoolType - The type of memory for the new pool pages
+
+ NumberOfPages - No of pages to allocate
+
+ Alignment - Bits to align.
+
+Returns:
+
+ The allocated memory, or NULL
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 Start;
+
+ //
+ // Find the pages to convert
+ //
+ Start = FindFreePages (EFI_MAX_ADDRESS, NumberOfPages, PoolType, Alignment);
+
+ //
+ // Convert it to boot services data
+ //
+ if (Start == 0) {
+ DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "AllocatePoolPages: failed to allocate %d pages\n", NumberOfPages));
+ } else {
+ Status = CoreConvertPages (Start, NumberOfPages, PoolType);
+ }
+
+ return (VOID *)(UINTN)Start;
+}
+
+VOID
+CoreFreePoolPages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Frees pool pages allocated via AllocatePoolPages ()
+
+Arguments:
+
+ Memory - The base address to free
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
+}
+
+
+EFI_STATUS
+CoreTerminateMemoryMap (
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ Make sure the memory map is following all the construction rules,
+ it is the last time to check memory map error before exit boot services.
+
+Arguments:
+
+ MapKey - Memory map key
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Memory map not consistent with construction rules.
+
+ EFI_SUCCESS - Valid memory map.
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+
+ Status = EFI_SUCCESS;
+
+ CoreAcquireMemoryLock ();
+
+ if (MapKey == mMemoryMapKey) {
+
+ //
+ // Make sure the memory map is following all the construction rules
+ // This is the last chance we will be able to display any messages on
+ // the console devices.
+ //
+
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ if (Entry->Attribute & EFI_MEMORY_RUNTIME) {
+ if (Entry->Type == EfiACPIReclaimMemory || Entry->Type == EfiACPIMemoryNVS) {
+ DEBUG((EFI_D_ERROR, "ExitBootServices: ACPI memory entry has RUNTIME attribute set.\n"));
+ CoreReleaseMemoryLock ();
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
+ DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
+ CoreReleaseMemoryLock ();
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
+ DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
+ CoreReleaseMemoryLock ();
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ //
+ // The map key they gave us matches what we expect. Fall through and
+ // return success. In an ideal world we would clear out all of
+ // EfiBootServicesCode and EfiBootServicesData. However this function
+ // is not the last one called by ExitBootServices(), so we have to
+ // preserve the memory contents.
+ //
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ CoreReleaseMemoryLock ();
+
+ return Status;
+}
+
+
+
+
+
+
+
+
diff --git a/EdkModulePkg/Core/Dxe/Mem/memdata.c b/EdkModulePkg/Core/Dxe/Mem/memdata.c
new file mode 100644
index 0000000000..2fa4843102
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Mem/memdata.c
@@ -0,0 +1,41 @@
+/*++
+
+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:
+
+ memdata.c
+
+Abstract:
+
+ Global data used in memory service
+
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+
+//
+// MemoryLock - synchronizes access to the memory map and pool lists
+//
+EFI_LOCK gMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+
+//
+// MemoryMap - the current memory map
+//
+LIST_ENTRY gMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap);
+
+//
+// MemoryLastConvert - the last memory descriptor used for a conversion request
+//
+MEMORY_MAP *gMemoryLastConvert;
diff --git a/EdkModulePkg/Core/Dxe/Mem/pool.c b/EdkModulePkg/Core/Dxe/Mem/pool.c
new file mode 100644
index 0000000000..2f4669e6c1
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Mem/pool.c
@@ -0,0 +1,613 @@
+/*++
+
+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:
+
+ pool.c
+
+Abstract:
+
+ EFI Memory pool management
+
+Revision History
+
+--*/
+
+#include <DxeMain.h>
+
+#define POOL_FREE_SIGNATURE EFI_SIGNATURE_32('p','f','r','0')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Index;
+ LIST_ENTRY Link;
+} POOL_FREE;
+
+
+#define POOL_HEAD_SIGNATURE EFI_SIGNATURE_32('p','h','d','0')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Size;
+ EFI_MEMORY_TYPE Type;
+ UINTN Reserved;
+ CHAR8 Data[1];
+} POOL_HEAD;
+
+#define SIZE_OF_POOL_HEAD EFI_FIELD_OFFSET(POOL_HEAD,Data)
+
+#define POOL_TAIL_SIGNATURE EFI_SIGNATURE_32('p','t','a','l')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Size;
+} POOL_TAIL;
+
+
+#define POOL_SHIFT 7
+
+#define POOL_OVERHEAD (SIZE_OF_POOL_HEAD + sizeof(POOL_TAIL))
+
+#define HEAD_TO_TAIL(a) \
+ ((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL)));
+
+
+#define SIZE_TO_LIST(a) ((a) >> POOL_SHIFT)
+#define LIST_TO_SIZE(a) ((a+1) << POOL_SHIFT)
+
+#define MAX_POOL_LIST SIZE_TO_LIST(DEFAULT_PAGE_ALLOCATION)
+
+#define MAX_POOL_SIZE 0xffffff00
+
+//
+// Globals
+//
+
+#define POOL_SIGNATURE EFI_SIGNATURE_32('p','l','s','t')
+typedef struct {
+ INTN Signature;
+ UINTN Used;
+ EFI_MEMORY_TYPE MemoryType;
+ LIST_ENTRY FreeList[MAX_POOL_LIST];
+ LIST_ENTRY Link;
+} POOL;
+
+
+POOL PoolHead[EfiMaxMemoryType];
+LIST_ENTRY PoolHeadList;
+
+//
+//
+//
+
+VOID
+CoreInitializePool (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the pool.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Type;
+ UINTN Index;
+
+ for (Type=0; Type < EfiMaxMemoryType; Type++) {
+ PoolHead[Type].Signature = 0;
+ PoolHead[Type].Used = 0;
+ PoolHead[Type].MemoryType = Type;
+ for (Index=0; Index < MAX_POOL_LIST; Index++) {
+ InitializeListHead (&PoolHead[Type].FreeList[Index]);
+ }
+ }
+ InitializeListHead (&PoolHeadList);
+}
+
+
+POOL *
+LookupPoolHead (
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+/*++
+
+Routine Description:
+
+ Look up pool head for specified memory type.
+
+Arguments:
+
+ MemoryType - Memory type of which pool head is looked for
+
+Returns:
+
+ Pointer of Corresponding pool head.
+
+--*/
+{
+ LIST_ENTRY *Link;
+ POOL *Pool;
+ UINTN Index;
+
+ if (MemoryType >= 0 && MemoryType < EfiMaxMemoryType) {
+ return &PoolHead[MemoryType];
+ }
+
+ if (MemoryType < 0) {
+
+ for (Link = PoolHeadList.ForwardLink; Link != &PoolHeadList; Link = Link->ForwardLink) {
+ Pool = CR(Link, POOL, Link, POOL_SIGNATURE);
+ if (Pool->MemoryType == MemoryType) {
+ return Pool;
+ }
+ }
+
+ Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL));
+ if (Pool == NULL) {
+ return NULL;
+ }
+
+ Pool->Signature = POOL_SIGNATURE;
+ Pool->Used = 0;
+ Pool->MemoryType = MemoryType;
+ for (Index=0; Index < MAX_POOL_LIST; Index++) {
+ InitializeListHead (&Pool->FreeList[Index]);
+ }
+
+ InsertHeadList (&PoolHeadList, &Pool->Link);
+
+ return Pool;
+ }
+
+ return NULL;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreAllocatePool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of a particular type.
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+ Buffer - The address to return a pointer to the allocated pool
+
+Returns:
+
+ EFI_INVALID_PARAMETER - PoolType not valid
+
+ EFI_OUT_OF_RESOURCES - Size exceeds max pool size or allocation failed.
+
+ EFI_SUCCESS - Pool successfully allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // If it's not a valid type, fail it
+ //
+ if ((PoolType >= EfiMaxMemoryType && PoolType <= 0x7fffffff) ||
+ PoolType == EfiConventionalMemory) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Buffer = NULL;
+
+ //
+ // If size is too large, fail it
+ // Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES
+ //
+ if (Size > MAX_POOL_SIZE) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Acquire the memory lock and make the allocation
+ //
+ Status = CoreAcquireLockOrFail (&gMemoryLock);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Buffer = CoreAllocatePoolI (PoolType, Size);
+ CoreReleaseMemoryLock ();
+ return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
+}
+
+
+VOID *
+CoreAllocatePoolI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Internal function to allocate pool of a particular type.
+
+ Caller must have the memory lock held
+
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+Returns:
+
+ The allocate pool, or NULL
+
+--*/
+{
+ POOL *Pool;
+ POOL_FREE *Free;
+ POOL_HEAD *Head;
+ POOL_TAIL *Tail;
+ CHAR8 *NewPage;
+ VOID *Buffer;
+ UINTN Index;
+ UINTN FSize;
+ UINTN offset;
+ UINTN Adjustment;
+ UINTN NoPages;
+
+ ASSERT_LOCKED (&gMemoryLock);
+
+ //
+ // Adjust the size by the pool header & tail overhead
+ //
+
+ //
+ // Adjusting the Size to be of proper alignment so that
+ // we don't get an unaligned access fault later when
+ // pool_Tail is being initialized
+ //
+ ALIGN_VARIABLE (Size, Adjustment);
+
+ Size += POOL_OVERHEAD;
+ Index = SIZE_TO_LIST(Size);
+ Pool = LookupPoolHead (PoolType);
+ if (Pool== NULL) {
+ return NULL;
+ }
+ Head = NULL;
+
+ //
+ // If allocation is over max size, just allocate pages for the request
+ // (slow)
+ //
+ if (Index >= MAX_POOL_LIST) {
+ NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
+ NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
+ Head = CoreAllocatePoolPages (PoolType, NoPages, DEFAULT_PAGE_ALLOCATION);
+ goto Done;
+ }
+
+ //
+ // If there's no free pool in the proper list size, go get some more pages
+ //
+ if (IsListEmpty (&Pool->FreeList[Index])) {
+
+ //
+ // Get another page
+ //
+ NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);
+ if (NewPage == NULL) {
+ goto Done;
+ }
+
+ //
+ // Carve up new page into free pool blocks
+ //
+ offset = 0;
+ while (offset < DEFAULT_PAGE_ALLOCATION) {
+ ASSERT (Index < MAX_POOL_LIST);
+ FSize = LIST_TO_SIZE(Index);
+
+ while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
+ Free = (POOL_FREE *) &NewPage[offset];
+ Free->Signature = POOL_FREE_SIGNATURE;
+ Free->Index = (UINT32)Index;
+ InsertHeadList (&Pool->FreeList[Index], &Free->Link);
+ offset += FSize;
+ }
+
+ Index -= 1;
+ }
+
+ ASSERT (offset == DEFAULT_PAGE_ALLOCATION);
+ Index = SIZE_TO_LIST(Size);
+ }
+
+ //
+ // Remove entry from free pool list
+ //
+ Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);
+ RemoveEntryList (&Free->Link);
+
+ Head = (POOL_HEAD *) Free;
+
+Done:
+ Buffer = NULL;
+
+ if (Head != NULL) {
+
+ //
+ // If we have a pool buffer, fill in the header & tail info
+ //
+ Head->Signature = POOL_HEAD_SIGNATURE;
+ Head->Size = (UINT32) Size;
+ Head->Type = (EFI_MEMORY_TYPE) PoolType;
+ Tail = HEAD_TO_TAIL (Head);
+ Tail->Signature = POOL_TAIL_SIGNATURE;
+ Tail->Size = (UINT32) Size;
+ Buffer = Head->Data;
+ DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);
+
+ DEBUG (
+ (EFI_D_POOL,
+ "AllcocatePoolI: Type %x, Addr %x (len %x) %,d\n",
+ PoolType,
+ Buffer,
+ Size - POOL_OVERHEAD,
+ Pool->Used)
+ );
+
+ //
+ // Account the allocation
+ //
+ Pool->Used += Size;
+
+ } else {
+ DEBUG ((EFI_D_ERROR | EFI_D_POOL, "AllocatePool: failed to allocate %d bytes\n", Size));
+ }
+
+ return Buffer;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreFreePool (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Frees pool.
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer is not a valid value.
+
+ EFI_SUCCESS - Pool successfully freed.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ if (NULL == Buffer) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireMemoryLock ();
+ Status = CoreFreePoolI (Buffer);
+ CoreReleaseMemoryLock ();
+ return Status;
+}
+
+
+EFI_STATUS
+CoreFreePoolI (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Internal function to free a pool entry.
+
+ Caller must have the memory lock held
+
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer not valid
+
+ EFI_SUCCESS - Buffer successfully freed.
+
+--*/
+{
+ POOL *Pool;
+ POOL_HEAD *Head;
+ POOL_TAIL *Tail;
+ POOL_FREE *Free;
+ UINTN Index;
+ UINTN NoPages;
+ UINTN Size;
+ CHAR8 *NewPage;
+ UINTN FSize;
+ UINTN offset;
+ BOOLEAN AllFree;
+
+ ASSERT(NULL != Buffer);
+ //
+ // Get the head & tail of the pool entry
+ //
+ Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);
+ ASSERT(NULL != Head);
+
+ if (Head->Signature != POOL_HEAD_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Tail = HEAD_TO_TAIL (Head);
+ ASSERT(NULL != Tail);
+
+ //
+ // Debug
+ //
+ ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);
+ ASSERT (Head->Size == Tail->Size);
+ ASSERT_LOCKED (&gMemoryLock);
+
+ if (Tail->Signature != POOL_TAIL_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Head->Size != Tail->Size) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Determine the pool type and account for it
+ //
+ Size = Head->Size;
+ Pool = LookupPoolHead (Head->Type);
+ if (Pool == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Pool->Used -= Size;
+ DEBUG ((EFI_D_POOL, "FreePool: %x (len %x) %,d\n", Head->Data, Head->Size - POOL_OVERHEAD, Pool->Used));
+
+ //
+ // Determine the pool list
+ //
+ Index = SIZE_TO_LIST(Size);
+ DEBUG_CLEAR_MEMORY (Head, Size);
+
+ //
+ // If it's not on the list, it must be pool pages
+ //
+ if (Index >= MAX_POOL_LIST) {
+
+ //
+ // Return the memory pages back to free memory
+ //
+ NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
+ NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
+ CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);
+
+ } else {
+
+ //
+ // Put the pool entry onto the free pool list
+ //
+ Free = (POOL_FREE *) Head;
+ ASSERT(NULL != Free);
+ Free->Signature = POOL_FREE_SIGNATURE;
+ Free->Index = (UINT32)Index;
+ InsertHeadList (&Pool->FreeList[Index], &Free->Link);
+
+ //
+ // See if all the pool entries in the same page as Free are freed pool
+ // entries
+ //
+ NewPage = (CHAR8 *)((UINTN)Free & ~((DEFAULT_PAGE_ALLOCATION) -1));
+ Free = (POOL_FREE *) &NewPage[0];
+ ASSERT(NULL != Free);
+
+ if (Free->Signature == POOL_FREE_SIGNATURE) {
+
+ Index = Free->Index;
+
+ AllFree = TRUE;
+ offset = 0;
+
+ while ((offset < DEFAULT_PAGE_ALLOCATION) && (AllFree)) {
+ FSize = LIST_TO_SIZE(Index);
+ while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
+ Free = (POOL_FREE *) &NewPage[offset];
+ ASSERT(NULL != Free);
+ if (Free->Signature != POOL_FREE_SIGNATURE) {
+ AllFree = FALSE;
+ }
+ offset += FSize;
+ }
+ Index -= 1;
+ }
+
+ if (AllFree) {
+
+ //
+ // All of the pool entries in the same page as Free are free pool
+ // entries
+ // Remove all of these pool entries from the free loop lists.
+ //
+ Free = (POOL_FREE *) &NewPage[0];
+ ASSERT(NULL != Free);
+ Index = Free->Index;
+ offset = 0;
+
+ while (offset < DEFAULT_PAGE_ALLOCATION) {
+ FSize = LIST_TO_SIZE(Index);
+ while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
+ Free = (POOL_FREE *) &NewPage[offset];
+ ASSERT(NULL != Free);
+ RemoveEntryList (&Free->Link);
+ offset += FSize;
+ }
+ Index -= 1;
+ }
+
+ //
+ // Free the page
+ //
+ CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION));
+ }
+ }
+ }
+
+ //
+ // If this is an OS specific memory type, then check to see if the last
+ // portion of that memory type has been freed. If it has, then free the
+ // list entry for that memory type
+ //
+ if (Pool->MemoryType < 0 && Pool->Used == 0) {
+ RemoveEntryList (&Pool->Link);
+ CoreFreePoolI (Pool);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Dxe/Misc/DebugImageInfo.c b/EdkModulePkg/Core/Dxe/Misc/DebugImageInfo.c
new file mode 100644
index 0000000000..e7f90de025
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Misc/DebugImageInfo.c
@@ -0,0 +1,260 @@
+/*++
+
+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:
+
+ DebugImageInfo.c
+
+Abstract:
+
+ Support functions for managing debug image info table when loading and unloading
+ images.
+
+--*/
+
+#include <DxeMain.h>
+
+
+static EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = {
+ 0, // volatile UINT32 UpdateStatus;
+ 0, // UINT32 TableSize;
+ NULL // EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
+};
+
+static EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL;
+
+
+VOID
+CoreInitializeDebugImageInfoTable (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Creates and initializes the DebugImageInfo Table. Also creates the configuration
+ table and registers it into the system table.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+Notes:
+ This function allocates memory, frees it, and then allocates memory at an
+ address within the initial allocation. Since this function is called early
+ in DXE core initialization (before drivers are dispatched), this should not
+ be a problem.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Mem;
+ UINTN NumberOfPages;
+
+ //
+ // Allocate boot services memory for the structure. It's required to be aligned on
+ // a 4M boundary, so allocate a 4M block (plus what we require), free it up, calculate
+ // a 4M aligned address within the memory we just freed, and then allocate memory at that
+ // address for our initial structure.
+ //
+ NumberOfPages = FOUR_MEG_PAGES + EFI_SIZE_TO_PAGES(sizeof (EFI_SYSTEM_TABLE_POINTER));
+
+ Status = CoreAllocatePages (AllocateAnyPages, EfiBootServicesData, NumberOfPages , &Mem);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ Status = CoreFreePages (Mem, NumberOfPages);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ //
+ // Now get a 4M aligned address within the memory range we were given.
+ // Then allocate memory at that address
+ //
+ Mem = (Mem + FOUR_MEG_MASK) & (~FOUR_MEG_MASK);
+
+ Status = CoreAllocatePages (AllocateAddress, EfiBootServicesData, NumberOfPages - FOUR_MEG_PAGES, &Mem);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ //
+ // We now have a 4M aligned page allocated, so fill in the data structure.
+ // Ideally we would update the CRC now as well, but the service may not yet be available.
+ // See comments in the CoreUpdateDebugTableCrc32() function below for details.
+ //
+ mDebugTable = (EFI_SYSTEM_TABLE_POINTER *)(UINTN)Mem;
+ mDebugTable->Signature = EFI_SYSTEM_TABLE_SIGNATURE;
+ mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) gST;
+ mDebugTable->Crc32 = 0;
+ Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader);
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+CoreUpdateDebugTableCrc32 (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Update the CRC32 in the Debug Table.
+ Since the CRC32 service is made available by the Runtime driver, we have to
+ wait for the Runtime Driver to be installed before the CRC32 can be computed.
+ This function is called elsewhere by the core when the runtime architectural
+ protocol is produced.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+--*/
+{
+ ASSERT(mDebugTable != NULL);
+ mDebugTable->Crc32 = 0;
+ gBS->CalculateCrc32 ((VOID *)mDebugTable, sizeof (EFI_SYSTEM_TABLE_POINTER), &mDebugTable->Crc32);
+}
+
+VOID
+CoreNewDebugImageInfoEntry (
+ IN UINTN ImageInfoType,
+ IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
+ the table if it's not large enough to accomidate another entry.
+
+Arguments:
+
+ ImageInfoType - type of debug image information
+ LoadedImage - pointer to the loaded image protocol for the image being loaded
+ ImageHandle - image handle for the image being loaded
+
+Returns:
+ NA
+
+--*/
+{
+ EFI_DEBUG_IMAGE_INFO *Table;
+ EFI_DEBUG_IMAGE_INFO *NewTable;
+ UINTN Index;
+ UINTN MaxTableIndex;
+ UINTN TableSize;
+
+ //
+ // Set the flag indicating that we're in the process of updating the table.
+ //
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
+ MaxTableIndex = mDebugInfoTableHeader.TableSize;
+
+ for (Index = 0; Index < MaxTableIndex; Index++) {
+ if (Table[Index].NormalImage == NULL) {
+ //
+ // We have found a free entry so exit the loop
+ //
+ break;
+ }
+ }
+ if (Index == MaxTableIndex) {
+ //
+ // Table is full, so re-allocate another page for a larger table...
+ //
+ TableSize = MaxTableIndex * EFI_DEBUG_TABLE_ENTRY_SIZE;
+ NewTable = CoreAllocateZeroBootServicesPool (TableSize + EFI_PAGE_SIZE);
+ if (NewTable == NULL) {
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+ return;
+ }
+ //
+ // Copy the old table into the new one
+ //
+ CopyMem (NewTable, Table, TableSize);
+ //
+ // Free the old table
+ //
+ CoreFreePool (Table);
+ //
+ // Update the table header
+ //
+ Table = NewTable;
+ mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
+ mDebugInfoTableHeader.TableSize += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
+ }
+ //
+ // Allocate data for new entry
+ //
+ Table[Index].NormalImage = CoreAllocateZeroBootServicesPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
+ if (Table[Index].NormalImage != NULL) {
+ //
+ // Update the entry
+ //
+ Table[Index].NormalImage->ImageInfoType = (UINT32) ImageInfoType;
+ Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage;
+ Table[Index].NormalImage->ImageHandle = ImageHandle;
+ }
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}
+
+
+VOID
+CoreRemoveDebugImageInfoEntry (
+ EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Removes and frees an entry from the DebugImageInfo Table.
+
+Arguments:
+
+ ImageHandle - image handle for the image being unloaded
+
+Returns:
+
+ NA
+
+--*/
+{
+ EFI_DEBUG_IMAGE_INFO *Table;
+ UINTN Index;
+
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
+
+ for (Index = 0; Index < mDebugInfoTableHeader.TableSize; Index++) {
+ if (Table[Index].NormalImage != NULL && Table[Index].NormalImage->ImageHandle == ImageHandle) {
+ //
+ // Found a match. Free up the record, then NULL the pointer to indicate the slot
+ // is free.
+ //
+ CoreFreePool (Table[Index].NormalImage);
+ Table[Index].NormalImage = NULL;
+ break;
+ }
+ }
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}
+
diff --git a/EdkModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c b/EdkModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c
new file mode 100644
index 0000000000..e81fcad35a
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c
@@ -0,0 +1,214 @@
+/*++
+
+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:
+
+ InstallConfigurationTable.c
+
+
+Abstract:
+
+ Tiano Miscellaneous Services InstallConfigurationTable service
+
+--*/
+
+#include <DxeMain.h>
+
+#define CONFIG_TABLE_SIZE_INCREASED 0x10
+
+UINTN mSystemTableAllocateSize = 0;
+
+
+EFI_STATUS
+CoreGetConfigTable (
+ IN EFI_GUID *Guid,
+ OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+
+ Find a config table by name in system table's ConfigurationTable.
+
+Arguments:
+
+ Guid - The table name to look for
+
+ Table - Pointer of the config table
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable.
+
+ EFI_SUCCESS - Table successfully found.
+
+--*/
+{
+ UINTN Index;
+
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (CompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) {
+ *Table = gST->ConfigurationTable[Index].VendorTable;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreInstallConfigurationTable (
+ IN EFI_GUID *Guid,
+ IN VOID *Table
+ )
+/*++
+
+Routine Description:
+
+ Boot Service called to add, modify, or remove a system configuration table from
+ the EFI System Table.
+
+Arguments:
+
+ Guid - Pointer to the GUID for the entry to add, update, or remove
+ Table - Pointer to the configuration table for the entry to add, update, or
+ remove, may be NULL.
+
+Returns:
+
+ EFI_SUCCESS Guid, Table pair added, updated, or removed.
+ EFI_INVALID_PARAMETER Input GUID not valid.
+ EFI_NOT_FOUND Attempted to delete non-existant entry
+ EFI_OUT_OF_RESOURCES Not enough memory available
+
+--*/
+{
+ UINTN Index;
+ EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
+
+ //
+ // If Guid is NULL, then this operation cannot be performed
+ //
+ if (Guid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EfiConfigurationTable = gST->ConfigurationTable;
+
+ //
+ // Search all the table for an entry that matches Guid
+ //
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (CompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) {
+ break;
+ }
+ }
+
+ if (Index < gST->NumberOfTableEntries) {
+ //
+ // A match was found, so this is either a modify or a delete operation
+ //
+ if (Table != NULL) {
+ //
+ // If Table is not NULL, then this is a modify operation.
+ // Modify the table enty and return.
+ //
+ gST->ConfigurationTable[Index].VendorTable = Table;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // A match was found and Table is NULL, so this is a delete operation.
+ //
+ gST->NumberOfTableEntries--;
+
+ //
+ // Copy over deleted entry
+ //
+ CopyMem (
+ &(EfiConfigurationTable[Index]),
+ &(gST->ConfigurationTable[Index + 1]),
+ (gST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
+ );
+
+ } else {
+
+ //
+ // No matching GUIDs were found, so this is an add operation.
+ //
+
+ if (Table == NULL) {
+ //
+ // If Table is NULL on an add operation, then return an error.
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Assume that Index == gST->NumberOfTableEntries
+ //
+ if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) {
+ //
+ // Allocate a table with one additional entry.
+ //
+ mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
+ EfiConfigurationTable = CoreAllocateRuntimePool (mSystemTableAllocateSize);
+ if (EfiConfigurationTable == NULL) {
+ //
+ // If a new table could not be allocated, then return an error.
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (gST->ConfigurationTable != NULL) {
+ //
+ // Copy the old table to the new table.
+ //
+ CopyMem (
+ EfiConfigurationTable,
+ gST->ConfigurationTable,
+ Index * sizeof (EFI_CONFIGURATION_TABLE)
+ );
+
+ //
+ // Free Old Table
+ //
+ CoreFreePool (gST->ConfigurationTable);
+ }
+
+ //
+ // Update System Table
+ //
+ gST->ConfigurationTable = EfiConfigurationTable;
+ }
+
+ //
+ // Fill in the new entry
+ //
+ CopyMem ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid, sizeof (EFI_GUID));
+ EfiConfigurationTable[Index].VendorTable = Table;
+
+ //
+ // This is an add operation, so increment the number of table entries
+ //
+ gST->NumberOfTableEntries++;
+ }
+
+ //
+ // Fix up the CRC-32 in the EFI System Table
+ //
+ CalculateEfiHdrCrc (&gST->Hdr);
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c b/EdkModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c
new file mode 100644
index 0000000000..c11c926e06
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c
@@ -0,0 +1,83 @@
+/*++
+
+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:
+
+ SetWatchdogTimer.c
+
+Abstract:
+
+ Tiano Miscellaneous Services SetWatchdogTimer service implementation
+
+--*/
+
+#include <DxeMain.h>
+
+#define WATCHDOG_TIMER_CALIBRATE_PER_SECOND 10000000
+
+
+EFI_STATUS
+EFIAPI
+CoreSetWatchdogTimer (
+ IN UINTN Timeout,
+ IN UINT64 WatchdogCode,
+ IN UINTN DataSize,
+ IN CHAR16 *WatchdogData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Sets the system's watchdog timer.
+
+Arguments:
+
+ Timeout The number of seconds. Zero disables the timer.
+
+ ///////following three parameters are left for platform specific using
+
+ WatchdogCode The numberic code to log. 0x0 to 0xffff are firmware
+ DataSize Size of the optional data
+ WatchdogData Optional Null terminated unicode string followed by binary
+ data.
+
+Returns:
+
+ EFI_SUCCESS Timeout has been set
+ EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet
+ EFI_UNSUPPORTED System does not have a timer (currently not used)
+ EFI_DEVICE_ERROR Could not complete due to hardware error
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Check our architectural protocol
+ //
+ if (gWatchdogTimer == NULL) {
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // Attempt to set the timeout
+ //
+ Status = gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, MultU64x32 (Timeout, WATCHDOG_TIMER_CALIBRATE_PER_SECOND));
+
+ //
+ // Check for errors
+ //
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Dxe/Misc/Stall.c b/EdkModulePkg/Core/Dxe/Misc/Stall.c
new file mode 100644
index 0000000000..c251f31dc9
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/Misc/Stall.c
@@ -0,0 +1,82 @@
+/*++
+
+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:
+
+ Stall.c
+
+Abstract:
+
+ Tiano Miscellaneous Services Stall service implementation
+
+--*/
+
+//
+// Include statements
+//
+
+#include <DxeMain.h>
+
+
+EFI_STATUS
+EFIAPI
+CoreStall (
+ IN UINTN Microseconds
+ )
+/*++
+
+Routine Description:
+
+ Introduces a fine-grained stall.
+
+Arguments:
+
+ Microseconds The number of microseconds to stall execution
+
+Returns:
+
+ EFI_SUCCESS - Execution was stalled for at least the requested amount
+ of microseconds.
+
+ EFI_NOT_AVAILABLE_YET - gMetronome is not available yet
+
+--*/
+{
+ UINT32 Counter;
+ UINT32 Remainder;
+
+ if (gMetronome == NULL) {
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // Calculate the number of ticks by dividing the number of microseconds by
+ // the TickPeriod.
+ // Calcullation is based on 100ns unit.
+ //
+ Counter = (UINT32) DivU64x32Remainder (
+ Microseconds * 10,
+ gMetronome->TickPeriod,
+ &Remainder
+ );
+
+ //
+ // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
+ // periods, thus attempting to ensure Microseconds of stall time.
+ //
+ if (Remainder != 0) {
+ Counter++;
+ }
+
+ gMetronome->WaitForTick (gMetronome, Counter);
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c b/EdkModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
new file mode 100644
index 0000000000..e98b80cddf
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
@@ -0,0 +1,1339 @@
+/*++
+
+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:
+
+ CoreSectionExtraction.c
+
+Abstract:
+
+ Section Extraction Protocol implementation.
+
+ Stream database is implemented as a linked list of section streams,
+ where each stream contains a linked list of children, which may be leaves or
+ encapsulations.
+
+ Children that are encapsulations generate new stream entries
+ when they are created. Streams can also be created by calls to
+ SEP->OpenSectionStream().
+
+ The database is only created far enough to return the requested data from
+ any given stream, or to determine that the requested data is not found.
+
+ If a GUIDed encapsulation is encountered, there are three possiblilites.
+
+ 1) A support protocol is found, in which the stream is simply processed with
+ the support protocol.
+
+ 2) A support protocol is not found, but the data is available to be read
+ without processing. In this case, the database is built up through the
+ recursions to return the data, and a RPN event is set that will enable
+ the stream in question to be refreshed if and when the required section
+ extraction protocol is published.This insures the AuthenticationStatus
+ does not become stale in the cache.
+
+ 3) A support protocol is not found, and the data is not available to be read
+ without it. This results in EFI_PROTOCOL_ERROR.
+
+--*/
+
+#include <DxeMain.h>
+
+//
+// Local defines and typedefs
+//
+#define CORE_SECTION_CHILD_SIGNATURE EFI_SIGNATURE_32('S','X','C','S')
+#define CHILD_SECTION_NODE_FROM_LINK(Node) \
+ CR (Node, CORE_SECTION_CHILD_NODE, Link, CORE_SECTION_CHILD_SIGNATURE)
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ UINT32 Type;
+ UINT32 Size;
+ //
+ // StreamBase + OffsetInStream == pointer to section header in stream. The
+ // stream base is always known when walking the sections within.
+ //
+ UINT32 OffsetInStream;
+ //
+ // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an
+ // encapsulating section. Otherwise, it contains the stream handle
+ // of the encapsulated stream. This handle is ALWAYS produced any time an
+ // encapsulating child is encountered, irrespective of whether the
+ // encapsulated stream is processed further.
+ //
+ UINTN EncapsulatedStreamHandle;
+ EFI_GUID *EncapsulationGuid;
+} CORE_SECTION_CHILD_NODE;
+
+#define CORE_SECTION_STREAM_SIGNATURE EFI_SIGNATURE_32('S','X','S','S')
+#define STREAM_NODE_FROM_LINK(Node) \
+ CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE)
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ UINTN StreamHandle;
+ UINT8 *StreamBuffer;
+ UINTN StreamLength;
+ LIST_ENTRY Children;
+ //
+ // Authentication status is from GUIDed encapsulations.
+ //
+ UINT32 AuthenticationStatus;
+} CORE_SECTION_STREAM_NODE;
+
+#define NULL_STREAM_HANDLE 0
+
+typedef struct {
+ CORE_SECTION_CHILD_NODE *ChildNode;
+ CORE_SECTION_STREAM_NODE *ParentStream;
+ VOID *Registration;
+ EFI_EVENT Event;
+} RPN_EVENT_CONTEXT;
+
+
+
+//
+// Local prototypes
+//
+
+STATIC
+BOOLEAN
+ChildIsType (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN CORE_SECTION_CHILD_NODE *Child,
+ IN EFI_SECTION_TYPE SearchType,
+ IN EFI_GUID *SectionDefinitionGuid
+ );
+
+STATIC
+VOID
+EFIAPI
+NotifyGuidedExtraction (
+ IN EFI_EVENT Event,
+ IN VOID *RpnContext
+ );
+
+STATIC
+VOID
+CreateGuidedExtractionRpnEvent (
+ IN CORE_SECTION_STREAM_NODE *ParentStream,
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ );
+
+EFI_STATUS
+EFIAPI
+OpenSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ OUT UINTN *SectionStreamHandle
+ );
+
+EFI_STATUS
+EFIAPI
+GetSection (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamHandle,
+ IN EFI_SECTION_TYPE *SectionType,
+ IN EFI_GUID *SectionDefinitionGuid,
+ IN UINTN SectionInstance,
+ IN VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ );
+
+EFI_STATUS
+EFIAPI
+CloseSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN StreamHandleToClose
+ );
+
+STATIC
+EFI_STATUS
+FindStreamNode (
+ IN UINTN SearchHandle,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream
+ );
+
+STATIC
+EFI_STATUS
+FindChildNode (
+ IN CORE_SECTION_STREAM_NODE *SourceStream,
+ IN EFI_SECTION_TYPE SearchType,
+ IN UINTN *SectionInstance,
+ IN EFI_GUID *SectionDefinitionGuid,
+ OUT CORE_SECTION_CHILD_NODE **FoundChild,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream,
+ OUT UINT32 *AuthenticationStatus
+ );
+
+STATIC
+EFI_STATUS
+CreateChildNode (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN UINT32 ChildOffset,
+ OUT CORE_SECTION_CHILD_NODE **ChildNode
+ );
+
+STATIC
+VOID
+FreeChildNode (
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ );
+
+STATIC
+EFI_STATUS
+OpenSectionStreamEx (
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ IN BOOLEAN AllocateBuffer,
+ IN UINT32 AuthenticationStatus,
+ OUT UINTN *SectionStreamHandle
+ );
+
+STATIC
+BOOLEAN
+IsValidSectionStream (
+ IN VOID *SectionStream,
+ IN UINTN SectionStreamLength
+ );
+
+//
+// Module globals
+//
+LIST_ENTRY mStreamRoot = INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot);
+
+EFI_HANDLE mSectionExtractionHandle = NULL;
+
+EFI_SECTION_EXTRACTION_PROTOCOL mSectionExtraction = {
+ OpenSectionStream,
+ GetSection,
+ CloseSectionStream
+};
+
+
+EFI_STATUS
+EFIAPI
+InitializeSectionExtraction (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Entry point of the section extraction code. Initializes an instance of the
+ section extraction interface and installs it on a new handle.
+
+Arguments:
+ ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver
+ SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+Returns:
+ EFI_SUCCESS: Driver initialized successfully
+ EFI_OUT_OF_RESOURCES: Could not allocate needed resources
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Install SEP to a new handle
+ //
+ Status = CoreInstallProtocolInterface (
+ &mSectionExtractionHandle,
+ &gEfiSectionExtractionProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSectionExtraction
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+OpenSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ OUT UINTN *SectionStreamHandle
+ )
+/*++
+
+Routine Description:
+ SEP member function. This function creates and returns a new section stream
+ handle to represent the new section stream.
+
+Arguments:
+ This - Indicates the calling context.
+ SectionStreamLength - Size in bytes of the section stream.
+ SectionStream - Buffer containing the new section stream.
+ SectionStreamHandle - A pointer to a caller allocated UINTN that on output
+ contains the new section stream handle.
+
+Returns:
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES - memory allocation failed.
+ EFI_INVALID_PARAMETER - section stream does not end concident with end of
+ last section.
+
+--*/
+{
+ //
+ // Check to see section stream looks good...
+ //
+ if (!IsValidSectionStream (SectionStream, SectionStreamLength)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return OpenSectionStreamEx (
+ SectionStreamLength,
+ SectionStream,
+ TRUE,
+ 0,
+ SectionStreamHandle
+ );
+}
+
+
+EFI_STATUS
+EFIAPI
+GetSection (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamHandle,
+ IN EFI_SECTION_TYPE *SectionType,
+ IN EFI_GUID *SectionDefinitionGuid,
+ IN UINTN SectionInstance,
+ IN VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ SEP member function. Retrieves requested section from section stream.
+
+Arguments:
+ This: Pointer to SEP instance.
+ SectionStreamHandle: The section stream from which to extract the requested
+ section.
+ SectionType: A pointer to the type of section to search for.
+ SectionDefinitionGuid: If the section type is EFI_SECTION_GUID_DEFINED, then
+ SectionDefinitionGuid indicates which of these types
+ of sections to search for.
+ SectionInstance: Indicates which instance of the requested section to
+ return.
+ Buffer: Double indirection to buffer. If *Buffer is non-null on
+ input, then the buffer is caller allocated. If
+ *Buffer is NULL, then the buffer is callee allocated.
+ In either case, the requried buffer size is returned
+ in *BufferSize.
+ BufferSize: On input, indicates the size of *Buffer if *Buffer is
+ non-null on input. On output, indicates the required
+ size (allocated size if callee allocated) of *Buffer.
+ AuthenticationStatus: Indicates the authentication status of the retrieved
+ section.
+
+Returns:
+ EFI_SUCCESS: Section was retrieved successfully
+ EFI_PROTOCOL_ERROR: A GUID defined section was encountered in the section
+ stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED
+ bit set, but there was no corresponding GUIDed Section
+ Extraction Protocol in the handle database. *Buffer is
+ unmodified.
+ EFI_NOT_FOUND: An error was encountered when parsing the SectionStream.
+ This indicates the SectionStream is not correctly
+ formatted.
+ EFI_NOT_FOUND: The requested section does not exist.
+ EFI_OUT_OF_RESOURCES: The system has insufficient resources to process the
+ request.
+ EFI_INVALID_PARAMETER: The SectionStreamHandle does not exist.
+ EFI_WARN_TOO_SMALL: The size of the caller allocated input buffer is
+ insufficient to contain the requested section. The
+ input buffer is filled and contents are section contents
+ are truncated.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *StreamNode;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ CORE_SECTION_CHILD_NODE *ChildNode;
+ CORE_SECTION_STREAM_NODE *ChildStreamNode;
+ UINTN CopySize;
+ UINT32 ExtractedAuthenticationStatus;
+ UINTN Instance;
+ UINT8 *CopyBuffer;
+ UINTN SectionSize;
+
+
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+ Instance = SectionInstance + 1;
+
+ //
+ // Locate target stream
+ //
+ Status = FindStreamNode (SectionStreamHandle, &StreamNode);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto GetSection_Done;
+ }
+
+ //
+ // Found the stream, now locate and return the appropriate section
+ //
+ if (SectionType == NULL) {
+ //
+ // SectionType == NULL means return the WHOLE section stream...
+ //
+ CopySize = StreamNode->StreamLength;
+ CopyBuffer = StreamNode->StreamBuffer;
+ *AuthenticationStatus = StreamNode->AuthenticationStatus;
+ } else {
+ //
+ // There's a requested section type, so go find it and return it...
+ //
+ Status = FindChildNode (
+ StreamNode,
+ *SectionType,
+ &Instance,
+ SectionDefinitionGuid,
+ &ChildNode,
+ &ChildStreamNode,
+ &ExtractedAuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ goto GetSection_Done;
+ }
+ CopySize = ChildNode->Size - sizeof (EFI_COMMON_SECTION_HEADER);
+ CopyBuffer = ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream + sizeof (EFI_COMMON_SECTION_HEADER);
+ *AuthenticationStatus = ExtractedAuthenticationStatus;
+ }
+
+ SectionSize = CopySize;
+ if (*Buffer != NULL) {
+ //
+ // Caller allocated buffer. Fill to size and return required size...
+ //
+ if (*BufferSize < CopySize) {
+ Status = EFI_WARN_BUFFER_TOO_SMALL;
+ CopySize = *BufferSize;
+ }
+ } else {
+ //
+ // Callee allocated buffer. Allocate buffer and return size.
+ //
+ *Buffer = CoreAllocateBootServicesPool (CopySize);
+ if (*Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto GetSection_Done;
+ }
+ }
+ CopyMem (*Buffer, CopyBuffer, CopySize);
+ *BufferSize = SectionSize;
+
+GetSection_Done:
+ CoreRestoreTpl (OldTpl);
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CloseSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN StreamHandleToClose
+ )
+/*++
+
+Routine Description:
+ SEP member function. Deletes an existing section stream
+
+Arguments:
+ This - Indicates the calling context.
+ StreamHandleToClose - Indicates the stream to close
+
+Returns:
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES - memory allocation failed.
+ EFI_INVALID_PARAMETER - section stream does not end concident with end of
+ last section.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *StreamNode;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ CORE_SECTION_CHILD_NODE *ChildNode;
+
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+
+ //
+ // Locate target stream
+ //
+ Status = FindStreamNode (StreamHandleToClose, &StreamNode);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Found the stream, so close it
+ //
+ RemoveEntryList (&StreamNode->Link);
+ while (!IsListEmpty (&StreamNode->Children)) {
+ Link = GetFirstNode (&StreamNode->Children);
+ ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);
+ FreeChildNode (ChildNode);
+ }
+ CoreFreePool (StreamNode->StreamBuffer);
+ CoreFreePool (StreamNode);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ CoreRestoreTpl (OldTpl);
+ return Status;
+}
+
+
+STATIC
+BOOLEAN
+ChildIsType (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN CORE_SECTION_CHILD_NODE *Child,
+ IN EFI_SECTION_TYPE SearchType,
+ IN EFI_GUID *SectionDefinitionGuid
+ )
+/*++
+
+Routine Description:
+ Worker function. Determine if the input stream:child matches the input type.
+
+Arguments:
+ Stream - Indicates the section stream associated with the child
+ Child - Indicates the child to check
+ SearchType - Indicates the type of section to check against for
+ SectionDefinitionGuid - Indicates the GUID to check against if the type is
+ EFI_SECTION_GUID_DEFINED
+Returns:
+ TRUE - The child matches
+ FALSE - The child doesn't match
+
+--*/
+{
+ EFI_GUID_DEFINED_SECTION *GuidedSection;
+
+ if (SearchType == EFI_SECTION_ALL) {
+ return TRUE;
+ }
+ if (Child->Type != SearchType) {
+ return FALSE;
+ }
+ if (SearchType != EFI_SECTION_GUID_DEFINED) {
+ return TRUE;
+ }
+ GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);
+ return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);
+}
+
+
+STATIC
+EFI_STATUS
+FindChildNode (
+ IN CORE_SECTION_STREAM_NODE *SourceStream,
+ IN EFI_SECTION_TYPE SearchType,
+ IN OUT UINTN *SectionInstance,
+ IN EFI_GUID *SectionDefinitionGuid,
+ OUT CORE_SECTION_CHILD_NODE **FoundChild,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Worker function Recursively searches / builds section stream database
+ looking for requested section.
+
+Arguments:
+ SourceStream - Indicates the section stream in which to do the search.
+ SearchType - Indicates the type of section to search for.
+ SectionInstance - Indicates which instance of section to find. This is
+ an in/out parameter to deal with recursions.
+ SectionDefinitionGuid - Guid of section definition
+ FoundChild - Output indicating the child node that is found.
+ FoundStream - Output indicating which section stream the child was
+ found in. If this stream was generated as a result of
+ an encapsulation section, the streamhandle is visible
+ within the SEP driver only.
+ AuthenticationStatus- Indicates the authentication status of the found section.
+
+Returns:
+ EFI_SUCCESS - Child node was found and returned.
+ EFI_OUT_OF_RESOURCES- Memory allocation failed.
+ EFI_NOT_FOUND - Requested child node does not exist.
+ EFI_PROTOCOL_ERROR - a required GUIDED section extraction protocol does not
+ exist
+
+--*/
+{
+ CORE_SECTION_CHILD_NODE *CurrentChildNode;
+ CORE_SECTION_CHILD_NODE *RecursedChildNode;
+ CORE_SECTION_STREAM_NODE *RecursedFoundStream;
+ UINT32 NextChildOffset;
+ EFI_STATUS ErrorStatus;
+ EFI_STATUS Status;
+
+ CurrentChildNode = NULL;
+ ErrorStatus = EFI_NOT_FOUND;
+
+ if (SourceStream->StreamLength == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (IsListEmpty (&SourceStream->Children) &&
+ SourceStream->StreamLength > sizeof (EFI_COMMON_SECTION_HEADER)) {
+ //
+ // This occurs when a section stream exists, but no child sections
+ // have been parsed out yet. Therefore, extract the first child and add it
+ // to the list of children so we can get started.
+ //
+ Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // At least one child has been parsed out of the section stream. So, walk
+ // through the sections that have already been parsed out looking for the
+ // requested section, if necessary, continue parsing section stream and
+ // adding children until either the requested section is found, or we run
+ // out of data
+ //
+ CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));
+
+ for (;;) {
+ if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) {
+ //
+ // The type matches, so check the instance count to see if it's the one we want
+ //
+ (*SectionInstance)--;
+ if (*SectionInstance == 0) {
+ //
+ // Got it!
+ //
+ *FoundChild = CurrentChildNode;
+ *FoundStream = SourceStream;
+ *AuthenticationStatus = SourceStream->AuthenticationStatus;
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
+ //
+ // If the current node is an encapsulating node, recurse into it...
+ //
+ Status = FindChildNode (
+ (CORE_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle,
+ SearchType,
+ SectionInstance,
+ SectionDefinitionGuid,
+ &RecursedChildNode,
+ &RecursedFoundStream,
+ AuthenticationStatus
+ );
+ //
+ // If the status is not EFI_SUCCESS, just save the error code and continue
+ // to find the request child node in the rest stream.
+ //
+ if (*SectionInstance == 0) {
+ ASSERT_EFI_ERROR (Status);
+ *FoundChild = RecursedChildNode;
+ *FoundStream = RecursedFoundStream;
+ return EFI_SUCCESS;
+ } else {
+ ErrorStatus = Status;
+ }
+ }
+
+ if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) {
+ //
+ // We haven't found the child node we're interested in yet, but there's
+ // still more nodes that have already been parsed so get the next one
+ // and continue searching..
+ //
+ CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link));
+ } else {
+ //
+ // We've exhausted children that have already been parsed, so see if
+ // there's any more data and continue parsing out more children if there
+ // is.
+ //
+ NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size;
+ //
+ // Round up to 4 byte boundary
+ //
+ NextChildOffset += 3;
+ NextChildOffset &= ~(UINTN)3;
+ if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) {
+ //
+ // There's an unparsed child remaining in the stream, so create a new child node
+ //
+ Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ ASSERT (EFI_ERROR (ErrorStatus));
+ return ErrorStatus;
+ }
+ }
+ }
+}
+
+
+STATIC
+EFI_STATUS
+CreateChildNode (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN UINT32 ChildOffset,
+ OUT CORE_SECTION_CHILD_NODE **ChildNode
+ )
+/*++
+
+Routine Description:
+ Worker function. Constructor for new child nodes.
+
+Arguments:
+ Stream - Indicates the section stream in which to add the child.
+ ChildOffset - Indicates the offset in Stream that is the beginning
+ of the child section.
+ ChildNode - Indicates the Callee allocated and initialized child.
+
+Returns:
+ EFI_SUCCESS - Child node was found and returned.
+ EFI_OUT_OF_RESOURCES- Memory allocation failed.
+ EFI_PROTOCOL_ERROR - Encapsulation sections produce new stream handles when
+ the child node is created. If the section type is GUID
+ defined, and the extraction GUID does not exist, and
+ producing the stream requires the GUID, then a protocol
+ error is generated and no child is produced.
+ Values returned by OpenSectionStreamEx.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ EFI_COMPRESSION_SECTION *CompressionHeader;
+ EFI_GUID_DEFINED_SECTION *GuidedHeader;
+ EFI_TIANO_DECOMPRESS_PROTOCOL *Decompress;
+ EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;
+ VOID *NewStreamBuffer;
+ VOID *ScratchBuffer;
+ UINT32 ScratchSize;
+ UINTN NewStreamBufferSize;
+ UINT32 AuthenticationStatus;
+ UINT32 SectionLength;
+
+ CORE_SECTION_CHILD_NODE *Node;
+
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) (Stream->StreamBuffer + ChildOffset);
+
+ //
+ // Allocate a new node
+ //
+ *ChildNode = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_CHILD_NODE));
+ Node = *ChildNode;
+ if (Node == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Now initialize it
+ //
+ Node->Signature = CORE_SECTION_CHILD_SIGNATURE;
+ Node->Type = SectionHeader->Type;
+ Node->Size = SECTION_SIZE (SectionHeader);
+ Node->OffsetInStream = ChildOffset;
+ Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE;
+ Node->EncapsulationGuid = NULL;
+
+ //
+ // If it's an encapsulating section, then create the new section stream also
+ //
+ switch (Node->Type) {
+ case EFI_SECTION_COMPRESSION:
+ //
+ // Get the CompressionSectionHeader
+ //
+ ASSERT (Node->Size >= sizeof (EFI_COMPRESSION_SECTION));
+
+ CompressionHeader = (EFI_COMPRESSION_SECTION *) SectionHeader;
+
+ //
+ // Allocate space for the new stream
+ //
+ if (CompressionHeader->UncompressedLength > 0) {
+ NewStreamBufferSize = CompressionHeader->UncompressedLength;
+ NewStreamBuffer = CoreAllocateBootServicesPool (NewStreamBufferSize);
+ if (NewStreamBuffer == NULL) {
+ CoreFreePool (Node);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (CompressionHeader->CompressionType == EFI_NOT_COMPRESSED) {
+ //
+ // stream is not actually compressed, just encapsulated. So just copy it.
+ //
+ CopyMem (NewStreamBuffer, CompressionHeader + 1, NewStreamBufferSize);
+ } else if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION ||
+ CompressionHeader->CompressionType == EFI_CUSTOMIZED_COMPRESSION) {
+ //
+ // Decompress the stream
+ //
+ if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION) {
+ Status = CoreLocateProtocol (&gEfiTianoDecompressProtocolGuid, NULL, (VOID **)&Decompress);
+ } else {
+ Status = CoreLocateProtocol (&gEfiCustomizedDecompressProtocolGuid, NULL, (VOID **)&Decompress);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Decompress->GetInfo (
+ Decompress,
+ CompressionHeader + 1,
+ Node->Size - sizeof (EFI_COMPRESSION_SECTION),
+ (UINT32 *)&NewStreamBufferSize,
+ &ScratchSize
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (NewStreamBufferSize == CompressionHeader->UncompressedLength);
+
+ ScratchBuffer = CoreAllocateBootServicesPool (ScratchSize);
+ if (ScratchBuffer == NULL) {
+ CoreFreePool (Node);
+ CoreFreePool (NewStreamBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Decompress->Decompress (
+ Decompress,
+ CompressionHeader + 1,
+ Node->Size - sizeof (EFI_COMPRESSION_SECTION),
+ NewStreamBuffer,
+ (UINT32)NewStreamBufferSize,
+ ScratchBuffer,
+ ScratchSize
+ );
+ ASSERT_EFI_ERROR (Status);
+ CoreFreePool (ScratchBuffer);
+ }
+ } else {
+ NewStreamBuffer = NULL;
+ NewStreamBufferSize = 0;
+ }
+
+ Status = OpenSectionStreamEx (
+ NewStreamBufferSize,
+ NewStreamBuffer,
+ FALSE,
+ Stream->AuthenticationStatus,
+ &Node->EncapsulatedStreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (Node);
+ CoreFreePool (NewStreamBuffer);
+ return Status;
+ }
+ break;
+
+ case EFI_SECTION_GUID_DEFINED:
+ GuidedHeader = (EFI_GUID_DEFINED_SECTION *) SectionHeader;
+ Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid;
+ Status = CoreLocateProtocol (Node->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction);
+ if (!EFI_ERROR (Status)) {
+ //
+ // NewStreamBuffer is always allocated by ExtractSection... No caller
+ // allocation here.
+ //
+ Status = GuidedExtraction->ExtractSection (
+ GuidedExtraction,
+ GuidedHeader,
+ &NewStreamBuffer,
+ &NewStreamBufferSize,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (*ChildNode);
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // Make sure we initialize the new stream with the correct
+ // authentication status for both aggregate and local status fields.
+ //
+ if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
+ //
+ // OR in the parent stream's aggregate status.
+ //
+ AuthenticationStatus |= Stream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL;
+ } else {
+ //
+ // since there's no authentication data contributed by the section,
+ // just inherit the full value from our immediate parent.
+ //
+ AuthenticationStatus = Stream->AuthenticationStatus;
+ }
+
+ Status = OpenSectionStreamEx (
+ NewStreamBufferSize,
+ NewStreamBuffer,
+ FALSE,
+ AuthenticationStatus,
+ &Node->EncapsulatedStreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (*ChildNode);
+ CoreFreePool (NewStreamBuffer);
+ return Status;
+ }
+ } else {
+ //
+ // There's no GUIDed section extraction protocol available.
+ //
+ if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {
+ //
+ // If the section REQUIRES an extraction protocol, then we're toast
+ //
+ CoreFreePool (*ChildNode);
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // Figure out the proper authentication status
+ //
+ AuthenticationStatus = Stream->AuthenticationStatus;
+ if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
+ //
+ // The local status of the new stream is contained in
+ // AuthenticaionStatus. This value needs to be ORed into the
+ // Aggregate bits also...
+ //
+
+ //
+ // Clear out and initialize the local status
+ //
+ AuthenticationStatus &= ~EFI_LOCAL_AUTH_STATUS_ALL;
+ AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED;
+ //
+ // OR local status into aggregate status
+ //
+ AuthenticationStatus |= AuthenticationStatus >> 16;
+ }
+
+ SectionLength = SECTION_SIZE (GuidedHeader);
+ Status = OpenSectionStreamEx (
+ SectionLength - GuidedHeader->DataOffset,
+ (UINT8 *) GuidedHeader + GuidedHeader->DataOffset,
+ TRUE,
+ AuthenticationStatus,
+ &Node->EncapsulatedStreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (Node);
+ return Status;
+ }
+ }
+
+ if ((AuthenticationStatus & EFI_LOCAL_AUTH_STATUS_ALL) ==
+ (EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED)) {
+ //
+ // Need to register for RPN for when the required GUIDed extraction
+ // protocol becomes available. This will enable us to refresh the
+ // AuthenticationStatus cached in the Stream if it's ever requested
+ // again.
+ //
+ CreateGuidedExtractionRpnEvent (Stream, Node);
+ }
+
+ break;
+
+ default:
+
+ //
+ // Nothing to do if it's a leaf
+ //
+ break;
+ }
+
+ //
+ // Last, add the new child node to the stream
+ //
+ InsertTailList (&Stream->Children, &Node->Link);
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+VOID
+CreateGuidedExtractionRpnEvent (
+ IN CORE_SECTION_STREAM_NODE *ParentStream,
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ )
+/*++
+
+Routine Description:
+ Worker function. Constructor for RPN event if needed to keep AuthenticationStatus
+ cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...
+
+Arguments:
+ ParentStream - Indicates the parent of the ecnapsulation section (child)
+ ChildNode - Indicates the child node that is the encapsulation section.
+
+Returns:
+ None
+
+--*/
+{
+ RPN_EVENT_CONTEXT *Context;
+
+ //
+ // Allocate new event structure and context
+ //
+ Context = CoreAllocateBootServicesPool (sizeof (RPN_EVENT_CONTEXT));
+ ASSERT (Context != NULL);
+
+ Context->ChildNode = ChildNode;
+ Context->ParentStream = ParentStream;
+
+ Context->Event = CoreCreateProtocolNotifyEvent (
+ Context->ChildNode->EncapsulationGuid,
+ EFI_TPL_NOTIFY,
+ NotifyGuidedExtraction,
+ Context,
+ &Context->Registration,
+ FALSE
+ );
+}
+
+
+STATIC
+VOID
+EFIAPI
+NotifyGuidedExtraction (
+ IN EFI_EVENT Event,
+ IN VOID *RpnContext
+ )
+/*++
+
+Routine Description:
+ RPN callback function. Removes a stale section stream and re-initializes it
+ with an updated AuthenticationStatus.
+
+Arguments:
+ Event - The event that fired
+ RpnContext - A pointer to the context that allows us to identify
+ the relevent encapsulation...
+
+Returns:
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_GUID_DEFINED_SECTION *GuidedHeader;
+ EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;
+ VOID *NewStreamBuffer;
+ UINTN NewStreamBufferSize;
+ UINT32 AuthenticationStatus;
+ RPN_EVENT_CONTEXT *Context;
+
+ Context = RpnContext;
+
+ Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle);
+ if (!EFI_ERROR (Status)) {
+ //
+ // The stream closed successfully, so re-open the stream with correct AuthenticationStatus
+ //
+
+ GuidedHeader = (EFI_GUID_DEFINED_SECTION *)
+ (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream);
+ ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED);
+
+ Status = CoreLocateProtocol (Context->ChildNode->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction);
+ ASSERT_EFI_ERROR (Status);
+
+
+ Status = GuidedExtraction->ExtractSection (
+ GuidedExtraction,
+ GuidedHeader,
+ &NewStreamBuffer,
+ &NewStreamBufferSize,
+ &AuthenticationStatus
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // OR in the parent stream's aggregagate status.
+ //
+ AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL;
+ Status = OpenSectionStreamEx (
+ NewStreamBufferSize,
+ NewStreamBuffer,
+ FALSE,
+ AuthenticationStatus,
+ &Context->ChildNode->EncapsulatedStreamHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // If above, the stream did not close successfully, it indicates it's
+ // alread been closed by someone, so just destroy the event and be done with
+ // it.
+ //
+
+ CoreCloseEvent (Event);
+ CoreFreePool (Context);
+}
+
+
+STATIC
+VOID
+FreeChildNode (
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ )
+/*++
+
+Routine Description:
+ Worker function. Destructor for child nodes.
+
+Arguments:
+ ChildNode - Indicates the node to destroy
+
+Returns:
+ none
+
+--*/
+{
+ ASSERT (ChildNode->Signature == CORE_SECTION_CHILD_SIGNATURE);
+ //
+ // Remove the child from it's list
+ //
+ RemoveEntryList (&ChildNode->Link);
+
+ if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
+ //
+ // If it's an encapsulating section, we close the resulting section stream.
+ // CloseSectionStream will free all memory associated with the stream.
+ //
+ CloseSectionStream (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle);
+ }
+ //
+ // Last, free the child node itself
+ //
+ CoreFreePool (ChildNode);
+}
+
+
+STATIC
+EFI_STATUS
+OpenSectionStreamEx (
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ IN BOOLEAN AllocateBuffer,
+ IN UINT32 AuthenticationStatus,
+ OUT UINTN *SectionStreamHandle
+ )
+/*++
+
+ Routine Description:
+ Worker function. Constructor for section streams.
+
+ Arguments:
+ SectionStreamLength - Size in bytes of the section stream.
+ SectionStream - Buffer containing the new section stream.
+ AllocateBuffer - Indicates whether the stream buffer is to be copied
+ or the input buffer is to be used in place.
+ AuthenticationStatus- Indicates the default authentication status for the
+ new stream.
+ SectionStreamHandle - A pointer to a caller allocated section stream handle.
+
+ Returns:
+ EFI_SUCCESS - Stream was added to stream database.
+ EFI_OUT_OF_RESOURCES - memory allocation failed.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *NewStream;
+ EFI_TPL OldTpl;
+
+ //
+ // Allocate a new stream
+ //
+ NewStream = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_STREAM_NODE));
+ if (NewStream == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (AllocateBuffer) {
+ //
+ // if we're here, we're double buffering, allocate the buffer and copy the
+ // data in
+ //
+ if (SectionStreamLength > 0) {
+ NewStream->StreamBuffer = CoreAllocateBootServicesPool (SectionStreamLength);
+ if (NewStream->StreamBuffer == NULL) {
+ CoreFreePool (NewStream);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy in stream data
+ //
+ CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);
+ } else {
+ //
+ // It's possible to have a zero length section stream.
+ //
+ NewStream->StreamBuffer = NULL;
+ }
+ } else {
+ //
+ // If were here, the caller has supplied the buffer (it's an internal call)
+ // so just assign the buffer. This happens when we open section streams
+ // as a result of expanding an encapsulating section.
+ //
+ NewStream->StreamBuffer = SectionStream;
+ }
+
+ //
+ // Initialize the rest of the section stream
+ //
+ NewStream->Signature = CORE_SECTION_STREAM_SIGNATURE;
+ NewStream->StreamHandle = (UINTN) NewStream;
+ NewStream->StreamLength = SectionStreamLength;
+ InitializeListHead (&NewStream->Children);
+ NewStream->AuthenticationStatus = AuthenticationStatus;
+
+ //
+ // Add new stream to stream list
+ //
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+ InsertTailList (&mStreamRoot, &NewStream->Link);
+ CoreRestoreTpl (OldTpl);
+
+ *SectionStreamHandle = NewStream->StreamHandle;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+FindStreamNode (
+ IN UINTN SearchHandle,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream
+ )
+/*++
+
+ Routine Description:
+ Worker function. Search stream database for requested stream handle.
+
+ Arguments:
+ SearchHandle - Indicates which stream to look for.
+ FoundStream - Output pointer to the found stream.
+
+ Returns:
+ EFI_SUCCESS - StreamHandle was found and *FoundStream contains
+ the stream node.
+ EFI_NOT_FOUND - SearchHandle was not found in the stream database.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *StreamNode;
+
+ if (!IsListEmpty (&mStreamRoot)) {
+ StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot));
+ for (;;) {
+ if (StreamNode->StreamHandle == SearchHandle) {
+ *FoundStream = StreamNode;
+ return EFI_SUCCESS;
+ } else if (IsNodeAtEnd (&mStreamRoot, &StreamNode->Link)) {
+ break;
+ } else {
+ StreamNode = STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot, &StreamNode->Link));
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+STATIC
+BOOLEAN
+IsValidSectionStream (
+ IN VOID *SectionStream,
+ IN UINTN SectionStreamLength
+ )
+/*++
+
+Routine Description:
+ Check if a stream is valid.
+
+Arguments:
+ SectionStream - The section stream to be checked
+ SectionStreamLength - The length of section stream
+
+Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ UINTN TotalLength;
+ UINTN SectionLength;
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ EFI_COMMON_SECTION_HEADER *NextSectionHeader;
+
+ TotalLength = 0;
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;
+
+ while (TotalLength < SectionStreamLength) {
+ SectionLength = SECTION_SIZE (SectionHeader);
+ TotalLength += SectionLength;
+
+ if (TotalLength == SectionStreamLength) {
+ return TRUE;
+ }
+
+ //
+ // Move to the next byte following the section...
+ //
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);
+
+ //
+ // Figure out where the next section begins
+ //
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) SectionHeader + 3);
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader & ~(UINTN)3);
+ TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;
+ SectionHeader = NextSectionHeader;
+ }
+
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/EdkModulePkg/Core/Dxe/build.xml b/EdkModulePkg/Core/Dxe/build.xml
new file mode 100644
index 0000000000..1041d64072
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="DxeMain"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Core\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="DxeMain">
+ <GenBuild baseName="DxeMain" mbdFilename="${MODULE_DIR}\DxeMain.mbd" msaFilename="${MODULE_DIR}\DxeMain.msa"/>
+ </target>
+ <target depends="DxeMain_clean" name="clean"/>
+ <target depends="DxeMain_cleanall" name="cleanall"/>
+ <target name="DxeMain_clean">
+ <OutputDirSetup baseName="DxeMain" mbdFilename="${MODULE_DIR}\DxeMain.mbd" msaFilename="${MODULE_DIR}\DxeMain.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\DxeMain_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\DxeMain_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="DxeMain_cleanall">
+ <OutputDirSetup baseName="DxeMain" mbdFilename="${MODULE_DIR}\DxeMain.mbd" msaFilename="${MODULE_DIR}\DxeMain.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\DxeMain_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\DxeMain_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**DxeMain*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Core/Dxe/exec.h b/EdkModulePkg/Core/Dxe/exec.h
new file mode 100644
index 0000000000..e7b0f7b660
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/exec.h
@@ -0,0 +1,209 @@
+/*++
+
+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:
+
+ exec.h
+
+Abstract:
+
+ EFI Event support
+
+--*/
+
+#ifndef _EXEC_H_
+#define _EXEC_H_
+
+#define VALID_TPL(a) ((a) <= EFI_TPL_HIGH_LEVEL)
+
+//
+// EFI_EVENT
+//
+
+
+
+#define EVENT_SIGNATURE EFI_SIGNATURE_32('e','v','n','t')
+typedef struct {
+ UINTN Signature;
+ UINT32 Type;
+ UINT32 SignalCount;
+
+ //
+ // Entry if the event is registered to be signalled
+ //
+
+ LIST_ENTRY SignalLink;
+
+ //
+ // Notification information for this event
+ //
+
+ EFI_TPL NotifyTpl;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ VOID *NotifyContext;
+ EFI_GUID EventGroup;
+ LIST_ENTRY NotifyLink;
+ BOOLEAN ExFlag;
+
+ //
+ // A list of all runtime events
+ //
+ LIST_ENTRY RuntimeLink;
+
+ //
+ // Information by event type
+ //
+
+ union {
+ //
+ // For timer events
+ //
+ struct {
+ LIST_ENTRY Link;
+ UINT64 TriggerTime;
+ UINT64 Period;
+ } Timer;
+ } u;
+
+} IEVENT;
+
+//
+// Internal prototypes
+//
+
+VOID
+CoreDispatchEventNotifies (
+ IN EFI_TPL Priority
+ )
+/*++
+
+Routine Description:
+
+ Dispatches all pending events.
+
+Arguments:
+
+ Priority - The task priority level of event notifications to dispatch
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+UINTN
+CoreHighestSetBit (
+ IN UINTN Number
+ )
+/*++
+
+Routine Description:
+
+ Return the highest set bit
+
+Arguments:
+
+ Number - The value to check
+
+Returns:
+
+ Bit position of the highest set bit
+
+--*/
+;
+
+
+BOOLEAN
+GetInterruptState (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Disables CPU interrupts.
+
+Arguments:
+
+ This - Protocol instance structure
+
+ State - Pointer to the CPU's current interrupt state
+
+Returns:
+
+ EFI_SUCCESS - If interrupts were disabled in the CPU.
+
+ EFI_INVALID_PARAMETER - State is NULL.
+
+--*/
+;
+
+//
+// Exported functions
+//
+
+VOID
+CoreEventVirtualAddressFixup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ A function out of date, should be removed.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+VOID
+CoreInitializeTimer (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes timer support
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+//
+// extern data declarations
+//
+
+extern EFI_LOCK gEventQueueLock;
+extern UINTN gEventPending;
+extern LIST_ENTRY gEventQueue[];
+extern LIST_ENTRY gEventSignalQueue;
+extern UINT8 gHSB[];
+extern LIST_ENTRY mRuntimeEventList;
+
+#endif
diff --git a/EdkModulePkg/Core/Dxe/gcd.h b/EdkModulePkg/Core/Dxe/gcd.h
new file mode 100644
index 0000000000..445821e913
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/gcd.h
@@ -0,0 +1,51 @@
+/*++
+
+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:
+
+ gcd.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _GCD_H
+#define _GCD_H
+
+//
+// GCD Operations
+//
+#define GCD_MEMORY_SPACE_OPERATION 0x20
+#define GCD_IO_SPACE_OPERATION 0x40
+
+#define GCD_ADD_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 0)
+#define GCD_ALLOCATE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 1)
+#define GCD_FREE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 2)
+#define GCD_REMOVE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 3)
+#define GCD_SET_ATTRIBUTES_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 4)
+
+#define GCD_ADD_IO_OPERATION (GCD_IO_SPACE_OPERATION | 0)
+#define GCD_ALLOCATE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 1)
+#define GCD_FREE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 2)
+#define GCD_REMOVE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 3)
+
+//
+// The data structure used to convert from GCD attributes to EFI Memory Map attributes
+//
+typedef struct {
+ UINT64 Attribute;
+ UINT64 Capability;
+ BOOLEAN Memory;
+} GCD_ATTRIBUTE_CONVERSION_ENTRY;
+
+#endif
diff --git a/EdkModulePkg/Core/Dxe/hand.h b/EdkModulePkg/Core/Dxe/hand.h
new file mode 100644
index 0000000000..c61af16234
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/hand.h
@@ -0,0 +1,337 @@
+/*++
+
+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:
+
+ hand.h
+
+Abstract:
+
+ EFI internal protocol definitions
+
+
+
+Revision History
+
+--*/
+
+#ifndef _HAND_H_
+#define _HAND_H_
+
+
+//
+// IHANDLE - contains a list of protocol handles
+//
+
+#define EFI_HANDLE_SIGNATURE EFI_SIGNATURE_32('h','n','d','l')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY AllHandles; // All handles list of IHANDLE
+ LIST_ENTRY Protocols; // List of PROTOCOL_INTERFACE's for this handle
+ UINTN LocateRequest; //
+ UINT64 Key; // The Handle Database Key value when this handle was last created or modified
+} IHANDLE;
+
+#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
+
+
+//
+// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol
+// database. Each handler that supports this protocol is listed, along
+// with a list of registered notifies.
+//
+
+#define PROTOCOL_ENTRY_SIGNATURE EFI_SIGNATURE_32('p','r','t','e')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY AllEntries; // All entries
+ EFI_GUID ProtocolID; // ID of the protocol
+ LIST_ENTRY Protocols; // All protocol interfaces
+ LIST_ENTRY Notify; // Registerd notification handlers
+} PROTOCOL_ENTRY;
+
+//
+// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked
+// with a protocol interface structure
+//
+
+#define PROTOCOL_INTERFACE_SIGNATURE EFI_SIGNATURE_32('p','i','f','c')
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle; // Back pointer
+ LIST_ENTRY Link; // Link on IHANDLE.Protocols
+ LIST_ENTRY ByProtocol; // Link on PROTOCOL_ENTRY.Protocols
+ PROTOCOL_ENTRY *Protocol; // The protocol ID
+ VOID *Interface; // The interface value
+
+ LIST_ENTRY OpenList; // OPEN_PROTOCOL_DATA list.
+ UINTN OpenListCount;
+
+ EFI_HANDLE ControllerHandle;
+
+} PROTOCOL_INTERFACE;
+
+#define OPEN_PROTOCOL_DATA_SIGNATURE EFI_SIGNATURE_32('p','o','d','l')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_HANDLE AgentHandle;
+ EFI_HANDLE ControllerHandle;
+ UINT32 Attributes;
+ UINT32 OpenCount;
+} OPEN_PROTOCOL_DATA;
+
+
+//
+// PROTOCOL_NOTIFY - used for each register notification for a protocol
+//
+
+#define PROTOCOL_NOTIFY_SIGNATURE EFI_SIGNATURE_32('p','r','t','n')
+typedef struct {
+ UINTN Signature;
+ PROTOCOL_ENTRY *Protocol;
+ LIST_ENTRY Link; // All notifications for this protocol
+ EFI_EVENT Event; // Event to notify
+ LIST_ENTRY *Position; // Last position notified
+} PROTOCOL_NOTIFY;
+
+//
+// Internal prototypes
+//
+
+
+PROTOCOL_ENTRY *
+CoreFindProtocolEntry (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN Create
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol entry for the requested protocol.
+
+ The gProtocolDatabaseLock must be owned
+
+Arguments:
+
+ Protocol - The ID of the protocol
+
+ Create - Create a new entry if not found
+
+Returns:
+
+ Protocol entry
+
+--*/
+;
+
+VOID
+CoreNotifyProtocolEntry (
+ IN PROTOCOL_ENTRY *ProtEntry
+ )
+/*++
+
+Routine Description:
+
+ Signal event for every protocol in protocol entry.
+
+Arguments:
+
+ ProtEntry - Protocol entry
+
+Returns:
+
+--*/
+;
+
+PROTOCOL_INTERFACE *
+CoreFindProtocolInterface (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol instance for the requested handle and protocol.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ Handle - The handle to search the protocol on
+
+ Protocol - GUID of the protocol
+
+ Interface - The interface for the protocol being searched
+
+Returns:
+
+ Protocol instance (NULL: Not found)
+
+--*/
+;
+
+PROTOCOL_INTERFACE *
+CoreRemoveInterfaceFromProtocol (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Removes Protocol from the protocol list (but not the handle list).
+
+Arguments:
+
+ Handle - The handle to remove protocol on.
+
+ Protocol - GUID of the protocol to be moved
+
+ Interface - The interface of the protocol
+
+Returns:
+
+ Protocol Entry
+
+--*/
+;
+
+EFI_STATUS
+CoreUnregisterProtocolNotify (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Removes all the events in the protocol database that match Event.
+
+Arguments:
+
+ Event - The event to search for in the protocol database.
+
+Returns:
+
+ EFI_SUCCESS when done searching the entire database.
+
+--*/
+;
+
+EFI_STATUS
+CoreDisconnectControllersUsingProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN PROTOCOL_INTERFACE *Prot
+ )
+/*++
+
+Routine Description:
+
+ Attempts to disconnect all drivers that are using the protocol interface being queried.
+ If failed, reconnect all drivers disconnected.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ UserHandle - The handle on which the protocol is installed
+ Prot - The protocol to disconnect drivers from
+
+Returns:
+
+ EFI_SUCCESS - Drivers using the protocol interface are all disconnected
+ EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers
+
+--*/
+;
+
+VOID
+CoreAcquireProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acquire lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreReleaseProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Release lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_STATUS
+CoreValidateHandle (
+ IN EFI_HANDLE UserHandle
+ )
+/*++
+
+Routine Description:
+
+ Check whether a handle is a valid EFI_HANDLE
+
+Arguments:
+
+ UserHandle - The handle to check
+
+Returns:
+
+ EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE.
+
+ EFI_SUCCESS - The handle is valid EFI_HANDLE.
+
+--*/
+;
+
+//
+// Externs
+//
+
+extern EFI_LOCK gProtocolDatabaseLock;
+extern LIST_ENTRY gHandleList;
+extern UINT64 gHandleDatabaseKey;
+
+#endif
diff --git a/EdkModulePkg/Core/Dxe/imem.h b/EdkModulePkg/Core/Dxe/imem.h
new file mode 100644
index 0000000000..e1f8215eb7
--- /dev/null
+++ b/EdkModulePkg/Core/Dxe/imem.h
@@ -0,0 +1,227 @@
+/*++
+
+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:
+
+ imem.h
+
+Abstract:
+
+ Head file to imem.h
+
+
+Revision History
+
+--*/
+
+#ifndef _IMEM_H_
+#define _IMEM_H_
+
+#if defined (MDE_CPU_IPF)
+//
+// For Itanium machines make the default allocations 8K aligned
+//
+#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE * 2)
+#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE * 2)
+
+#else
+//
+// For genric EFI machines make the default allocations 4K aligned
+//
+#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE)
+#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE)
+
+#endif
+
+
+//
+// MEMORY_MAP_ENTRY
+//
+
+#define MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('m','m','a','p')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ BOOLEAN FromPool;
+
+ EFI_MEMORY_TYPE Type;
+ UINT64 Start;
+ UINT64 End;
+
+ UINT64 VirtualStart;
+ UINT64 Attribute;
+} MEMORY_MAP;
+
+//
+// Internal prototypes
+//
+
+VOID *
+CoreAllocatePoolPages (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN NumberOfPages,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Used by the pool functions to allocate pages
+ to back pool allocation requests.
+
+Arguments:
+
+ PoolType - The type of memory for the new pool pages
+
+ NumberOfPages - No of pages to allocate
+
+ Alignment - Bits to align.
+
+Returns:
+
+ The allocated memory, or NULL
+
+--*/
+;
+
+
+VOID
+CoreFreePoolPages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Frees pool pages allocated via AllocatePoolPages ()
+
+Arguments:
+
+ Memory - The base address to free
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+VOID *
+CoreAllocatePoolI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Internal function to allocate pool of a particular type.
+
+ Caller must have the memory lock held
+
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+Returns:
+
+ The allocate pool, or NULL
+
+--*/
+;
+
+
+EFI_STATUS
+CoreFreePoolI (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Internal function to free a pool entry.
+
+ Caller must have the memory lock held
+
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer not valid
+
+ EFI_SUCCESS - Buffer successfully freed.
+
+--*/
+;
+
+
+VOID
+CoreAcquireMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by gaining lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreReleaseMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+//
+// Internal Global data
+//
+
+extern EFI_LOCK gMemoryLock;
+extern LIST_ENTRY gMemoryMap;
+extern MEMORY_MAP *gMemoryLastConvert;
+extern LIST_ENTRY mGcdMemorySpaceMap;
+#endif
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.dxs b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.dxs
new file mode 100644
index 0000000000..6370d86cbf
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.dxs
@@ -0,0 +1,29 @@
+/*++
+
+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:
+
+ DxeIpl.dxs
+
+Abstract:
+
+ Dependency expression file for DXE Initial Program Loader PEIM.
+
+--*/
+
+#include <AutoGen.h>
+#include <PeimDepex.h>
+
+DEPENDENCY_START
+ EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID
+DEPENDENCY_END
+
+
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h
new file mode 100644
index 0000000000..bc50666df6
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h
@@ -0,0 +1,146 @@
+/*++
+
+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:
+
+ DxeIpl.h
+
+Abstract:
+
+--*/
+
+#ifndef __PEI_DXEIPL_H__
+#define __PEI_DXEIPL_H__
+
+#define STACK_SIZE 0x20000
+#define BSP_STORE_SIZE 0x4000
+
+extern BOOLEAN gInMemory;
+
+VOID
+SwitchIplStacks (
+ VOID *EntryPoint,
+ UINTN Parameter1,
+ UINTN Parameter2,
+ VOID *NewStack,
+ VOID *NewBsp
+ )
+;
+
+EFI_STATUS
+PeiFindFile (
+ IN UINT8 Type,
+ IN UINT16 SectionType,
+ OUT EFI_GUID *FileName,
+ OUT VOID **Pe32Data
+ )
+;
+
+EFI_STATUS
+PeiLoadFile (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
+ IN VOID *Pe32Data,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+;
+
+
+EFI_STATUS
+CreateArchSpecificHobs (
+ OUT EFI_PHYSICAL_ADDRESS *BspStore
+ )
+;
+
+EFI_STATUS
+GetImageReadFunction (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+;
+
+EFI_STATUS
+PeiImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+DxeIplLoadFile (
+ IN EFI_PEI_FV_FILE_LOADER_PPI *This,
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ );
+
+EFI_STATUS
+ShadowDxeIpl (
+ IN EFI_FFS_FILE_HEADER *DxeIpl,
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader
+ );
+
+EFI_STATUS
+EFIAPI
+DxeLoadCore (
+ IN EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ );
+
+EFI_STATUS
+PeiProcessFile (
+ IN UINT16 SectionType,
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ OUT VOID **Pe32Data
+ );
+
+EFI_STATUS
+EFIAPI
+PeimInitializeDxeIpl (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+EFI_STATUS
+PeiLoadx64File (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
+ IN VOID *Pe32Data,
+ IN EFI_MEMORY_TYPE MemoryType,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+;
+
+EFI_PHYSICAL_ADDRESS
+CreateIdentityMappingPageTables (
+ IN UINT32 NumberOfProcessorPhysicalAddressBits
+ )
+;
+
+VOID
+ActivateLongMode (
+ IN EFI_PHYSICAL_ADDRESS PageTables,
+ IN EFI_PHYSICAL_ADDRESS HobStart,
+ IN EFI_PHYSICAL_ADDRESS Stack,
+ IN EFI_PHYSICAL_ADDRESS CodeEntryPoint1,
+ IN EFI_PHYSICAL_ADDRESS CodeEntryPoint2
+ );
+
+VOID
+LoadGo64Gdt();
+
+#endif
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.mbd b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.mbd
new file mode 100644
index 0000000000..a604fccf08
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.mbd
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>DxeIpl</BaseName>
+ <Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00020000</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-22 18:54</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>PeimEntryPoint</Library>
+ <Library>PeiMemoryLib</Library>
+ <Library>PeiCoreLib</Library>
+ <Library>PeiServicesTablePointerLib</Library>
+ <Library>PeiHobLib</Library>
+ <Library>BaseCacheMaintenanceLib</Library>
+ <Library>BaseUefiTianoDecompressLib</Library>
+ <Library>BaseCustomDecompressLibNull</Library>
+ <Library>PeiReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>BaseLib</Library>
+ <Library>PeiMemoryAllocationLib</Library>
+ <Arch ArchType="IA32">
+ <Library OverrideID="8888">EdkPeCoffLoaderLib</Library>
+ <Library OverrideID="8888">BasePeCoffLib</Library>
+ </Arch>
+ <Arch ArchType="X64">
+ <Library>EdkPeCoffLoaderLib</Library>
+ <Library>BasePeCoffLib</Library>
+ </Arch>
+ <Arch ArchType="IPF">
+ <Library>EdkPeCoffLoaderLib</Library>
+ <Library>BasePeCoffLib</Library>
+ </Arch>
+ <Arch ArchType="EBC">
+ <Library>EdkPeCoffLoaderLib</Library>
+ <Library>BasePeCoffLib</Library>
+ </Arch>
+ </Libraries>
+ <BuildOptions ToolChain="MSFT">
+ <ImageEntryPoint>_ModuleEntryPoint</ImageEntryPoint>
+ </BuildOptions>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa
new file mode 100644
index 0000000000..7d7d531cca
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>DxeIpl</BaseName>
+ <ModuleType>PEIM</ModuleType>
+ <ComponentType>PE32_PEIM</ComponentType>
+ <Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00020000</Version>
+ <Abstract>Component description file for DxeIpl module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>EFI_SPECIFICATION_VERSION 0x00000000</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-22 18:54</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeimEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">CacheMaintenanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">TianoDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">CustomDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiServicesTablePointerLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>DxeLoad.c</Filename>
+ <Filename>DxeIpl.dxs</Filename>
+ <Arch ArchType="IA32">
+ <Filename>ia32\ImageRead.c</Filename>
+ <Filename>ia32\DxeLoadFunc.c</Filename>
+ </Arch>
+ <Arch ArchType="X64">
+ <Filename>ia32\ImageRead.c</Filename>
+ <Filename>ia32\DxeLoadFunc.c</Filename>
+ </Arch>
+ <Arch ArchType="IPF">
+ <Filename>ipf\ImageRead.c</Filename>
+ <Filename>ipf\DxeLoadFunc.c</Filename>
+ </Arch>
+ <Arch ArchType="EBC">
+ <Filename>ia32\ImageRead.c</Filename>
+ <Filename>ia32\DxeLoadFunc.c</Filename>
+ </Arch>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="SOMETIMES_PRODUCED">Decompress</Protocol>
+ <Protocol Usage="SOMETIMES_PRODUCED">TianoDecompress</Protocol>
+ <Protocol Usage="SOMETIMES_PRODUCED">CustomizedDecompress</Protocol>
+ </Protocols>
+ <Hobs>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="MEMORY_ALLOCATION">
+ <C_Name>gEfiHobMemoryAllocBspStoreGuid</C_Name>
+ <Guid>0x564b33cd, 0xc92a, 0x4593, 0x90, 0xbf, 0x24, 0x73, 0xe4, 0x3c, 0x63, 0x22</Guid>
+ </Hob>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
+ <C_Name>gEfiDecompressProtocolGuid</C_Name>
+ <Guid>0xd8117cfe, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d</Guid>
+ </Hob>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
+ <C_Name>gEfiTianoDecompressProtocolGuid</C_Name>
+ <Guid>0xe84cf29c, 0x191f, 0x4eae, 0x96, 0xe1, 0xf4, 0x6a, 0xec, 0xea, 0xea, 0x0b</Guid>
+ </Hob>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
+ <C_Name>gEfiCustomizedDecompressProtocolGuid</C_Name>
+ <Guid>0x9a44198e, 0xa4a2, 0x44e6, 0x8a, 0x1f, 0x39, 0xbe, 0xfd, 0xac, 0x89, 0x6f</Guid>
+ </Hob>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
+ <C_Name>gEfiPeiPeCoffLoaderGuid</C_Name>
+ <Guid>0xd8117cff, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d</Guid>
+ </Hob>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="MEMORY_ALLOCATION">
+ <C_Name>gEfiHobMemoryAllocModuleGuid</C_Name>
+ <Guid>0xf8e21975, 0x0899, 0x4f58, 0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6, 0xd7, 0x7a</Guid>
+ </Hob>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="FIRMWARE_VOLUME">
+ <Name>DecompressedFvmain.fv</Name>
+ </Hob>
+ </Hobs>
+ <PPIs>
+ <Ppi Usage="SOMETIMES_PRODUCED">DxeIpl</Ppi>
+ <Ppi Usage="SOMETIMES_PRODUCED">FvFileLoader</Ppi>
+ <Ppi Usage="SOMETIMES_PRODUCED">EndOfPeiSignal</Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">RecoveryModule</Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">S3Resume</Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">SectionExtraction</Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">Security</Ppi>
+ <Ppi Usage="PRIVATE">PeiInMemory</Ppi>
+ </PPIs>
+ <Guids>
+ <GuidEntry Usage="SOMETIMES_CONSUMED">
+ <C_Name>PeiPeCoffLoader</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>PeimInitializeDxeIpl</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.mbd b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.mbd
new file mode 100644
index 0000000000..2df91ecde8
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.mbd
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>DxeIpl</BaseName>
+ <Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00020000</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright 2004-2006, 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>
+ <Created>2006-04-03 23:58</Created>
+ </MbdHeader>
+ <Libraries>
+ <Library>PeimEntryPoint</Library>
+ <Library>PeiMemoryLib</Library>
+ <Library>PeiCoreLib</Library>
+ <Library>PeiServicesTablePointerLib</Library>
+ <Library>PeiHobLib</Library>
+ <Library>BaseCacheMaintenanceLib</Library>
+ <Library>BaseUefiTianoDecompressLib</Library>
+ <Library>BaseCustomDecompressLibNull</Library>
+ <Library>PeiReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>BaseLib</Library>
+ <Library>PeiMemoryAllocationLib</Library>
+ <Library>PeiReportStatusCodeLib</Library>
+ <Arch ArchType="IA32" OverrideID="8888">
+ <Library>EdkPeCoffLoaderX64Lib</Library>
+ <Library>EdkPeCoffLoaderLib</Library>
+ <Library>BasePeCoffLib</Library>
+ </Arch>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa
new file mode 100644
index 0000000000..df4efbc285
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>DxeIpl</BaseName>
+ <ModuleType>PEIM</ModuleType>
+ <ComponentType>PE32_PEIM</ComponentType>
+ <Guid>86D70125-BAA3-4296-A62F-602BEBBB9081</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00020000</Version>
+ <Abstract>Component description file for DxeIpl module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright 2004-2006, 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>EFI_SPECIFICATION_VERSION 0x00000000</Specification>
+ <Created>2006-04-03 23:58</Created>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeimEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">CacheMaintenanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">TianoDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">CustomDecompressLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiServicesTablePointerLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkPeCoffLoaderX64Lib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>DxeIpl.dxs</Filename>
+ <Filename>DxeLoadX64.c</Filename>
+ <Arch ArchType="IA32">
+ <Filename>x64\ImageRead.c</Filename>
+ <Filename>x64\LongMode.asm</Filename>
+ <Filename>x64\DxeLoadFunc.c</Filename>
+ <Filename>x64\VirtualMemory.c</Filename>
+ </Arch>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">Decompress</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">TianoDecompress</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">CustomizedDecompress</Protocol>
+ </Protocols>
+ <PPIs>
+ <Ppi Usage="ALWAYS_CONSUMED">PeiInMemory</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">RecoveryModule</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">SectionExtraction</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">Security</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">DxeIpl</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">S3Resume</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">EndOfPeiSignal</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">FvFileLoader</Ppi>
+ </PPIs>
+ <Guids>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>PeiPeCoffLoader</C_Name>
+ </GuidEntry>
+ </Guids>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c b/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
new file mode 100644
index 0000000000..a181095813
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -0,0 +1,1010 @@
+/*++
+
+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:
+
+ DxeLoad.c
+
+Abstract:
+
+ Last PEIM.
+ Responsibility of this module is to load the DXE Core from a Firmware Volume.
+
+--*/
+
+#include <DxeIpl.h>
+
+BOOLEAN gInMemory = FALSE;
+
+//
+// Module Globals used in the DXE to PEI handoff
+// These must be module globals, so the stack can be switched
+//
+static EFI_DXE_IPL_PPI mDxeIplPpi = {
+ DxeLoadCore
+};
+
+static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {
+ DxeIplLoadFile
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiFvFileLoaderPpiGuid,
+ &mLoadFilePpi
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiDxeIplPpiGuid,
+ &mDxeIplPpi
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiInMemoryGuid,
+ NULL
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ NULL
+};
+
+DECOMPRESS_LIBRARY gEfiDecompress = {
+ UefiDecompressGetInfo,
+ UefiDecompress
+};
+
+DECOMPRESS_LIBRARY gTianoDecompress = {
+ TianoDecompressGetInfo,
+ TianoDecompress
+};
+
+DECOMPRESS_LIBRARY gCustomDecompress = {
+ CustomDecompressGetInfo,
+ CustomDecompress
+};
+
+STATIC
+UINTN
+GetOccupiedSize (
+ IN UINTN ActualSize,
+ IN UINTN Alignment
+ )
+{
+ UINTN OccupiedSize;
+
+ OccupiedSize = ActualSize;
+ while ((OccupiedSize & (Alignment - 1)) != 0) {
+ OccupiedSize++;
+ }
+
+ return OccupiedSize;
+}
+
+EFI_STATUS
+EFIAPI
+PeimInitializeDxeIpl (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ Initializes the Dxe Ipl PPI
+
+Arguments:
+
+ FfsHeader - Pointer to FFS file header
+ PeiServices - General purpose services available to every PEIM.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
+ EFI_BOOT_MODE BootMode;
+
+ Status = PeiCoreGetBootMode (&BootMode);
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiCoreLocatePpi (
+ &gPeiInMemoryGuid,
+ 0,
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // The DxeIpl has not yet been shadowed
+ //
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
+
+ //
+ // Shadow DxeIpl and then re-run its entry point
+ //
+ Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ } else {
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ //
+ // The DxeIpl has been shadowed
+ //
+ gInMemory = TRUE;
+
+ //
+ // Install LoadFile PPI
+ //
+ Status = PeiCoreInstallPpi (&mPpiLoadFile);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // Install DxeIpl PPI
+ //
+ PeiCoreInstallPpi (&mPpiList);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DxeLoadCore (
+ IN EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ )
+/*++
+
+Routine Description:
+
+ Main entry point to last PEIM
+
+Arguments:
+ This - Entry point for DXE IPL PPI
+ PeiServices - General purpose services available to every PEIM.
+ HobList - Address to the Pei HOB list
+
+Returns:
+
+ EFI_SUCCESS - DEX core was successfully loaded.
+ EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *TopOfStack;
+ VOID *BaseOfStack;
+ EFI_PHYSICAL_ADDRESS BspStore;
+ EFI_GUID DxeCoreFileName;
+ EFI_GUID FirmwareFileName;
+ VOID *Pe32Data;
+ EFI_PHYSICAL_ADDRESS DxeCoreAddress;
+ UINT64 DxeCoreSize;
+ EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;
+ EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
+ EFI_BOOT_MODE BootMode;
+ EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;
+ EFI_PEI_S3_RESUME_PPI *S3Resume;
+
+// PERF_START (PeiServices, L"DxeIpl", NULL, 0);
+ TopOfStack = NULL;
+ BaseOfStack = NULL;
+ BspStore = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // if in S3 Resume, restore configure
+ //
+ Status = PeiCoreGetBootMode (&BootMode);
+
+ if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiS3ResumePpiGuid,
+ 0,
+ NULL,
+ (VOID **)&S3Resume
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = S3Resume->S3RestoreConfig (PeiServices);
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Install the PEI Protocols that are shared between PEI and DXE
+ //
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
+ ASSERT (PeiEfiPeiPeCoffLoader != NULL);
+
+
+ //
+ // Allocate 128KB for the Stack
+ //
+ BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
+ ASSERT (BaseOfStack != NULL);
+
+ //
+ // Compute the top of the stack we were allocated. Pre-allocate a UINTN
+ // for safety.
+ //
+ TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - sizeof (UINTN));
+
+ //
+ // Add architecture-specifc HOBs (including the BspStore HOB)
+ //
+ Status = CreateArchSpecificHobs (&BspStore);
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Add HOB for the EFI Decompress Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiDecompressProtocolGuid,
+ (VOID *)&gEfiDecompress,
+ sizeof (gEfiDecompress)
+ );
+
+ //
+ // Add HOB for the Tiano Decompress Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiTianoDecompressProtocolGuid,
+ (VOID *)&gTianoDecompress,
+ sizeof (gTianoDecompress)
+ );
+
+ //
+ // Add HOB for the user customized Decompress Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiCustomizedDecompressProtocolGuid,
+ (VOID *)&gCustomDecompress,
+ sizeof (gCustomDecompress)
+ );
+
+ //
+ // Add HOB for the PE/COFF Loader Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiPeiPeCoffLoaderGuid,
+ (VOID *)&PeiEfiPeiPeCoffLoader,
+ sizeof (VOID *)
+ );
+
+ //
+ // See if we are in crisis recovery
+ //
+ Status = PeiCoreGetBootMode (&BootMode);
+
+ if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) {
+
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiRecoveryModulePpiGuid,
+ 0,
+ NULL,
+ (VOID **)&PeiRecovery
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Now should have a HOB with the DXE core w/ the old HOB destroyed
+ //
+ }
+
+ //
+ // Find the EFI_FV_FILETYPE_RAW type compressed Firmware Volume file in FTW spare block
+ // The file found will be processed by PeiProcessFile: It will first be decompressed to
+ // a normal FV, then a corresponding FV type hob will be built which is provided for DXE
+ // core to find and dispatch drivers in this FV. Because PeiProcessFile typically checks
+ // for EFI_FV_FILETYPE_DXE_CORE type file, in this condition we need not check returned
+ // status
+ //
+ Status = PeiFindFile (
+ EFI_FV_FILETYPE_RAW,
+ EFI_SECTION_PE32,
+ &FirmwareFileName,
+ &Pe32Data
+ );
+
+ //
+ // Find the DXE Core in a Firmware Volume
+ //
+ Status = PeiFindFile (
+ EFI_FV_FILETYPE_DXE_CORE,
+ EFI_SECTION_PE32,
+ &DxeCoreFileName,
+ &Pe32Data
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Load the DXE Core from a Firmware Volume
+ //
+ Status = PeiLoadFile (
+ PeiEfiPeiPeCoffLoader,
+ Pe32Data,
+ &DxeCoreAddress,
+ &DxeCoreSize,
+ &DxeCoreEntryPoint
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Transfer control to the DXE Core
+ // The handoff state is simply a pointer to the HOB list
+ //
+// PERF_END (PeiServices, L"DxeIpl", NULL, 0);
+
+ Status = PeiCoreInstallPpi (&mPpiSignal);
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Add HOB for the DXE Core
+ //
+ BuildModuleHob (
+ &DxeCoreFileName,
+ DxeCoreAddress,
+ DxeCoreSize,
+ DxeCoreEntryPoint
+ );
+
+ //
+ // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
+ );
+
+ DEBUG ((EFI_D_INFO, "DXE Core Entry\n"));
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
+ HobList.Raw,
+ (VOID *) (UINTN) BspStore,
+ TopOfStack
+ );
+
+ //
+ // If we get here, then the DXE Core returned. This is an error
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+EFI_STATUS
+PeiFindFile (
+ IN UINT8 Type,
+ IN UINT16 SectionType,
+ OUT EFI_GUID *FileName,
+ OUT VOID **Pe32Data
+ )
+/*++
+
+Routine Description:
+
+ Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
+ described in the HOB list. Able to search in a compression set in a FFS file.
+ But only one level of compression is supported, that is, not able to search
+ in a compression set that is within another compression set.
+
+Arguments:
+
+ Type - The Type of file to retrieve
+
+ SectionType - The type of section to retrieve from a file
+
+ FileName - The name of the file found in the Firmware Volume
+
+ Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
+
+Returns:
+
+ EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
+ the PE/COFF image is returned in Pe32Data
+
+ EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ VOID *SectionData;
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS Hob;
+
+
+ FwVolHeader = NULL;
+ FfsFileHeader = NULL;
+ SectionData = NULL;
+
+ //
+ // Foreach Firmware Volume, look for a specified type
+ // of file and break out when one is found
+ //
+ Hob.Raw = GetHobList ();
+ while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress);
+ Status = PeiCoreFfsFindNextFile (
+ Type,
+ FwVolHeader,
+ &FfsFileHeader
+ );
+ if (!EFI_ERROR (Status)) {
+ CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));
+ Status = PeiProcessFile (
+ SectionType,
+ FfsFileHeader,
+ Pe32Data
+ );
+ return Status;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+PeiLoadFile (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
+ IN VOID *Pe32Data,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ Loads and relocates a PE/COFF image into memory.
+
+Arguments:
+
+ PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
+
+ Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
+
+ ImageAddress - The base address of the relocated PE/COFF image
+
+ ImageSize - The size of the relocated PE/COFF image
+
+ EntryPoint - The entry point of the relocated PE/COFF image
+
+Returns:
+
+ EFI_SUCCESS - The file was loaded and relocated
+
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = Pe32Data;
+ Status = GetImageReadFunction (&ImageContext);
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate Memory for the image
+ //
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
+ ASSERT (ImageContext.ImageAddress != 0);
+
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+ *ImageAddress = ImageContext.ImageAddress;
+ *ImageSize = ImageContext.ImageSize;
+ *EntryPoint = ImageContext.EntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ShadowDxeIpl (
+ IN EFI_FFS_FILE_HEADER *DxeIplFileHeader,
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader
+ )
+/*++
+
+Routine Description:
+
+ Shadow the DXE IPL to a different memory location. This occurs after permanent
+ memory has been discovered.
+
+Arguments:
+
+ DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
+
+ PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
+
+Returns:
+
+ EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
+
+ EFI_ ERROR - The shadow was unsuccessful.
+
+
+--*/
+{
+ UINTN SectionLength;
+ UINTN OccupiedSectionLength;
+ EFI_PHYSICAL_ADDRESS DxeIplAddress;
+ UINT64 DxeIplSize;
+ EFI_PHYSICAL_ADDRESS DxeIplEntryPoint;
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER *Section;
+
+ Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1);
+
+ while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) {
+ SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
+ OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
+ }
+ //
+ // Relocate DxeIpl into memory by using loadfile service
+ //
+ Status = PeiLoadFile (
+ PeiEfiPeiPeCoffLoader,
+ (VOID *) (Section + 1),
+ &DxeIplAddress,
+ &DxeIplSize,
+ &DxeIplEntryPoint
+ );
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Install PeiInMemory to indicate the Dxeipl is shadowed
+ //
+ Status = PeiCoreInstallPpi (&mPpiPeiInMemory);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DxeIplLoadFile (
+ IN EFI_PEI_FV_FILE_LOADER_PPI *This,
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ Given a pointer to an FFS file containing a PE32 image, get the
+ information on the PE32 image, and then "load" it so that it
+ can be executed.
+
+Arguments:
+
+ This - pointer to our file loader protocol
+
+ FfsHeader - pointer to the FFS file header of the FFS file that
+ contains the PE32 image we want to load
+
+ ImageAddress - returned address where the PE32 image is loaded
+
+ ImageSize - returned size of the loaded PE32 image
+
+ EntryPoint - entry point to the loaded PE32 image
+
+Returns:
+
+ EFI_SUCCESS - The FFS file was successfully loaded.
+
+ EFI_ERROR - Unable to load the FFS file.
+
+--*/
+{
+ EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
+ EFI_STATUS Status;
+ VOID *Pe32Data;
+
+ Pe32Data = NULL;
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
+
+ //
+ // Preprocess the FFS file to get a pointer to the PE32 information
+ // in the enclosed PE32 image.
+ //
+ Status = PeiProcessFile (
+ EFI_SECTION_PE32,
+ FfsHeader,
+ &Pe32Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Load the PE image from the FFS file
+ //
+ Status = PeiLoadFile (
+ PeiEfiPeiPeCoffLoader,
+ Pe32Data,
+ ImageAddress,
+ ImageSize,
+ EntryPoint
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+PeiProcessFile (
+ IN UINT16 SectionType,
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ OUT VOID **Pe32Data
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ SectionType - The type of section in the FFS file to process.
+
+ FfsFileHeader - Pointer to the FFS file to process, looking for the
+ specified SectionType
+
+ Pe32Data - returned pointer to the start of the PE32 image found
+ in the FFS file.
+
+Returns:
+
+ EFI_SUCCESS - found the PE32 section in the FFS file
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *SectionData;
+ DECOMPRESS_LIBRARY *DecompressLibrary;
+ UINT8 *DstBuffer;
+ UINT8 *ScratchBuffer;
+ UINT32 DstBufferSize;
+ UINT32 ScratchBufferSize;
+ EFI_COMMON_SECTION_HEADER *CmpSection;
+ UINTN CmpSectionLength;
+ UINTN OccupiedCmpSectionLength;
+ VOID *CmpFileData;
+ UINTN CmpFileSize;
+ EFI_COMMON_SECTION_HEADER *Section;
+ UINTN SectionLength;
+ UINTN OccupiedSectionLength;
+ UINT64 FileSize;
+ EFI_GUID_DEFINED_SECTION *GuidedSectionHeader;
+ UINT32 AuthenticationStatus;
+ EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract;
+ UINT32 BufferSize;
+ UINT8 *Buffer;
+ EFI_PEI_SECURITY_PPI *Security;
+ BOOLEAN StartCrisisRecovery;
+ EFI_GUID TempGuid;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_COMPRESSION_SECTION *CompressionSection;
+
+ Status = PeiCoreFfsFindSectionData (
+ EFI_SECTION_COMPRESSION,
+ FfsFileHeader,
+ &SectionData
+ );
+
+ //
+ // Upon finding a DXE Core file, see if there is first a compression section
+ //
+ if (!EFI_ERROR (Status)) {
+ //
+ // Yes, there is a compression section, so extract the contents
+ // Decompress the image here
+ //
+ Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));
+
+ do {
+ SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
+ OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
+
+ //
+ // Was the DXE Core file encapsulated in a GUID'd section?
+ //
+ if (Section->Type == EFI_SECTION_GUID_DEFINED) {
+ //
+ // Locate the GUID'd Section Extractor
+ //
+ GuidedSectionHeader = (VOID *) (Section + 1);
+
+ //
+ // This following code constitutes the addition of the security model
+ // to the DXE IPL.
+ //
+ //
+ // Set a default authenticatino state
+ //
+ AuthenticationStatus = 0;
+
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiSectionExtractionPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SectionExtract
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Verify Authentication State
+ //
+ CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));
+
+ Status = SectionExtract->PeiGetSection (
+ GetPeiServicesTablePointer(),
+ SectionExtract,
+ (EFI_SECTION_TYPE *) &SectionType,
+ &TempGuid,
+ 0,
+ (VOID **) &Buffer,
+ &BufferSize,
+ &AuthenticationStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // If not ask the Security PPI, if exists, for disposition
+ //
+ //
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiSecurityPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&Security
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = Security->AuthenticationState (
+ GetPeiServicesTablePointer(),
+ (struct _EFI_PEI_SECURITY_PPI *) Security,
+ AuthenticationStatus,
+ FfsFileHeader,
+ &StartCrisisRecovery
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // If there is a security violation, report to caller and have
+ // the upper-level logic possible engender a crisis recovery
+ //
+ if (StartCrisisRecovery) {
+ return EFI_SECURITY_VIOLATION;
+ }
+ }
+
+ if (Section->Type == EFI_SECTION_PE32) {
+ //
+ // This is what we want
+ //
+ *Pe32Data = (VOID *) (Section + 1);
+ return EFI_SUCCESS;
+ } else if (Section->Type == EFI_SECTION_COMPRESSION) {
+ //
+ // This is a compression set, expand it
+ //
+ CompressionSection = (EFI_COMPRESSION_SECTION *) Section;
+
+ switch (CompressionSection->CompressionType) {
+ case EFI_STANDARD_COMPRESSION:
+ DecompressLibrary = &gTianoDecompress;
+ break;
+
+ case EFI_CUSTOMIZED_COMPRESSION:
+ //
+ // Load user customized compression protocol.
+ //
+ DecompressLibrary = &gCustomDecompress;
+ break;
+
+ case EFI_NOT_COMPRESSED:
+ default:
+ //
+ // Need to support not compressed file
+ //
+ ASSERT_EFI_ERROR (Status);
+ return EFI_NOT_FOUND;
+ }
+
+ Status = DecompressLibrary->GetInfo (
+ (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
+ (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
+ &DstBufferSize,
+ &ScratchBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // GetInfo failed
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate scratch buffer
+ //
+ ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
+ if (ScratchBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Allocate destination buffer
+ //
+ DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
+ if (DstBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Call decompress function
+ //
+ Status = DecompressLibrary->Decompress (
+ (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
+ DstBuffer,
+ ScratchBuffer
+ );
+
+ CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;
+ if (CmpSection->Type == EFI_SECTION_RAW) {
+ //
+ // Skip the section header and
+ // adjust the pointer alignment to 16
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16);
+
+ if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
+ FfsFileHeader = NULL;
+ BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);
+ Status = PeiCoreFfsFindNextFile (
+ EFI_FV_FILETYPE_DXE_CORE,
+ FvHeader,
+ &FfsFileHeader
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return PeiProcessFile (SectionType, FfsFileHeader, Pe32Data);
+ }
+ }
+ //
+ // Decompress successfully.
+ // Loop the decompressed data searching for expected section.
+ //
+ CmpFileData = (VOID *) DstBuffer;
+ CmpFileSize = DstBufferSize;
+ do {
+ CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;
+ if (CmpSection->Type == EFI_SECTION_PE32) {
+ //
+ // This is what we want
+ //
+ *Pe32Data = (VOID *) (CmpSection + 1);
+ return EFI_SUCCESS;
+ }
+
+ OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4);
+ CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);
+ } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);
+ }
+
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
+ FileSize = FfsFileHeader->Size[0] & 0xFF;
+ FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;
+ FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;
+ FileSize &= 0x00FFFFFF;
+ } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);
+
+ //
+ // End of the decompression activity
+ //
+ } else {
+
+ Status = PeiCoreFfsFindSectionData (
+ EFI_SECTION_PE32,
+ FfsFileHeader,
+ &SectionData
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = PeiCoreFfsFindSectionData (
+ EFI_SECTION_TE,
+ FfsFileHeader,
+ &SectionData
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ }
+
+ *Pe32Data = SectionData;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c b/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c
new file mode 100644
index 0000000000..6727bf4ca7
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c
@@ -0,0 +1,1018 @@
+/*++
+
+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:
+
+ DxeLoad.c
+
+Abstract:
+
+ Last PEIM.
+ Responsibility of this module is to load the DXE Core from a Firmware Volume.
+
+--*/
+
+#include <DxeIpl.h>
+
+#pragma warning( disable : 4305 )
+
+BOOLEAN gInMemory = FALSE;
+
+//
+// GUID for EM64T
+//
+#define EFI_PPI_NEEDED_BY_DXE \
+ { \
+ 0x4d37da42, 0x3a0c, 0x4eda, 0xb9, 0xeb, 0xbc, 0x0e, 0x1d, 0xb4, 0x71, 0x3b \
+ }
+EFI_GUID mPpiNeededByDxeGuid = EFI_PPI_NEEDED_BY_DXE;
+
+//
+// Module Globals used in the DXE to PEI handoff
+// These must be module globals, so the stack can be switched
+//
+static EFI_DXE_IPL_PPI mDxeIplPpi = {
+ DxeLoadCore
+};
+
+static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {
+ DxeIplLoadFile
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiFvFileLoaderPpiGuid,
+ &mLoadFilePpi
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiDxeIplPpiGuid,
+ &mDxeIplPpi
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiInMemoryGuid,
+ NULL
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ NULL
+};
+
+DECOMPRESS_LIBRARY gEfiDecompress = {
+ UefiDecompressGetInfo,
+ UefiDecompress
+};
+
+DECOMPRESS_LIBRARY gTianoDecompress = {
+ TianoDecompressGetInfo,
+ TianoDecompress
+};
+
+DECOMPRESS_LIBRARY gCustomDecompress = {
+ CustomDecompressGetInfo,
+ CustomDecompress
+};
+
+STATIC
+UINTN
+GetOccupiedSize (
+ IN UINTN ActualSize,
+ IN UINTN Alignment
+ )
+{
+ UINTN OccupiedSize;
+
+ OccupiedSize = ActualSize;
+ while ((OccupiedSize & (Alignment - 1)) != 0) {
+ OccupiedSize++;
+ }
+
+ return OccupiedSize;
+}
+
+EFI_STATUS
+EFIAPI
+PeimInitializeDxeIpl (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ Initializes the Dxe Ipl PPI
+
+Arguments:
+
+ FfsHeader - Pointer to FFS file header
+ PeiServices - General purpose services available to every PEIM.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
+ EFI_BOOT_MODE BootMode;
+
+ Status = PeiCoreGetBootMode (&BootMode);
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiCoreLocatePpi (
+ &gPeiInMemoryGuid,
+ 0,
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // The DxeIpl has not yet been shadowed
+ //
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
+
+ //
+ // Shadow DxeIpl and then re-run its entry point
+ //
+ Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ } else {
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ //
+ // The DxeIpl has been shadowed
+ //
+ gInMemory = TRUE;
+
+ //
+ // Install LoadFile PPI
+ //
+ Status = PeiCoreInstallPpi (&mPpiLoadFile);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // Install DxeIpl PPI
+ //
+ PeiCoreInstallPpi (&mPpiList);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DxeLoadCore (
+ IN EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ )
+/*++
+
+Routine Description:
+
+ Main entry point to last PEIM
+
+Arguments:
+
+ This - Entry point for DXE IPL PPI
+ PeiServices - General purpose services available to every PEIM.
+ HobList - Address to the Pei HOB list
+
+Returns:
+
+ EFI_SUCCESS - DEX core was successfully loaded.
+ EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TopOfStack;
+ EFI_PHYSICAL_ADDRESS BaseOfStack;
+ EFI_PHYSICAL_ADDRESS BspStore;
+ EFI_GUID DxeCoreFileName;
+ VOID *DxeCorePe32Data;
+ EFI_PHYSICAL_ADDRESS DxeCoreAddress;
+ UINT64 DxeCoreSize;
+ EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;
+ VOID *PpisNeededByDxePe32Data;
+ EFI_PHYSICAL_ADDRESS PpisNeededByDxeAddress;
+ UINT64 PpisNeededByDxeSize;
+ EFI_PHYSICAL_ADDRESS PpisNeededByDxeEntryPoint;
+ EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
+ EFI_BOOT_MODE BootMode;
+ EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;
+ EFI_PEI_S3_RESUME_PPI *S3Resume;
+ EFI_PHYSICAL_ADDRESS PageTables;
+
+ TopOfStack = 0;
+ BaseOfStack = 0;
+ BspStore = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // if in S3 Resume, restore configure
+ //
+ Status = PeiCoreGetBootMode (&BootMode);
+
+ if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiS3ResumePpiGuid,
+ 0,
+ NULL,
+ (VOID **)&S3Resume
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = S3Resume->S3RestoreConfig (PeiServices);
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Install the PEI Protocols that are shared between PEI and DXE
+ //
+#ifdef EFI_NT_EMULATOR
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
+ ASSERT (PeiEfiPeiPeCoffLoader != NULL);
+#else
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderX64Protocol ();
+#endif
+
+#if 0
+ Status = InstallEfiPeiPeCoffLoader64 (PeiServices, &PeiEfiPeiPeCoffLoader, NULL);
+ ASSERT_EFI_ERROR (Status);
+#endif
+ //
+ // Allocate 128KB for the Stack
+ //
+ PeiCoreAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
+ ASSERT (BaseOfStack != 0);
+
+ //
+ // Compute the top of the stack we were allocated. Pre-allocate a 32 bytes
+ // for safety (PpisNeededByDxe and DxeCore).
+ //
+ TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;
+
+ //
+ // Add architecture-specifc HOBs (including the BspStore HOB)
+ //
+ Status = CreateArchSpecificHobs (&BspStore);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // See if we are in crisis recovery
+ //
+ Status = PeiCoreGetBootMode (&BootMode);
+ if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) {
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiRecoveryModulePpiGuid,
+ 0,
+ NULL,
+ (VOID **)&PeiRecovery
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Find the DXE Core in a Firmware Volume
+ //
+ Status = PeiFindFile (
+ EFI_FV_FILETYPE_DXE_CORE,
+ EFI_SECTION_PE32,
+ &DxeCoreFileName,
+ &DxeCorePe32Data
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find the PpisNeededByDxe in a Firmware Volume
+ //
+ Status = PeiFindFile (
+ EFI_FV_FILETYPE_ALL,
+ EFI_SECTION_PE32,
+ &mPpiNeededByDxeGuid,
+ &PpisNeededByDxePe32Data
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Transfer control to the DXE Core
+ // The handoff state is simply a pointer to the HOB list
+ //
+ // PEI_PERF_END (PeiServices, L"DxeIpl", NULL, 0);
+
+ Status = PeiCoreInstallPpi (&mPpiSignal);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \
+ // memory, it may be corrupted when copying FV to high-end memory
+ LoadGo64Gdt();
+
+ //
+ // Limit to 36 bits of addressing for debug. Should get it from CPU
+ //
+ PageTables = CreateIdentityMappingPageTables (36);
+
+ //
+ // Load the PpiNeededByDxe from a Firmware Volume
+ //
+ Status = PeiLoadx64File (
+ PeiEfiPeiPeCoffLoader,
+ PpisNeededByDxePe32Data,
+ EfiBootServicesData,
+ &PpisNeededByDxeAddress,
+ &PpisNeededByDxeSize,
+ &PpisNeededByDxeEntryPoint
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Load the DXE Core from a Firmware Volume
+ //
+ Status = PeiLoadx64File (
+ PeiEfiPeiPeCoffLoader,
+ DxeCorePe32Data,
+ EfiBootServicesData,
+ &DxeCoreAddress,
+ &DxeCoreSize,
+ &DxeCoreEntryPoint
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ //
+ // Add HOB for the DXE Core
+ //
+ BuildModuleHob (
+ &DxeCoreFileName,
+ DxeCoreAddress,
+ DxeCoreSize,
+ DxeCoreEntryPoint
+ );
+
+ //
+ // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
+ );
+
+ DEBUG ((EFI_D_INFO, "DXE Core Entry\n"));
+ //
+ // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
+ // Call x64 drivers passing in single argument, a pointer to the HOBs.
+ //
+ ActivateLongMode (
+ PageTables,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),
+ TopOfStack,
+ PpisNeededByDxeEntryPoint,
+ DxeCoreEntryPoint
+ );
+
+ //
+ // If we get here, then the DXE Core returned. This is an error
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+EFI_STATUS
+PeiFindFile (
+ IN UINT8 Type,
+ IN UINT16 SectionType,
+ OUT EFI_GUID *FileName,
+ OUT VOID **Pe32Data
+ )
+/*++
+
+Routine Description:
+
+ Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
+ described in the HOB list. Able to search in a compression set in a FFS file.
+ But only one level of compression is supported, that is, not able to search
+ in a compression set that is within another compression set.
+
+Arguments:
+
+ Type - The Type of file to retrieve
+
+ SectionType - The type of section to retrieve from a file
+
+ FileName - The name of the file found in the Firmware Volume
+
+ Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
+
+Returns:
+
+ EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
+ the PE/COFF image is returned in Pe32Data
+
+ EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ VOID *SectionData;
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS Hob;
+
+
+ FwVolHeader = NULL;
+ FfsFileHeader = NULL;
+ SectionData = NULL;
+
+ //
+ // Foreach Firmware Volume, look for a specified type
+ // of file and break out when one is found
+ //
+ Hob.Raw = GetHobList ();
+ while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress);
+ Status = PeiCoreFfsFindNextFile (
+ Type,
+ FwVolHeader,
+ &FfsFileHeader
+ );
+ if (!EFI_ERROR (Status)) {
+ CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));
+ Status = PeiProcessFile (
+ SectionType,
+ FfsFileHeader,
+ Pe32Data
+ );
+ return Status;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+PeiLoadx64File (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
+ IN VOID *Pe32Data,
+ IN EFI_MEMORY_TYPE MemoryType,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ Loads and relocates a PE/COFF image into memory.
+
+Arguments:
+
+ PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
+
+ Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
+
+ ImageAddress - The base address of the relocated PE/COFF image
+
+ ImageSize - The size of the relocated PE/COFF image
+
+ EntryPoint - The entry point of the relocated PE/COFF image
+
+Returns:
+
+ EFI_SUCCESS - The file was loaded and relocated
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ EFI_PHYSICAL_ADDRESS MemoryBuffer;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = Pe32Data;
+ Status = GetImageReadFunction (&ImageContext);
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate Memory for the image
+ //
+ //
+ // Allocate Memory for the image
+ //
+ PeiCoreAllocatePages (MemoryType, EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), &MemoryBuffer);
+ ImageContext.ImageAddress = MemoryBuffer;
+ ASSERT (ImageContext.ImageAddress != 0);
+
+ //
+ // Load the image to our new buffer
+ //
+
+ Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+ *ImageAddress = ImageContext.ImageAddress;
+ *ImageSize = ImageContext.ImageSize;
+ *EntryPoint = ImageContext.EntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ShadowDxeIpl (
+ IN EFI_FFS_FILE_HEADER *DxeIplFileHeader,
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader
+ )
+/*++
+
+Routine Description:
+
+ Shadow the DXE IPL to a different memory location. This occurs after permanent
+ memory has been discovered.
+
+Arguments:
+
+ DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
+
+ PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
+
+Returns:
+
+ EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
+
+ EFI_ ERROR - The shadow was unsuccessful.
+
+
+--*/
+{
+ UINTN SectionLength;
+ UINTN OccupiedSectionLength;
+ EFI_PHYSICAL_ADDRESS DxeIplAddress;
+ UINT64 DxeIplSize;
+ EFI_PHYSICAL_ADDRESS DxeIplEntryPoint;
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER *Section;
+
+ Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1);
+
+ while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) {
+ SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
+ OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
+ }
+
+ //
+ // Relocate DxeIpl into memory by using loadfile service
+ //
+ Status = PeiLoadx64File (
+ PeiEfiPeiPeCoffLoader,
+ (VOID *) (Section + 1),
+ EfiBootServicesData,
+ &DxeIplAddress,
+ &DxeIplSize,
+ &DxeIplEntryPoint
+ );
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Install PeiInMemory to indicate the Dxeipl is shadowed
+ //
+ Status = PeiCoreInstallPpi (&mPpiPeiInMemory);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DxeIplLoadFile (
+ IN EFI_PEI_FV_FILE_LOADER_PPI *This,
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ Given a pointer to an FFS file containing a PE32 image, get the
+ information on the PE32 image, and then "load" it so that it
+ can be executed.
+
+Arguments:
+
+ This - pointer to our file loader protocol
+ FfsHeader - pointer to the FFS file header of the FFS file that
+ contains the PE32 image we want to load
+ ImageAddress - returned address where the PE32 image is loaded
+ ImageSize - returned size of the loaded PE32 image
+ EntryPoint - entry point to the loaded PE32 image
+
+Returns:
+
+ EFI_SUCCESS - The FFS file was successfully loaded.
+ EFI_ERROR - Unable to load the FFS file.
+
+--*/
+{
+ EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
+ EFI_STATUS Status;
+ VOID *Pe32Data;
+
+ Pe32Data = NULL;
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
+
+ //
+ // Preprocess the FFS file to get a pointer to the PE32 information
+ // in the enclosed PE32 image.
+ //
+ Status = PeiProcessFile (
+ EFI_SECTION_PE32,
+ FfsHeader,
+ &Pe32Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Load the PE image from the FFS file
+ //
+ Status = PeiLoadx64File (
+ PeiEfiPeiPeCoffLoader,
+ Pe32Data,
+ EfiBootServicesData,
+ ImageAddress,
+ ImageSize,
+ EntryPoint
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+PeiProcessFile (
+ IN UINT16 SectionType,
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ OUT VOID **Pe32Data
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ SectionType - The type of section in the FFS file to process.
+
+ FfsFileHeader - Pointer to the FFS file to process, looking for the
+ specified SectionType
+
+ Pe32Data - returned pointer to the start of the PE32 image found
+ in the FFS file.
+
+Returns:
+
+ EFI_SUCCESS - found the PE32 section in the FFS file
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *SectionData;
+ DECOMPRESS_LIBRARY *DecompressLibrary;
+ UINT8 *DstBuffer;
+ UINT8 *ScratchBuffer;
+ UINT32 DstBufferSize;
+ UINT32 ScratchBufferSize;
+ EFI_COMMON_SECTION_HEADER *CmpSection;
+ UINTN CmpSectionLength;
+ UINTN OccupiedCmpSectionLength;
+ VOID *CmpFileData;
+ UINTN CmpFileSize;
+ EFI_COMMON_SECTION_HEADER *Section;
+ UINTN SectionLength;
+ UINTN OccupiedSectionLength;
+ UINT64 FileSize;
+ EFI_GUID_DEFINED_SECTION *GuidedSectionHeader;
+ UINT32 AuthenticationStatus;
+ EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract;
+ UINT32 BufferSize;
+ UINT8 *Buffer;
+ EFI_PEI_SECURITY_PPI *Security;
+ BOOLEAN StartCrisisRecovery;
+ EFI_GUID TempGuid;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_COMPRESSION_SECTION *CompressionSection;
+
+ Status = PeiCoreFfsFindSectionData (
+ EFI_SECTION_COMPRESSION,
+ FfsFileHeader,
+ &SectionData
+ );
+
+ //
+ // Upon finding a DXE Core file, see if there is first a compression section
+ //
+ if (!EFI_ERROR (Status)) {
+ //
+ // Yes, there is a compression section, so extract the contents
+ // Decompress the image here
+ //
+ Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));
+
+ do {
+ SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
+ OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
+
+ //
+ // Was the DXE Core file encapsulated in a GUID'd section?
+ //
+ if (Section->Type == EFI_SECTION_GUID_DEFINED) {
+ //
+ // Locate the GUID'd Section Extractor
+ //
+ GuidedSectionHeader = (VOID *) (Section + 1);
+
+ //
+ // This following code constitutes the addition of the security model
+ // to the DXE IPL.
+ //
+ //
+ // Set a default authenticatino state
+ //
+ AuthenticationStatus = 0;
+
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiSectionExtractionPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SectionExtract
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Verify Authentication State
+ //
+ CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));
+
+ Status = SectionExtract->PeiGetSection (
+ GetPeiServicesTablePointer(),
+ SectionExtract,
+ (EFI_SECTION_TYPE *) &SectionType,
+ &TempGuid,
+ 0,
+ (VOID **) &Buffer,
+ &BufferSize,
+ &AuthenticationStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // If not ask the Security PPI, if exists, for disposition
+ //
+ //
+ Status = PeiCoreLocatePpi (
+ &gEfiPeiSecurityPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&Security
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = Security->AuthenticationState (
+ GetPeiServicesTablePointer(),
+ (struct _EFI_PEI_SECURITY_PPI *) Security,
+ AuthenticationStatus,
+ FfsFileHeader,
+ &StartCrisisRecovery
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // If there is a security violation, report to caller and have
+ // the upper-level logic possible engender a crisis recovery
+ //
+ if (StartCrisisRecovery) {
+ return EFI_SECURITY_VIOLATION;
+ }
+ }
+
+ if (Section->Type == EFI_SECTION_PE32) {
+ //
+ // This is what we want
+ //
+ *Pe32Data = (VOID *) (Section + 1);
+ return EFI_SUCCESS;
+ } else if (Section->Type == EFI_SECTION_COMPRESSION) {
+ //
+ // This is a compression set, expand it
+ //
+ CompressionSection = (EFI_COMPRESSION_SECTION *) Section;
+
+ switch (CompressionSection->CompressionType) {
+ case EFI_STANDARD_COMPRESSION:
+ DecompressLibrary = &gTianoDecompress;
+ break;
+
+ case EFI_CUSTOMIZED_COMPRESSION:
+ //
+ // Load user customized compression protocol.
+ //
+ DecompressLibrary = &gCustomDecompress;
+ break;
+
+ case EFI_NOT_COMPRESSED:
+ default:
+ //
+ // Need to support not compressed file
+ //
+ ASSERT_EFI_ERROR (Status);
+ return EFI_NOT_FOUND;
+ }
+
+ Status = DecompressLibrary->GetInfo (
+ (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
+ (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
+ &DstBufferSize,
+ &ScratchBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // GetInfo failed
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate scratch buffer
+ //
+ ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
+ if (ScratchBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Allocate destination buffer
+ //
+ DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
+ if (DstBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Call decompress function
+ //
+ Status = DecompressLibrary->Decompress (
+ (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
+ DstBuffer,
+ ScratchBuffer
+ );
+
+ CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;
+ if (CmpSection->Type == EFI_SECTION_RAW) {
+ //
+ // Skip the section header and
+ // adjust the pointer alignment to 16
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16);
+
+ if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
+ FfsFileHeader = NULL;
+ BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);
+ Status = PeiCoreFfsFindNextFile (
+ EFI_FV_FILETYPE_DXE_CORE,
+ FvHeader,
+ &FfsFileHeader
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return PeiProcessFile (SectionType, FfsFileHeader, Pe32Data);
+ }
+ }
+ //
+ // Decompress successfully.
+ // Loop the decompressed data searching for expected section.
+ //
+ CmpFileData = (VOID *) DstBuffer;
+ CmpFileSize = DstBufferSize;
+ do {
+ CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;
+ if (CmpSection->Type == EFI_SECTION_PE32) {
+ //
+ // This is what we want
+ //
+ *Pe32Data = (VOID *) (CmpSection + 1);
+ return EFI_SUCCESS;
+ }
+
+ OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4);
+ CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);
+ } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);
+ }
+
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
+ FileSize = FfsFileHeader->Size[0] & 0xFF;
+ FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;
+ FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;
+ FileSize &= 0x00FFFFFF;
+ } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);
+
+ //
+ // End of the decompression activity
+ //
+ } else {
+
+ Status = PeiCoreFfsFindSectionData (
+ EFI_SECTION_PE32,
+ FfsFileHeader,
+ &SectionData
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = PeiCoreFfsFindSectionData (
+ EFI_SECTION_TE,
+ FfsFileHeader,
+ &SectionData
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ }
+
+ *Pe32Data = SectionData;
+
+ return EFI_SUCCESS;
+} \ No newline at end of file
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c
new file mode 100644
index 0000000000..95fb0937c5
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c
@@ -0,0 +1,70 @@
+/*++
+
+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:
+
+ IpfDxeLoad.c
+
+Abstract:
+
+ Ipf-specifc functionality for DxeLoad.
+
+--*/
+
+#include <DxeIpl.h>
+
+EFI_STATUS
+CreateArchSpecificHobs (
+ OUT EFI_PHYSICAL_ADDRESS *BspStore
+ )
+/*++
+
+Routine Description:
+
+ Creates architecture-specific HOBs.
+
+ Note: New parameters should NOT be added for any HOBs that are added to this
+ function. BspStore is a special case because it is required for the
+ call to SwitchStacks() in DxeLoad().
+
+Arguments:
+
+ BspStore - The address of the BSP Store for those architectures that need
+ it. Otherwise 0.
+
+Returns:
+
+ EFI_SUCCESS - The HOBs were created successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ ASSERT (NULL != BspStore);
+
+ //
+ // Allocate 16KB for the BspStore
+ //
+ Status = PeiCoreAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (BSP_STORE_SIZE), BspStore);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BuildBspStoreHob (
+ *BspStore,
+ BSP_STORE_SIZE,
+ EfiBootServicesData
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c
new file mode 100644
index 0000000000..16b44b24d8
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c
@@ -0,0 +1,72 @@
+/*++
+
+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:
+
+ ImageRead.c
+
+Abstract:
+
+--*/
+
+#include <DxeIpl.h>
+
+EFI_STATUS
+PeiImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINTN Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetImageReadFunction (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ ImageContext->ImageRead = PeiImageRead;
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/DxeIplPeim/build.xml b/EdkModulePkg/Core/DxeIplPeim/build.xml
new file mode 100644
index 0000000000..5f83fe7365
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="DxeIpl"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Core\DxeIplPeim"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="DxeIpl">
+ <GenBuild baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIpl.mbd" msaFilename="${MODULE_DIR}\DxeIpl.msa"/>
+ </target>
+ <target depends="DxeIpl_clean" name="clean"/>
+ <target depends="DxeIpl_cleanall" name="cleanall"/>
+ <target name="DxeIpl_clean">
+ <OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIpl.mbd" msaFilename="${MODULE_DIR}\DxeIpl.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="DxeIpl_cleanall">
+ <OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIpl.mbd" msaFilename="${MODULE_DIR}\DxeIpl.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**DxeIpl*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Core/DxeIplPeim/build_X64.xml b/EdkModulePkg/Core/DxeIplPeim/build_X64.xml
new file mode 100644
index 0000000000..aef68ec4dc
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/build_X64.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="DxeIpl"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Core\DxeIplPeim"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="DxeIpl">
+ <GenBuild baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIplX64.mbd" msaFilename="${MODULE_DIR}\DxeIplX64.msa"/>
+ </target>
+ <target depends="DxeIpl_clean" name="clean"/>
+ <target depends="DxeIpl_cleanAll" name="cleanAll"/>
+ <target name="DxeIpl_clean">
+ <OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIplX64.mbd" msaFilename="${MODULE_DIR}\DxeIplX64.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="DxeIpl_cleanAll">
+ <OutputDirSetup baseName="DxeIpl" mbdFilename="${MODULE_DIR}\DxeIplX64.mbd" msaFilename="${MODULE_DIR}\DxeIplX64.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\DxeIpl_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\DxeIpl_build.xml" target="cleanAll"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**DxeIpl*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Core/DxeIplPeim/ia32/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/ia32/DxeLoadFunc.c
new file mode 100644
index 0000000000..4d1015bbd8
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/ia32/DxeLoadFunc.c
@@ -0,0 +1,51 @@
+/*++
+
+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:
+
+ DxeLoadFunc.c
+
+Abstract:
+
+ Ia32-specifc functionality for DxeLoad.
+
+--*/
+
+#include <DxeIpl.h>
+
+EFI_STATUS
+CreateArchSpecificHobs (
+ OUT EFI_PHYSICAL_ADDRESS *BspStore
+ )
+/*++
+
+Routine Description:
+
+ Creates architecture-specific HOBs.
+
+ Note: New parameters should NOT be added for any HOBs that are added to this
+ function. BspStore is a special case because it is required for the
+ call to SwitchStacks() in DxeLoad().
+
+Arguments:
+
+ BspStore - The address of the BSP Store for those architectures that need
+ it. Otherwise 0.
+
+Returns:
+
+ EFI_SUCCESS - The HOBs were created successfully.
+
+--*/
+{
+ *BspStore = 0;
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/DxeIplPeim/ia32/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/ia32/ImageRead.c
new file mode 100644
index 0000000000..fe07608290
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/ia32/ImageRead.c
@@ -0,0 +1,112 @@
+/*++
+
+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:
+
+ ImageRead.c
+
+Abstract:
+
+--*/
+
+#include <DxeIpl.h>
+
+EFI_STATUS
+EFIAPI
+PeiImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ UINT8 *Destination32;
+ UINT8 *Source32;
+ UINTN Length;
+
+
+ Destination32 = Buffer;
+ Source32 = (UINT8 *) ((UINTN) FileHandle + FileOffset);
+
+ //
+ // This function assumes 32-bit alignment to increase performance
+ //
+// ASSERT (ALIGN_POINTER (Destination32, sizeof (UINT32)) == Destination32);
+// ASSERT (ALIGN_POINTER (Source32, sizeof (UINT32)) == Source32);
+
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination32++) = *(Source32++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetImageReadFunction (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+ Support routine to return the PE32 Image Reader.
+ If the PeiImageRead() function is less than a page
+ in legnth. If the function is more than a page the DXE IPL will crash!!!!
+
+Arguments:
+ ImageContext - The context of the image being loaded
+
+Returns:
+ EFI_SUCCESS - If Image function location is found
+
+--*/
+{
+ VOID *MemoryBuffer;
+
+ if (gInMemory) {
+ ImageContext->ImageRead = PeiImageRead;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // BugBug; This code assumes PeiImageRead() is less than a page in size!
+ // Allocate a page so we can shaddow the read function from FLASH into
+ // memory to increase performance.
+ //
+
+ MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead);
+ ASSERT (MemoryBuffer != NULL);
+
+ ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c
new file mode 100644
index 0000000000..c93c7e1747
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c
@@ -0,0 +1,53 @@
+/*++
+
+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:
+
+ DxeLoadFunc.c
+
+Abstract:
+
+ Ia32-specifc functionality for DxeLoad X64 Lakeport.
+
+--*/
+
+#include <DxeIpl.h>
+
+EFI_STATUS
+CreateArchSpecificHobs (
+ OUT EFI_PHYSICAL_ADDRESS *BspStore
+ )
+/*++
+
+Routine Description:
+
+ Creates architecture-specific HOBs.
+
+ Note: New parameters should NOT be added for any HOBs that are added to this
+ function. BspStore is a special case because it is required for the
+ call to SwitchStacks() in DxeLoad().
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ BspStore - The address of the BSP Store for those architectures that need
+ it. Otherwise 0.
+
+Returns:
+
+ EFI_SUCCESS - The HOBs were created successfully.
+
+--*/
+{
+ *BspStore = 0;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c
new file mode 100644
index 0000000000..dd977f2d2e
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c
@@ -0,0 +1,106 @@
+/*++
+
+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:
+
+ ImageRead.c
+
+Abstract:
+
+--*/
+
+#include <DxeIpl.h>
+
+EFI_STATUS
+EFIAPI
+PeiImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINTN Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetImageReadFunction (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Support routine to return the PE32 Image Reader.
+ If the PeiImageRead() function is less than a page
+ in legnth. If the function is more than a page the DXE IPL will crash!!!!
+
+Arguments:
+ ImageContext - The context of the image being loaded
+
+Returns:
+
+ EFI_SUCCESS - If Image function location is found
+
+--*/
+{
+ VOID *MemoryBuffer;
+
+ if (gInMemory) {
+ ImageContext->ImageRead = PeiImageRead;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // BugBug; This code assumes PeiImageRead() is less than a page in size!
+ // Allocate a page so we can shaddow the read function from FLASH into
+ // memory to increase performance.
+ //
+
+ MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead);
+ ASSERT (MemoryBuffer != NULL);
+
+ ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm b/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm
new file mode 100644
index 0000000000..a9c4e774cf
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm
@@ -0,0 +1,1357 @@
+ TITLE LongMode.asm: Assembly code for the entering long mode
+
+;------------------------------------------------------------------------------
+;*
+;* 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.
+;*
+;* LongMode.asm
+;*
+;* Abstract:
+;*
+;* Transition from 32-bit protected mode EFI environment into x64
+;* 64-bit bit long mode.
+;*
+;------------------------------------------------------------------------------
+
+.686p
+.model flat
+
+;
+; Create the exception handler code in IA32 C code
+;
+
+.code
+.stack
+.MMX
+.XMM
+
+_LoadGo64Gdt PROC Near Public
+ push ebp ; C prolog
+ push edi
+ mov ebp, esp
+ ;
+ ; Disable interrupts
+ ;
+ cli
+ ;
+ ; Reload the selectors
+ ; Note:
+ ; Make the Selectors 64-bit ready
+ ;
+ mov edi, OFFSET gdtr ; Load GDT register
+ mov ax,cs ; Get the selector data from our code image
+ mov es,ax
+ lgdt FWORD PTR es:[edi] ; and update the GDTR
+
+ db 067h
+ db 0eah ; Far Jump Offset:Selector to reload CS
+ dd OFFSET DataSelectorRld; Offset is ensuing instruction boundary
+ dw LINEAR_CODE_SEL ; Selector is our code selector, 10h
+DataSelectorRld::
+ mov ax, SYS_DATA_SEL ; Update the Base for the new selectors, too
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ pop edi
+ pop ebp
+ ret
+_LoadGo64Gdt endp
+
+
+; VOID
+; ActivateLongMode (
+; IN EFI_PHYSICAL_ADDRESS PageTables,
+; IN EFI_PHYSICAL_ADDRESS HobStart,
+; IN EFI_PHYSICAL_ADDRESS Stack,
+; IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint,
+; IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
+; )
+;
+; Input: [ebp][0h] = Original ebp
+; [ebp][4h] = Return address
+; [ebp][8h] = PageTables
+; [ebp][10h] = HobStart
+; [ebp][18h] = Stack
+; [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer)
+; [ebp][28h] = CodeEntryPoint2 <--- Call this second
+;
+;
+_ActivateLongMode PROC Near Public
+ push ebp ; C prolog
+ mov ebp, esp
+
+ ;
+ ; Use CPUID to determine if the processor supports long mode.
+ ;
+ mov eax, 80000000h ; Extended-function code 8000000h.
+ cpuid ; Is largest extended function
+ cmp eax, 80000000h ; any function > 80000000h?
+ jbe no_long_mode ; If not, no long mode.
+ mov eax, 80000001h ; Extended-function code 8000001h.
+ cpuid ; Now EDX = extended-features flags.
+ bt edx, 29 ; Test if long mode is supported.
+ jnc no_long_mode ; Exit if not supported.
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ mov eax, cr4
+ bts eax, 5
+ mov cr4, eax
+
+ ;
+ ; Get the long-mode page tables, and initialize the
+ ; 64-bit CR3 (page-table base address) to point to the base
+ ; of the PML4 page table. The PML4 page table must be located
+ ; below 4 Gbytes because only 32 bits of CR3 are loaded when
+ ; the processor is not in 64-bit mode.
+ ;
+ mov eax, [ebp+8h] ; Get Page Tables
+ mov cr3, eax ; Initialize CR3 with PML4 base.
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ mov ecx, 0c0000080h ; EFER MSR number.
+ rdmsr ; Read EFER.
+ bts eax, 8 ; Set LME=1.
+ wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+
+
+ mov eax, cr0 ; Read CR0.
+ bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp go_to_long_mode
+go_to_long_mode:
+
+ ;
+ ; This is the next instruction after enabling paging. Jump to long mode
+ ;
+ db 067h
+ db 0eah ; Far Jump Offset:Selector to reload CS
+ dd OFFSET in_long_mode; Offset is ensuing instruction boundary
+ dw SYS_CODE64_SEL ; Selector is our code selector, 10h
+in_long_mode::
+ mov ax, SYS_DATA64_SEL
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+;; jmp $
+
+
+ ;
+ ; We're in long mode, so marshall the arguments to call the
+ ; passed in function pointers
+ ; Recall
+ ; [ebp][10h] = HobStart
+ ; [ebp][18h] = Stack
+ ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
+ ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second
+ ;
+ db 48h
+ mov ebx, [ebp+18h] ; Setup the stack
+ db 48h
+ mov esp, ebx ; On a new stack now
+
+ db 48h
+ mov ecx, [ebp+10h] ; Pass Hob Start in RCX
+ db 48h
+ mov eax, [ebp+20h] ; Get the function pointer for
+ ; PpisNeededByDxeIplEntryPoint into EAX
+
+;; 00000905 FF D0 call rax
+ db 0ffh
+ db 0d0h
+
+ db 48h
+ mov ecx, [ebp+10h] ; Pass Hob Start in RCX
+ db 48h
+ mov eax, [ebp+28h] ; Get the function pointer for
+ ; DxeCoreEntryPoint into EAX
+
+;; 00000905 FF D0 call rax
+ db 0ffh
+ db 0d0h
+
+ ;
+ ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
+ ;
+no_long_mode:
+ jmp no_long_mode
+_ActivateLongMode endp
+
+ align 16
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd OFFSET GDT_BASE ; (GDT base gets set above)
+
+;-----------------------------------------------------------------------------;
+; global descriptor table (GDT)
+;-----------------------------------------------------------------------------;
+
+ align 16
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Fh ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 093h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+;
+;
+;------------------------------------------------------------------------------
+; Generic IDT Vector Handlers for the Host. They are all the same so they
+; will compress really well.
+;
+; By knowing the return address for Vector 00 you can can calculate the
+; vector number by looking at the call CommonInterruptEntry return address.
+; (return address - AsmIdtVector00Base)/8 == IDT index
+;
+;------------------------------------------------------------------------------
+
+_AsmIdtVector00 PROC NEAR PUBLIC
+ call CommonInterruptEntry
+_AsmIdtVector00 ENDP
+AsmIdtVector00Base PROC NEAR PUBLIC
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+ call CommonInterruptEntry
+ nop
+ nop
+ nop
+AsmIdtVector00Base ENDP
+
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition
+;
+;
+CommonInterruptEntry PROC NEAR PUBLIC
+ cli
+ jmp $
+ iret
+
+CommonInterruptEntry ENDP
+
+END
+
diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c
new file mode 100644
index 0000000000..40eaed2ce6
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c
@@ -0,0 +1,434 @@
+/*++
+
+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:
+ VirtualMemory.c
+
+Abstract:
+
+ x64 Virtual Memory Management Services in the form of an IA-32 driver.
+ Used to establish a 1:1 Virtual to Physical Mapping that is required to
+ enter Long Mode (x64 64-bit mode).
+
+ While we make a 1:1 mapping (identity mapping) for all physical pages
+ we still need to use the MTRR's to ensure that the cachability attirbutes
+ for all memory regions is correct.
+
+ The basic idea is to use 2MB page table entries where ever possible. If
+ more granularity of cachability is required then 4K page tables are used.
+
+ References:
+ 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+
+--*/
+
+#include "VirtualMemory.h"
+
+x64_MTRR_VARIABLE_RANGE *mMTRRVariableRange;
+x64_MTRR_FIXED_RANGE mMTRRFixedRange;
+
+
+//
+// Physial memory limit values for each of the 11 fixed MTRRs
+//
+UINTN mFixedRangeLimit[] = {
+ 0x7FFFF, // Fixed MTRR #0 describes 0x00000..0x7FFFF
+ 0x9FFFF, // Fixed MTRR #1 describes 0x80000..0x9FFFF
+ 0xBFFFF, // Fixed MTRR #2 describes 0xA0000..0xBFFFF
+ 0xC7FFF, // Fixed MTRR #3 describes 0xC0000..0xC7FFF
+ 0xCFFFF, // Fixed MTRR #4 describes 0xC8000..0xCFFFF
+ 0xD7FFF, // Fixed MTRR #5 describes 0xD0000..0xD7FFF
+ 0xDFFFF, // Fixed MTRR #6 describes 0xD8000..0xDFFFF
+ 0xE7FFF, // Fixed MTRR #7 describes 0xE0000..0xE7FFF
+ 0xEFFFF, // Fixed MTRR #8 describes 0xE8000..0xEFFFF
+ 0xF7FFF, // Fixed MTRR #9 describes 0xF0000..0xF7FFF
+ 0xFFFFF // Fixed MTRR #10 describes 0xF8000..0xFFFFF
+};
+
+//
+// The size, in bits, of each of the 11 fixed MTRR.
+//
+UINTN mFixedRangeShift[] = {
+ 16, // Fixed MTRR #0 describes 8, 64 KB ranges
+ 14, // Fixed MTRR #1 describes 8, 16 KB ranges
+ 14, // Fixed MTRR #2 describes 8, 16 KB ranges
+ 12, // Fixed MTRR #3 describes 8, 4 KB ranges
+ 12, // Fixed MTRR #4 describes 8, 4 KB ranges
+ 12, // Fixed MTRR #5 describes 8, 4 KB ranges
+ 12, // Fixed MTRR #6 describes 8, 4 KB ranges
+ 12, // Fixed MTRR #7 describes 8, 4 KB ranges
+ 12, // Fixed MTRR #8 describes 8, 4 KB ranges
+ 12, // Fixed MTRR #9 describes 8, 4 KB ranges
+ 12 // Fixed MTRR #10 describes 8, 4 KB ranges
+};
+
+
+UINTN mPowerOf2[] = {
+ 1,
+ 2,
+ 4,
+ 8,
+ 16,
+ 32,
+ 64,
+ 128,
+ 256,
+ 512
+};
+
+x64_MTRR_MEMORY_TYPE
+EfiGetMTRRMemoryType (
+ IN EFI_PHYSICAL_ADDRESS Address
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the memory type from the MTRR that describes a physical address.
+
+Arguments:
+
+ VariableRange - Set of Variable MTRRs
+
+ FixedRange - Set of Fixed MTRRs
+
+ Address - The physical address for which the MTRR memory type is being retrieved
+
+Returns:
+
+ The MTRR Memory Type for the physical memory specified by Address.
+
+--*/
+{
+ UINTN Index;
+ UINTN TypeIndex;
+ BOOLEAN Found;
+ x64_MTRR_MEMORY_TYPE VariableType;
+ EFI_PHYSICAL_ADDRESS MaskBase;
+ EFI_PHYSICAL_ADDRESS PhysMask;
+
+ //
+ // If the MTRRs are disabled, then return the Uncached Memory Type
+ //
+ if (mMTRRFixedRange.DefaultType.Bits.E == 0) {
+ return Uncached;
+ }
+
+ //
+ // If the CPU supports Fixed MTRRs and the Fixed MTRRs are enabled, then
+ // see if Address falls into one of the Fixed MTRRs
+ //
+ if (mMTRRFixedRange.Capabilities.Bits.FIX && mMTRRFixedRange.DefaultType.Bits.FE) {
+ //
+ // Loop though 11 fixed MTRRs
+ //
+ for (Index = 0; Index < 11; Index++) {
+ //
+ // Check for a matching range
+ //
+ if (Address <= mFixedRangeLimit[Index]) {
+ //
+ // Compute the offset address into the MTRR bu subtrating the base address of the MTRR
+ //
+ if (Index > 0) {
+ Address = Address - (mFixedRangeLimit[Index-1] + 1);
+ }
+ //
+ // Retrieve the index into the MTRR to extract the memory type. The range is 0..7
+ //
+ TypeIndex = (UINTN)RShiftU64 (Address, mFixedRangeShift[Index]);
+
+ //
+ // Retrieve and return the memory type for the matching range
+ //
+ return mMTRRFixedRange.Fixed[Index].Type[TypeIndex];
+ }
+ }
+ }
+
+ //
+ // If Address was not found in a Fixed MTRR, then search the Variable MTRRs
+ //
+ for (Index = 0, Found = FALSE, VariableType = WriteBack; Index < mMTRRFixedRange.Capabilities.Bits.VCNT; Index++) {
+ //
+ // BugBug: __aullshr complier error
+ //
+ if ((mMTRRVariableRange[Index].PhysMask.Uint64 & 0x800) == 0x800) {
+ //if (mMTRRVariableRange[Index].PhysMask.Bits.Valid == 1) {
+ PhysMask = mMTRRVariableRange[Index].PhysMask.Uint64 & ~0xfff;
+ MaskBase = PhysMask & (mMTRRVariableRange[Index].PhysBase.Uint64 & ~0xfff);
+ if (MaskBase == (PhysMask & Address)) {
+ //
+ // Check to see how many matches we find
+ //
+ Found = TRUE;
+ if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == Uncached) || (VariableType == Uncached)) {
+ //
+ // If any matching region uses UC, the memory region is UC
+ //
+ VariableType = Uncached;
+ } else if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == WriteThrough) || (VariableType == WriteThrough)){
+ //
+ // If it's WT and WB then set it to WT. If it's WT and other type it's undefined
+ //
+ VariableType = WriteThrough;
+ } else {
+ VariableType = mMTRRVariableRange[Index].PhysBase.Bits.Type;
+ }
+ }
+ }
+ }
+
+ if (Found) {
+ return VariableType;
+ }
+
+ //
+ // Address was not found in the Fixed or Variable MTRRs, so return the default memory type
+ //
+ return mMTRRFixedRange.DefaultType.Bits.Type;
+}
+
+
+BOOLEAN
+CanNotUse2MBPage (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress
+ )
+/*++
+
+Routine Description:
+ Test to see if a 2MB aligned page has all the same attributes. If a 2MB page
+ has more than one attibute type it needs to be split into multiple 4K pages.
+
+Arguments:
+ BaseAddress - 2MB aligned address to check out
+
+Returns:
+ TRUE - This 2MB address range (BaseAddress) can NOT be mapped by a 2MB page
+ FALSE - This 2MB address range can be mapped by a 2MB page
+
+--*/
+{
+ UINTN Index;
+ x64_MTRR_MEMORY_TYPE MemoryType;
+ x64_MTRR_MEMORY_TYPE PreviousMemoryType;
+
+ //
+ // Address needs to be 2MB aligned
+ //
+ ASSERT ((BaseAddress & 0x1fffff) == 0);
+
+ PreviousMemoryType = -1;
+ for (Index = 0; Index < 512; Index++, BaseAddress += 0x1000) {
+ MemoryType = EfiGetMTRRMemoryType (BaseAddress);
+ if ((Index != 0) && (MemoryType != PreviousMemoryType)) {
+ return TRUE;
+ }
+
+ PreviousMemoryType = MemoryType;
+ }
+
+ //
+ // All the pages had the same type
+ //
+ return FALSE;
+}
+
+
+
+
+VOID
+Convert2MBPageTo4KPages (
+ IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB,
+ IN EFI_PHYSICAL_ADDRESS PageAddress
+ )
+/*++
+
+Routine Description:
+ Convert a single 2MB page entry to 512 4K page entries. The attributes for
+ the 4K pages are read from the MTRR registers.
+
+Arguments:
+ PageDirectoryEntry2MB - Page directory entry for PageAddress
+ PageAddress - 2MB algined address of region to convert
+
+Returns:
+ None
+
+--*/
+{
+ EFI_PHYSICAL_ADDRESS Address;
+ x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k;
+ x64_PAGE_TABLE_ENTRY_4K *PageTableEntry;
+ UINTN Index1;
+
+ //
+ // Allocate the page table entry for the 4K pages
+ //
+ PageTableEntry = (x64_PAGE_TABLE_ENTRY_4K *) AllocatePages (1);
+
+ ASSERT (PageTableEntry != NULL);
+
+ //
+ // Convert PageDirectoryEntry2MB into a 4K Page Directory
+ //
+ PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *)PageDirectoryEntry2MB;
+ PageDirectoryEntry2MB->Uint64 = (UINT64)PageTableEntry;
+ PageDirectoryEntry2MB->Bits.ReadWrite = 1;
+ PageDirectoryEntry2MB->Bits.Present = 1;
+
+ //
+ // Fill in the 4K page entries with the attributes from the MTRRs
+ //
+ for (Index1 = 0, Address = PageAddress; Index1 < 512; Index1++, PageTableEntry++, Address += 0x1000) {
+ PageTableEntry->Uint64 = (UINT64)Address;
+ PageTableEntry->Bits.ReadWrite = 1;
+ PageTableEntry->Bits.Present = 1;
+ }
+}
+
+
+EFI_PHYSICAL_ADDRESS
+CreateIdentityMappingPageTables (
+ IN UINT32 NumberOfProcessorPhysicalAddressBits
+ )
+/*++
+
+Routine Description:
+
+ Allocates and fills in the Page Directory and Page Table Entries to
+ establish a 1:1 Virtual to Physical mapping for physical memory from
+ 0 to 4GB. Memory above 4GB is not mapped. The MTRRs are used to
+ determine the cachability of the physical memory regions
+
+Arguments:
+
+ NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use.
+ Limits the number of page table entries
+ to the physical address space.
+
+Returns:
+ EFI_OUT_OF_RESOURCES There are not enough resources to allocate the Page Tables
+
+ EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created
+
+--*/
+{
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN Index;
+ UINTN MaxBitsSupported;
+ UINTN Index1;
+ UINTN Index2;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMap;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;
+ x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;
+
+
+ //
+ // Page Table structure 4 level 4K, 3 level 2MB.
+ //
+ // PageMapLevel4Entry : bits 47-39
+ // PageDirectoryPointerEntry : bits 38-30
+ // Page Table 2MB : PageDirectoryEntry2M : bits 29-21
+ // Page Table 4K : PageDirectoryEntry4K : bits 29 - 21
+ // PageTableEntry : bits 20 - 12
+ //
+ // Strategy is to map every thing in the processor address space using
+ // 2MB pages. If more granularity is required the 2MB page will get
+ // converted to set of 4K pages.
+ //
+
+ //
+ // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.
+ //
+ PageMap = PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1);
+ ASSERT (PageMap != NULL);
+ PageAddress = 0;
+
+ //
+ // The number of page-map Level-4 Offset entries is based on the number of
+ // physical address bits. Less than equal to 38 bits only takes one entry.
+ // 512 entries represents 48 address bits.
+ //
+ if (NumberOfProcessorPhysicalAddressBits <= 38) {
+ MaxBitsSupported = 1;
+ } else {
+ MaxBitsSupported = mPowerOf2[NumberOfProcessorPhysicalAddressBits - 39];
+ }
+
+ for (Index = 0; Index < MaxBitsSupported; Index++, PageMapLevel4Entry++) {
+ //
+ // Each PML4 entry points to a page of Page Directory Pointer entires.
+ // So lets allocate space for them and fill them in in the Index1 loop.
+ //
+ PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1);
+ ASSERT (PageDirectoryPointerEntry != NULL);
+
+ //
+ // Make a PML4 Entry
+ //
+ PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
+ PageMapLevel4Entry->Bits.ReadWrite = 1;
+ PageMapLevel4Entry->Bits.Present = 1;
+
+ for (Index1 = 0; Index1 < 512; Index1++, PageDirectoryPointerEntry++) {
+ //
+ // Each Directory Pointer entries points to a page of Page Directory entires.
+ // So lets allocate space for them and fill them in in the Index2 loop.
+ //
+ PageDirectoryEntry2MB = (x64_PAGE_TABLE_ENTRY_2M *) AllocatePages (1);
+ ASSERT (PageDirectoryEntry2MB != NULL);
+
+ //
+ // Fill in a Page Directory Pointer Entries
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry2MB;
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (Index2 = 0; Index2 < 512; Index2++, PageDirectoryEntry2MB++, PageAddress += 0x200000) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;
+ PageDirectoryEntry2MB->Bits.ReadWrite = 1;
+ PageDirectoryEntry2MB->Bits.Present = 1;
+ PageDirectoryEntry2MB->Bits.MustBe1 = 1;
+
+ if (CanNotUse2MBPage (PageAddress)) {
+ //
+ // Check to see if all 2MB has the same mapping. If not convert
+ // to 4K pages by adding the 4th level of page table entries
+ //
+ Convert2MBPageTo4KPages (PageDirectoryEntry2MB, PageAddress);
+ }
+ }
+ }
+ }
+
+ //
+ // For the PML4 entries we are not using fill in a null entry.
+ // for now we just copy the first entry.
+ //
+ for (; Index < 512; Index++, PageMapLevel4Entry++) {
+ // EfiCopyMem (PageMapLevel4Entry, PageMap, sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K));
+ CopyMem (PageMapLevel4Entry,
+ PageMap,
+ sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K)
+ );
+ }
+
+ return (EFI_PHYSICAL_ADDRESS)PageMap;
+}
+
diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h
new file mode 100644
index 0000000000..8133ad447f
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h
@@ -0,0 +1,239 @@
+/*++
+
+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:
+ VirtualMemory.h
+
+Abstract:
+
+ x64 Long Mode Virtual Memory Management Definitions
+
+ References:
+ 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+ 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
+--*/
+#ifndef _VIRTUAL_MEMORY_H_
+#define _VIRTUAL_MEMORY_H_
+
+
+#pragma pack(1)
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K;
+
+//
+// Page-Directory Offset 4K
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:1; // Must Be Zero
+ UINT64 Reserved2:1; // Reserved
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_DIRECTORY_ENTRY_4K;
+
+//
+// Page Table Entry 4K
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 PAT:1; // 0 = Ignore Page Attribute Table
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_TABLE_ENTRY_4K;
+
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_TABLE_ENTRY_2M;
+
+typedef union {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 Reserved:57;
+} x64_PAGE_TABLE_ENTRY_COMMON;
+
+typedef union {
+ x64_PAGE_TABLE_ENTRY_4K Page4k;
+ x64_PAGE_TABLE_ENTRY_2M Page2Mb;
+ x64_PAGE_TABLE_ENTRY_COMMON Common;
+} x64_PAGE_TABLE_ENTRY;
+
+//
+// MTRR Definitions
+//
+typedef enum {
+ Uncached = 0,
+ WriteCombining = 1,
+ WriteThrough = 4,
+ WriteProtected = 5,
+ WriteBack = 6
+} x64_MTRR_MEMORY_TYPE;
+
+typedef union {
+ struct {
+ UINT32 VCNT:8; // The number of Variable Range MTRRs
+ UINT32 FIX:1; // 1=Fixed Range MTRRs supported. 0=Fixed Range MTRRs not supported
+ UINT32 Reserved_0; // Reserved
+ UINT32 WC:1; // Write combining memory type supported
+ UINT32 Reserved_1:21; // Reserved
+ UINT32 Reserved_2:32; // Reserved
+ } Bits;
+ UINT64 Uint64;
+} x64_MTRRCAP_MSR;
+
+typedef union {
+ struct {
+ UINT32 Type:8; // Default Memory Type
+ UINT32 Reserved_0:2; // Reserved
+ UINT32 FE:1; // 1=Fixed Range MTRRs enabled. 0=Fixed Range MTRRs disabled
+ UINT32 E:1; // 1=MTRRs enabled, 0=MTRRs disabled
+ UINT32 Reserved_1:20; // Reserved
+ UINT32 Reserved_2:32; // Reserved
+ } Bits;
+ UINT64 Uint64;
+} x64_MTRR_DEF_TYPE_MSR;
+
+typedef union {
+ UINT8 Type[8]; // The 8 Memory Type values in the 64-bit MTRR
+ UINT64 Uint64; // The full 64-bit MSR
+} x64_MTRR_FIXED_RANGE_MSR;
+
+typedef struct {
+ x64_MTRRCAP_MSR Capabilities; // MTRR Capabilities MSR value
+ x64_MTRR_DEF_TYPE_MSR DefaultType; // Default Memory Type MSR Value
+ x64_MTRR_FIXED_RANGE_MSR Fixed[11]; // The 11 Fixed MTRR MSR Values
+} x64_MTRR_FIXED_RANGE;
+
+
+typedef union {
+ struct {
+ UINT64 Type:8; // Memory Type
+ UINT64 Reserved0:4; // Reserved
+ UINT64 PhysBase:40; // The physical base address(bits 35..12) of the MTRR
+ UINT64 Reserved1:12 ; // Reserved
+ } Bits;
+ UINT64 Uint64;
+} x64_MTRR_PHYSBASE_MSR;
+
+typedef union {
+ struct {
+ UINT64 Reserved0:11; // Reserved
+ UINT64 Valid:1; // 1=MTRR is valid, 0=MTRR is not valid
+ UINT64 PhysMask:40; // The physical address mask (bits 35..12) of the MTRR
+ UINT64 Reserved1:12; // Reserved
+ } Bits;
+ UINT64 Uint64;
+} x64_MTRR_PHYSMASK_MSR;
+
+typedef struct {
+ x64_MTRR_PHYSBASE_MSR PhysBase; // Variable MTRR Physical Base MSR
+ x64_MTRR_PHYSMASK_MSR PhysMask; // Variable MTRR Physical Mask MSR
+} x64_MTRR_VARIABLE_RANGE;
+
+#pragma pack()
+
+x64_MTRR_MEMORY_TYPE
+EfiGetMTRRMemoryType (
+ IN EFI_PHYSICAL_ADDRESS Address
+ )
+;
+
+BOOLEAN
+CanNotUse2MBPage (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress
+ )
+;
+
+VOID
+Convert2MBPageTo4KPages (
+ IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB,
+ IN EFI_PHYSICAL_ADDRESS PageAddress
+ )
+;
+
+EFI_PHYSICAL_ADDRESS
+CreateIdentityMappingPageTables (
+ IN UINT32 NumberOfProcessorPhysicalAddressBits
+ )
+;
+
+#endif
diff --git a/EdkModulePkg/Core/Pei/BootMode/BootMode.c b/EdkModulePkg/Core/Pei/BootMode/BootMode.c
new file mode 100644
index 0000000000..049cfd1a8f
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/BootMode/BootMode.c
@@ -0,0 +1,106 @@
+/*++
+
+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 <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/EdkModulePkg/Core/Pei/Dependency/dependency.c b/EdkModulePkg/Core/Pei/Dependency/dependency.c
new file mode 100644
index 0000000000..5c82eefa1b
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Dependency/dependency.c
@@ -0,0 +1,264 @@
+/*++
+
+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 <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 = PeiCoreLocatePpi(
+ &PpiGuid, // GUID
+ 0, // INSTANCE
+ NULL, // EFI_PEI_PPI_DESCRIPTOR
+ &PeiInstance // PPI
+ );
+
+ if (EFI_ERROR(Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+EFI_STATUS
+PeimDispatchReadiness (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN VOID *DependencyExpression,
+ OUT BOOLEAN *Runnable
+ )
+/*++
+
+Routine Description:
+
+ This is the POSTFIX version of the dependency evaluator. When a
+ PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on
+ the evaluation stack. When that entry is poped from the evaluation
+ stack, the PPI is checked if it is installed. This method allows
+ some time savings as not all PPIs must be checked for certain
+ operation types (AND, OR).
+
+Arguments:
+
+ PeiServices - Calling context.
+
+ DependencyExpression - Pointer to a dependency expression. The Grammar adheres to
+ the BNF described above and is stored in postfix notation.
+ Runnable - is True if the driver can be scheduled and False if the driver
+ cannot be scheduled. This is the value that the schedulers
+ should use for deciding the state of the driver.
+
+Returns:
+
+ Status = EFI_SUCCESS if it is a well-formed Grammar
+ EFI_INVALID_PARAMETER if the dependency expression overflows
+ the evaluation stack
+ EFI_INVALID_PARAMETER if the dependency expression underflows
+ the evaluation stack
+ EFI_INVALID_PARAMETER if the dependency expression is not a
+ well-formed Grammar.
+--*/
+{
+ EFI_STATUS Status;
+ DEPENDENCY_EXPRESSION_OPERAND *Iterator;
+ EVAL_STACK_ENTRY *StackPtr;
+ EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE];
+
+ Status = EFI_SUCCESS;
+ Iterator = DependencyExpression;
+ *Runnable = FALSE;
+
+ StackPtr = &EvalStack[0];
+
+ while (TRUE) {
+
+ switch (*(Iterator++)) {
+
+ //
+ // For performance reason we put the frequently used items in front of
+ // the rarely used items
+ //
+
+ case (EFI_DEP_PUSH):
+ //
+ // Check to make sure the dependency grammar doesn't overflow the
+ // EvalStack on the push
+ //
+ if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Push the pointer to the PUSH opcode operator (pointer to PPI GUID)
+ // We will evaluate if the PPI is insalled on the POP operation.
+ //
+ StackPtr->Operator = (VOID *) Iterator;
+ Iterator = Iterator + sizeof (EFI_GUID);
+ StackPtr++;
+ break;
+
+ case (EFI_DEP_AND):
+ case (EFI_DEP_OR):
+ //
+ // Check to make sure the dependency grammar doesn't underflow the
+ // EvalStack on the two POPs for the AND operation. Don't need to
+ // check for the overflow on PUSHing the result since we already
+ // did two POPs.
+ //
+ if (StackPtr < &EvalStack[2]) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Evaluate the first POPed operator only. If the operand is
+ // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the
+ // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE,
+ // we don't need to check the second operator, and the result will be
+ // evaluation of the POPed operator. Otherwise, don't POP the second
+ // operator since it will now evaluate to the final result on the
+ // next operand that causes a POP.
+ //
+ StackPtr--;
+ //
+ // Iterator has increased by 1 after we retrieve the operand, so here we
+ // should get the value pointed by (Iterator - 1), in order to obtain the
+ // same operand.
+ //
+ if (*(Iterator - 1) == EFI_DEP_AND) {
+ if (!(IsPpiInstalled (PeiServices, StackPtr))) {
+ (StackPtr-1)->Result = FALSE;
+ (StackPtr-1)->Operator = NULL;
+ }
+ } else {
+ if (IsPpiInstalled (PeiServices, StackPtr)) {
+ (StackPtr-1)->Result = TRUE;
+ (StackPtr-1)->Operator = NULL;
+ }
+ }
+ break;
+
+ case (EFI_DEP_END):
+ StackPtr--;
+ //
+ // Check to make sure EvalStack is balanced. If not, then there is
+ // an error in the dependency grammar, so return EFI_INVALID_PARAMETER.
+ //
+ if (StackPtr != &EvalStack[0]) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *Runnable = IsPpiInstalled (PeiServices, StackPtr);
+ return EFI_SUCCESS;
+ break;
+
+ case (EFI_DEP_NOT):
+ //
+ // Check to make sure the dependency grammar doesn't underflow the
+ // EvalStack on the POP for the NOT operation. Don't need to
+ // check for the overflow on PUSHing the result since we already
+ // did a POP.
+ //
+ if (StackPtr < &EvalStack[1]) {
+ return EFI_INVALID_PARAMETER;
+ }
+ (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1));
+ (StackPtr-1)->Operator = NULL;
+ break;
+
+ case (EFI_DEP_TRUE):
+ case (EFI_DEP_FALSE):
+ //
+ // Check to make sure the dependency grammar doesn't overflow the
+ // EvalStack on the push
+ //
+ if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Iterator has increased by 1 after we retrieve the operand, so here we
+ // should get the value pointed by (Iterator - 1), in order to obtain the
+ // same operand.
+ //
+ if (*(Iterator - 1) == EFI_DEP_TRUE) {
+ StackPtr->Result = TRUE;
+ } else {
+ StackPtr->Result = FALSE;
+ }
+ StackPtr->Operator = NULL;
+ StackPtr++;
+ break;
+
+ default:
+ //
+ // The grammar should never arrive here
+ //
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+ }
+}
diff --git a/EdkModulePkg/Core/Pei/Dependency/dependency.h b/EdkModulePkg/Core/Pei/Dependency/dependency.h
new file mode 100644
index 0000000000..a1a54ed0cd
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Dependency/dependency.h
@@ -0,0 +1,38 @@
+/*++
+
+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_
+
+#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/EdkModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/EdkModulePkg/Core/Pei/Dispatcher/Dispatcher.c
new file mode 100644
index 0000000000..b4e09e3fca
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -0,0 +1,535 @@
+/*++
+
+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 <PeiMain.h>
+
+VOID *
+TransferOldDataToNewDataRange (
+ IN PEI_CORE_INSTANCE *PrivateData
+ );
+
+EFI_GUID gEfiPeiCorePrivateGuid = EFI_PEI_CORE_PRIVATE_GUID;
+
+
+EFI_STATUS
+PeiDispatcher (
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN PEI_CORE_DISPATCH_DATA *DispatchData
+ )
+
+/*++
+
+Routine Description:
+
+ Conduct PEIM dispatch.
+
+Arguments:
+
+ PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR
+ PrivateData - Pointer to the private data passed in from caller
+ DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data.
+
+Returns:
+
+ EFI_SUCCESS - Successfully dispatched PEIM.
+ EFI_NOT_FOUND - The dispatch failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ PEI_CORE_TEMP_POINTERS TempPtr;
+ UINTN PrivateDataInMem;
+ BOOLEAN NextFvFound;
+ EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress;
+ EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress;
+ //
+ // Debug data for uninstalled Peim list
+ //
+ EFI_GUID DebugFoundPeimList[32];
+ REPORT_STATUS_CODE_LIBRARY_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 (
+
+ //
+ // Fill list of found Peims for later list of those not installed
+ //
+ CopyMem (
+ &DebugFoundPeimList[DispatchData->CurrentPeim],
+ &DispatchData->CurrentPeimAddress->Name,
+ sizeof (EFI_GUID)
+ );
+
+ );
+
+ if (!Dispatched (
+ DispatchData->CurrentPeim,
+ DispatchData->DispatchedPeimBitMap
+ )) {
+ if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) {
+ Status = PeiLoadImage (
+ &PrivateData->PS,
+ DispatchData->CurrentPeimAddress,
+ &TempPtr.Raw
+ );
+ if (Status == EFI_SUCCESS) {
+
+ //
+ // The PEIM has its dependencies satisfied, and its entry point
+ // has been found, so invoke it.
+ //
+ 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) {
+
+ Status = TempPtr.PeimEntry (
+ 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);
+ //
+ //Subtract 0x10 from the 4th parameter indicating the new stack base,
+ //in order to provide buffer protection against possible illegal stack
+ //access that might corrupt the stack.
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)TempPtr.Raw,
+ PeiStartupDescriptor,
+ (VOID*)PrivateDataInMem,
+ (VOID*)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize)
+ );
+ }
+ }
+ }
+ }
+ 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 = PeiCoreLocatePpi (
+ &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 (
+ //
+ // 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;
+ }
+
+ );
+
+ 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
+ //
+ DEBUG_CODE (
+ if (CurrentPeim > (sizeof (*DispatchedPeimBitMap) * 8 - 1)) {
+ ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
+ }
+ );
+
+ *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 = PeiCoreFfsFindSectionData (
+ 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;
+}
+
+
+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
+
+--*/
+{
+ return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE));
+}
+
diff --git a/EdkModulePkg/Core/Pei/FwVol/FwVol.c b/EdkModulePkg/Core/Pei/FwVol/FwVol.c
new file mode 100644
index 0000000000..d034513bb0
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/FwVol/FwVol.c
@@ -0,0 +1,474 @@
+/*++
+
+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 <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_FVB_ERASE_POLARITY
+ in the Attributes field.
+ FfsHeader - Pointer to FFS File Header.
+
+Returns:
+ Returns the highest bit in the State field
+
+--*/
+{
+ EFI_FFS_FILE_STATE FileState;
+ EFI_FFS_FILE_STATE HighestBit;
+
+ FileState = FfsHeader->State;
+
+ if (ErasePolarity != 0) {
+ FileState = (EFI_FFS_FILE_STATE)~FileState;
+ }
+
+ HighestBit = 0x80;
+ while (HighestBit != 0 && (HighestBit & FileState) == 0) {
+ HighestBit >>= 1;
+ }
+
+ return HighestBit;
+}
+
+STATIC
+UINT8
+CalculateHeaderChecksum (
+ IN EFI_FFS_FILE_HEADER *FileHeader
+ )
+/*++
+
+Routine Description:
+
+ Calculates the checksum of the header of a file.
+
+Arguments:
+
+ FileHeader - Pointer to FFS File Header.
+
+Returns:
+ Checksum of the header.
+
+ The header is zero byte checksum.
+ - Zero means the header is good.
+ - Non-zero means the header is bad.
+
+
+Bugbug: For PEI performance reason, we comments this code at this time.
+--*/
+{
+ UINT8 *ptr;
+ UINTN Index;
+ UINT8 Sum;
+
+ Sum = 0;
+ ptr = (UINT8 *)FileHeader;
+
+ for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {
+ Sum = (UINT8)(Sum + ptr[Index]);
+ Sum = (UINT8)(Sum + ptr[Index+1]);
+ Sum = (UINT8)(Sum + ptr[Index+2]);
+ Sum = (UINT8)(Sum + ptr[Index+3]);
+ }
+
+ for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
+ Sum = (UINT8)(Sum + ptr[Index]);
+ }
+
+ //
+ // State field (since this indicates the different state of file).
+ //
+ Sum = (UINT8)(Sum - FileHeader->State);
+ //
+ // Checksum field of the file is not part of the header checksum.
+ //
+ Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);
+
+ return Sum;
+}
+
+STATIC
+EFI_STATUS
+PeiFfsFindNextFileEx (
+ IN EFI_FV_FILETYPE SearchType,
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ IN OUT EFI_FFS_FILE_HEADER **FileHeader,
+ IN BOOLEAN Flag
+ )
+/*++
+
+Routine Description:
+ Given the input file pointer, search for the next matching file in the
+ FFS volume as defined by SearchType. The search starts from FileHeader inside
+ the Firmware Volume defined by FwVolHeader.
+
+Arguments:
+ PeiServices - Pointer to the PEI Core Services Table.
+ SearchType - Filter to find only files of this type.
+ Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
+ FwVolHeader - Pointer to the FV header of the volume to search.
+ This parameter must point to a valid FFS volume.
+ FileHeader - Pointer to the current file from which to begin searching.
+ This pointer will be updated upon return to reflect the file found.
+ Flag - Indicator for if this is for PEI Dispath search
+Returns:
+ EFI_NOT_FOUND - No files matching the search criteria were found
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ UINT32 FileLength;
+ UINT32 FileOccupiedSize;
+ UINT32 FileOffset;
+ UINT64 FvLength;
+ UINT8 ErasePolarity;
+ UINT8 FileState;
+
+
+ FvLength = FwVolHeader->FvLength;
+ if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
+ ErasePolarity = 1;
+ } else {
+ ErasePolarity = 0;
+ }
+
+ //
+ // If FileHeader is not specified (NULL) start with the first file in the
+ // firmware volume. Otherwise, start from the FileHeader.
+ //
+ if (*FileHeader == NULL) {
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
+ } else {
+ //
+ // Length is 24 bits wide so mask upper 8 bits
+ // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
+ //
+ FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;
+ FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
+ }
+
+ FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
+ 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 = PeiCoreLocatePpi (
+ &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/EdkModulePkg/Core/Pei/Hob/Hob.c b/EdkModulePkg/Core/Pei/Hob/Hob.c
new file mode 100644
index 0000000000..6117827522
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Hob/Hob.c
@@ -0,0 +1,189 @@
+/*++
+
+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 <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 (
+ if (HobList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ );
+
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
+
+ *HobList = PrivateData->HobList.Raw;
+
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+PeiCreateHob (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT16 Type,
+ IN UINT16 Length,
+ IN OUT VOID **Hob
+ )
+/*++
+
+Routine Description:
+
+ Add a new HOB to the HOB List.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ Type - Type of the new HOB.
+ Length - Length of the new HOB to allocate.
+ Hob - Pointer to the new HOB.
+
+Returns:
+
+ Status - EFI_SUCCESS
+ - EFI_INVALID_PARAMETER if Hob is NULL
+ - EFI_NOT_AVAILABLE_YET if HobList is still not available.
+ - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
+ EFI_HOB_GENERIC_HEADER *HobEnd;
+ EFI_PHYSICAL_ADDRESS FreeMemory;
+
+
+ Status = PeiGetHobList (PeiServices, Hob);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ HandOffHob = *Hob;
+
+ Length = (UINT16)((Length + 0x7) & (~0x7));
+
+ FreeMemory = HandOffHob->EfiFreeMemoryTop -
+ HandOffHob->EfiFreeMemoryBottom;
+
+ if (FreeMemory < Length) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0;
+
+ HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length);
+ HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+ HobEnd++;
+ HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+PeiCoreBuildHobHandoffInfoTable (
+ IN EFI_BOOT_MODE BootMode,
+ IN EFI_PHYSICAL_ADDRESS MemoryBegin,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ Builds a Handoff Information Table HOB
+
+Arguments:
+
+ BootMode - Current Bootmode
+ MemoryBegin - Start Memory Address.
+ MemoryLength - Length of Memory.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *Hob;
+ EFI_HOB_GENERIC_HEADER *HobEnd;
+
+ Hob = (VOID *)(UINTN)MemoryBegin;
+ HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1);
+ Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;
+ Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE);
+ Hob->Header.Reserved = 0;
+
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+
+ Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;
+ Hob->BootMode = BootMode;
+
+ Hob->EfiMemoryTop = MemoryBegin + MemoryLength;
+ Hob->EfiMemoryBottom = MemoryBegin;
+ Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength;
+ Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1);
+ Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Pei/Image/Image.c b/EdkModulePkg/Core/Pei/Image/Image.c
new file mode 100644
index 0000000000..74286cff31
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Image/Image.c
@@ -0,0 +1,237 @@
+/*++
+
+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:
+
+ Image.c
+
+Abstract:
+
+ Pei Core Load Image Support
+
+--*/
+
+#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;
+//#ifdef EFI_NT_EMULATOR
+// EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor;
+// NT_PEI_LOAD_FILE_PPI *PeiNtService;
+//#endif
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+ EFI_PHYSICAL_ADDRESS ImageEntryPoint;
+ EFI_TE_IMAGE_HEADER *TEImageHeader;
+
+ *EntryPoint = NULL;
+ TEImageHeader = NULL;
+
+ //
+ // Try to find a PE32 section.
+ //
+ Status = PeiCoreFfsFindSectionData (
+ EFI_SECTION_PE32,
+ PeimFileHeader,
+ &Pe32Data
+ );
+ //
+ // If we didn't find a PE32 section, try to find a TE section.
+ //
+ if (EFI_ERROR (Status)) {
+ Status = PeiCoreFfsFindSectionData (
+ 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 = PeiCoreLocatePpi (
+ &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;
+ }
+
+ //
+ // Retrieve the entry point from the PE/COFF image header
+ //
+ Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageAddress, EntryPoint);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ } 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;
+ }
+ }
+
+ //
+ // 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 ", Pe32Data, *EntryPoint));
+ DEBUG_CODE (
+ EFI_IMAGE_DATA_DIRECTORY * DirectoryEntry;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * DebugEntry;
+ UINTN DirCount;
+ UINTN Index;
+ UINTN Index1;
+ BOOLEAN FileNameFound;
+ CHAR8 *AsciiString;
+ CHAR8 AsciiBuffer[512];
+ VOID *CodeViewEntryPointer;
+ INTN TEImageAdjust;
+ EFI_IMAGE_DOS_HEADER *DosHeader;
+ EFI_IMAGE_NT_HEADERS *PeHeader;
+
+ 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
+ //
+ PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff));
+ } else {
+ //
+ // DOS image header is not present, so PE header is at the image base
+ //
+ PeHeader = (EFI_IMAGE_NT_HEADERS *) 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;
+ TEImageAdjust = 0;
+ if (TEImageHeader == NULL) {
+ if (PeHeader->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHeader->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress);
+ }
+ } else {
+ if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
+ DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
+ TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize;
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader +
+ TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
+ TEImageAdjust);
+ }
+ }
+
+ if (DebugEntry != NULL && DirectoryEntry != NULL) {
+ for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) {
+ if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ if (DebugEntry->SizeOfData > 0) {
+ CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust);
+ switch (* (UINT32 *) CodeViewEntryPointer) {
+ case CODEVIEW_SIGNATURE_NB10:
+ AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+ break;
+
+ case CODEVIEW_SIGNATURE_RSDS:
+ AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+ break;
+
+ default:
+ AsciiString = NULL;
+ break;
+ }
+ if (AsciiString != NULL) {
+ FileNameFound = FALSE;
+ for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) {
+ if (AsciiString[Index] == '\\') {
+ Index1 = Index;
+ FileNameFound = TRUE;
+ }
+ }
+
+ if (FileNameFound) {
+ for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) {
+ AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index];
+ }
+ AsciiBuffer[Index - (Index1 + 1)] = 0;
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ );
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.i b/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.i
new file mode 100644
index 0000000000..c8a209debc
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.i
@@ -0,0 +1,93 @@
+//++
+// 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_
+
+#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/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.s b/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.s
new file mode 100644
index 0000000000..d8744b522f
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.s
@@ -0,0 +1,192 @@
+//++
+// 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 "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/EdkModulePkg/Core/Pei/Ipf/SwitchToCacheMode.c b/EdkModulePkg/Core/Pei/Ipf/SwitchToCacheMode.c
new file mode 100644
index 0000000000..34018d3100
--- /dev/null
+++ b/EdkModulePkg/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 <PeiMain.h>
+#include "IpfCpuCore.i"
+
+extern
+SAL_RETURN_REGS
+GetHandOffStatus (
+ VOID
+ );
+
+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;
+} \ No newline at end of file
diff --git a/EdkModulePkg/Core/Pei/Memory/MemoryServices.c b/EdkModulePkg/Core/Pei/Memory/MemoryServices.c
new file mode 100644
index 0000000000..48b2b3818c
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Memory/MemoryServices.c
@@ -0,0 +1,314 @@
+/*++
+
+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 <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 (
+ PrivateData->SizeOfCacheAsRam = PeiStartupDescriptor->SizeOfCacheAsRam;
+ PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) SizeOfCarHeap);
+ );
+
+ PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap;
+
+ PeiCoreBuildHobHandoffInfoTable (
+ BOOT_WITH_FULL_CONFIGURATION,
+ (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap,
+ (UINTN) SizeOfCarHeap
+ );
+ //
+ // Copy PeiServices from ROM to Cache in PrivateData
+ //
+ 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) {
+ 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;
+
+
+ Status = PeiCoreCreateHob (
+ EFI_HOB_TYPE_PEI_MEMORY_POOL,
+ (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
+ (VOID **)&Hob
+ );
+ *Buffer = Hob+1;
+
+
+ return Status;
+}
diff --git a/EdkModulePkg/Core/Pei/PeiMain.h b/EdkModulePkg/Core/Pei/PeiMain.h
new file mode 100644
index 0000000000..783fcd5867
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/PeiMain.h
@@ -0,0 +1,1141 @@
+/*++
+
+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.h
+
+Abstract:
+
+ Definition of Pei Core Structures and Services
+
+Revision History
+
+--*/
+
+#ifndef _PEI_MAIN_H_
+#define _PEI_MAIN_H_
+
+#ifdef EFI64
+#include "SalApi.h"
+#endif
+
+//
+//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range
+//
+#define EFI_PEI_CORE_PRIVATE_GUID \
+ {0xd641a0f5, 0xcb7c, 0x4846, { 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9 } }
+
+//
+// Pei Core private data structures
+//
+typedef union {
+ 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;
+
+
+//
+// Main PEI entry
+//
+EFI_STATUS
+EFIAPI
+PeiMain (
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor
+ )
+/*++
+
+Routine Description:
+
+ Main entry point to Pei Core.
+
+Arguments:
+
+ PeiStartupDescriptor - Information and services provided by SEC phase.
+
+Returns:
+
+ This function never returns
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+PeiCore (
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
+ IN PEI_CORE_INSTANCE *OldCoreData
+ )
+/*++
+
+Routine Description:
+
+ The entry routine to Pei Core, invoked by PeiMain during transition
+ from SEC to PEI. After switching stack in the PEI core, it will restart
+ with the old core data.
+
+Arguments:
+
+ PeiStartupDescriptor - Information and services provided by SEC phase.
+ OldCoreData - Pointer to old core data that is used to initialize the
+ core's data areas.
+
+Returns:
+
+ This function never returns
+
+--*/
+;
+
+
+//
+// Dispatcher support functions
+//
+
+EFI_STATUS
+PeimDispatchReadiness (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN VOID *DependencyExpression,
+ IN OUT BOOLEAN *Runnable
+ )
+/*++
+
+Routine Description:
+
+ This is the POSTFIX version of the dependency evaluator. When a
+ PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on
+ the evaluation stack. When that entry is poped from the evaluation
+ stack, the PPI is checked if it is installed. This method allows
+ some time savings as not all PPIs must be checked for certain
+ operation types (AND, OR).
+
+Arguments:
+
+ PeiServices - Calling context.
+
+ DependencyExpression - Pointer to a dependency expression. The Grammar adheres to
+ the BNF described above and is stored in postfix notation.
+ Runnable - is True if the driver can be scheduled and False if the driver
+ cannot be scheduled. This is the value that the schedulers
+ should use for deciding the state of the driver.
+
+Returns:
+
+ Status = EFI_SUCCESS if it is a well-formed Grammar
+ EFI_INVALID_PARAMETER if the dependency expression overflows
+ the evaluation stack
+ EFI_INVALID_PARAMETER if the dependency expression underflows
+ the evaluation stack
+ EFI_INVALID_PARAMETER if the dependency expression is not a
+ well-formed Grammar.
+--*/
+;
+
+
+EFI_STATUS
+PeiDispatcher (
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN PEI_CORE_DISPATCH_DATA *DispatchData
+ )
+
+/*++
+
+Routine Description:
+
+ Conduct PEIM dispatch.
+
+Arguments:
+
+ PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR
+ PrivateData - Pointer to the private data passed in from caller
+ DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data.
+
+Returns:
+
+ EFI_SUCCESS - Successfully dispatched PEIM.
+ EFI_NOT_FOUND - The dispatch failed.
+
+--*/
+;
+
+
+VOID
+InitializeDispatcherData (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CORE_INSTANCE *OldCoreData,
+ IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor
+ )
+/*++
+
+Routine Description:
+
+ Initialize the Dispatcher's data members
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ OldCoreData - Pointer to old core data (before switching stack).
+ NULL if being run in non-permament memory mode.
+ PeiStartupDescriptor - Information and services provided by SEC phase.
+
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+EFI_STATUS
+FindNextPeim (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader
+ )
+/*++
+
+Routine Description:
+ Given the input file pointer, search for the next matching file in the
+ FFS volume. The search starts from FileHeader inside
+ the Firmware Volume defined by FwVolHeader.
+
+Arguments:
+ PeiServices - Pointer to the PEI Core Services Table.
+
+ FwVolHeader - Pointer to the FV header of the volume to search.
+ This parameter must point to a valid FFS volume.
+
+ PeimFileHeader - Pointer to the current file from which to begin searching.
+ This pointer will be updated upon return to reflect the file found.
+
+Returns:
+ EFI_NOT_FOUND - No files matching the search criteria were found
+ EFI_SUCCESS
+
+--*/
+;
+
+BOOLEAN
+Dispatched (
+ IN UINT8 CurrentPeim,
+ IN 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
+
+--*/
+;
+
+#ifdef EFI64
+ //
+ // In Ipf we should make special changes for the PHIT pointers to support
+ // recovery boot in cache mode.
+ //
+#define SWITCH_TO_CACHE_MODE(CoreData) SwitchToCacheMode(CoreData)
+#define CACHE_MODE_ADDRESS_MASK 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.
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Core/Pei/PeiMain.mbd b/EdkModulePkg/Core/Pei/PeiMain.mbd
new file mode 100644
index 0000000000..c9d64e336a
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/PeiMain.mbd
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>PeiMain</BaseName>
+ <Guid>52C05B14-0B98-496c-BC3B-04B50211D680</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>PeiCoreEntryPoint</Library>
+ <Library>BaseLib</Library>
+ <Library>BaseMemoryLib</Library>
+ <Library>PeiServicesTablePointerLib</Library>
+ <Library>PeiCoreLib</Library>
+ <Library>PeiHobLib</Library>
+ <Library>PeiReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>BasePerformanceLibNull</Library>
+ <Arch ArchType="IA32">
+ <Library OverrideID="6666">BasePeCoffGetEntryPointLib</Library>
+ </Arch>
+ <Arch ArchType="X64">
+ <Library>BasePeCoffGetEntryPointLib</Library>
+ </Arch>
+ <Arch ArchType="IPF">
+ <Library>BasePeCoffGetEntryPointLib</Library>
+ </Arch>
+ <Arch ArchType="EBC">
+ <Library>BasePeCoffGetEntryPointLib</Library>
+ </Arch>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Core/Pei/PeiMain.msa b/EdkModulePkg/Core/Pei/PeiMain.msa
new file mode 100644
index 0000000000..b18b178caa
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/PeiMain.msa
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>PeiMain</BaseName>
+ <ModuleType>PEI_CORE</ModuleType>
+ <ComponentType>PEI_CORE</ComponentType>
+ <Guid>52C05B14-0B98-496c-BC3B-04B50211D680</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for PeiMain module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeiCoreLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeCoffGetEntryPointLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">TimerLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>PeiMain.h</Filename>
+ <Filename>BootMode\BootMode.c</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>
+ <Arch ArchType="IPF">
+ <Filename>ipf\SwitchToCacheMode.c</Filename>
+ <Filename>ipf\IpfCpuCore.i</Filename>
+ <Filename>ipf\IpfCpuCore.s</Filename>
+ </Arch>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Hobs>
+ <Hob Usage="ALWAYS_PRODUCED" HobType="PHIT"></Hob>
+ <Hob Usage="SOMETIMES_PRODUCED" HobType="GUID_EXTENSION">
+ <C_Name>gPeiPerformanceHobGuid</C_Name>
+ <Guid>0xec4df5af, 0x4395, 0x4cc9, 0x94, 0xde, 0x77, 0x50, 0x6d, 0x12, 0xc7, 0xb8</Guid>
+ </Hob>
+ </Hobs>
+ <PPIs>
+ <Ppi Usage="ALWAYS_PRODUCED">MemoryDiscovered</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">FindFv</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">FvFileLoader</Ppi>
+ <Ppi Usage="ALWAYS_CONSUMED">DxeIpl</Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">Reset</Ppi>
+ <Ppi Usage="SOMETIMES_CONSUMED">StatusCode</Ppi>
+ <PpiNotify Usage="SOMETIMES_CONSUMED">Security</PpiNotify>
+ </PPIs>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>PeiCore</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Core/Pei/PeiMain/PeiMain.c b/EdkModulePkg/Core/Pei/PeiMain/PeiMain.c
new file mode 100644
index 0000000000..014c571c05
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -0,0 +1,243 @@
+/*++
+
+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 <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 PEI_CORE_INSTANCE *OldCoreData
+ )
+/*++
+
+Routine Description:
+
+ The entry routine to Pei Core, invoked by PeiMain during transition
+ from SEC to PEI. After switching stack in the PEI core, it will restart
+ with the old core data.
+
+Arguments:
+
+ PeiStartupDescriptor - Information and services provided by SEC phase.
+ OldCoreData - Pointer to old core data that is used to initialize the
+ core's data areas.
+
+Returns:
+
+ This function never returns
+ EFI_NOT_FOUND - Never reach
+
+--*/
+{
+ PEI_CORE_INSTANCE PrivateData;
+ EFI_STATUS Status;
+ PEI_CORE_TEMP_POINTERS TempPtr;
+ PEI_CORE_DISPATCH_DATA *DispatchData;
+ UINT64 mTick;
+
+ mTick = 0;
+
+#ifdef EFI_PEI_PERFORMANCE
+ if (OldCoreData == NULL) {
+ mTick = GetPerformanceCounter ();
+ }
+#endif
+
+
+ //
+ // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory()
+ // the 63-bit of address is set to 1.
+ //
+ SWITCH_TO_CACHE_MODE (OldCoreData);
+
+ if (OldCoreData != NULL) {
+ 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 macro is used to prevent this code from being compiled
+ // on a debug build.
+ //
+ DEBUG_CODE (
+ UINTN *StackPointer;
+ UINTN StackValue;
+
+ StackValue = INIT_CAR_VALUE;
+ for (StackPointer = (UINTN *) OldCoreData->MaxTopOfCarHeap;
+ ((UINTN) StackPointer < ((UINTN) OldCoreData->BottomOfCarHeap + OldCoreData->SizeOfCacheAsRam))
+ && StackValue == INIT_CAR_VALUE;
+ StackPointer++) {
+ StackValue = *StackPointer;
+ }
+
+ 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)
+ ));
+ );
+
+ //
+ // Alert any listeners that there is permanent memory available
+ //
+ PERF_START (NULL,"DisMem", NULL, 0);
+ Status = PeiCoreInstallPpi (&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
+ );
+
+ //
+ // 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 = PeiCoreInstallPpi (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 = PeiCoreLocatePpi (
+ &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/EdkModulePkg/Core/Pei/Ppi/Ppi.c b/EdkModulePkg/Core/Pei/Ppi/Ppi.c
new file mode 100644
index 0000000000..7fdb08c66f
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Ppi/Ppi.c
@@ -0,0 +1,658 @@
+/*++
+
+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 <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_INFO, "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_INFO, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
+ NotifyDispatchCount ++;
+ }
+
+ PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyList;
+
+ PrivateData->PpiData.NotifyListEnd--;
+ 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/EdkModulePkg/Core/Pei/Reset/Reset.c b/EdkModulePkg/Core/Pei/Reset/Reset.c
new file mode 100644
index 0000000000..6bcb4ce31b
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Reset/Reset.c
@@ -0,0 +1,68 @@
+/*++
+
+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 <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 = PeiCoreLocatePpi (
+ &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/EdkModulePkg/Core/Pei/Security/Security.c b/EdkModulePkg/Core/Pei/Security/Security.c
new file mode 100644
index 0000000000..5908928c7b
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/Security/Security.c
@@ -0,0 +1,192 @@
+/*++
+
+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 <PeiMain.h>
+
+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) {
+ PeiCoreNotifyPpi (&mNotifyList);
+ }
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+SecurityPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+/*++
+
+Routine Description:
+
+ Provide a callback for when the security PPI is installed.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ NotifyDescriptor - The descriptor for the notification event.
+ Ppi - Pointer to the PPI in question.
+
+Returns:
+
+ EFI_SUCCESS - The function is successfully processed.
+
+--*/
+{
+ PEI_CORE_INSTANCE *PrivateData;
+
+ //
+ // Get PEI Core private data
+ //
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
+
+ //
+ // If there isn't a security PPI installed, use the one from notification
+ //
+ if (PrivateData->PrivateSecurityPpi == NULL) {
+ PrivateData->PrivateSecurityPpi = (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/EdkModulePkg/Core/Pei/StatusCode/StatusCode.c b/EdkModulePkg/Core/Pei/StatusCode/StatusCode.c
new file mode 100644
index 0000000000..496effa5e5
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/StatusCode/StatusCode.c
@@ -0,0 +1,95 @@
+/*++
+
+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 <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 = PeiCoreLocatePpi (
+ &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;
+}
+
+
+
diff --git a/EdkModulePkg/Core/Pei/build.xml b/EdkModulePkg/Core/Pei/build.xml
new file mode 100644
index 0000000000..94a26db352
--- /dev/null
+++ b/EdkModulePkg/Core/Pei/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="PeiMain"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Core\Pei"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="PeiMain">
+ <GenBuild baseName="PeiMain" mbdFilename="${MODULE_DIR}\PeiMain.mbd" msaFilename="${MODULE_DIR}\PeiMain.msa"/>
+ </target>
+ <target depends="PeiMain_clean" name="clean"/>
+ <target depends="PeiMain_cleanall" name="cleanall"/>
+ <target name="PeiMain_clean">
+ <OutputDirSetup baseName="PeiMain" mbdFilename="${MODULE_DIR}\PeiMain.mbd" msaFilename="${MODULE_DIR}\PeiMain.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\PeiMain_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\PeiMain_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="PeiMain_cleanall">
+ <OutputDirSetup baseName="PeiMain" mbdFilename="${MODULE_DIR}\PeiMain.mbd" msaFilename="${MODULE_DIR}\PeiMain.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\PeiMain_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\PeiMain_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**PeiMain*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file