summaryrefslogtreecommitdiff
path: root/EDK/Foundation/Core/Dxe
diff options
context:
space:
mode:
Diffstat (limited to 'EDK/Foundation/Core/Dxe')
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.cif38
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf65
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.mak69
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.sdl26
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.h100
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.h33
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.c28
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.h361
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.h109
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.h35
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.h43
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.h40
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.c29
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.h114
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.c28
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.h146
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.c29
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.h100
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.h260
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.c29
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.h41
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.c30
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.h41
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.c27
-rw-r--r--EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.h206
-rw-r--r--EDK/Foundation/Core/Dxe/Dispatcher/Dispatcher.c1203
-rw-r--r--EDK/Foundation/Core/Dxe/Dispatcher/dependency.c451
-rw-r--r--EDK/Foundation/Core/Dxe/DxeMain.cif53
-rw-r--r--EDK/Foundation/Core/Dxe/DxeMain.inf111
-rw-r--r--EDK/Foundation/Core/Dxe/DxeMain/DxeMain.c1010
-rw-r--r--EDK/Foundation/Core/Dxe/DxeMain/DxeProtocolNotify.c319
-rw-r--r--EDK/Foundation/Core/Dxe/Event/event.c845
-rw-r--r--EDK/Foundation/Core/Dxe/Event/exec.h209
-rw-r--r--EDK/Foundation/Core/Dxe/Event/execdata.c50
-rw-r--r--EDK/Foundation/Core/Dxe/Event/timer.c386
-rw-r--r--EDK/Foundation/Core/Dxe/Event/tpl.c198
-rw-r--r--EDK/Foundation/Core/Dxe/FwVol/Ffs.c266
-rw-r--r--EDK/Foundation/Core/Dxe/FwVol/FwVol.c556
-rw-r--r--EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c99
-rw-r--r--EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h487
-rw-r--r--EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c520
-rw-r--r--EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c60
-rw-r--r--EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.c621
-rw-r--r--EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.h334
-rw-r--r--EDK/Foundation/Core/Dxe/Gcd/gcd.c2509
-rw-r--r--EDK/Foundation/Core/Dxe/Gcd/gcd.h54
-rw-r--r--EDK/Foundation/Core/Dxe/Hand/DriverSupport.c860
-rw-r--r--EDK/Foundation/Core/Dxe/Hand/Notify.c335
-rw-r--r--EDK/Foundation/Core/Dxe/Hand/hand.h339
-rw-r--r--EDK/Foundation/Core/Dxe/Hand/handle.c1716
-rw-r--r--EDK/Foundation/Core/Dxe/Hand/locate.c743
-rw-r--r--EDK/Foundation/Core/Dxe/Ia32/Processor.h27
-rw-r--r--EDK/Foundation/Core/Dxe/Image/Image.c1626
-rw-r--r--EDK/Foundation/Core/Dxe/Image/Image.h399
-rw-r--r--EDK/Foundation/Core/Dxe/Image/ImageFile.c646
-rw-r--r--EDK/Foundation/Core/Dxe/Include/DxeCore.h2535
-rw-r--r--EDK/Foundation/Core/Dxe/Include/Library.h531
-rw-r--r--EDK/Foundation/Core/Dxe/Ipf/Processor.h27
-rw-r--r--EDK/Foundation/Core/Dxe/Library/Library.c878
-rw-r--r--EDK/Foundation/Core/Dxe/Mem/Page.c1648
-rw-r--r--EDK/Foundation/Core/Dxe/Mem/imem.h214
-rw-r--r--EDK/Foundation/Core/Dxe/Mem/memdata.c41
-rw-r--r--EDK/Foundation/Core/Dxe/Mem/pool.c613
-rw-r--r--EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.c262
-rw-r--r--EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.h129
-rw-r--r--EDK/Foundation/Core/Dxe/Misc/DebugMask.c400
-rw-r--r--EDK/Foundation/Core/Dxe/Misc/DebugMask.h122
-rw-r--r--EDK/Foundation/Core/Dxe/Misc/InstallConfigurationTable.c230
-rw-r--r--EDK/Foundation/Core/Dxe/Misc/SetWatchdogTimer.c84
-rw-r--r--EDK/Foundation/Core/Dxe/Misc/Stall.c79
-rw-r--r--EDK/Foundation/Core/Dxe/SectionExtraction/CoreSectionExtraction.c1387
-rw-r--r--EDK/Foundation/Core/Dxe/x64/Processor.h27
79 files changed, 28455 insertions, 0 deletions
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.cif b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.cif
new file mode 100644
index 0000000..de96301
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.cif
@@ -0,0 +1,38 @@
+<component>
+ name = "ArchProtocolLib"
+ category = ModulePart
+ LocalRoot = "EDK\Foundation\Core\Dxe\ArchProtocol"
+ RefName = "ArchProtocolLib"
+[files]
+"ArchProtocolLib.sdl"
+"ArchProtocolLib.mak"
+"Bds\Bds.c"
+"Bds\Bds.h"
+"Capsule\Capsule.c"
+"Capsule\Capsule.h"
+"Cpu\Cpu.c"
+"Cpu\Cpu.h"
+"Metronome\Metronome.c"
+"Metronome\Metronome.h"
+"MonotonicCounter\MonotonicCounter.c"
+"MonotonicCounter\MonotonicCounter.h"
+"RealTimeClock\RealTimeClock.c"
+"RealTimeClock\RealTimeClock.h"
+"Reset\Reset.c"
+"Reset\Reset.h"
+"Runtime\Runtime.c"
+"Runtime\Runtime.h"
+"Security\Security.c"
+"Security\Security.h"
+"StatusCode\StatusCode.c"
+"StatusCode\StatusCode.h"
+"Timer\Timer.c"
+"Timer\Timer.h"
+"Variable\Variable.c"
+"Variable\Variable.h"
+"VariableWrite\VariableWrite.c"
+"VariableWrite\VariableWrite.h"
+"WatchdogTimer\WatchdogTimer.c"
+"WatchdogTimer\WatchdogTimer.h"
+"ArchProtocolLib.inf"
+<endComponent>
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf
new file mode 100644
index 0000000..705c606
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf
@@ -0,0 +1,65 @@
+#/*++
+#
+# Copyright (c) 2004 - 2006, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# ArchProtocolLib.inf
+#
+# Abstract:
+#
+# Component description file for the Architectural Protocol Library.
+#
+#--*/
+
+[defines]
+BASE_NAME = ArchProtocolLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ Bds\Bds.c
+ Bds\Bds.h
+ Capsule\Capsule.c
+ Capsule\Capsule.h
+ Cpu\Cpu.c
+ Cpu\Cpu.h
+ Metronome\Metronome.c
+ Metronome\Metronome.h
+ MonotonicCounter\MonotonicCounter.c
+ MonotonicCounter\MonotonicCounter.h
+ RealTimeClock\RealTimeClock.c
+ RealTimeClock\RealTimeClock.h
+ Reset\Reset.c
+ Reset\Reset.h
+ Runtime\Runtime.c
+ Runtime\Runtime.h
+ Security\Security.c
+ Security\Security.h
+ StatusCode\StatusCode.c
+ StatusCode\StatusCode.h
+ Timer\Timer.c
+ Timer\Timer.h
+ Variable\Variable.c
+ Variable\Variable.h
+ VariableWrite\VariableWrite.c
+ VariableWrite\VariableWrite.h
+ WatchdogTimer\WatchdogTimer.c
+ WatchdogTimer\WatchdogTimer.h
+
+[includes.common]
+ $(EDK_SOURCE)\Foundation\Efi
+ $(EDK_SOURCE)\Foundation\Include
+ $(EDK_SOURCE)\Foundation\Efi\Include
+ $(EDK_SOURCE)\Foundation\Framework\Include
+ $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+ $(EDK_SOURCE)\Foundation\Core\Dxe
+ $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+
+[nmake.common]
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.mak b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.mak
new file mode 100644
index 0000000..5a37110
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.mak
@@ -0,0 +1,69 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/IntelEDK/ArchProtocolLib/ArchProtocolLib.mak 1 1/20/12 4:12a Jeffch $
+#
+# $Revision: 1 $
+#
+# $Date: 1/20/12 4:12a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/IntelEDK/ArchProtocolLib/ArchProtocolLib.mak $
+#
+# 1 1/20/12 4:12a Jeffch
+# Create Intel EDK 1117 Patch 7.
+#
+# 1 9/27/11 6:34a Wesleychen
+# Intel EDK initially releases.
+#
+# 2 9/02/09 3:06a Iminglin
+# EIP24919
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: ArchProtocolLib.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+$(ARCHPROTOCOLLIB) : ArchProtocolLib
+
+$(BUILD_DIR)\ArchProtocolLib.lib : ArchProtocolLib
+
+ArchProtocolLib : $(BUILD_DIR)\ArchProtocolLib.mak ArchProtocolLibBin
+
+$(BUILD_DIR)\ArchProtocolLib.mak : $(ArchProtocolLib_DIR)\$(@B).cif $(ArchProtocolLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(ArchProtocolLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+ArchProtocolLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS)\
+ /f $(BUILD_DIR)\ArchProtocolLib.mak all\
+ TYPE=LIBRARY \
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.sdl b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.sdl
new file mode 100644
index 0000000..f758364
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.sdl
@@ -0,0 +1,26 @@
+TOKEN
+ Name = "ArchProtocolLib_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable ArchProtocolLib support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "ARCHPROTOCOLLIB"
+ Value = "$(BUILD_DIR)\ArchProtocolLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "ArchProtocolLib_DIR"
+End
+
+MODULE
+ Help = "Includes ArchProtocolLib.mak to Project"
+ File = "ArchProtocolLib.mak"
+End
+
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.c
new file mode 100644
index 0000000..5bd71bf
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.c
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Bds.c
+
+Abstract:
+
+ Boot Device Selection Architectural Protocol GUID as defined in Tiano
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Bds)
+
+EFI_GUID gEfiBdsArchProtocolGuid = EFI_BDS_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiBdsArchProtocolGuid, "BDS", "BDS Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.h
new file mode 100644
index 0000000..a1282df
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Bds/Bds.h
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Bds.h
+
+Abstract:
+
+ Boot Device Selection Architectural Protocol as defined in Tiano
+
+ When the DXE core is done it calls the BDS via this protocol.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_BDS_H_
+#define _ARCH_PROTOCOL_BDS_H_
+
+//
+// Global ID for the BDS Architectural Protocol
+//
+#define EFI_BDS_ARCH_PROTOCOL_GUID \
+ { 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
+
+//
+// Declare forward reference for the BDS Architectural Protocol
+//
+EFI_FORWARD_DECLARATION (EFI_BDS_ARCH_PROTOCOL);
+
+typedef
+VOID
+(EFIAPI *EFI_BDS_ENTRY) (
+ IN EFI_BDS_ARCH_PROTOCOL * This
+ );
+/*++
+
+Routine Description:
+
+ This function uses policy data from the platform to determine what operating
+ system or system utility should be loaded and invoked. This function call
+ also optionally make the use of user input to determine the operating system
+ or system utility to be loaded and invoked. When the DXE Core has dispatched
+ all the drivers on the dispatch queue, this function is called. This
+ function will attempt to connect the boot devices required to load and invoke
+ the selected operating system or system utility. During this process,
+ additional firmware volumes may be discovered that may contain addition DXE
+ drivers that can be dispatched by the DXE Core. If a boot device cannot be
+ fully connected, this function calls the DXE Service Dispatch() to allow the
+ DXE drivers from any newly discovered firmware volumes to be dispatched.
+ Then the boot device connection can be attempted again. If the same boot
+ device connection operation fails twice in a row, then that boot device has
+ failed, and should be skipped. This function should never return.
+
+Arguments:
+
+ This - The EFI_BDS_ARCH_PROTOCOL instance.
+
+Returns:
+
+ None.
+
+--*/
+
+//
+// Interface stucture for the BDS Architectural Protocol
+//
+typedef struct _EFI_BDS_ARCH_PROTOCOL {
+ EFI_BDS_ENTRY Entry;
+} EFI_BDS_ARCH_PROTOCOL;
+
+/*++
+
+ Protocol Description:
+ The EFI_BDS_ARCH_PROTOCOL transfers control from DXE to an operating
+ system or a system utility. If there are not enough drivers initialized
+ when this protocol is used to access the required boot device(s), then
+ this protocol should add drivers to the dispatch queue and return control
+ back to the dispatcher. Once the required boot devices are available, then
+ the boot device can be used to load and invoke an OS or a system utility.
+
+ Parameters:
+
+ Entry - The entry point to BDS. This call does not take any parameters,
+ and the return value can be ignored. If it returns, then the
+ dispatcher must be invoked again, if it never returns, then an
+ operating system or a system utility have been invoked.
+
+--*/
+
+extern EFI_GUID gEfiBdsArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.c
new file mode 100644
index 0000000..42673a2
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.c
@@ -0,0 +1,27 @@
+/*++
+
+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:
+
+ Capsule.c
+
+Abstract:
+
+ Capsule Architectural Protocol is used to produce the UEFI 2.0 capsule runtime services
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Capsule)
+
+EFI_GUID gEfiCapsuleArchProtocolGuid = EFI_CAPSULE_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiCapsuleArchProtocolGuid, "Capsule", "Capsule Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.h
new file mode 100644
index 0000000..2e11f83
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Capsule/Capsule.h
@@ -0,0 +1,33 @@
+/*++
+
+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:
+
+ Capsule.h
+
+Abstract:
+
+ Capsule Architectural Protocol is newly added to produce UEFI2.0 capsule runtime services.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_CAPSULE_ARCH_H_
+#define _ARCH_PROTOCOL_CAPSULE_ARCH_H_
+
+//
+// Global ID for the Capsule Architectural Protocol
+//
+#define EFI_CAPSULE_ARCH_PROTOCOL_GUID \
+ { 0x5053697e, 0x2cbc, 0x4819, 0x90, 0xd9, 0x5, 0x80, 0xde, 0xee, 0x57, 0x54 }
+
+extern EFI_GUID gEfiCapsuleArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.c
new file mode 100644
index 0000000..40dbb06
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.c
@@ -0,0 +1,28 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Cpu.c
+
+Abstract:
+
+ CPU Architectural Protocol GUID as defined in Tiano
+
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
+
+EFI_GUID gEfiCpuArchProtocolGuid = EFI_CPU_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiCpuArchProtocolGuid, "CPU", "CPU Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.h
new file mode 100644
index 0000000..fdc426b
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Cpu/Cpu.h
@@ -0,0 +1,361 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Cpu.h
+
+Abstract:
+
+ CPU Architectural Protocol as defined in Tiano
+
+ This code abstracts the DXE core from processor implementation details.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_CPU_H_
+#define _ARCH_PROTOCOL_CPU_H_
+
+#include EFI_PROTOCOL_DEFINITION (DebugSupport)
+
+#define EFI_CPU_ARCH_PROTOCOL_GUID \
+ { 0x26baccb1, 0x6f42, 0x11d4, 0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }
+
+EFI_FORWARD_DECLARATION (EFI_CPU_ARCH_PROTOCOL);
+
+typedef enum {
+ EfiCpuFlushTypeWriteBackInvalidate,
+ EfiCpuFlushTypeWriteBack,
+ EfiCpuFlushTypeInvalidate,
+ EfiCpuMaxFlushType
+} EFI_CPU_FLUSH_TYPE;
+
+typedef enum {
+ EfiCpuInit,
+ EfiCpuMaxInitType
+} EFI_CPU_INIT_TYPE;
+
+typedef
+VOID
+(*EFI_CPU_INTERRUPT_HANDLER) (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_FLUSH_DATA_CACHE) (
+ IN EFI_CPU_ARCH_PROTOCOL * This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+/*++
+
+Routine Description:
+
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+ Start - The beginning physical address to flush from the processor's data
+ cache.
+ Length - The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ FlushType - Specifies the type of flush operation to perform.
+
+Returns:
+
+ EFI_SUCCESS - The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ EFI_UNSUPPORTEDT - The processor does not support the cache flush type specified
+ by FlushType.
+ EFI_DEVICE_ERROR - The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_ENABLE_INTERRUPT) (
+ IN EFI_CPU_ARCH_PROTOCOL * This
+ );
+
+/*++
+
+Routine Description:
+
+ This function enables interrupt processing by the processor.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS - Interrupts are enabled on the processor.
+ EFI_DEVICE_ERROR - Interrupts could not be enabled on the processor.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_DISABLE_INTERRUPT) (
+ IN EFI_CPU_ARCH_PROTOCOL * This
+ );
+
+/*++
+
+Routine Description:
+
+ This function disables interrupt processing by the processor.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS - Interrupts are disabled on the processor.
+ EFI_DEVICE_ERROR - Interrupts could not be disabled on the processor.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_GET_INTERRUPT_STATE) (
+ IN EFI_CPU_ARCH_PROTOCOL * This,
+ OUT BOOLEAN *State
+ );
+
+/*++
+
+Routine Description:
+
+ This function retrieves the processor's current interrupt state a returns it in
+ State. If interrupts are currently enabled, then TRUE is returned. If interrupts
+ are currently disabled, then FALSE is returned.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+ State - A pointer to the processor's current interrupt state. Set to TRUE if
+ interrupts are enabled and FALSE if interrupts are disabled.
+Returns:
+
+ EFI_SUCCESS - The processor's current interrupt state was returned in State.
+ EFI_INVALID_PARAMETER - State is NULL.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_INIT) (
+ IN EFI_CPU_ARCH_PROTOCOL * This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+/*++
+
+Routine Description:
+
+ This function generates an INIT on the processor. If this function succeeds, then the
+ processor will be reset, and control will not be returned to the caller. If InitType is
+ not supported by this processor, or the processor cannot programmatically generate an
+ INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
+ occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+ InitType - The type of processor INIT to perform.
+
+Returns:
+
+ EFI_SUCCESS - The processor INIT was performed. This return code should never be seen.
+ EFI_UNSUPPORTED - The processor INIT operation specified by InitType is not supported
+ by this processor.
+ EFI_DEVICE_ERROR - The processor INIT failed.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_REGISTER_INTERRUPT_HANDLER) (
+ IN EFI_CPU_ARCH_PROTOCOL * This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+/*++
+
+Routine Description:
+
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+ InterruptType - A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ InterruptHandler - A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+Returns:
+
+ EFI_SUCCESS - The handler for the processor interrupt was successfully installed or uninstalled.
+ EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ EFI_UNSUPPORTED - The interrupt specified by InterruptType is not supported.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_GET_TIMER_VALUE) (
+ IN EFI_CPU_ARCH_PROTOCOL * This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+/*++
+
+Routine Description:
+
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+ TimerIndex - Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ TimerValue - Pointer to the returned timer value.
+ TimerPeriod - A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+Returns:
+
+ EFI_SUCCESS - The processor timer value specified by TimerIndex was returned in TimerValue.
+ EFI_DEVICE_ERROR - An error occurred attempting to read one of the processor's timers.
+ EFI_INVALID_PARAMETER - TimerValue is NULL or TimerIndex is not valid.
+ EFI_UNSUPPORTED - The processor does not have any readable timers.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CPU_SET_MEMORY_ATTRIBUTES) (
+ IN EFI_CPU_ARCH_PROTOCOL * This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+/*++
+
+Routine Description:
+
+ This function modifies the attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+Arguments:
+
+ This - The EFI_CPU_ARCH_PROTOCOL instance.
+ BaseAddress - The physical address that is the start address of a memory region.
+ Length - The size in bytes of the memory region.
+ Attributes - The bit mask of attributes to set for the memory region.
+
+Returns:
+
+ EFI_SUCCESS - The attributes were set for the memory region.
+ EFI_ACCESS_DENIED - The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ EFI_INVALID_PARAMETER - Length is zero.
+ EFI_OUT_OF_RESOURCES - There are not enough system resources to modify the attributes of
+ the memory resource range.
+ EFI_UNSUPPORTED - The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+
+--*/
+
+typedef struct _EFI_CPU_ARCH_PROTOCOL {
+ EFI_CPU_FLUSH_DATA_CACHE FlushDataCache;
+ EFI_CPU_ENABLE_INTERRUPT EnableInterrupt;
+ EFI_CPU_DISABLE_INTERRUPT DisableInterrupt;
+ EFI_CPU_GET_INTERRUPT_STATE GetInterruptState;
+ EFI_CPU_INIT Init;
+ EFI_CPU_REGISTER_INTERRUPT_HANDLER RegisterInterruptHandler;
+ EFI_CPU_GET_TIMER_VALUE GetTimerValue;
+ EFI_CPU_SET_MEMORY_ATTRIBUTES SetMemoryAttributes;
+ UINT32 NumberOfTimers;
+ UINT32 DmaBufferAlignment;
+} EFI_CPU_ARCH_PROTOCOL;
+
+/*++
+
+Protocol Description:
+
+ The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE
+ Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt
+ vectors and exception vectors, reading internal processor timers, resetting the processor, and
+ determining the processor frequency.
+
+Parameters:
+
+ FlushDataCache - Flushes a range of the processor's data cache. If the processor does
+ not contain a data cache, or the data cache is fully coherent, then this
+ function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of addresses from the data cache, then the entire data
+ cache must be flushed.
+ EnableInterrupt - Enables interrupt processing by the processor.
+ DisableInterrupt - Disables interrupt processing by the processor.
+ GetInterruptState - Retrieves the processor's current interrupt state.
+ Init - Generates an INIT on the processor. If a processor cannot programmatically
+ generate an INIT without help from external hardware, then this function
+ returns EFI_UNSUPPORTED.
+ RegisterInterruptHandler - Associates an interrupt service routine with one of the processor's interrupt
+ vectors. This function is typically used by the EFI_TIMER_ARCH_PROTOCOL to
+ hook the timer interrupt in a system. It can also be used by the debugger to
+ hook exception vectors.
+ GetTimerValue - Returns the value of one of the processor's internal timers.
+ SetMemoryAttributes - Attempts to set the attributes of a memory region.
+ NumberOfTimers - The number of timers that are available in a processor. The value in this
+ field is a constant that must not be modified after the CPU Architectural
+ Protocol is installed. All consumers must treat this as a read-only field.
+ DmaBufferAlignment - The size, in bytes, of the alignment required for DMA buffer allocations.
+ This is typically the size of the largest data cache line in the platform.
+ The value in this field is a constant that must not be modified after the
+ CPU Architectural Protocol is installed. All consumers must treat this as
+ a read-only field.
+
+--*/
+
+extern EFI_GUID gEfiCpuArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.c
new file mode 100644
index 0000000..a09a0d5
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.c
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Metronome.c
+
+Abstract:
+
+ Metronome Architectural Protocol as defined in Tiano
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+
+EFI_GUID gEfiMetronomeArchProtocolGuid = EFI_METRONOME_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiMetronomeArchProtocolGuid, "Metronome", "Metronome Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.h
new file mode 100644
index 0000000..c254d9b
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Metronome/Metronome.h
@@ -0,0 +1,109 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Metronome.h
+
+Abstract:
+
+ Metronome Architectural Protocol as defined in DXE CIS
+
+ This code abstracts the DXE core to provide delay services.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_METRONOME_H_
+#define _ARCH_PROTOCOL_METRONOME_H_
+
+//
+// Global ID for the Metronome Architectural Protocol
+//
+#define EFI_METRONOME_ARCH_PROTOCOL_GUID \
+ { 0x26baccb2, 0x6f42, 0x11d4, 0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }
+
+//
+// Declare forward reference for the Metronome Architectural Protocol
+//
+EFI_FORWARD_DECLARATION (EFI_METRONOME_ARCH_PROTOCOL);
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_METRONOME_WAIT_FOR_TICK) (
+ IN EFI_METRONOME_ARCH_PROTOCOL *This,
+ IN UINT32 TickNumber
+ );
+/*++
+
+Routine Description:
+
+ The WaitForTick() function waits for the number of ticks specified by
+ TickNumber from a known time source in the platform. If TickNumber of
+ ticks are detected, then EFI_SUCCESS is returned. The actual time passed
+ between entry of this function and the first tick is between 0 and
+ TickPeriod 100 nS units. If you want to guarantee that at least TickPeriod
+ time has elapsed, wait for two ticks. This function waits for a hardware
+ event to determine when a tick occurs. It is possible for interrupt
+ processing, or exception processing to interrupt the execution of the
+ WaitForTick() function. Depending on the hardware source for the ticks, it
+ is possible for a tick to be missed. This function cannot guarantee that
+ ticks will not be missed. If a timeout occurs waiting for the specified
+ number of ticks, then EFI_TIMEOUT is returned.
+
+Arguments:
+
+ This - The EFI_METRONOME_ARCH_PROTOCOL instance.
+
+ TickNumber - Number of ticks to wait.
+
+Returns:
+
+ EFI_SUCCESS - The wait for the number of ticks specified by TickNumber
+ succeeded.
+
+ EFI_TIMEOUT - A timeout occurred waiting for the specified number of ticks.
+
+--*/
+
+//
+// Interface stucture for the Metronome Architectural Protocol
+//
+typedef struct _EFI_METRONOME_ARCH_PROTOCOL {
+ EFI_METRONOME_WAIT_FOR_TICK WaitForTick;
+ UINT32 TickPeriod;
+} EFI_METRONOME_ARCH_PROTOCOL;
+
+/*++
+
+ Protocol Description:
+ This protocol provides access to a known time source in the platform to the
+ core. The core uses this known time source to produce core services that
+ require calibrated delays.
+
+ Parameters:
+
+ WaitForTick - Waits for a specified number of ticks from a known time source
+ in the platform. The actual time passed between entry of this
+ function and the first tick is between 0 and TickPeriod 100 nS
+ units. If you want to guarantee that at least TickPeriod time
+ has elapsed, wait for two ticks.
+
+ TickPeriod - The period of platform's known time source in 100 nS units.
+ This value on any platform must be at least 10 uS, and must not
+ exceed 200 uS. The value in this field is a constant that must
+ not be modified after the Metronome architectural protocol is
+ installed. All consumers must treat this as a read-only field.
+
+--*/
+
+extern EFI_GUID gEfiMetronomeArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.c b/EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.c
new file mode 100644
index 0000000..54d9ca4
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.c
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MonotonicCounter.c
+
+Abstract:
+
+ Monotonic Counter Architectural Protocol GUID as defined in the DXE CIS
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION(MonotonicCounter)
+
+EFI_GUID gEfiMonotonicCounterArchProtocolGuid = EFI_MONTONIC_COUNTER_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiMonotonicCounterArchProtocolGuid, "Monotonic Counter", "Monotonic Counter Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.h b/EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.h
new file mode 100644
index 0000000..39e68aa
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/MonotonicCounter/MonotonicCounter.h
@@ -0,0 +1,35 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MonotonicCounter.h
+
+Abstract:
+
+ Monotonic Counter Architectural Protocol as defined in DXE CIS
+
+ This code provides the services required to access the systems monotonic counter
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_MONTONIC_COUNTER_H_
+#define _ARCH_PROTOCOL_MONTONIC_COUNTER_H_
+
+//
+// Global ID for the Monotonic Counter Architectural Protocol
+//
+#define EFI_MONTONIC_COUNTER_ARCH_PROTOCOL_GUID \
+ {0x1da97072, 0xbddc, 0x4b30, 0x99, 0xf1, 0x72, 0xa0, 0xb5, 0x6f, 0xff, 0x2a}
+
+extern EFI_GUID gEfiMonotonicCounterArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.c b/EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.c
new file mode 100644
index 0000000..1109957
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.c
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ RealTimeClock.c
+
+Abstract:
+
+ Real Time clock Architectural Protocol GUID as defined in Tiano
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (RealTimeClock)
+
+EFI_GUID gEfiRealTimeClockArchProtocolGuid = EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiRealTimeClockArchProtocolGuid, "RTC", "Real Time Clock Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.h b/EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.h
new file mode 100644
index 0000000..9b98c15
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/RealTimeClock/RealTimeClock.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ RealTimeClock.h
+
+Abstract:
+
+ Real Time clock Architectural Protocol as defined in Tiano
+
+ This code abstracts time and data functions. Used to provide
+ Time and date related EFI runtime services.
+
+ The GetTime (), SetTime (), GetWakeupTime (), and SetWakeupTime () EFI 1.0
+ services are added to the EFI system table and the
+ EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID protocol is registered with a NULL
+ pointer.
+
+ No CRC of the EFI system table is required, as it is done in the DXE core.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_REAL_TIME_CLOCK_H_
+#define _ARCH_PROTOCOL_REAL_TIME_CLOCK_H_
+
+//
+// Global ID for the Real Time Clock Architectural Protocol
+//
+#define EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID \
+ { 0x27CFAC87, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
+
+extern EFI_GUID gEfiRealTimeClockArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.c
new file mode 100644
index 0000000..13896f6
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.c
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Reset.c
+
+Abstract:
+
+ Reset Architectural Protocol GUID as defined in Tiano
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Reset)
+
+EFI_GUID gEfiResetArchProtocolGuid = EFI_RESET_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiResetArchProtocolGuid, "Reset", "Reset Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.h
new file mode 100644
index 0000000..d26b661
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Reset/Reset.h
@@ -0,0 +1,40 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Reset.h
+
+Abstract:
+
+ Reset Architectural Protocol as defined in the DXE CIS
+
+ Used to provide ResetSystem runtime services
+
+ The ResetSystem () EFI 1.0 service is added to the EFI system table and the
+ EFI_RESET_ARCH_PROTOCOL_GUID protocol is registered with a NULL pointer.
+
+ No CRC of the EFI system table is required, as it is done in the DXE core.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_RESET_H_
+#define _ARCH_PROTOCOL_RESET_H_
+
+//
+// Global ID for the Reset Architectural Protocol
+//
+#define EFI_RESET_ARCH_PROTOCOL_GUID \
+ { 0x27CFAC88, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
+
+extern EFI_GUID gEfiResetArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.c
new file mode 100644
index 0000000..4f58708
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.c
@@ -0,0 +1,29 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Runtime.c
+
+Abstract:
+
+ Runtime Architectural Protocol as defined in Tiano
+
+ This code is used to produce the EFI 1.0 runtime virtual switch over
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Runtime)
+
+EFI_GUID gEfiRuntimeArchProtocolGuid = EFI_RUNTIME_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiRuntimeArchProtocolGuid, "Runtime", "Runtime Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.h
new file mode 100644
index 0000000..28f0b41
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Runtime/Runtime.h
@@ -0,0 +1,114 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Runtime.h
+
+Abstract:
+
+ Runtime Architectural Protocol as defined in DXE CIS.
+
+
+ This code is used to produce the EFI runtime services that are callable
+ only in physical mode.
+
+ This driver must add SetVirtualAddressMap () and ConvertPointer () to
+ the EFI system table. This driver is not responcible for CRCing the
+ EFI system table.
+
+ This driver will add EFI_RUNTIME_ARCH_PROTOCOL_GUID protocol with a
+ pointer to the Runtime Arch Protocol instance structure. The protocol
+ member functions are used by the DXE core to export information needed
+ by this driver to produce the runtime transition of runtime drivers from
+ physical mode calling to virtual mode calling.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_RUNTIME_H_
+#define _ARCH_PROTOCOL_RUNTIME_H_
+
+#include "LinkedList.h"
+
+//
+// Global ID for the Runtime Architectural Protocol
+//
+#define EFI_RUNTIME_ARCH_PROTOCOL_GUID \
+ { 0xb7dfb4e1, 0x52f, 0x449f, 0x87, 0xbe, 0x98, 0x18, 0xfc, 0x91, 0xb7, 0x33 }
+
+EFI_FORWARD_DECLARATION (EFI_RUNTIME_ARCH_PROTOCOL);
+
+typedef struct _EFI_RUNTIME_IMAGE_ENTRY {
+ VOID *ImageBase;
+ UINT64 ImageSize;
+ VOID *RelocationData;
+ EFI_HANDLE Handle;
+ EFI_LIST_ENTRY Link;
+} EFI_RUNTIME_IMAGE_ENTRY;
+
+typedef struct _EFI_RUNTIME_EVENT_ENTRY {
+ UINT32 Type;
+ EFI_TPL NotifyTpl;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ VOID *NotifyContext;
+ EFI_EVENT *Event;
+ EFI_LIST_ENTRY Link;
+} EFI_RUNTIME_EVENT_ENTRY;
+
+//
+// Interface stucture for the Runtime Architectural Protocol
+//
+typedef struct _EFI_RUNTIME_ARCH_PROTOCOL {
+ EFI_LIST_ENTRY ImageHead;
+ EFI_LIST_ENTRY EventHead;
+ UINTN MemoryDescriptorSize;
+ UINT32 MemoryDesciptorVersion;
+ UINTN MemoryMapSize;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapPhysical;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapVirtual;
+ BOOLEAN VirtualMode;
+ BOOLEAN AtRuntime;
+} EFI_RUNTIME_ARCH_PROTOCOL;
+/*++
+
+Protocol Description:
+
+ Allows the runtime functionality of the DXE Foundation to be contained in a
+ separate driver. It also provides hooks for the DXE Foundation to export
+ information that is needed at runtime. As such, this protocol allows the DXE
+ Foundation to manage runtime drivers and events. This protocol also implies
+ that the runtime services required to transition to virtual mode,
+ SetVirtualAddressMap() and ConvertPointer(), have been registered into the
+ EFI Runtime Table in the EFI System Partition. This protocol must be produced
+ by a runtime DXE driver and may only be consumed by the DXE Foundation.
+
+Parameters:
+
+ ImageHead - A list of type EFI_RUNTIME_IMAGE_ENTRY.
+ EventHead - A list of type EFI_RUNTIME_EVENT_ENTRY.
+ MemoryDescriptorSize - Size of a memory descriptor that is return by
+ GetMemoryMap().
+ MemoryDescriptorVersion - Version of a memory descriptor that is return by
+ GetMemoryMap().
+ MemoryMapSize - Size of the memory map in bytes contained in
+ MemoryMapPhysical and MemoryMapVirtual.
+ MemoryMapPhysical - Pointer to a runtime buffer that contains a copy of the
+ memory map returned via GetMemoryMap().
+ MemoryMapVirtual - Pointer to MemoryMapPhysical that is updated to virtual mode
+ after SetVirtualAddressMap().
+ VirtualMode - Boolean that is TRUE if SetVirtualAddressMap() has been called.
+ AtRuntime - Boolean that is TRUE if ExitBootServices () has been called.
+
+--*/
+
+extern EFI_GUID gEfiRuntimeArchProtocolGuid;
+
+#endif \ No newline at end of file
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.c
new file mode 100644
index 0000000..0b84bd5
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.c
@@ -0,0 +1,28 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Security.c
+
+Abstract:
+
+ Security Architectural Protocol GUID as defined in DXE CIS
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION(Security)
+
+EFI_GUID gEfiSecurityArchProtocolGuid = EFI_SECURITY_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiSecurityArchProtocolGuid, "Security", "Security Arch Protocol");
+
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.h
new file mode 100644
index 0000000..96ced0a
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Security/Security.h
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Security.h
+
+Abstract:
+
+ Security Architectural Protocol as defined in the DXE CIS
+
+ Used to provide Security services. Specifically, dependening upon the
+ authentication state of a discovered driver in a Firmware Volume, the
+ portable DXE Core Dispatcher will call into the Security Architectural
+ Protocol (SAP) with the authentication state of the driver.
+
+ This call-out allows for OEM-specific policy decisions to be made, such
+ as event logging for attested boots, locking flash in response to discovering
+ an unsigned driver or failed signature check, or other exception response.
+
+ The SAP can also change system behavior by having the DXE core put a driver
+ in the Schedule-On-Request (SOR) state. This will allow for later disposition
+ of the driver by platform agent, such as Platform BDS.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_SECURITY_H_
+#define _ARCH_PROTOCOL_SECURITY_H_
+
+//
+// Global ID for the Security Code Architectural Protocol
+//
+#define EFI_SECURITY_ARCH_PROTOCOL_GUID \
+ { 0xA46423E3, 0x4617, 0x49f1, 0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 }
+
+EFI_FORWARD_DECLARATION (EFI_SECURITY_ARCH_PROTOCOL);
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) (
+ IN EFI_SECURITY_ARCH_PROTOCOL *This,
+ IN UINT32 AuthenticationStatus,
+ IN EFI_DEVICE_PATH_PROTOCOL *File
+ )
+/*++
+
+Routine Description:
+
+ The EFI_SECURITY_ARCH_PROTOCOL (SAP) is used to abstract platform-specific
+ policy from the DXE core response to an attempt to use a file that returns a
+ given status for the authentication check from the section extraction protocol.
+
+ The possible responses in a given SAP implementation may include locking
+ flash upon failure to authenticate, attestation logging for all signed drivers,
+ and other exception operations. The File parameter allows for possible logging
+ within the SAP of the driver.
+
+ If File is NULL, then EFI_INVALID_PARAMETER is returned.
+
+ If the file specified by File with an authentication status specified by
+ AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.
+
+ If the file specified by File with an authentication status specified by
+ AuthenticationStatus is not safe for the DXE Core to use under any circumstances,
+ then EFI_ACCESS_DENIED is returned.
+
+ If the file specified by File with an authentication status specified by
+ AuthenticationStatus is not safe for the DXE Core to use right now, but it
+ might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is
+ returned.
+
+Arguments:
+
+ This - The EFI_SECURITY_ARCH_PROTOCOL instance.
+
+ AuthenticationStatus - This is the authentication type returned from the Section
+ Extraction protocol. See the Section Extraction Protocol
+ Specification for details on this type.
+
+ File - This is a pointer to the device path of the file that is
+ being dispatched. This will optionally be used for logging.
+
+Returns:
+
+ EFI_SUCCESS - The file specified by File did authenticate, and the
+ platform policy dictates that the DXE Core may use File.
+
+ EFI_INVALID_PARAMETER - Driver is NULL.
+
+ EFI_SECURITY_VIOLATION - The file specified by File did not authenticate, and
+ the platform policy dictates that File should be placed
+ in the untrusted state. A file may be promoted from
+ the untrusted to the trusted state at a future time
+ with a call to the Trust() DXE Service.
+
+ EFI_ACCESS_DENIED - The file specified by File did not authenticate, and
+ the platform policy dictates that File should not be
+ used for any purpose.
+
+--*/
+;
+
+//
+// Interface stucture for the Timer Architectural Protocol
+//
+typedef struct _EFI_SECURITY_ARCH_PROTOCOL {
+ EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState;
+} EFI_SECURITY_ARCH_PROTOCOL;
+/*++
+
+ Protocol Description:
+
+ The EFI_SECURITY_ARCH_PROTOCOL is used to abstract platform-specific policy
+ from the DXE core. This includes locking flash upon failure to authenticate,
+ attestation logging, and other exception operations.
+
+ The driver that produces the EFI_SECURITY_ARCH_PROTOCOL may also optionally
+ install the EFI_SECURITY_POLICY_PROTOCOL_GUID onto a new handle with a NULL
+ interface. The existence of this GUID in the protocol database means that
+ the GUIDed Section Extraction Protocol should authenticate the contents of
+ an Authentication Section. The expectation is that the GUIDed Section
+ Extraction protocol will look for the existence of the EFI_SECURITY_POLICY_
+ PROTOCOL_GUID in the protocol database. If it exists, then the publication
+ thereof is taken as an injunction to attempt an authentication of any section
+ wrapped in an Authentication Section. See the Firmware File System
+ Specification for details on the GUIDed Section Extraction Protocol and
+ Authentication Sections.
+
+ Parameters:
+
+ FileAuthenticationState - This service is called upon fault with respect to
+ the authentication of a section of a file.
+
+--*/
+
+extern EFI_GUID gEfiSecurityArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.c b/EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.c
new file mode 100644
index 0000000..1c0890c
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.c
@@ -0,0 +1,29 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ StatusCode.c
+
+Abstract:
+
+ Status code Architectural Protocol as defined in Tiano
+
+ This code abstracts Status Code reporting.
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (StatusCode)
+
+EFI_GUID gEfiStatusCodeRuntimeProtocolGuid = EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiStatusCodeRuntimeProtocolGuid, "Status Code", "Status Code Arch Protocol"); \ No newline at end of file
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.h b/EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.h
new file mode 100644
index 0000000..3346d87
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/StatusCode/StatusCode.h
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ StatusCode.h
+
+Abstract:
+
+ Status code Architectural Protocol as defined in the DXE CIS
+
+ This code abstracts Status Code reporting.
+
+ The StatusCode () Tiano service is added to the EFI system table and the
+ EFI_STATUS_CODE_ARCH_PROTOCOL_GUID protocol is registered with a NULL
+ pointer.
+
+ No CRC of the EFI system table is required, as it is done in the DXE core.
+
+--*/
+
+#ifndef __STATUS_CODE_RUNTIME_PROTOCOL_H__
+#define __STATUS_CODE_RUNTIME_PROTOCOL_H__
+
+#define EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID \
+ { 0xd2b2b828, 0x826, 0x48a7, 0xb3, 0xdf, 0x98, 0x3c, 0x0, 0x60, 0x24, 0xf0}
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REPORT_STATUS_CODE) (
+ IN EFI_STATUS_CODE_TYPE Type,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN UINT32 Instance,
+ IN EFI_GUID *CallerId OPTIONAL,
+ IN EFI_STATUS_CODE_DATA *Data OPTIONAL
+ )
+/*++
+Routine Description:
+
+ Provides an interface that a software module can call to report a status code.
+
+Arguments:
+
+ Type - Indicates the type of status code being reported.
+
+ Value - Describes the current status of a hardware or software entity.
+ This included information about the class and subclass that is
+ used to classify the entity as well as an operation.
+
+ Instance - The enumeration of a hardware or software entity within
+ the system. Valid instance numbers start with 1.
+
+ CallerId - This optional parameter may be used to identify the caller.
+ This parameter allows the status code driver to apply different
+ rules to different callers.
+
+ Data - This optional parameter may be used to pass additional data.
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+
+ EFI_DEVICE_ERROR - The function should not be completed due to a device error.
+
+--*/
+;
+#endif
+
+//
+// Interface stucture for the STATUS CODE Architectural Protocol
+//
+typedef struct _EFI_STATUS_CODE_PROTOCOL {
+ EFI_REPORT_STATUS_CODE ReportStatusCode;
+} EFI_STATUS_CODE_PROTOCOL;
+
+/*++
+// Protocol Description:
+//
+// Provides the service required to report a status code to the platform firmware.
+// This protocol must be produced by a runtime DXE driver and may be consumed
+// only by the DXE Foundation.
+//
+// Parameter:
+//
+// ReportStatusCode - Emit a status code.
+--*/
+
+
+extern EFI_GUID gEfiStatusCodeRuntimeProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.c
new file mode 100644
index 0000000..b2946f8
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.c
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Timer.c
+
+Abstract:
+
+ Timer Architectural Protocol GUID as defined in Tiano
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Timer)
+
+EFI_GUID gEfiTimerArchProtocolGuid = EFI_TIMER_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiTimerArchProtocolGuid, "Timer", "Timer Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.h
new file mode 100644
index 0000000..2e5c80d
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Timer/Timer.h
@@ -0,0 +1,260 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Timer.h
+
+Abstract:
+
+ Timer Architectural Protocol as defined in the DXE CIS
+
+ This code is used to provide the timer tick for the DXE core.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_TIMER_H_
+#define _ARCH_PROTOCOL_TIMER_H_
+
+//
+// Global ID for the Timer Architectural Protocol
+//
+#define EFI_TIMER_ARCH_PROTOCOL_GUID \
+ { 0x26baccb3, 0x6f42, 0x11d4, 0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }
+
+//
+// Declare forward reference for the Timer Architectural Protocol
+//
+EFI_FORWARD_DECLARATION (EFI_TIMER_ARCH_PROTOCOL);
+
+typedef
+VOID
+(EFIAPI *EFI_TIMER_NOTIFY) (
+ IN UINT64 Time
+ );
+/*++
+
+Routine Description:
+
+ This function of this type is called when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will register a funtion
+ of tyis type to be called for the timer interrupt, so it can know how much
+ time has passed. This information is used to signal timer based events.
+
+Arguments:
+
+ Time - Time since the last timer interrupt in 100 ns units. This will
+ typically be TimerPeriod, but if a timer interrupt is missed, and the
+ EFI_TIMER_ARCH_PROTOCOL driver can detect missed interrupts, then Time
+ will contain the actual amount of time since the last interrupt.
+
+Returns:
+
+ None.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TIMER_REGISTER_HANDLER) (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+);
+/*++
+
+Routine Description:
+
+ This function registers the handler NotifyFunction so it is called every time
+ the timer interrupt fires. It also passes the amount of time since the last
+ handler call to the NotifyFunction. If NotifyFunction is NULL, then the
+ handler is unregistered. If the handler is registered, then EFI_SUCCESS is
+ returned. If the CPU does not support registering a timer interrupt handler,
+ then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
+ when a handler is already registered, then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to unregister a handler when a handler is not registered,
+ then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
+ register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
+ is returned.
+
+Arguments:
+
+ This - The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ NotifyFunction - The function to call when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will
+ register a handler for the timer interrupt, so it can know
+ how much time has passed. This information is used to
+ signal timer based events. NULL will unregister the handler.
+
+Returns:
+
+ EFI_SUCCESS - The timer handler was registered.
+
+ EFI_UNSUPPORTED - The platform does not support timer interrupts.
+
+ EFI_ALREADY_STARTED - NotifyFunction is not NULL, and a handler is already
+ registered.
+
+ EFI_INVALID_PARAMETER - NotifyFunction is NULL, and a handler was not
+ previously registered.
+
+ EFI_DEVICE_ERROR - The timer handler could not be registered.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TIMER_SET_TIMER_PERIOD) (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ );
+/*++
+
+Routine Description:
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+Arguments:
+
+ This - The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ TimerPeriod - The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+Returns:
+
+ EFI_SUCCESS - The timer period was changed.
+
+ EFI_UNSUPPORTED - The platform cannot change the period of the timer interrupt.
+
+ EFI_DEVICE_ERROR - The timer period could not be changed due to a device error.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TIMER_GET_TIMER_PERIOD) (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ );
+/*++
+
+Routine Description:
+
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+Arguments:
+
+ This - The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ TimerPeriod - A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+Returns:
+
+ EFI_SUCCESS - The timer period was returned in TimerPeriod.
+
+ EFI_INVALID_PARAMETER - TimerPeriod is NULL.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TIMER_GENERATE_SOFT_INTERRUPT) (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ );
+/*++
+
+Routine Description:
+
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+Arguments:
+
+ This - The EFI_TIMER_ARCH_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS - The soft timer interrupt was generated.
+
+ EFI_UNSUPPORTEDT - The platform does not support the generation of soft timer interrupts.
+
+--*/
+
+//
+// Interface stucture for the Timer Architectural Protocol
+//
+typedef struct _EFI_TIMER_ARCH_PROTOCOL {
+ EFI_TIMER_REGISTER_HANDLER RegisterHandler;
+ EFI_TIMER_SET_TIMER_PERIOD SetTimerPeriod;
+ EFI_TIMER_GET_TIMER_PERIOD GetTimerPeriod;
+ EFI_TIMER_GENERATE_SOFT_INTERRUPT GenerateSoftInterrupt;
+} EFI_TIMER_ARCH_PROTOCOL;
+
+/*++
+
+ Protocol Description:
+ This protocol provides the services to initialize a periodic timer
+ interrupt, and to register a handler that is called each time the timer
+ interrupt fires. It may also provide a service to adjust the rate of the
+ periodic timer interrupt. When a timer interrupt occurs, the handler is
+ passed the amount of time that has passed since the previous timer
+ interrupt.
+
+ Parameters:
+
+ RegisterHandler - Registers a handler that will be called each time the
+ timer interrupt fires. TimerPeriod defines the minimum
+ time between timer interrupts, so TimerPeriod will also
+ be the minimum time between calls to the registered
+ handler.
+
+ SetTimerPeriod - Sets the period of the timer interrupt in 100 nS units.
+ This function is optional, and may return EFI_UNSUPPORTED.
+ If this function is supported, then the timer period will
+ be rounded up to the nearest supported timer period.
+
+ GetTimerPeriod - Retrieves the period of the timer interrupt in 100 nS units.
+
+ GenerateSoftInterrupt -
+ Generates a soft timer interrupt that simulates the firing of
+ the timer interrupt. This service can be used to invoke the
+ registered handler if the timer interrupt has been masked for
+ a period of time.
+
+--*/
+
+extern EFI_GUID gEfiTimerArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.c b/EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.c
new file mode 100644
index 0000000..5ff0e9b
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.c
@@ -0,0 +1,29 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Variable.c
+
+Abstract:
+
+ Variable Architectural Protocol as defined in Tiano
+
+ This code is used to produce the EFI 1.0 runtime variable services
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Variable)
+
+EFI_GUID gEfiVariableArchProtocolGuid = EFI_VARIABLE_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiVariableArchProtocolGuid, "Variable", "Variable Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.h b/EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.h
new file mode 100644
index 0000000..8d9d4df
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/Variable/Variable.h
@@ -0,0 +1,41 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Variable.h
+
+Abstract:
+
+ Variable Architectural Protocol as defined in the DXE CIS
+
+ This code is used to produce the EFI 1.0 runtime variable services
+
+ The GetVariable (), GetNextVariableName (), and SetVariable () EFI 1.0
+ services are added to the EFI system table and the
+ EFI_VARIABLE_ARCH_PROTOCOL_GUID protocol is registered with a NULL pointer.
+
+ No CRC of the EFI system table is required, as it is done in the DXE core.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_VARIABLE_ARCH_H_
+#define _ARCH_PROTOCOL_VARIABLE_ARCH_H_
+
+//
+// Global ID for the Variable Architectural Protocol
+//
+#define EFI_VARIABLE_ARCH_PROTOCOL_GUID \
+ { 0x1e5668e2, 0x8481, 0x11d4, 0xbc, 0xf1, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }
+
+extern EFI_GUID gEfiVariableArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.c b/EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.c
new file mode 100644
index 0000000..7daf743
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.c
@@ -0,0 +1,30 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ VariableWrite.c
+
+Abstract:
+
+ Variable Write Architectural Protocol as defined in DXE CIS
+
+ This code is used to indicate the EFI 1.0 runtime variable services
+ support writting to variables.
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (VariableWrite)
+
+EFI_GUID gEfiVariableWriteArchProtocolGuid = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiVariableWriteArchProtocolGuid, "VariableWrite", "Variable Write Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.h b/EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.h
new file mode 100644
index 0000000..7629b09
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/VariableWrite/VariableWrite.h
@@ -0,0 +1,41 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ VariableWrite.h
+
+Abstract:
+
+ Variable Write Architectural Protocol as defined in the DXE CIS
+
+ This code is used to produce the EFI 1.0 runtime variable services
+
+ The GetVariable (), GetNextVariableName (), and SetVariable () EFI 1.0
+ services are added to the EFI system table and the
+ EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID protocol is registered with a NULL pointer.
+
+ No CRC of the EFI system table is required, as it is done in the DXE core.
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_VARIABLE_WRITE_ARCH_H_
+#define _ARCH_PROTOCOL_VARIABLE_WRITE_ARCH_H_
+
+//
+// Global ID for the Variable Write Architectural Protocol
+//
+#define EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID \
+ { 0x6441f818, 0x6362, 0x4e44, 0xb5, 0x70, 0x7d, 0xba, 0x31, 0xdd, 0x24, 0x53 }
+
+extern EFI_GUID gEfiVariableWriteArchProtocolGuid;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.c b/EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.c
new file mode 100644
index 0000000..d6ee113
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.c
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ WatchdogTimer.c
+
+Abstract:
+
+ Watchdog Timer Architectural Protocol GUID as defined in Tiano
+
+--*/
+
+#include "Tiano.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (WatchdogTimer)
+
+EFI_GUID gEfiWatchdogTimerArchProtocolGuid = EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiWatchdogTimerArchProtocolGuid, "Watchdog Timer", "Watchdog Timer Arch Protocol");
diff --git a/EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.h b/EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.h
new file mode 100644
index 0000000..6586594
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/ArchProtocol/WatchdogTimer/WatchdogTimer.h
@@ -0,0 +1,206 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ WatchdogTimer.h
+
+Abstract:
+
+ Watchdog Timer Architectural Protocol as defined in the DXE CIS
+
+ Used to provide system watchdog timer services
+
+--*/
+
+#ifndef _ARCH_PROTOCOL_WATCHDOG_TIMER_H_
+#define _ARCH_PROTOCOL_WATCHDOG_TIMER_H_
+
+//
+// Global ID for the Watchdog Timer Architectural Protocol
+//
+#define EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID \
+ { 0x665E3FF5, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
+
+//
+// Declare forward reference for the Timer Architectural Protocol
+//
+EFI_FORWARD_DECLARATION (EFI_WATCHDOG_TIMER_ARCH_PROTOCOL);
+
+typedef
+VOID
+(EFIAPI *EFI_WATCHDOG_TIMER_NOTIFY) (
+ IN UINT64 Time
+ );
+/*++
+
+Routine Description:
+
+ A function of this type is called when the watchdog timer fires if a
+ handler has been registered.
+
+Arguments:
+
+ Time - The time in 100 ns units that has passed since the watchdog
+ timer was armed. For the notify function to be called, this
+ must be greater than TimerPeriod.
+
+Returns:
+
+ None.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_WATCHDOG_TIMER_REGISTER_HANDLER) (
+ IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction
+ );
+/*++
+
+Routine Description:
+
+ This function registers a handler that is to be invoked when the watchdog
+ timer fires. By default, the EFI_WATCHDOG_TIMER protocol will call the
+ Runtime Service ResetSystem() when the watchdog timer fires. If a
+ NotifyFunction is registered, then the NotifyFunction will be called before
+ the Runtime Service ResetSystem() is called. If NotifyFunction is NULL, then
+ the watchdog handler is unregistered. If a watchdog handler is registered,
+ then EFI_SUCCESS is returned. If an attempt is made to register a handler
+ when a handler is already registered, then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to uninstall a handler when a handler is not installed,
+ then return EFI_INVALID_PARAMETER.
+
+Arguments:
+
+ This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.
+
+ NotifyFunction - The function to call when the watchdog timer fires. If this
+ is NULL, then the handler will be unregistered.
+
+Returns:
+
+ EFI_SUCCESS - The watchdog timer handler was registered or
+ unregistered.
+
+ EFI_ALREADY_STARTED - NotifyFunction is not NULL, and a handler is already
+ registered.
+
+ EFI_INVALID_PARAMETER - NotifyFunction is NULL, and a handler was not
+ previously registered.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD) (
+ IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ );
+/*++
+
+Routine Description:
+
+ This function sets the amount of time to wait before firing the watchdog
+ timer to TimerPeriod 100 nS units. If TimerPeriod is 0, then the watchdog
+ timer is disabled.
+
+Arguments:
+
+ This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.
+
+ TimerPeriod - The amount of time in 100 nS units to wait before the watchdog
+ timer is fired. If TimerPeriod is zero, then the watchdog
+ timer is disabled.
+
+Returns:
+
+ EFI_SUCCESS - The watchdog timer has been programmed to fire in Time
+ 100 nS units.
+
+ EFI_DEVICE_ERROR - A watchdog timer could not be programmed due to a device
+ error.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD) (
+ IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ );
+/*++
+
+Routine Description:
+
+ This function retrieves the amount of time the system will wait before firing
+ the watchdog timer. This period is returned in TimerPeriod, and EFI_SUCCESS
+ is returned. If TimerPeriod is NULL, then EFI_INVALID_PARAMETER is returned.
+
+Arguments:
+
+ This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.
+
+ TimerPeriod - A pointer to the amount of time in 100 nS units that the system
+ will wait before the watchdog timer is fired. If TimerPeriod of
+ zero is returned, then the watchdog timer is disabled.
+
+Returns:
+
+ EFI_SUCCESS - The amount of time that the system will wait before
+ firing the watchdog timer was returned in TimerPeriod.
+
+ EFI_INVALID_PARAMETER - TimerPeriod is NULL.
+
+--*/
+
+//
+// Interface stucture for the Watchdog Timer Architectural Protocol
+//
+typedef struct _EFI_WATCHDOG_TIMER_ARCH_PROTOCOL {
+ EFI_WATCHDOG_TIMER_REGISTER_HANDLER RegisterHandler;
+ EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD SetTimerPeriod;
+ EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD GetTimerPeriod;
+} EFI_WATCHDOG_TIMER_ARCH_PROTOCOL;
+
+/*++
+
+ Protocol Description:
+ This protocol provides the services required to implement the Boot Service
+ SetWatchdogTimer(). It provides a service to set the amount of time to wait
+ before firing the watchdog timer, and it also provides a service to register
+ a handler that is invoked when the watchdog timer fires. This protocol can
+ implement the watchdog timer by using the event and timer Boot Services, or
+ it can make use of custom hardware. When the watchdog timer fires, control
+ will be passed to a handler if one has been registered. If no handler has
+ been registered, or the registered handler returns, then the system will be
+ reset by calling the Runtime Service ResetSystem().
+
+ Parameters:
+
+ RegisterHandler - Registers a handler that is invoked when the watchdog
+ timer fires.
+
+ SetTimerPeriod - Sets the amount of time in 100 ns units to wait before the
+ watchdog timer is fired. If this function is supported,
+ then the watchdog timer period will be rounded up to the
+ nearest supported watchdog timer period.
+
+ GetTimerPeriod - Retrieves the amount of time in 100 ns units that the
+ system will wait before the watchdog timer is fired.
+
+--*/
+
+extern EFI_GUID gEfiWatchdogTimerArchProtocolGuid;
+
+#endif
+
diff --git a/EDK/Foundation/Core/Dxe/Dispatcher/Dispatcher.c b/EDK/Foundation/Core/Dxe/Dispatcher/Dispatcher.c
new file mode 100644
index 0000000..fa23df7
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Dispatcher/Dispatcher.c
@@ -0,0 +1,1203 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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 "Tiano.h"
+#include "DxeCore.h"
+#include "FwVolBlock.h"
+#include EFI_GUID_DEFINITION (Apriori)
+
+//
+// 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
+//
+EFI_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.
+//
+EFI_LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
+
+//
+// List of handles who's Fv's have been parsed and added to the mFwDriverList.
+//
+EFI_LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList); // list of KNOWN_HANDLE
+
+//
+// Lock for mDiscoveredList, mScheduledQueue, mDispatcherRunning.
+//
+EFI_LOCK mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
+
+
+//
+// Flag for the DXE Dispacher. TRUE if dispatcher is execuing.
+//
+BOOLEAN mDispatcherRunning = 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.
+
+--*/
+{
+ EFI_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 &&
+ EfiCompareGuid (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.
+
+--*/
+{
+ EFI_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 &&
+ EfiCompareGuid (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;
+ EFI_LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+ BOOLEAN ReadyToRun;
+ UINT8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
+ EFI_STATUS_CODE_DATA *StatusCodeData;
+ EFI_DEVICE_HANDLE_EXTENDED_DATA *DeviceHandleExtData;
+
+ DeviceHandleExtData = (EFI_DEVICE_HANDLE_EXTENDED_DATA *) Buffer;
+ StatusCodeData = (EFI_STATUS_CODE_DATA *) Buffer;
+ DeviceHandleExtData->DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
+ DeviceHandleExtData->DataHeader.Size =
+ sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) -
+ sizeof (EFI_STATUS_CODE_DATA);
+
+ EfiCommonLibCopyMem (
+ &DeviceHandleExtData->DataHeader.Type,
+ &gEfiStatusCodeSpecificDataGuid,
+ sizeof (EFI_GUID)
+ );
+
+ if (mDispatcherRunning) {
+ //
+ // If the dispatcher is running don't let it be restarted.
+ //
+ return EFI_ALREADY_STARTED;
+ }
+
+ mDispatcherRunning = 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 (
+ FALSE,
+ 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 ();
+
+ //
+ // Report Status Code here to notify drivers has
+ // been initialized (INIT_BEGIN)
+ //
+ EfiCommonLibCopyMem (
+ &DeviceHandleExtData->Handle,
+ &DriverEntry->ImageHandle,
+ sizeof (EFI_HANDLE)
+ );
+
+ 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);
+
+ mDispatcherRunning = 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
+
+--*/
+{
+ EFI_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 (EfiCompareGuid (&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 (EfiCompareGuid (&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
+
+--*/
+{
+ EFI_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);
+ if (KnownHandle == NULL) {
+ //
+ // Failed to allocate memory, no recovery path implemented as this is not expected to occur
+ //
+ EFI_DEADLOOP ();
+ }
+
+ 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, &FvDevicePath);
+ if (EFI_ERROR (Status)) {
+ FileNameDevicePath = NULL;
+ } else {
+ //
+ // Build a device path to the file in the FV to pass into gBS->LoadImage
+ //
+ CoreInitializeFwVolDevicepathNode (&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);
+ if (DriverEntry == NULL) {
+ //
+ // Failed to allocate memory, no recovery path implemented as this is not expected to occur
+ //
+ EFI_DEADLOOP ();
+ }
+
+ DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE;
+ EfiCommonLibCopyMem (&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
+ //
+ gBS->FreePool (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;
+ EFI_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, &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, &Fv);
+ if (EFI_ERROR (Status) || (Fv == NULL)) {
+ //
+ // 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, &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 (EfiCompareGuid (&NameGuid, gDxeCoreFileName)) {
+ CoreInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);
+ mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
+ mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
+
+ 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,
+ &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 (EfiCompareGuid (&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 ()
+ //
+ gBS->FreePool (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
+//
+DEBUG_CODE (
+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
+
+--*/
+{
+ EFI_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/EDK/Foundation/Core/Dxe/Dispatcher/dependency.c b/EDK/Foundation/Core/Dxe/Dispatcher/dependency.c
new file mode 100644
index 0000000..b08c5bf
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Dispatcher/dependency.c
@@ -0,0 +1,451 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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 "Tiano.h"
+#include "DxeCore.h"
+#include "EfiDependency.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
+ //
+ EfiCommonLibCopyMem (
+ 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) {
+ EfiCommonLibCopyMem (&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.
+ //
+ EfiCommonLibCopyMem (&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/EDK/Foundation/Core/Dxe/DxeMain.cif b/EDK/Foundation/Core/Dxe/DxeMain.cif
new file mode 100644
index 0000000..cd1fa6c
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/DxeMain.cif
@@ -0,0 +1,53 @@
+<component>
+ name = "DxeMain"
+ category = ModulePart
+ LocalRoot = "EDK\Foundation\Core\Dxe\"
+ RefName = "DxeMain"
+[files]
+"DxeMain.inf"
+"Dispatcher\dependency.c"
+"Dispatcher\Dispatcher.c"
+"DxeMain\DxeMain.c"
+"DxeMain\DxeProtocolNotify.c"
+"Event\event.c"
+"Event\exec.h"
+"Event\execdata.c"
+"Event\timer.c"
+"Event\tpl.c"
+"FwVol\Ffs.c"
+"FwVol\FwVol.c"
+"FwVol\FwVolAttrib.c"
+"FwVol\FwVolDriver.h"
+"FwVol\FwVolRead.c"
+"FwVol\FwVolWrite.c"
+"FwVolBlock\FwVolBlock.c"
+"FwVolBlock\FwVolBlock.h"
+"Gcd\gcd.c"
+"Gcd\gcd.h"
+"Hand\DriverSupport.c"
+"Hand\hand.h"
+"Hand\handle.c"
+"Hand\locate.c"
+"Hand\Notify.c"
+"Ia32\Processor.h"
+"Image\Image.c"
+"Image\Image.h"
+"Image\ImageFile.c"
+"Include\DxeCore.h"
+"Include\Library.h"
+"Ipf\Processor.h"
+"Library\Library.c"
+"Mem\imem.h"
+"Mem\memdata.c"
+"Mem\Page.c"
+"Mem\pool.c"
+"Misc\DebugImageInfo.c"
+"Misc\DebugImageInfo.h"
+"Misc\DebugMask.c"
+"Misc\DebugMask.h"
+"Misc\InstallConfigurationTable.c"
+"Misc\SetWatchdogTimer.c"
+"Misc\Stall.c"
+"SectionExtraction\CoreSectionExtraction.c"
+"x64\Processor.h"
+<endComponent>
diff --git a/EDK/Foundation/Core/Dxe/DxeMain.inf b/EDK/Foundation/Core/Dxe/DxeMain.inf
new file mode 100644
index 0000000..5f6a047
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/DxeMain.inf
@@ -0,0 +1,111 @@
+#/*++
+#
+# Copyright (c) 2004 - 2005, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# DxeMain.inf
+#
+# Abstract:
+#
+# Component description file for DxeMain.
+#
+--*/
+
+[defines]
+BASE_NAME = DxeMain
+FILE_GUID = 35B898CA-B6A9-49CE-8C72-904735CC49B7
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ DxeMain\DxeMain.c
+ DxeMain\DxeProtocolNotify.c
+ Dispatcher\Dispatcher.c
+ Dispatcher\Dependency.c
+ Event\ExecData.c
+ Event\Event.c
+ Event\Exec.h
+ Event\Timer.c
+ Event\Tpl.c
+ FwVol\FwVolDriver.h
+ FwVol\FwVol.c
+ FwVol\Ffs.c
+ FwVol\FwVolAttrib.c
+ FwVol\FwVolRead.c
+ FwVol\FwVolWrite.c
+ FwVolBlock\FwVolBlock.c
+ FwVolBlock\FwVolBlock.h
+ Mem\Imem.h
+ Mem\MemData.c
+ Mem\Page.c
+ Mem\Pool.c
+ Gcd\Gcd.h
+ Gcd\Gcd.c
+ Hand\Hand.h
+ Hand\Handle.c
+ Hand\Locate.c
+ Hand\Notify.c
+ Hand\DriverSupport.c
+ Library\Library.c
+ Misc\InstallConfigurationTable.c
+ Misc\SetWatchdogTimer.c
+ Misc\Stall.c
+ Misc\DebugImageInfo.h
+ Misc\DebugImageInfo.c
+ Misc\DebugMask.h
+ Misc\DebugMask.c
+ Image\Image.h
+ Image\Image.c
+ Image\ImageFile.c
+ SectionExtraction\CoreSectionExtraction.c
+
+[sources.Ia32]
+ Ia32\Processor.h
+
+[sources.Ipf]
+ Ipf\Processor.h
+
+[sources.x64]
+ x64\Processor.h
+
+[includes.common]
+ $(EDK_SOURCE)\Foundation\Framework
+ $(EDK_SOURCE)\Foundation\Efi
+ $(EDK_SOURCE)\Foundation
+ .
+ $(EDK_SOURCE)\Foundation\Include
+ $(EDK_SOURCE)\Foundation\Efi\Include
+ $(EDK_SOURCE)\Foundation\Framework\Include
+ $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+ $(EDK_SOURCE)\Foundation\Core\Dxe
+ $(EDK_SOURCE)\Foundation\Core\Dxe\Hand
+ $(EDK_SOURCE)\Foundation\Core\Dxe\Include
+ $(EDK_SOURCE)\Foundation\Core\Dxe\Misc
+ $(EDK_SOURCE)\Foundation\Core\Dxe\FwVolBlock
+ $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+ $(EDK_SOURCE)\Foundation\Include\Pei
+ $(EDK_SOURCE)\Foundation\Library\Pei\Include
+
+[libraries.common]
+ EdkGuidLib
+ EdkFrameworkGuidLib
+ EfiGuidLib
+ EdkProtocolLib
+ EdkFrameworkProtocolLib
+ EfiProtocolLib
+ EfiCommonLib
+ HobLib
+ ArchProtocolLib
+ EfiDriverLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT=DxeMain
+ C_PROJ_FLAGS = $(C_PROJ_FLAGS) /Ob0
+
diff --git a/EDK/Foundation/Core/Dxe/DxeMain/DxeMain.c b/EDK/Foundation/Core/Dxe/DxeMain/DxeMain.c
new file mode 100644
index 0000000..4dc53be
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/DxeMain/DxeMain.c
@@ -0,0 +1,1010 @@
+/*++
+
+Copyright (c) 2004 - 2011, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DxeMain.c
+
+Abstract:
+
+ DXE Core Main Entry Point
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiHobLib.h"
+#include "EfiPerf.h"
+#include "FwVolBlock.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
+ );
+
+PERF_CODE (
+ EFI_STATUS
+ GetTimerValue (
+ OUT UINT64 *TimerValue
+ );
+)
+
+//
+// DXE Core Global Variables for Protocols from PEI
+//
+EFI_DECOMPRESS_PROTOCOL *gEfiDecompress = NULL;
+EFI_TIANO_DECOMPRESS_PROTOCOL *gEfiTianoDecompress = NULL;
+EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *gEfiCustomizedDecompress = NULL;
+EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *gEfiPeiFlushInstructionCache = NULL;
+EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader = NULL;
+EFI_PEI_TRANSFER_CONTROL_PROTOCOL *gEfiPeiTransferControl = 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;
+
+//
+// DXE Core Global used to update core loaded image protocol handle
+//
+EFI_GUID *gDxeCoreFileName;
+EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage;
+
+//
+// BugBug: I'n not runtime, but is the PPI?
+//
+EFI_STATUS_CODE_PROTOCOL gStatusCodeInstance = {
+ NULL
+};
+
+EFI_STATUS_CODE_PROTOCOL *gStatusCode = &gStatusCodeInstance;
+
+//
+// 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) EfiCommonLibCopyMem, // CopyMem
+ (EFI_SET_MEM) EfiCommonLibSetMem // SetMem
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ ,
+ //
+ // UEFI 2.0 Extension to the table
+ //
+ (EFI_CREATE_EVENT_EX) CoreCreateEventEx
+#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 (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ (EFI_UPDATE_CAPSULE) CoreEfiNotAvailableYetArg3, // UpdateCapsule
+ (EFI_QUERY_CAPSULE_CAPABILITIES) CoreEfiNotAvailableYetArg4, // QueryCapsuleCapabilities
+ (EFI_QUERY_VARIABLE_INFO) CoreEfiNotAvailableYetArg4 // QueryVariableInfo
+#elif (TIANO_RELEASE_VERSION != 0)
+ (EFI_REPORT_STATUS_CODE) CoreEfiNotAvailableYetArg5 // ReportStatusCode
+#endif
+};
+
+EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate = {
+ INITIALIZE_LIST_HEAD_VARIABLE (gRuntimeTemplate.ImageHead),
+ INITIALIZE_LIST_HEAD_VARIABLE (gRuntimeTemplate.EventHead),
+
+ //
+ // 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.
+ //
+ sizeof (EFI_MEMORY_DESCRIPTOR) + sizeof (UINT64) - (sizeof (EFI_MEMORY_DESCRIPTOR) % sizeof (UINT64)),
+ EFI_MEMORY_DESCRIPTOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ FALSE,
+ FALSE
+};
+
+EFI_RUNTIME_ARCH_PROTOCOL *gRuntime = &gRuntimeTemplate;
+
+//
+// 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;
+
+VOID *mHobStart;
+
+//
+// Main entry point to the DXE Core
+//
+EFI_DXE_ENTRY_POINT (DxeMain)
+
+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_HANDLE DecompressHandle;
+ EFI_PHYSICAL_ADDRESS MemoryBaseAddress;
+ UINT64 MemoryLength;
+
+#ifdef FIRMWARE_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);
+ if (gST == NULL) {
+ //
+ // Failed to allocate memory for EFI System Table. No recovery path implemented as this is not expected to occur.
+ //
+ EFI_DEADLOOP ();
+ }
+
+ gRT = CoreAllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
+ ASSERT (gRT != NULL);
+
+ gST->RuntimeServices = gRT;
+
+ //
+ // Start the Image Services.
+ //
+ Status = CoreInitializeImageServices (HobStart);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the Global Coherency Domain Services
+ //
+ Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // The HobStart is relocated in gcd service init. Sync mHobStart variable.
+ //
+ mHobStart = HobStart;
+
+ //
+ // 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 ((TIANO_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000))
+ if (gStatusCode->ReportStatusCode != NULL) {
+ 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_CODE (
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "HOBLIST address in DXE = 0x%x\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.
+ //
+
+ Status = CoreGetPeiProtocol (&gEfiDecompressProtocolGuid, &gEfiDecompress);
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Publish the EFI Decompress protocol for use by other DXE components
+ //
+
+ DecompressHandle = NULL;
+ Status = CoreInstallProtocolInterface (
+ &DecompressHandle,
+ &gEfiDecompressProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gEfiDecompress
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = CoreGetPeiProtocol (&gEfiTianoDecompressProtocolGuid, &gEfiTianoDecompress);
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Publish the Tiano Decompress protocol for use by other DXE components
+ //
+
+ DecompressHandle = NULL;
+ Status = CoreInstallProtocolInterface (
+ &DecompressHandle,
+ &gEfiTianoDecompressProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gEfiTianoDecompress
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = CoreGetPeiProtocol (&gEfiCustomizedDecompressProtocolGuid, &gEfiCustomizedDecompress);
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Publish the Tiano Decompress protocol for use by other DXE components
+ //
+ DecompressHandle = NULL;
+ Status = CoreInstallProtocolInterface (
+ &DecompressHandle,
+ &gEfiCustomizedDecompressProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gEfiCustomizedDecompress
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ CoreGetPeiProtocol (&gEfiPeiFlushInstructionCacheGuid, &gEfiPeiFlushInstructionCache);
+
+ CoreGetPeiProtocol (&gEfiPeiPeCoffLoaderGuid, &gEfiPeiPeCoffLoader);
+
+ CoreGetPeiProtocol (&gEfiPeiTransferControlGuid, &gEfiPeiTransferControl);
+
+
+ //
+ // 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 Performance monitoring if enabled in build
+ //
+ PERF_ENABLE (0, gST, Tick);
+
+ PERF_START (0,DXE_TOK, NULL, Tick) ;
+
+ //
+ // Initialize the DXE Dispatcher
+ //
+ PERF_START (0,L"CoreInitializeDispatcher", L"DxeMain", 0) ;
+ CoreInitializeDispatcher ();
+ PERF_END (0,L"CoreInitializeDispatcher", L"DxeMain", 0) ;
+
+ //
+ // Invoke the DXE Dispatcher
+ //
+ PERF_START (0, L"CoreDispatcher", L"DxeMain", 0);
+ CoreDispatcher ();
+ PERF_END (0, L"CoreDispatcher", L"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);
+ EFI_DEADLOOP ();
+}
+
+
+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 EFI_BREAKPOINT() 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 EFI_BREAKPOINT() 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 EFI_BREAKPOINT() 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 EFI_BREAKPOINT() 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 EFI_BREAKPOINT() 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 EFI_BREAKPOINT() 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_STATUS Status;
+ VOID *HobList;
+ VOID *Buffer;
+
+ //
+ // Initialize 'Buffer' to NULL before usage.
+ //
+ Buffer = NULL;
+
+ HobList = mHobStart;
+ Status = GetNextGuidHob (&HobList, ProtocolGuid, &Buffer, NULL);
+ if (EFI_ERROR (Status) || (Buffer == NULL)) {
+ //
+ // Failed to find a HOB containing the desired protocol
+ //
+ return Status;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ *Interface = (VOID *)(*(UINTN *)(Buffer));
+
+ return Status;
+}
+
+
+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_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreExitBootServices (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ Terminates all boot services.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the exiting image.
+ MapKey - Key to the latest memory map.
+
+Returns:
+
+ EFI_SUCCESS - Boot services have been terminated.
+ EFI_INVALID_PARAMETER - MapKey is incorrect.
+
+--*/
+{
+ EFI_STATUS Status, Status2;
+ EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;
+
+ //
+ // Measure invocation of ExitBootServices,
+ // which is defined by TCG_EFI_Platform_1_20_Final Specification
+ //
+ TcgPlatformProtocol = NULL;
+ Status = CoreLocateProtocol (
+ &gEfiTcgPlatformProtocolGuid,
+ NULL,
+ &TcgPlatformProtocol
+ );
+ if (!EFI_ERROR (Status) && (TcgPlatformProtocol != NULL)) {
+ Status = TcgPlatformProtocol->MeasureAction (EFI_EXIT_BOOT_SERVICES_INVOCATION);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Terminate memory services if the MapKey matches
+ //
+ Status = CoreTerminateMemoryMap (MapKey);
+ if (EFI_ERROR (Status)) {
+ //
+ // Measure failure of ExitBootServices
+ //
+ if (TcgPlatformProtocol != NULL) {
+ Status2 = TcgPlatformProtocol->MeasureAction (EFI_EXIT_BOOT_SERVICES_FAILED);
+ ASSERT_EFI_ERROR (Status2);
+ }
+
+ return Status;
+ }
+
+ //
+ // Disable Timer
+ //
+ gTimer->SetTimerPeriod (gTimer, 0);
+
+
+ //
+ // Notify other drivers that we are exiting boot services.
+ //
+ CoreNotifySignalList (&gEfiEventExitBootServicesGuid);
+
+
+
+ //
+ // Disable CPU Interrupts
+ //
+ gCpu->DisableInterrupt (gCpu);
+
+ //
+ // 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);
+
+ //
+ // Update the AtRuntime field in Runtiem AP.
+ //
+ gRuntime->AtRuntime = TRUE;
+
+ //
+ // Measure success of ExitBootServices
+ //
+ if (TcgPlatformProtocol != NULL) {
+ Status2 = TcgPlatformProtocol->MeasureAction (EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
+ ASSERT_EFI_ERROR (Status2);
+ }
+
+ //
+ // Zero out the Boot Service Table
+ //
+ EfiCommonLibSetMem (gBS, sizeof (EFI_BOOT_SERVICES), 0);
+ gBS = NULL;
+
+ return Status;
+}
diff --git a/EDK/Foundation/Core/Dxe/DxeMain/DxeProtocolNotify.c b/EDK/Foundation/Core/Dxe/DxeMain/DxeProtocolNotify.c
new file mode 100644
index 0000000..15886f9
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/DxeMain/DxeProtocolNotify.c
@@ -0,0 +1,319 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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 "Tiano.h"
+#include "DxeCore.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, &gSecurity, NULL, NULL, FALSE},
+ { &gEfiCpuArchProtocolGuid, &gCpu, NULL, NULL, FALSE},
+ { &gEfiMetronomeArchProtocolGuid, &gMetronome, NULL, NULL, FALSE},
+ { &gEfiTimerArchProtocolGuid, &gTimer, NULL, NULL, FALSE},
+ { &gEfiBdsArchProtocolGuid, &gBds, NULL, NULL, FALSE},
+ { &gEfiWatchdogTimerArchProtocolGuid, &gWatchdogTimer, NULL, NULL, FALSE},
+ { &gEfiRuntimeArchProtocolGuid, &gRuntime, NULL, NULL, FALSE},
+ { &gEfiVariableArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiVariableWriteArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ { &gEfiCapsuleArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ #endif
+ { &gEfiMonotonicCounterArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiResetArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiStatusCodeRuntimeProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiRealTimeClockArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ NULL
+};
+
+
+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;
+ EFI_LIST_ENTRY *Link;
+ EFI_LIST_ENTRY TempLinkNode;
+
+ 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 (EfiCompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
+ //
+ // Register the Core timer tick handler with the Timer AP
+ //
+ gTimer->RegisterHandler (gTimer, CoreTimerTick);
+ }
+
+ if (EfiCompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
+ //
+ // When runtime architectural protocol is available, updates CRC32 in the Debug Table
+ //
+ CoreUpdateDebugTableCrc32 ();
+
+ //
+ // Update the Runtime Architectural protocol with the template that the core was
+ // using so there would not need to be a dependency on the Runtime AP
+ //
+
+ //
+ // Copy all the registered Image to new gRuntime protocol
+ //
+ for (Link = gRuntimeTemplate.ImageHead.ForwardLink; Link != &gRuntimeTemplate.ImageHead; Link = TempLinkNode.ForwardLink) {
+ EfiCommonLibCopyMem (&TempLinkNode, Link, sizeof(EFI_LIST_ENTRY));
+ InsertTailList (&gRuntime->ImageHead, Link);
+ }
+ //
+ // Copy all the registered Event to new gRuntime protocol
+ //
+ for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
+ EfiCommonLibCopyMem (&TempLinkNode, Link, sizeof(EFI_LIST_ENTRY));
+ InsertTailList (&gRuntime->EventHead, Link);
+ }
+
+ //
+ // Clean up gRuntimeTemplate
+ //
+ gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
+ gRuntimeTemplate.ImageHead.BackLink = &gRuntimeTemplate.ImageHead;
+ gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
+ gRuntimeTemplate.EventHead.BackLink = &gRuntimeTemplate.EventHead;
+ }
+
+ if (EfiCompareGuid (Entry->ProtocolGuid, &gEfiStatusCodeRuntimeProtocolGuid)) {
+ //
+ // Update StatusCode instance used by DXE core
+ //
+ gStatusCode = (EFI_STATUS_CODE_PROTOCOL *) Protocol;
+ }
+ }
+
+ //
+ // 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);
+
+ }
+}
+
+#ifdef EFI_DEBUG
+//
+// Following is needed to display missing architectural protocols in debug builds
+//
+typedef struct {
+ EFI_GUID *ProtocolGuid;
+ CHAR16 *GuidString;
+} GUID_TO_STRING_PROTOCOL_ENTRY;
+
+GUID_TO_STRING_PROTOCOL_ENTRY MissingProtocols[] = {
+ { &gEfiSecurityArchProtocolGuid, L"Security" },
+ { &gEfiCpuArchProtocolGuid, L"CPU" },
+ { &gEfiMetronomeArchProtocolGuid, L"Metronome" },
+ { &gEfiTimerArchProtocolGuid, L"Timer" },
+ { &gEfiBdsArchProtocolGuid, L"Bds" },
+ { &gEfiWatchdogTimerArchProtocolGuid, L"Watchdog Timer" },
+ { &gEfiRuntimeArchProtocolGuid, L"Runtime" },
+ { &gEfiVariableArchProtocolGuid, L"Variable" },
+ { &gEfiVariableWriteArchProtocolGuid, L"Variable Write" },
+ #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ { &gEfiCapsuleArchProtocolGuid, L"Capsule" },
+ #endif
+ { &gEfiMonotonicCounterArchProtocolGuid, L"Monotonic Counter" },
+ { &gEfiResetArchProtocolGuid, L"Reset" },
+ { &gEfiStatusCodeRuntimeProtocolGuid, L"Status Code" },
+ { &gEfiRealTimeClockArchProtocolGuid, L"Real Time Clock" }
+};
+#endif
+
+DEBUG_CODE (
+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
+
+--*/
+{
+
+
+ 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 (EfiCompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
+ DEBUG ((EFI_D_ERROR, "\n%s Arch Protocol not present!!\n", MissingEntry->GuidString));
+ break;
+ }
+ }
+ }
+
+ }
+}
+)
diff --git a/EDK/Foundation/Core/Dxe/Event/event.c b/EDK/Foundation/Core/Dxe/Event/event.c
new file mode 100644
index 0000000..ee2eefa
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Event/event.c
@@ -0,0 +1,845 @@
+/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ event.c
+
+Abstract:
+
+ EFI Event support.
+
+--*/
+
+#include "exec.h"
+#include "hand.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;
+}
+
+
+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;
+ EFI_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
+ //
+ 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 on the requested list
+
+Arguments:
+
+ SignalType - The list to signal
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_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 ((Event->ExFlag) && EfiCompareGuid (&Event->EventGroup, EventGroup)) {
+ CoreNotifyEvent (Event);
+ }
+ }
+
+ CoreReleaseEventLock ();
+}
+
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+
+static
+VOID
+EFIAPI
+EventNotifySignalAllNullEvent (
+ 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_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCreateEvent (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ 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 = EventNotifySignalAllNullEvent;
+ }
+
+ //
+ // Map the Tiano extensions Events to CreateEventEx form
+ //
+ if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) {
+ GuidPtr = &gEfiEventReadyToBootGuid;
+ } 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 == EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES) {
+ Type = 0;
+ GuidPtr = &gEfiEventExitBootServicesGuid;
+ } else if (Type == EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
+ Type = 0;
+ GuidPtr = &gEfiEventVirtualAddressChangeGuid;
+ }
+
+ return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event);
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCreateEventEx (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ 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
+ EventGroup - 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;
+ }
+
+ //
+ // For event group, type EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES and EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+ // are not valid
+ //
+ if (EventGroup != NULL) {
+ if ((Type == EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {
+ 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;
+ }
+
+ //
+ // Convert Event type for pre-defined Event groups
+ //
+ if (EventGroup != NULL) {
+ if (EfiCompareGuid ((VOID *) EventGroup, &gEfiEventExitBootServicesGuid)) {
+ Type = EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES;
+ } else if (EfiCompareGuid ((VOID *) EventGroup, &gEfiEventVirtualAddressChangeGuid)) {
+ Type = EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;
+ }
+ }
+
+ //
+ // 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) || (IEvent == NULL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EfiCommonLibSetMem (IEvent, sizeof (IEVENT), 0);
+
+ IEvent->Signature = EVENT_SIGNATURE;
+ IEvent->Type = Type;
+ IEvent->NotifyTpl = NotifyTpl;
+ IEvent->NotifyFunction = NotifyFunction;
+ IEvent->NotifyContext = (VOID *)NotifyContext;
+ if (EventGroup != NULL) {
+ EfiCommonLibCopyMem (&IEvent->EventGroup, (VOID*)EventGroup, sizeof (EFI_GUID));
+ IEvent->ExFlag = TRUE;
+ }
+
+ *Event = IEvent;
+
+ if (Type & EFI_EVENT_RUNTIME) {
+ //
+ // Keep a list of all RT events so we can tell the RT AP.
+ //
+ IEvent->RuntimeData.Type = Type;
+ IEvent->RuntimeData.NotifyTpl = NotifyTpl;
+ IEvent->RuntimeData.NotifyFunction = NotifyFunction;
+ IEvent->RuntimeData.NotifyContext = NotifyContext;
+ IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;
+ InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);
+ }
+
+ 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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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->RuntimeData.Link.ForwardLink != NULL) {
+ RemoveEntryList (&Event->RuntimeData.Link);
+ }
+
+ 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/EDK/Foundation/Core/Dxe/Event/exec.h b/EDK/Foundation/Core/Dxe/Event/exec.h
new file mode 100644
index 0000000..2abdc90
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Event/exec.h
@@ -0,0 +1,209 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ exec.h
+
+Abstract:
+
+ EFI Event support
+
+--*/
+
+#ifndef _EXEC_H_
+#define _EXEC_H_
+
+#include "Tiano.h"
+#include "DxeCore.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
+ //
+
+ EFI_LIST_ENTRY SignalLink;
+
+ //
+ // Notification information for this event
+ //
+
+ EFI_TPL NotifyTpl;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ VOID *NotifyContext;
+ EFI_GUID EventGroup;
+ EFI_LIST_ENTRY NotifyLink;
+ BOOLEAN ExFlag;
+
+ //
+ // A list of all runtime events
+ //
+ EFI_RUNTIME_EVENT_ENTRY RuntimeData;
+
+ //
+ // Information by event type
+ //
+
+ union {
+ //
+ // For timer events
+ //
+ struct {
+ EFI_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 EFI_LIST_ENTRY gEventQueue[];
+extern EFI_LIST_ENTRY gEventSignalQueue;
+extern UINT8 gHSB[];
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/Event/execdata.c b/EDK/Foundation/Core/Dxe/Event/execdata.c
new file mode 100644
index 0000000..284b89b
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Event/execdata.c
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ execdata.c
+
+Abstract:
+
+
+
+
+Revision History
+
+--*/
+
+#include "exec.h"
+
+
+//
+// gTpl - Task priority level
+//
+EFI_TPL gEfiCurrentTpl = EFI_TPL_DRIVER;
+
+
+//
+// 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
+//
+EFI_LIST_ENTRY gEventQueue[EFI_TPL_HIGH_LEVEL + 1];
+UINTN gEventPending = 0;
+
+//
+// gEventSignalQueue - A list of events to signal when the EFI operation occurs
+//
+EFI_LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue);
+
diff --git a/EDK/Foundation/Core/Dxe/Event/timer.c b/EDK/Foundation/Core/Dxe/Event/timer.c
new file mode 100644
index 0000000..28ce124
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Event/timer.c
@@ -0,0 +1,386 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ timer.c
+
+Abstract:
+
+ EFI Event support
+
+Revision History
+
+--*/
+
+
+#include "exec.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 EFI_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;
+ EFI_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_BOOTSERVICE
+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 >= TimerTypeMax || !(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/EDK/Foundation/Core/Dxe/Event/tpl.c b/EDK/Foundation/Core/Dxe/Event/tpl.c
new file mode 100644
index 0000000..3ac99fc
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Event/tpl.c
@@ -0,0 +1,198 @@
+/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ tpl.c
+
+Abstract:
+
+ Task priority function
+
+--*/
+
+#include "exec.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_BOOTSERVICE
+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;
+}
+
+
+EFI_BOOTSERVICE
+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/EDK/Foundation/Core/Dxe/FwVol/Ffs.c b/EDK/Foundation/Core/Dxe/FwVol/Ffs.c
new file mode 100644
index 0000000..3361ce2
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVol/Ffs.c
@@ -0,0 +1,266 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Ffs.c
+
+Abstract:
+
+ FFS file access utilities.
+
+--*/
+
+
+#include "FwVolDriver.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/EDK/Foundation/Core/Dxe/FwVol/FwVol.c b/EDK/Foundation/Core/Dxe/FwVol/FwVol.c
new file mode 100644
index 0000000..eb0117c
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVol/FwVol.c
@@ -0,0 +1,556 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FwVol.c
+
+Abstract:
+
+ 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 "FwVolDriver.h"
+#include "DxeCore.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
+ //
+ EfiCommonLibCopyMem (*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;
+ EFI_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, &Fvb);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status) || (Fvb == NULL)) {
+ return;
+ }
+
+ //
+ // Make sure the Fv Header is O.K.
+ //
+ Status = GetFwVolHeader (Fvb, &FwVolHeader);
+ if (EFI_ERROR (Status) || (FwVolHeader == NULL)) {
+ 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 (!EfiCompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystemGuid)) {
+ continue;
+ }
+
+ //
+ // Check if there is an FV protocol already installed in that handle
+ //
+ Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeProtocolGuid, &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/EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c b/EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c
new file mode 100644
index 0000000..690d919
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c
@@ -0,0 +1,99 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FwVolAttrib.c
+
+Abstract:
+
+ Implements get/set firmware volume attributes
+
+--*/
+
+#include "FwVolDriver.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/EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h b/EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h
new file mode 100644
index 0000000..4bd336d
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h
@@ -0,0 +1,487 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiFirmwareFileSystem.h"
+#include "EfiFirmwareVolumeHeader.h"
+
+//
+// Consumed protocol
+//
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeBlock)
+#include EFI_PROTOCOL_DEFINITION (SectionExtraction)
+
+//
+// Consumed GUID
+//
+#include EFI_GUID_DEFINITION (FirmwareFileSystem)
+
+//
+// Produced protocol
+//
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolume)
+
+
+//
+// Used to track all non-deleted files
+//
+typedef struct {
+ EFI_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;
+
+ EFI_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 \ No newline at end of file
diff --git a/EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c b/EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c
new file mode 100644
index 0000000..acaffa8
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c
@@ -0,0 +1,520 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FwVolRead.c
+
+Abstract:
+
+ Implements read firmware file
+
+--*/
+
+#include "FwVolDriver.h"
+#include "DxeCore.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;
+ EFI_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 = (EFI_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;
+ EfiCommonLibCopyMem (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 (!EfiCompareGuid (&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
+ //
+ EfiCommonLibCopyMem (*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,
+ &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, &Sep);
+ //
+ // Section Extraction Protocol is part of Dxe Core so this should never fail
+ //
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status) || (Sep == NULL)) {
+ goto Done;
+ }
+
+ 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/EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c b/EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c
new file mode 100644
index 0000000..1db7305
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c
@@ -0,0 +1,60 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FwVolWrite.c
+
+Abstract:
+
+ Implements write firmware file
+
+--*/
+
+#include "FwVolDriver.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/EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.c b/EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.c
new file mode 100644
index 0000000..ebe3964
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.c
@@ -0,0 +1,621 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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 "Tiano.h"
+#include "FwVolBlock.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
+ //
+ EfiCommonLibCopyMem (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_STATUS Status;
+ VOID *HobList;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ EFI_STATUS HobStatus;
+
+ //
+ // First walk hobs and create appropriate FVs.
+ //
+ Status = CoreGetConfigTable (&gEfiHobListGuid, &HobList);
+ //
+ // Core Needs Firmware Volumes to function
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ BaseAddress = 0;
+ Length = 0;
+ HobStatus = GetNextFirmwareVolumeHob (
+ &HobList,
+ &BaseAddress,
+ &Length
+ );
+ while (!EFI_ERROR (HobStatus)) {
+ //
+ // Produce an FVB protocol for it
+ //
+ ProduceFVBProtocolOnBuffer (BaseAddress, Length, NULL, NULL);
+ HobStatus = GetNextFirmwareVolumeHob (
+ &HobList,
+ &BaseAddress,
+ &Length
+ );
+ }
+
+ 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, &Ptr);
+ if (EFI_ERROR(Status) || (Ptr == NULL)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+ return EFI_SUCCESS;
+ }
+ return Status;
+}
+
+
diff --git a/EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.h b/EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.h
new file mode 100644
index 0000000..cbf9ffc
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/FwVolBlock/FwVolBlock.h
@@ -0,0 +1,334 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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_
+
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeBlock)
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+#include "Peihob.h"
+#include "EfiHobLib.h"
+#include "DxeCore.h"
+
+#include EFI_GUID_DEFINITION (Hob)
+
+
+
+#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/EDK/Foundation/Core/Dxe/Gcd/gcd.c b/EDK/Foundation/Core/Dxe/Gcd/gcd.c
new file mode 100644
index 0000000..586826b
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Gcd/gcd.c
@@ -0,0 +1,2509 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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 "gcd.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);
+EFI_LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap);
+EFI_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 EFI_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) {
+ EfiCommonLibCopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
+ Entry->BaseAddress = BaseAddress;
+ BottomEntry->EndAddress = BaseAddress - 1;
+ InsertTailList (Link, &BottomEntry->Link);
+ }
+
+ if ((BaseAddress + Length - 1) < Entry->EndAddress) {
+ EfiCommonLibCopyMem (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 EFI_LIST_ENTRY *Link,
+ IN BOOLEAN Forward,
+ IN EFI_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.
+
+--*/
+{
+ EFI_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 EFI_LIST_ENTRY *StartLink,
+ IN EFI_LIST_ENTRY *EndLink,
+ IN EFI_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.
+
+--*/
+{
+ EFI_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 EFI_LIST_ENTRY **StartLink,
+ OUT EFI_LIST_ENTRY **EndLink,
+ IN EFI_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.
+
+--*/
+{
+ EFI_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 EFI_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;
+ EFI_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;
+ EFI_LIST_ENTRY *Map;
+ EFI_LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *TopEntry;
+ EFI_GCD_MAP_ENTRY *BottomEntry;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_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;
+ }
+
+ if (Map == NULL) {
+ //
+ // Fail if 'Map' doesn't point to a valid address
+ //
+ Status = EFI_UNSUPPORTED;
+
+ 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) || (StartLink == NULL) || (EndLink == NULL)) {
+ 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) || (TopEntry == NULL) || (BottomEntry == NULL)) {
+ 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 = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, &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;
+ EFI_LIST_ENTRY *Map;
+ EFI_LIST_ENTRY *Link;
+ EFI_LIST_ENTRY *SubLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *TopEntry;
+ EFI_GCD_MAP_ENTRY *BottomEntry;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_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) != 0) {
+ CoreAcquireGcdMemoryLock ();
+ Map = &mGcdMemorySpaceMap;
+ }
+ if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
+ CoreAcquireGcdIoLock ();
+ Map = &mGcdIoSpaceMap;
+ }
+
+ if (Map == NULL) {
+ //
+ // Fail if 'Map' doesn't point to a valid address
+ //
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ 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) || (StartLink == NULL) || (EndLink == NULL)) {
+ 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;
+ } 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 > 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) || (StartLink == NULL) || (EndLink == NULL)) {
+ 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) || (TopEntry == NULL) || (BottomEntry == NULL)) {
+ 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) != 0) {
+ CoreReleaseGcdMemoryLock ();
+ }
+ if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
+ 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;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_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) || (StartLink == NULL) || (EndLink == NULL)) {
+ 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;
+ EFI_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;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_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) || (StartLink == NULL) || (EndLink == NULL)) {
+ 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;
+ EFI_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_STATUS Status;
+ 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;
+
+ //
+ // 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
+ //
+ Status = GetNextGuidHob (&Hob.Raw, &gEfiMemoryTypeInformationGuid, &EfiMemoryTypeInformation, &DataSize);
+ if (!EFI_ERROR (Status) &&
+ EfiMemoryTypeInformation != NULL &&
+ DataSize > 0 &&
+ DataSize < EfiMaxMemoryType * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {
+ gBS->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)*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;
+ }
+ if (ResourceHob != NULL) {
+ 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;
+
+ //
+ // 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
+ //
+ Status = GetCpuHobInfo (*HobStart, &SizeOfMemorySpace, &SizeOfIoSpace);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the GCD Memory Space Map
+ //
+ Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
+ ASSERT (Entry != NULL);
+ if (Entry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ 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);
+ if (Entry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ 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);
+ if (EFI_ERROR (Status) || (MemorySpaceMap == NULL)) {
+ return Status;
+ }
+ 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);
+//
+// EDK Defect Start: EDK836
+//
+// BUG FIX:
+// Skip zero length descriptors
+//
+ if (Length == 0) {
+ continue;
+ }
+//
+// EDK Defect End: EDK836
+//
+ 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/EDK/Foundation/Core/Dxe/Gcd/gcd.h b/EDK/Foundation/Core/Dxe/Gcd/gcd.h
new file mode 100644
index 0000000..13d448d
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Gcd/gcd.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ gcd.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _GCD_H
+#define _GCD_H
+
+#include "Tiano.h"
+#include "DxeCore.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/EDK/Foundation/Core/Dxe/Hand/DriverSupport.c b/EDK/Foundation/Core/Dxe/Hand/DriverSupport.c
new file mode 100644
index 0000000..0597475
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Hand/DriverSupport.c
@@ -0,0 +1,860 @@
+/*++
+
+Copyright (c) 2004 - 2011, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DriverSupport.c
+
+Abstract:
+
+ EFI Driver Support Protocol
+
+Revision History
+
+--*/
+
+#include "Tiano.h"
+#include "hand.h"
+#include "EfiPerf.h"
+
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION(DriverBinding)
+#include EFI_PROTOCOL_DEFINITION(PlatformDriverOverride)
+#include EFI_PROTOCOL_DEFINITION(BusSpecificDriverOverride)
+
+
+
+#ifdef FIRMWARE_PERFORMANCE
+STATIC
+EFI_STATUS
+GetHandleFromDriverBinding (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,
+ OUT EFI_HANDLE *Handle
+ );
+#endif
+
+//
+// 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_BOOTSERVICE11
+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;
+ EFI_LIST_ENTRY *Link;
+ EFI_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,
+ &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;
+
+#ifdef FIRMWARE_PERFORMANCE
+ EFI_HANDLE DriverBindingHandle;
+#endif
+
+ //
+ // 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,
+ &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,
+ &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.
+ //
+
+#ifdef FIRMWARE_PERFORMANCE
+ GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle);
+#endif
+
+ 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_BOOTSERVICE11
+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;
+ EFI_LIST_ENTRY *Link;
+ EFI_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,
+ &DriverBinding
+ );
+ if (EFI_ERROR (Status) || (DriverBinding == NULL)) {
+ 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;
+}
+
+
+
+#ifdef FIRMWARE_PERFORMANCE
+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 = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) {
+ Status = gBS->OpenProtocol(
+ DriverBindingHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ &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 ;
+}
+#endif \ No newline at end of file
diff --git a/EDK/Foundation/Core/Dxe/Hand/Notify.c b/EDK/Foundation/Core/Dxe/Hand/Notify.c
new file mode 100644
index 0000000..8b12657
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Hand/Notify.c
@@ -0,0 +1,335 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ notify.c
+
+Abstract:
+
+ EFI notify infrastructure
+
+
+
+Revision History
+
+--*/
+
+#include "hand.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;
+ EFI_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;
+ EFI_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_BOOTSERVICE
+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_BOOTSERVICE
+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/EDK/Foundation/Core/Dxe/Hand/hand.h b/EDK/Foundation/Core/Dxe/Hand/hand.h
new file mode 100644
index 0000000..d048073
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Hand/hand.h
@@ -0,0 +1,339 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ hand.h
+
+Abstract:
+
+ EFI internal protocol definitions
+
+
+
+Revision History
+
+--*/
+
+#ifndef _HAND_H_
+#define _HAND_H_
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+//
+// IHANDLE - contains a list of protocol handles
+//
+
+#define EFI_HANDLE_SIGNATURE EFI_SIGNATURE_32('h','n','d','l')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY AllHandles; // All handles list of IHANDLE
+ EFI_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;
+ EFI_LIST_ENTRY AllEntries; // All entries
+ EFI_GUID ProtocolID; // ID of the protocol
+ EFI_LIST_ENTRY Protocols; // All protocol interfaces
+ EFI_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
+ EFI_LIST_ENTRY Link; // Link on IHANDLE.Protocols
+ EFI_LIST_ENTRY ByProtocol; // Link on PROTOCOL_ENTRY.Protocols
+ PROTOCOL_ENTRY *Protocol; // The protocol ID
+ VOID *Interface; // The interface value
+
+ EFI_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;
+ EFI_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;
+ EFI_LIST_ENTRY Link; // All notifications for this protocol
+ EFI_EVENT Event; // Event to notify
+ EFI_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.
+
+ N.B. 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 EFI_LIST_ENTRY gHandleList;
+extern UINT64 gHandleDatabaseKey;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/Hand/handle.c b/EDK/Foundation/Core/Dxe/Hand/handle.c
new file mode 100644
index 0000000..45874b4
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Hand/handle.c
@@ -0,0 +1,1716 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ handle.c
+
+Abstract:
+
+ EFI handle & protocol handling
+
+
+
+Revision History
+
+--*/
+
+#include "hand.h"
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+#include EFI_PROTOCOL_DEFINITION (LoadedImage)
+#include EFI_PROTOCOL_DEFINITION (DebugMask)
+
+//
+// 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 EFI_LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
+EFI_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.
+
+ N.B. The gProtocolDatabaseLock must be owned
+
+Arguments:
+
+ Protocol - The ID of the protocol
+
+ Create - Create a new entry if not found
+
+Returns:
+
+ Protocol entry
+
+--*/
+{
+ EFI_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 (EfiCompareGuid (&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;
+ ProtEntry->ProtocolID = *Protocol;
+ 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;
+ EFI_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.
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *ProtEntry;
+ EFI_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_BOOTSERVICE
+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;
+
+ DEBUG_CODE (
+ UINTN ErrorLevel;
+ )
+
+ //
+ // 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_CODE (
+ if (EfiCompareGuid (Protocol, &gEfiLoadedImageProtocolGuid) ||
+ EfiCompareGuid (Protocol, &gEfiDebugMaskProtocolGuid)) {
+ //
+ // Print these protocols only at EFI_D_INFO level, for cleaner log.
+ // They are installed for every DXE driver.
+ //
+ ErrorLevel = EFI_D_INFO;
+ } else {
+ ErrorLevel = EFI_D_ERROR;
+ }
+ DEBUG ((ErrorLevel, "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_BOOTSERVICE11
+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 (EfiCompareGuid (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;
+ EFI_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_BOOTSERVICE
+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_BOOTSERVICE11
+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;
+ EFI_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 (EfiCompareGuid (&ProtEntry->ProtocolID, Protocol)) {
+ return Prot;
+ }
+ }
+ return NULL;
+}
+
+EFI_BOOTSERVICE
+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_BOOTSERVICE11
+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;
+ EFI_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_BOOTSERVICE11
+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;
+ EFI_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_BOOTSERVICE11
+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;
+ EFI_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_BOOTSERVICE11
+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;
+ EFI_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;
+ EFI_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/EDK/Foundation/Core/Dxe/Hand/locate.c b/EDK/Foundation/Core/Dxe/Hand/locate.c
new file mode 100644
index 0000000..4cd41e4
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Hand/locate.c
@@ -0,0 +1,743 @@
+/*++
+
+Copyright (c) 2004 - 2011, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ locate.c
+
+Abstract:
+
+ Locate handle functions
+
+Revision History
+
+--*/
+
+#include "hand.h"
+
+//
+// ProtocolRequest - Last LocateHandle request ID
+//
+UINTN mEfiLocateHandleRequest = 0;
+
+//
+// Internal prototypes
+//
+
+typedef struct {
+ EFI_GUID *Protocol;
+ VOID *SearchKey;
+ EFI_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_BOOTSERVICE
+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) {
+ return 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) || (GetNext == NULL)) {
+ 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;
+ EFI_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;
+ EFI_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_BOOTSERVICE
+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_HANDLE BestDevice;
+ 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;
+ }
+
+ BestDevice = NULL;
+ SourcePath = *DevicePath;
+ TmpDevicePath = SourcePath;
+ while (!IsDevicePathEnd (TmpDevicePath)) {
+ if (EfiIsDevicePathEndInstance (TmpDevicePath)) {
+ //
+ // If DevicePath is a multi-instance device path,
+ // the function will operate on the first instance
+ //
+ break;
+ }
+ TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+ }
+
+ SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;
+
+ //
+ // 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, &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) && EfiCompareMem (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;
+ BestDevice = 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;
+ }
+
+ if (Device == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *Device = BestDevice;
+
+ //
+ // Return the remaining part of the device path
+ //
+ *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);
+ return EFI_SUCCESS;
+}
+
+
+EFI_BOOTSERVICE11
+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_BOOTSERVICE11
+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/EDK/Foundation/Core/Dxe/Ia32/Processor.h b/EDK/Foundation/Core/Dxe/Ia32/Processor.h
new file mode 100644
index 0000000..0084d4a
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Ia32/Processor.h
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Processor.h
+
+Abstract:
+ This file contains the IA-32 processor specific definitions
+
+--*/
+
+#ifndef _PROCESSOR_H_
+#define _PROCESSOR_H_
+
+#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE)
+
+#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE)
+
+#endif \ No newline at end of file
diff --git a/EDK/Foundation/Core/Dxe/Image/Image.c b/EDK/Foundation/Core/Dxe/Image/Image.c
new file mode 100644
index 0000000..bdf1783
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Image/Image.c
@@ -0,0 +1,1626 @@
+/*++
+
+Copyright (c) 2004 - 2012, 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 "Image.h"
+#include "EfiHobLib.h"
+#include "EfiPerf.h"
+
+//
+// Module Globals
+//
+
+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
+ },
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ NULL, // Loaded Image Device Path
+#endif
+ (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage
+ 0, // NumberOfPages
+ NULL, // FixupData
+ 0, // Tpl
+ EFI_SUCCESS, // Status
+ 0, // ExitDataSize
+ NULL, // ExitData
+ NULL, // JumpContext
+ 0, // Machine
+ NULL, // Ebc
+ NULL, // RuntimeData
+};
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+CoreFlushICache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length
+ );
+
+EFI_STATUS
+GetTimerValue (
+ OUT UINT64 *TimerValue
+ );
+
+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;
+
+
+ //
+ // Searching for image hob
+ //
+ Status = GetDxeCoreHobInfo (
+ HobStart,
+ &DxeCoreImageBaseAddress,
+ &DxeCoreImageLength,
+ &DxeCoreEntryPoint,
+ &gDxeCoreFileName
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // 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);
+
+ //
+ // Install Debug Mask Protocol
+ //
+ DEBUG_CODE (
+ if (!EFI_ERROR (Status)) {
+ Status = InstallCoreDebugMaskProtocol(Image->Handle);
+ 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,
+ &gEfiLoadPeImageGuid,
+ EFI_NATIVE_INTERFACE,
+ &mLoadPe32PrivateData.Pe32Image
+ );
+}
+
+
+STATIC
+EFI_STATUS
+CoreLoadPeImage (
+ IN BOOLEAN BootPolicy,
+ IN VOID *Pe32Handle,
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute,
+ IN BOOLEAN CrossLoad
+ )
+/*++
+
+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.
+ CrossLoad - Whether expect to support cross architecture loading.
+
+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;
+ BOOLEAN DstBufAlocated;
+ UINTN Size;
+ EFI_IMAGE_NT_HEADERS64 *PeHdr;
+ EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;
+ IMAGE_FILE_HANDLE *FHandle;
+ BOOLEAN NeedAllocateAddress;
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ BOOLEAN OffsetMode;
+ STATIC BOOLEAN PrintTopAddress = TRUE;
+#endif
+
+ DEBUG_CODE (
+ UINTN Index;
+ UINTN StartIndex;
+ CHAR8 EfiFileName[256];
+ )
+
+ EfiCommonLibZeroMem (&(Image->ImageContext), sizeof (Image->ImageContext));
+
+ Image->ImageContext.Handle = Pe32Handle;
+ Image->ImageContext.ImageRead = (EFI_PEI_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;
+ }
+
+ //
+ // Check the processor architecture of the image
+ //
+ if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ if (CrossLoad) {
+ if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Allocate memory of the correct memory type aligned on the required image boundary.
+ //
+ DstBufAlocated = FALSE;
+ 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);
+ //
+ // Following code is to support load a PE image at fixed offset relative to TOLM
+ //
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ {
+ typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_PHYSICAL_ADDRESS MaximumAddress;
+ UINT64 CurrentNumberOfPages;
+ UINT64 NumberOfPages;
+ UINTN InformationIndex;
+ BOOLEAN Special;
+ BOOLEAN Runtime;
+ } EFI_MEMORY_TYPE_STAISTICS;
+
+
+ extern EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1];
+ INT32 Offset;
+ UINTN ReadSize = sizeof (UINT32);
+
+ if (PrintTopAddress) {
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Runtime code top address: %lX\n", mMemoryTypeStatistics[EfiRuntimeServicesCode].MaximumAddress + 1));
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Boot time code top address: %lX\n", mMemoryTypeStatistics[EfiBootServicesCode].MaximumAddress + 1));
+ PrintTopAddress = FALSE;
+ }
+ OffsetMode = FALSE;
+ Status = Image->ImageContext.ImageRead (
+ Image->ImageContext.Handle,
+ Image->ImageContext.PeCoffHeaderOffset + 12,
+ &ReadSize,
+ &Offset
+ );
+ if (!EFI_ERROR (Status) && Offset != 0 &&
+ Image->ImageContext.ImageCodeMemoryType != EfiLoaderCode) {
+ OffsetMode = TRUE;
+ Image->ImageContext.ImageAddress = mMemoryTypeStatistics[Image->ImageContext.ImageCodeMemoryType].MaximumAddress + 1 - Offset;
+ }
+ }
+#endif
+
+ //
+ // If the image relocations are stripped, or fixed address/offset feature is valid,
+ // try to load the image to the specified address first.
+ // Otherwise try to load the image at any page if image relocations are available.
+ //
+ NeedAllocateAddress = FALSE;
+ if (Image->ImageContext.RelocationsStripped) {
+ NeedAllocateAddress = TRUE;
+ }
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_ADDRESS
+ NeedAllocateAddress = TRUE;
+#endif
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ if (OffsetMode) {
+ NeedAllocateAddress = TRUE;
+ }
+#endif
+ Status = EFI_OUT_OF_RESOURCES;
+ if (NeedAllocateAddress) {
+ Status = CoreAllocatePages (
+ AllocateAddress,
+ Image->ImageContext.ImageCodeMemoryType,
+ Image->NumberOfPages,
+ &Image->ImageContext.ImageAddress
+ );
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ if (EFI_ERROR (Status) && OffsetMode) {
+ DEBUG((EFI_D_ERROR, "\nOffset mode load failure!"));
+ }
+#endif
+ }
+ if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
+ Status = CoreAllocatePages (
+ AllocateAnyPages,
+ Image->ImageContext.ImageCodeMemoryType,
+ Image->NumberOfPages,
+ &Image->ImageContext.ImageAddress
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ DstBufAlocated = TRUE;
+ } 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;
+ }
+
+ Size = EFI_SIZE_TO_PAGES ((UINTN) Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
+
+ if ((Image->NumberOfPages != 0) && (Image->NumberOfPages < Size)) {
+ Image->NumberOfPages = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Image->NumberOfPages = Size;
+ 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)) {
+ goto Done;
+ }
+
+ //
+ // 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 &&
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
+ if (Image->ImageContext.FixupData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // Measure the image before applying fixup
+ //
+ Status = CoreLocateProtocol (
+ &gEfiTcgPlatformProtocolGuid,
+ NULL,
+ &TcgPlatformProtocol
+ );
+ if (!EFI_ERROR (Status) && (TcgPlatformProtocol != NULL)) {
+ PeHdr = (EFI_IMAGE_NT_HEADERS64 *)(UINTN) (
+ Image->ImageContext.ImageAddress +
+ Image->ImageContext.PeCoffHeaderOffset
+ );
+ FHandle = (IMAGE_FILE_HANDLE *)Image->ImageContext.Handle;
+
+ Status = TcgPlatformProtocol->MeasurePeImage (
+ BootPolicy,
+ (EFI_PHYSICAL_ADDRESS)FHandle->Source,
+ FHandle->SourceSize,
+ (UINTN) PeHdr->OptionalHeader.ImageBase,
+ Image->ImageContext.ImageType,
+ Image->Info.DeviceHandle,
+ Image->Info.FilePath
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Relocate the image in memory
+ //
+ Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &(Image->ImageContext));
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Flush the Instruction Cache
+ //
+ Status = CoreFlushICache (Image->ImageContext.ImageAddress, Image->ImageContext.ImageSize);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // 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;
+
+ //
+ // 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;
+ if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
+ //
+ // Locate the EBC interpreter protocol
+ //
+ Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, &Image->Ebc);
+ if (EFI_ERROR (Status) || (Image->Ebc == NULL)) {
+ goto Done;
+ }
+
+ //
+ // Register a callback for flushing the instruction cache so that created
+ // thunks can be flushed.
+ //
+ Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, CoreFlushICache);
+ 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;
+
+ if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
+ if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+ //
+ // Make a list off all the RT images so we can let the RT AP know about them.
+ //
+ Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
+ if (Image->RuntimeData == NULL) {
+ goto Done;
+ }
+ Image->RuntimeData->ImageBase = Image->Info.ImageBase;
+ Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);
+ Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
+ Image->RuntimeData->Handle = Image->Handle;
+ InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
+ }
+ }
+
+ //
+ // 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 (
+ {
+ DEBUG ((
+ EFI_D_INFO | EFI_D_LOAD,
+ "Loading driver at 0x%x EntryPoint=0x%x ",
+ (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));
+ }
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
+ }
+ );
+
+ return EFI_SUCCESS;
+
+Done:
+
+ //
+ // Free memory.
+ //
+
+ if (DstBufAlocated) {
+ CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
+ }
+
+ if (Image->ImageContext.FixupData != NULL) {
+ CoreFreePool (Image->ImageContext.FixupData);
+ }
+
+ 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,
+ &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,
+ IN BOOLEAN CrossLoad
+ )
+/*++
+
+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, on input a pointer to the page number of DstBuffer and on
+ output a pointer to the page number of the image. If this number of DstBuffer
+ 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
+ CrossLoad - Whether expect to support cross architecture loading
+
+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;
+
+ SecurityStatus = EFI_SUCCESS;
+
+ 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
+ //
+ FilePath = OriginalFilePath;
+ Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, &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;
+ }
+
+ //
+ // Install Debug Mask Protocol
+ //
+ DEBUG_CODE (
+ Status = InstallDebugMaskProtocol(Image->Handle);
+ ASSERT_EFI_ERROR (Status);
+ )
+
+ //
+ // Load the image. If EntryPoint is Null, it will not be set.
+ //
+ Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute, CrossLoad);
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
+ if (NumberOfPages != NULL) {
+ *NumberOfPages = Image->NumberOfPages;
+ }
+ }
+ goto Done;
+ }
+ if (NumberOfPages != NULL) {
+ *NumberOfPages = Image->NumberOfPages;
+ }
+
+ //
+ // 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;
+ }
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
+ // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
+ //
+ if (OriginalFilePath != NULL) {
+ Image->LoadedImageDevicePath = CoreDuplicateDevicePath (OriginalFilePath);
+ }
+
+ //
+ // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
+ //
+ Status = CoreInstallProtocolInterface (
+ &Image->Handle,
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ Image->LoadedImageDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Install HII Package List Protocol onto the image handle
+ //
+ if (Image->ImageContext.HiiResourceData != 0) {
+ Status = CoreInstallProtocolInterface (
+ &Image->Handle,
+ &gEfiHiiPackageListProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *) (UINTN) Image->ImageContext.HiiResourceData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+#endif
+
+ //
+ // 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;
+ }
+ } else if (EFI_ERROR (SecurityStatus)) {
+ Status = SecurityStatus;
+ }
+
+ return Status;
+}
+
+
+EFI_BOOTSERVICE
+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;
+ UINT64 Ticker;
+
+ GetTimerValue (&Ticker);
+
+ 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,
+ FALSE
+ );
+
+ if (!EFI_ERROR (Status)) {
+ PERF_START (0, L"LoadImage", NULL, Ticker);
+ PERF_END (*ImageHandle, L"LoadImage", NULL, 0);
+ } else {
+ PERF_START (0, L"Load Failed", L"CoreLoadImage", Ticker);
+ PERF_END (0, L"Load Failed", L"CoreLoadImage", 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 (
+ FALSE,
+ ParentImageHandle,
+ FilePath,
+ SourceBuffer,
+ SourceSize,
+ DstBuffer,
+ NumberOfPages,
+ ImageHandle,
+ EntryPoint,
+ Attribute,
+ TRUE
+ );
+}
+
+
+
+EFI_BOOTSERVICE
+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;
+
+ Image = CoreLoadedImageInfo (ImageHandle);
+ if (Image == NULL_HANDLE || Image->Started) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Cannot start image of an unsupported processor architecture
+ //
+ if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Don't profile Objects or invalid start requests
+ //
+ PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);
+
+ //
+ // 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 (gEfiPeiTransferControl->JumpContextSize);
+ if (Image->JumpContext == NULL) {
+ PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gEfiPeiTransferControl->SetJump (gEfiPeiTransferControl, Image->JumpContext);
+ //
+ // The SetJump returns EFI_SUCCESS when LongJump Buffer has been armed
+ // SetJump returns EFI_WARN_RETURN_FROM_LONG_JUMP as a result of the LongJump
+ // All other return values for SetJump are undefined.
+ //
+ if (Status == EFI_SUCCESS) {
+
+ //
+ // 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 (&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 (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = CoreUninstallProtocolInterface (
+ Image->Handle,
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ Image->LoadedImageDevicePath
+ );
+
+ if (Image->LoadedImageDevicePath != NULL) {
+ CoreFreePool (Image->LoadedImageDevicePath);
+ }
+
+ if (Image->ImageContext.HiiResourceData != 0) {
+ Status = CoreUninstallProtocolInterface (
+ Image->Handle,
+ &gEfiHiiPackageListProtocolGuid,
+ (VOID *) (UINTN) Image->ImageContext.HiiResourceData
+ );
+ }
+#endif
+
+ //
+ // Uninstall Debug Mask Protocol
+ //
+ DEBUG_CODE (
+ Status = UninstallDebugMaskProtocol(Image->Handle);
+ ASSERT_EFI_ERROR (Status);
+ )
+
+ }
+
+ if (Image->RuntimeData != NULL) {
+ if (Image->RuntimeData->Link.ForwardLink != NULL) {
+ //
+ // Remove the Image from the Runtime Image list as we are about to Free it!
+ //
+ RemoveEntryList (&Image->RuntimeData->Link);
+ }
+ CoreFreePool (Image->RuntimeData);
+ }
+
+ //
+ // 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_BOOTSERVICE
+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;
+ }
+ EfiCommonLibCopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
+ }
+
+ //
+ // return to StartImage
+ //
+ Status = gEfiPeiTransferControl->LongJump (gEfiPeiTransferControl, Image->JumpContext);
+
+ //
+ // If we return from LongJump, then it is an error
+ //
+ ASSERT (FALSE);
+ return EFI_ACCESS_DENIED;
+}
+
+
+EFI_BOOTSERVICE
+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);
+}
+
+
+
+//
+// This callback function is used by the EBC interpreter driver to flush the
+// processor instruction cache after creating thunks. We're simply hiding
+// the "this" pointer that must be passed into the real flush function.
+//
+STATIC
+EFI_STATUS
+EFIAPI
+CoreFlushICache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ flush the processor instruction cache.
+
+Arguments:
+
+ Start - Start adddress in memory to flush.
+
+ Length - Length of memory to flush.
+
+Returns:
+
+--*/
+{
+ return gEfiPeiFlushInstructionCache->Flush (
+ gEfiPeiFlushInstructionCache,
+ Start,
+ Length
+ );
+}
+
+
diff --git a/EDK/Foundation/Core/Dxe/Image/Image.h b/EDK/Foundation/Core/Dxe/Image/Image.h
new file mode 100644
index 0000000..6cee212
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Image/Image.h
@@ -0,0 +1,399 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ EFI image loader
+
+--*/
+
+
+#ifndef _IMAGE_H_
+#define _IMAGE_H_
+
+
+#include "Tiano.h"
+#include "LinkedList.h"
+#include "DxeCore.h"
+
+#include EFI_PROTOCOL_PRODUCER (LoadedImage)
+#include EFI_PROTOCOL_PRODUCER (LoadPe32Image)
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+#include EFI_PROTOCOL_PRODUCER (LoadedImageDevicePath)
+#include EFI_PROTOCOL_CONSUMER (LoadFile2)
+#include EFI_PROTOCOL_PRODUCER (HiiPackageList)
+#endif
+
+#include EFI_PROTOCOL_CONSUMER (Ebc)
+#include EFI_PROTOCOL_CONSUMER (SimpleFileSystem)
+#include EFI_PROTOCOL_CONSUMER (FileInfo)
+#include EFI_PROTOCOL_CONSUMER (LoadFile)
+#include EFI_PROTOCOL_CONSUMER (FirmwareVolume)
+
+#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','d','r','i')
+
+typedef struct {
+ UINTN Signature; // Data 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
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; // Loaded Image Device Path Protocl pointer
+#endif
+
+ 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
+ VOID *JumpContext; // Pointer to buffer for context save/retore
+ UINT16 Machine; // Machine type from PE image
+
+ EFI_EBC_PROTOCOL *Ebc; // EBC Protocol pointer
+
+ EFI_RUNTIME_IMAGE_ENTRY *RuntimeData; // Runtime image list
+
+ EFI_PEI_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;
+ 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.
+
+--*/
+;
+
+STATIC
+EFI_STATUS
+CoreLoadPeImage (
+ IN BOOLEAN BootPolicy,
+ IN VOID *Pe32Handle,
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute,
+ IN BOOLEAN CrossLoad
+ )
+/*++
+
+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
+ CrossLoad - Whether expect to support cross architecture loading
+
+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/EDK/Foundation/Core/Dxe/Image/ImageFile.c b/EDK/Foundation/Core/Dxe/Image/ImageFile.c
new file mode 100644
index 0000000..462446f
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Image/ImageFile.c
@@ -0,0 +1,646 @@
+/*++
+
+Copyright (c) 2004 - 2011, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ImageFile.c
+
+
+Abstract:
+
+
+
+
+Revision History
+
+--*/
+
+#include "Image.h"
+#include "DxeCore.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;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_LOAD_FILE2_PROTOCOL *LoadFile2;
+#endif
+ 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;
+ FILEPATH_DEVICE_PATH *OriginalFilePathNode;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+#endif
+
+ *AuthenticationStatus = 0;
+ EfiCommonLibZeroMem (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;
+ CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, FilePath, DeviceHandle);
+ 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 (
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+ #else
+ &gEfiFirmwareVolume2ProtocolGuid,
+ #endif
+ (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode,
+ (VOID*)&FwVol,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status) && (FwVol != NULL)) {
+ //
+ // For FwVol File system there is only a single file name that is a GUID.
+ //
+ NameGuid = CoreGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode);
+ if (NameGuid != NULL) {
+
+ SectionType = EFI_SECTION_PE32;
+ Pe32Buffer = NULL;
+ Status = FwVol->ReadSection (
+ FwVol,
+ &FwVolFilePathNode->NameGuid,
+ SectionType,
+ 0,
+ &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,
+ &FwVolFilePathNode->NameGuid,
+ &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) && (Volume != NULL)) {
+ //
+ // Open the Volume to get the File System handle
+ //
+ Status = Volume->OpenVolume (Volume, &FileHandle);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Duplicate the device path to avoid the access to unaligned device path node.
+ // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH
+ // nodes, It assures the fields in device path nodes are 2 byte aligned.
+ //
+ FilePathNode = (FILEPATH_DEVICE_PATH *) CoreDuplicateDevicePath(
+ (EFI_DEVICE_PATH_PROTOCOL *)(UINTN)FilePathNode
+ );
+ if (FilePathNode == NULL) {
+ FileHandle->Close (FileHandle);
+ FileHandle = NULL;
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ OriginalFilePathNode = FilePathNode;
+ //
+ // 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);
+ }
+ //
+ // Free the allocated memory pool
+ //
+ CoreFreePool (OriginalFilePathNode);
+ }
+
+ 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, &FileInfo, FileInfoSize)) {
+ //
+ // Automatically allocate buffer of the correct size and make the call
+ //
+ Status = FileHandle->GetInfo (
+ FileHandle,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo
+ );
+ }
+ if (!EFI_ERROR (Status) && (FileInfo != NULL)) {
+ //
+ // 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);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Close the file since we are done
+ //
+ FileHandle->Close (FileHandle);
+ CoreFreePool (FileInfo);
+ goto Done;
+ }
+
+ if (FileInfo != NULL) {
+ CoreFreePool (FileInfo);
+ }
+ }
+ if (FileHandle != NULL) {
+ FileHandle->Close (FileHandle);
+ }
+ }
+ }
+
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // Try LoadFile2 style
+ //
+ if (!BootPolicy) {
+ TempFilePath = *FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiLoadFile2ProtocolGuid,
+ &TempFilePath,
+ (VOID*)&LoadFile2,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status) && (LoadFile2 != NULL)) {
+ //
+ // Call LoadFile2 with the correct buffer size
+ //
+ while (CoreGrowBuffer (&Status, &ImageFileHandle->Source, ImageFileHandle->SourceSize)) {
+ Status = LoadFile2->LoadFile (
+ LoadFile2,
+ 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)) {
+ ImageFileHandle->FreeBuffer = TRUE;
+ goto Done;
+ }
+ }
+ }
+#endif
+
+ //
+ // Try LoadFile style
+ //
+ TempFilePath = *FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiLoadFileProtocolGuid,
+ &TempFilePath,
+ (VOID*)&LoadFile,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status) && (LoadFile != NULL)) {
+ //
+ // Call LoadFile with the correct buffer size
+ //
+ while (CoreGrowBuffer (&Status, &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;
+ }
+
+ EfiCommonLibCopyMem (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 += EfiStrLen (FilePathNode->PathName);
+
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
+ }
+
+ *String = CoreAllocateBootServicesPool (StringSize);
+ if (*String == NULL) {
+ return;
+ }
+
+ FilePathNode = FilePath;
+ Str = *String;
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {
+ EfiStrCat (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/EDK/Foundation/Core/Dxe/Include/DxeCore.h b/EDK/Foundation/Core/Dxe/Include/DxeCore.h
new file mode 100644
index 0000000..2587d7c
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Include/DxeCore.h
@@ -0,0 +1,2535 @@
+/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DxeCore.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _DXECORE_H_
+#define _DXECORE_H_
+
+#include EFI_GUID_DEFINITION (PeiFlushInstructionCache)
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)
+#include EFI_GUID_DEFINITION (PeiTransferControl)
+#include EFI_GUID_DEFINITION (Hob)
+#include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
+#include EFI_GUID_DEFINITION (DxeServices)
+#include EFI_GUID_DEFINITION (MemoryTypeInformation)
+#include EFI_GUID_DEFINITION (StatusCodeCallerId)
+#include EFI_GUID_DEFINITION (EventGroup)
+#include EFI_GUID_DEFINITION (EventLegacyBios)
+#include EFI_GUID_DEFINITION (FrameworkDevicePath)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+#include EFI_ARCH_PROTOCOL_DEFINITION (MonotonicCounter)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Timer)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Bds)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Reset)
+#include EFI_ARCH_PROTOCOL_DEFINITION (RealTimeClock)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Variable)
+#include EFI_ARCH_PROTOCOL_DEFINITION (VariableWrite)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Capsule)
+#include EFI_ARCH_PROTOCOL_DEFINITION (WatchdogTimer)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Runtime)
+#include EFI_ARCH_PROTOCOL_DEFINITION (StatusCode)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Security)
+#include EFI_PROTOCOL_DEFINITION (Decompress)
+#include EFI_PROTOCOL_DEFINITION (TianoDecompress)
+#include EFI_PROTOCOL_DEFINITION (CustomizedDecompress)
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolume)
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeDispatch)
+#include EFI_PROTOCOL_DEFINITION (LoadedImage)
+#include EFI_PROTOCOL_DEFINITION (TcgService)
+#include "LinkedList.h"
+#include "DebugImageInfo.h"
+#include "EfiCommonLib.h"
+#include "Library.h"
+#include "Peihob.h"
+#include "EfiHobLib.h"
+#include "DebugMask.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;
+ EFI_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;
+ EFI_LIST_ENTRY Link; // mDriverList
+
+ EFI_LIST_ENTRY ScheduledLink; // mScheduledQueue
+
+ EFI_HANDLE FvHandle;
+ EFI_GUID FileName;
+ EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+#endif
+ 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;
+ EFI_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_FLUSH_INSTRUCTION_CACHE_PROTOCOL *gEfiPeiFlushInstructionCache;
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader;
+extern EFI_PEI_TRANSFER_CONTROL_PROTOCOL *gEfiPeiTransferControl;
+
+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 EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate;
+
+//
+// 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.
+
+ N.B. 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 OUT 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. The HobStart will be relocated to a pool
+ buffer.
+
+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
+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.
+
+--*/
+;
+
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE11
+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_BOOTSERVICE11
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE11
+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_BOOTSERVICE11
+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_BOOTSERVICE11
+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_BOOTSERVICE11
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE11
+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_BOOTSERVICE11
+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_BOOTSERVICE11
+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_BOOTSERVICE11
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCreateEventEx (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ 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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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_BOOTSERVICE
+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
+//
+DEBUG_CODE (
+ 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/EDK/Foundation/Core/Dxe/Include/Library.h b/EDK/Foundation/Core/Dxe/Include/Library.h
new file mode 100644
index 0000000..9cd4da2
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Include/Library.h
@@ -0,0 +1,531 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Library.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _DXE_LIBRARY_H_
+#define _DXE_LIBRARY_H_
+
+typedef struct {
+ EFI_TPL Tpl;
+ EFI_TPL OwnerTpl;
+ UINTN Lock;
+} EFI_LOCK;
+
+
+//
+// Macro to initialize the state of a lock when a lock variable is declared
+//
+#define EFI_INITIALIZE_LOCK_VARIABLE(Tpl) {Tpl,0,0}
+
+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.
+
+--*/
+;
+
+VOID
+EfiDebugAssert (
+ IN CHAR8 *FileName,
+ IN INTN LineNumber,
+ IN CHAR8 *Description
+ )
+/*++
+
+Routine Description:
+
+ Worker function for ASSERT(). If Error Logging hub is loaded, log DEBUG
+ information; If not, do BREAKPOINT().
+
+Arguments:
+
+ FileName - File name of failing routine.
+
+ LineNumber - Line number of failing ASSERT().
+
+ Description - Descritption, usally the assertion string.
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+EfiDebugPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Wrapper for EfiDebugVPrint ()
+
+Arguments:
+
+ ErrorLevel - If error level is set do the debug print.
+
+ Format - String to use for the print, followed by Print arguments.
+
+ ... - Print arguments.
+
+Returns:
+
+ None
+
+--*/
+;
+
+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.
+
+--*/
+;
+
+VOID
+EFIAPI
+CoreInitializeFwVolDevicepathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode,
+ IN EFI_GUID *NameGuid
+ )
+/*++
+
+Routine Description:
+
+ Initialize a Firmware Volume (FV) Media Device Path node.
+
+ Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
+ so as we move to UEFI 2.0 support we must use a mechanism that conforms with
+ the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
+ device path is defined for PIWG extensions of device path. If the code
+ is compiled to conform with the UEFI 2.0 specification use the new device path
+ else use the old form for backwards compatability.
+
+Arguments:
+
+ FvDevicePathNode - Pointer to a FV device path node to initialize
+ NameGuid - FV file name to use in FvDevicePathNode
+
+--*/
+;
+
+EFI_GUID *
+EFIAPI
+CoreGetNameGuidFromFwVolDevicePathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode
+ )
+/*++
+
+Routine Description:
+
+ Check to see if the Firmware Volume (FV) Media Device Path is valid.
+
+ Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
+ so as we move to UEFI 2.0 support we must use a mechanism that conforms with
+ the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
+ device path is defined for PIWG extensions of device path. If the code
+ is compiled to conform with the UEFI 2.0 specification use the new device path
+ else use the old form for backwards compatability. The return value to this
+ function points to a location in FvDevicePathNode and it does not allocate
+ new memory for the GUID pointer that is returned.
+
+Arguments:
+
+ FvDevicePathNode Pointer to FV device path to check
+
+Returns:
+
+ NULL - FvDevicePathNode is not valid.
+ Other - FvDevicePathNode is valid and pointer to NameGuid was returned.
+
+--*/
+;
+#endif
diff --git a/EDK/Foundation/Core/Dxe/Ipf/Processor.h b/EDK/Foundation/Core/Dxe/Ipf/Processor.h
new file mode 100644
index 0000000..8e49d37
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Ipf/Processor.h
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Processor.h
+
+Abstract:
+ This file contains the Ipf processor specific definitions
+
+--*/
+
+#ifndef _PROCESSOR_H_
+#define _PROCESSOR_H_
+
+#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE * 2)
+
+#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE * 2)
+
+#endif \ No newline at end of file
diff --git a/EDK/Foundation/Core/Dxe/Library/Library.c b/EDK/Foundation/Core/Dxe/Library/Library.c
new file mode 100644
index 0000000..6014656
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Library/Library.c
@@ -0,0 +1,878 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Library.c
+
+Abstract:
+
+ DXE Core library services.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiCommonLib.h"
+
+DEBUG_CODE (
+ UINTN mErrorLevel = EFI_DBUG_MASK | EFI_D_LOAD;
+)
+
+EFI_DEVICE_HANDLE_EXTENDED_DATA mStatusCodeData = {
+ sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA),
+ 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);
+ EfiCommonLibSetMem (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);
+ EfiCommonLibCopyMem (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);
+ EfiCommonLibCopyMem (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.
+
+--*/
+{
+ if (Lock->Lock != 0) {
+ //
+ // Lock is already owned, so bail out
+ //
+ return EFI_ACCESS_DENIED;
+ }
+
+ Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);
+ Lock->Lock += 1;
+
+ 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
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = CoreAcquireLockOrFail (Lock);
+
+ //
+ // Lock was already locked.
+ //
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+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;
+
+ Tpl = Lock->OwnerTpl;
+
+ ASSERT (Lock->Lock == 1);
+ Lock->Lock -= 1;
+
+ 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)));
+ EfiCommonLibCopyMem (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;
+}
+
+/*++
+Routine Description:
+
+ Initialize a Firmware Volume (FV) Media Device Path node.
+
+ Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
+ so as we move to UEFI 2.0 support we must use a mechanism that conforms with
+ the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
+ device path is defined for PIWG extensions of device path. If the code
+ is compiled to conform with the UEFI 2.0 specification use the new device path
+ else use the old form for backwards compatability.
+
+Arguments:
+
+ FvDevicePathNode - Pointer to a FV device path node to initialize
+ NameGuid - FV file name to use in FvDevicePathNode
+
+--*/
+VOID
+EFIAPI
+CoreInitializeFwVolDevicepathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode,
+ IN EFI_GUID *NameGuid
+ )
+{
+//
+// EDK Defect Start: EDK848
+//
+#if 1
+//#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+//
+// EDK Defect End: EDK848
+//
+ //
+ // Use old Device Path that conflicts with UEFI
+ //
+ FvDevicePathNode->Header.Type = MEDIA_DEVICE_PATH;
+ FvDevicePathNode->Header.SubType = MEDIA_FV_FILEPATH_DP;
+ SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
+
+#else
+ //
+ // Use the new Device path that does not conflict with the UEFI
+ //
+ FvDevicePathNode->Piwg.Header.Type = MEDIA_DEVICE_PATH;
+ FvDevicePathNode->Piwg.Header.SubType = MEDIA_VENDOR_DP;
+ SetDevicePathNodeLength (&FvDevicePathNode->Piwg.Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
+
+ //
+ // Add the GUID for generic PIWG device paths
+ //
+ EfiCommonLibCopyMem (&FvDevicePathNode->Piwg.PiwgSpecificDevicePath, &gEfiFrameworkDevicePathGuid, sizeof(EFI_GUID));
+
+ //
+ // Add in the FW Vol File Path PIWG defined inforation
+ //
+ FvDevicePathNode->Piwg.Type = PIWG_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH_TYPE;
+
+#endif
+ EfiCommonLibCopyMem (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));
+}
+
+/*++
+
+Routine Description:
+
+ Check to see if the Firmware Volume (FV) Media Device Path is valid.
+
+ Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
+ so as we move to UEFI 2.0 support we must use a mechanism that conforms with
+ the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
+ device path is defined for PIWG extensions of device path. If the code
+ is compiled to conform with the UEFI 2.0 specification use the new device path
+ else use the old form for backwards compatability. The return value to this
+ function points to a location in FvDevicePathNode and it does not allocate
+ new memory for the GUID pointer that is returned.
+
+Arguments:
+
+ @param FvDevicePathNode Pointer to FV device path to check
+
+Returns:
+
+ NULL - FvDevicePathNode is not valid.
+ Other - FvDevicePathNode is valid and pointer to NameGuid was returned.
+
+--*/
+EFI_GUID *
+EFIAPI
+CoreGetNameGuidFromFwVolDevicePathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode
+ )
+{
+//
+// EDK Defect Start: EDK848
+//
+#if 1
+//#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+//
+// EDK Defect End: EDK848
+//
+ //
+ // Use old Device Path that conflicts with UEFI
+ //
+ if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {
+ return &FvDevicePathNode->NameGuid;
+ }
+
+#else
+ //
+ // Use the new Device path that does not conflict with the UEFI
+ //
+ if (DevicePathType (&FvDevicePathNode->Piwg.Header) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (&FvDevicePathNode->Piwg.Header) == MEDIA_VENDOR_DP) {
+ if (EfiCompareGuid (&gEfiFrameworkDevicePathGuid, &FvDevicePathNode->Piwg.PiwgSpecificDevicePath)) {
+ if (FvDevicePathNode->Piwg.Type == PIWG_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH_TYPE) {
+ return &FvDevicePathNode->NameGuid;
+ }
+ }
+ }
+#endif
+ return NULL;
+}
+
+DEBUG_CODE (
+
+VOID
+EfiDebugAssert (
+ IN CHAR8 *FileName,
+ IN INTN LineNumber,
+ IN CHAR8 *Description
+ )
+/*++
+
+Routine Description:
+
+ Worker function for ASSERT(). If Error Logging hub is loaded, log DEBUG
+ information; If not, do BREAKPOINT().
+
+ We use UINT64 buffers due to IPF alignment concerns.
+
+Arguments:
+
+ FileName - File name of failing routine.
+
+ LineNumber - Line number of failing ASSERT().
+
+ Description - Descritption, usally the assertion string.
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
+
+ EfiDebugAssertWorker (FileName, LineNumber,Description, sizeof (Buffer), Buffer);
+
+ //
+ // Check if our pointers are valid. Can't assert because that would recurse.
+ //
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ (EFI_SOFTWARE_DXE_CORE | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE),
+ 0,
+ &gEfiDxeServicesTableGuid,
+ (EFI_STATUS_CODE_DATA *)Buffer
+ );
+ }
+
+ //
+ // Put break point in module that contained the error.
+ //
+ EFI_BREAKPOINT ();
+}
+
+
+VOID
+EfiDebugVPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ IN VA_LIST Marker
+ )
+/*++
+
+Routine Description:
+
+ Worker function for DEBUG(). If Error Logging hub is loaded, DEBUG
+ information will be logged. If Error Logging hub is not loaded, do nothing.
+
+ We use UINT64 buffers due to IPF alignment concerns.
+
+Arguments:
+
+ ErrorLevel - If error level is set do the debug print.
+
+ Format - String to use for the print, followed by Print arguments.
+
+ Marker - VarArgs
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
+
+ if (!(mErrorLevel & ErrorLevel)) {
+ return;
+ }
+
+ EfiDebugVPrintWorker (ErrorLevel, Format, Marker, sizeof (Buffer), Buffer);
+
+ //
+ // Check if our pointers are valid. Can't assert because that would recurse.
+ //
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ EFI_DEBUG_CODE,
+ (EFI_SOFTWARE_DXE_CORE | EFI_DC_UNSPECIFIED),
+ 0,
+ &gEfiDxeServicesTableGuid,
+ (EFI_STATUS_CODE_DATA *)Buffer
+ );
+ }
+}
+
+
+VOID
+EfiDebugPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Wrapper for EfiDebugVPrint ()
+
+Arguments:
+
+ ErrorLevel - If error level is set do the debug print.
+
+ Format - String to use for the print, followed by Print arguments.
+
+ ... - Print arguments.
+
+Returns:
+
+ None
+
+--*/
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, Format);
+ EfiDebugVPrint (ErrorLevel, Format, Marker);
+ VA_END (Marker);
+}
+)
diff --git a/EDK/Foundation/Core/Dxe/Mem/Page.c b/EDK/Foundation/Core/Dxe/Mem/Page.c
new file mode 100644
index 0000000..0f79cb3
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Mem/Page.c
@@ -0,0 +1,1648 @@
+/*++
+
+Copyright (c) 2007 - 2011, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ page.c
+
+Abstract:
+
+ EFI Memory page management
+
+
+Revision History
+
+--*/
+
+#include "imem.h"
+
+#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE)
+
+//
+// Entry for tracking the memory regions for each memory type to help coalesce like memory types
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress; // Base address of the coalesce bin if NumberOfPages is not 0, or 0 otherwise
+ EFI_PHYSICAL_ADDRESS MaximumAddress; // Top address of the coalesce bin if NumberOfPages is not 0, or the top address below all bin ranges
+ UINT64 CurrentNumberOfPages; // CurrentNumberOfPages allocated for this memory type
+ UINT64 NumberOfPages; // Number of pages specified in gMemoryTypeInformation
+ UINTN InformationIndex; // Index into gMemoryTypeInformation
+ BOOLEAN Special; // If this type of coalesce bin needs to be filled in memory map
+ BOOLEAN Runtime; // If this type is runtime available
+} 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;
+//
+// This list maintain the free memory map list
+//
+EFI_LIST_ENTRY mFreeMemoryMapEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList);
+BOOLEAN mMemoryTypeInformationInitialized = FALSE;
+
+EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiReservedMemoryType
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderData
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesData
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesData
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiConventionalMemory
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiUnusableMemory
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIReclaimMemory
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIMemoryNVS
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIO
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIOPortSpace
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiPalCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE } // 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
+ );
+
+
+MEMORY_MAP *
+AllocateMemoryMapEntry (
+ );
+
+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
+
+--*/
+{
+ EFI_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)
+ );
+ mMemoryTypeStatistics[EfiConventionalMemory].CurrentNumberOfPages += RShiftU64 ((Entry->EndAddress - Entry->BaseAddress + 1), EFI_PAGE_SHIFT);
+ 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.
+
+ N.B. 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);
+ mMemoryTypeStatistics[Type].CurrentNumberOfPages += NumberOfPages;
+ 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
+ );
+ mMemoryTypeStatistics[Type].NumberOfPages = 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;
+ }
+ }
+ 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
+
+--*/
+{
+ EFI_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, (UINTN)Type));
+
+ //
+ // Memory map being altered
+ //
+
+ mMemoryMapKey += 1;
+
+ //
+ // 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].FromPages = 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;
+ EFI_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) {
+ //
+ // Deque an memory map entry from mFreeMemoryMapEntryList
+ //
+ Entry = AllocateMemoryMapEntry ();
+
+ ASSERT (Entry);
+
+ //
+ // Update to proper entry
+ //
+ mMapDepth -= 1;
+
+ if (mMapStack[mMapDepth].Link.ForwardLink != NULL) {
+
+ //
+ // Move this entry to general memory
+ //
+ RemoveEntryList (&mMapStack[mMapDepth].Link);
+ mMapStack[mMapDepth].Link.ForwardLink = NULL;
+
+ *Entry = mMapStack[mMapDepth];
+ Entry->FromPages = TRUE;
+
+ //
+ // Find insertion location
+ //
+ for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) {
+ Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ if (Entry2->FromPages && Entry2->Start > Entry->Start) {
+ break;
+ }
+ }
+
+ InsertTailList (Link2, &Entry->Link);
+
+ } else {
+ //
+ // This item of mMapStack[mMapDepth] has already been dequeued from gMemoryMap list,
+ // so here no need to move it to memory.
+ //
+ InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);
+ }
+ }
+
+ 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->FromPages) {
+ //
+ // Insert the free memory map descriptor to the end of mFreeMemoryMapEntryList
+ //
+ InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);
+ }
+}
+
+MEMORY_MAP *
+AllocateMemoryMapEntry (
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Deque a descriptor entry from the mFreeMemoryMapEntryList.
+ If the list is emtry, then allocate a new page to refuel the list.
+ Please Note this algorithm to allocate the memory map descriptor has a property
+ that the memory allocated for memory entries always grows, and will never really be freed
+ For example, if the current boot uses 2000 memory map entries at the maximum point, but
+ ends up with only 50 at the time the OS is booted, then the memory associated with the 1950
+ memory map entries is still allocated from EfiBootServicesMemory.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ The Memory map descriptor dequed from the mFreeMemoryMapEntryList
+
+--*/
+{
+ MEMORY_MAP* FreeDescriptorEntries;
+ MEMORY_MAP* Entry;
+ UINTN Index;
+
+ if (IsListEmpty (&mFreeMemoryMapEntryList)) {
+ //
+ // The list is empty, to allocate one page to refuel the list
+ //
+ FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData, EFI_SIZE_TO_PAGES(DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);
+ if(FreeDescriptorEntries != NULL) {
+ //
+ // Enque the free memmory map entries into the list
+ //
+ for (Index = 0; Index< DEFAULT_PAGE_ALLOCATION / sizeof(MEMORY_MAP); Index++) {
+ FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE;
+ InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link);
+ }
+ } else {
+ return NULL;
+ }
+ }
+ //
+ // dequeue the first descriptor from the list
+ //
+ Entry = CR (mFreeMemoryMapEntryList.ForwardLink, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ RemoveEntryList (&Entry->Link);
+
+ return 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;
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+ UINT64 NumberOfRangePages;
+
+ 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) || (Entry == NULL)) {
+ 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, (UINTN)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
+ //
+ NumberOfRangePages = RShiftU64 (RangeEnd - Start + 1, EFI_PAGE_SHIFT);
+ if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {
+ ASSERT (NumberOfRangePages <= mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages);
+ mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfRangePages;
+ gMemoryTypeInformation[mMemoryTypeStatistics[Entry->Type].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages;
+ }
+
+ if (NewType >= 0 && NewType < EfiMaxMemoryType) {
+ mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfRangePages;
+ 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].FromPages = 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;
+ EFI_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_BOOTSERVICE
+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_BOOTSERVICE
+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;
+ EFI_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) || (Entry == NULL)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ 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) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
+ NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
+
+ Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Destroy the contents
+ //
+ if (Memory < EFI_MAX_ADDRESS) {
+ DEBUG_SET_MEMORY ((VOID *)(UINTN)Memory, NumberOfPages << EFI_PAGE_SHIFT);
+ }
+
+ Done:
+ CoreReleaseMemoryLock ();
+
+ return Status;
+}
+
+
+EFI_BOOTSERVICE
+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;
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+ EFI_GCD_MAP_ENTRY *GcdMapEntry;
+ EFI_MEMORY_TYPE Type;
+
+ //
+ // 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) && ((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
+ //
+ EfiCommonLibZeroMem (MemoryMap, BufferSize);
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ ASSERT (Entry->VirtualStart == 0);
+
+ //
+ // Convert internal map into an EFI_MEMORY_DESCRIPTOR
+ //
+ MemoryMap->Type = Entry->Type;
+ MemoryMap->PhysicalStart = Entry->Start;
+ MemoryMap->VirtualStart = Entry->VirtualStart;
+ MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
+ //
+ // If the memory type is EfiConventionalMemory, then determine if the range is part of a
+ // memory type bin and needs to be converted to the same memory type as the rest of the
+ // memory type bin in order to minimize EFI Memory Map changes across reboots. This
+ // improves the chances for a successful S4 resume in the presence of minor page allocation
+ // differences across reboots.
+ //
+ if (MemoryMap->Type == EfiConventionalMemory) {
+ for (Type = (EFI_MEMORY_TYPE) 0; Type < EfiMaxMemoryType; Type++) {
+ if (mMemoryTypeStatistics[Type].Special &&
+ mMemoryTypeStatistics[Type].NumberOfPages > 0 &&
+ Entry->Start >= mMemoryTypeStatistics[Type].BaseAddress &&
+ Entry->End <= mMemoryTypeStatistics[Type].MaximumAddress ) {
+ MemoryMap->Type = Type;
+ }
+ }
+ }
+ MemoryMap->Attribute = Entry->Attribute;
+ if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {
+ MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
+ }
+
+ 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) && ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME))) {
+
+ MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;
+ MemoryMap->VirtualStart = 0;
+ 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;
+ EFI_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/EDK/Foundation/Core/Dxe/Mem/imem.h b/EDK/Foundation/Core/Dxe/Mem/imem.h
new file mode 100644
index 0000000..d9029c5
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Mem/imem.h
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ imem.h
+
+Abstract:
+
+ Head file to imem.h
+
+
+Revision History
+
+--*/
+
+#ifndef _IMEM_H_
+#define _IMEM_H_
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "Processor.h"
+
+//
+// MEMORY_MAP_ENTRY
+//
+
+#define MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('m','m','a','p')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY Link;
+ BOOLEAN FromPages;
+
+ 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.
+
+ N.B. 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.
+
+ N.B. 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 EFI_LIST_ENTRY gMemoryMap;
+extern MEMORY_MAP *gMemoryLastConvert;
+extern EFI_LIST_ENTRY mGcdMemorySpaceMap;
+#endif
diff --git a/EDK/Foundation/Core/Dxe/Mem/memdata.c b/EDK/Foundation/Core/Dxe/Mem/memdata.c
new file mode 100644
index 0000000..580b0bd
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Mem/memdata.c
@@ -0,0 +1,41 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ memdata.c
+
+Abstract:
+
+ Global data used in memory service
+
+
+Revision History
+
+--*/
+
+#include "imem.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
+//
+EFI_LIST_ENTRY gMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap);
+
+//
+// MemoryLastConvert - the last memory descriptor used for a conversion request
+//
+MEMORY_MAP *gMemoryLastConvert;
diff --git a/EDK/Foundation/Core/Dxe/Mem/pool.c b/EDK/Foundation/Core/Dxe/Mem/pool.c
new file mode 100644
index 0000000..a13d94d
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Mem/pool.c
@@ -0,0 +1,613 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ pool.c
+
+Abstract:
+
+ EFI Memory pool management
+
+Revision History
+
+--*/
+
+#include "imem.h"
+
+#define POOL_FREE_SIGNATURE EFI_SIGNATURE_32('p','f','r','0')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Index;
+ EFI_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 (EFI_MAX_ADDRESS - POOL_OVERHEAD)
+
+//
+// Globals
+//
+
+#define POOL_SIGNATURE EFI_SIGNATURE_32('p','l','s','t')
+typedef struct {
+ INTN Signature;
+ UINTN Used;
+ EFI_MEMORY_TYPE MemoryType;
+ EFI_LIST_ENTRY FreeList[MAX_POOL_LIST];
+ EFI_LIST_ENTRY Link;
+} POOL;
+
+
+POOL PoolHead[EfiMaxMemoryType];
+EFI_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.
+
+--*/
+{
+ EFI_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_BOOTSERVICE
+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;
+ //
+ // As we need to reserve memory for other resources, we can't expect to allocate
+ // all memory( EFI_MAX_ADDRESS - POOL_OVERHEAD + 1) using this function,
+ // the following check operation is only used to make sure the allocated pool size will
+ // not rool over from a very large number to a very small number.
+ //
+ 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.
+
+ N.B. 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_SET_MEMORY (Buffer, Size - POOL_OVERHEAD);
+
+ DEBUG (
+ (EFI_D_POOL,
+ "AllcocatePoolI: Type %x, Addr %x (len %x) %,d\n",
+ (UINTN)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_BOOTSERVICE
+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.
+
+ N.B. 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, (UINTN)Head->Size - POOL_OVERHEAD, Pool->Used));
+
+ //
+ // Determine the pool list
+ //
+ Index = SIZE_TO_LIST(Size);
+ DEBUG_SET_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/EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.c b/EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.c
new file mode 100644
index 0000000..c1a81a3
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.c
@@ -0,0 +1,262 @@
+/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DebugImageInfo.c
+
+Abstract:
+
+ Support functions for managing debug image info table when loading and unloading
+ images.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "DebugImageInfo.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 UINT32 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
+ //
+ EfiCommonLibCopyMem (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 = 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/EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.h b/EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.h
new file mode 100644
index 0000000..a4e86e7
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Misc/DebugImageInfo.h
@@ -0,0 +1,129 @@
+/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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__
+
+#include EFI_PROTOCOL_DEFINITION(LoadedImage)
+#include EFI_GUID_DEFINITION(DebugImageInfoTable)
+
+#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 (
+ UINT32 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/EDK/Foundation/Core/Dxe/Misc/DebugMask.c b/EDK/Foundation/Core/Dxe/Misc/DebugMask.c
new file mode 100644
index 0000000..c2dee47
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Misc/DebugMask.c
@@ -0,0 +1,400 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DebugMask.c
+
+Abstract:
+
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "DebugMask.h"
+#include EFI_GUID_DEFINITION (GlobalVariable)
+
+extern UINTN mErrorLevel;
+static VOID *mVariableReadyNotify;
+
+VOID
+UpdateDebugMask (
+ EFI_EVENT Event,
+ VOID *Context
+ );
+
+EFI_STATUS
+EFIAPI
+GetDebugMask (
+ IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context
+ IN OUT UINTN *CurrentDebugMask // Ptr to store current debug mask
+ )
+/*++
+
+Routine Description:
+ DebugMask protocol member function.
+ Gets the current debug mask for an image, on which this protocol has been installed.
+
+Arguments:
+
+ This - Indicates calling context
+ CurrentDebugMask - Ptr to store current debug mask
+
+Returns:
+ EFI_SUCCESS - Debug mask is retrieved successfully
+ EFI_INVALID_PARAMETER - CurrentDebugMask is NULL.
+ EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle.
+
+--*/
+{
+ DEBUG_MASK_PRIVATE_DATA *Private;
+ //
+ // Check Parameter
+ //
+ if (CurrentDebugMask == NULL){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get Private Data
+ //
+ Private = DEBUG_MASK_PRIVATE_DATA_FROM_THIS(This);
+ *CurrentDebugMask = Private->ImageDebugMask;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+SetDebugMask (
+ IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context
+ IN UINTN NewDebugMask // New Debug Mask value to set
+ )
+/*++
+
+Routine Description:
+ DebugMask protocol member function.
+ Updates the current debug mask for an image, on which this protocol has been installed.
+
+Arguments:
+
+ This - Calling context
+ NewDebugMask - New Debug Mask value to set
+
+Returns:
+ EFI_SUCCESS - Debug mask is updated with the new value successfully
+ EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle.
+
+--*/
+{
+ DEBUG_MASK_PRIVATE_DATA *Private;
+ //
+ // Set Private Data
+ //
+ Private = DEBUG_MASK_PRIVATE_DATA_FROM_THIS(This);
+ Private->ImageDebugMask = NewDebugMask;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SetCoreDebugMask (
+ IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context
+ IN UINTN NewDebugMask // New Debug Mask value to set
+ )
+/*++
+
+Routine Description:
+ DebugMask protocol member function.
+ Updates the current debug mask for core.
+
+Arguments:
+
+ This - Calling context
+ NewDebugMask - New Debug Mask value to set
+
+Returns:
+ EFI_SUCCESS - Debug mask is updated with the new value successfully
+ EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle.
+
+--*/
+{
+ mErrorLevel = NewDebugMask;
+ return SetDebugMask(This, NewDebugMask);
+}
+
+EFI_STATUS
+InstallDebugMaskProtocol(
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will install on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadImageInterface;
+ DEBUG_MASK_PRIVATE_DATA *DebugMaskPrivate;
+
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check Image Handle
+ //
+ Status = CoreHandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID*)&LoadImageInterface
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Create Pool for Private Data
+ //
+ DebugMaskPrivate = CoreAllocateZeroBootServicesPool (sizeof (DEBUG_MASK_PRIVATE_DATA));
+
+ if (DebugMaskPrivate == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Fill in private data structure
+ //
+ DebugMaskPrivate->Signature = DEBUGMASK_PRIVATE_DATA_SIGNATURE;
+ DebugMaskPrivate->ImageDebugMask = mErrorLevel;
+ DebugMaskPrivate->DebugMaskInterface.Revision = EFI_DEBUG_MASK_REVISION;
+ DebugMaskPrivate->DebugMaskInterface.GetDebugMask = GetDebugMask;
+ DebugMaskPrivate->DebugMaskInterface.SetDebugMask = SetDebugMask;
+ //
+ // Install Debug Mask Protocol in Image Handle
+ //
+ Status = CoreInstallProtocolInterface (
+ &ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(DebugMaskPrivate->DebugMaskInterface)
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+UninstallDebugMaskProtocol(
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Uninstall debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will uninstall on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_SUCCESS - Debug mask protocol successfully uninstalled
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEBUG_MASK_PROTOCOL *DebugMaskInterface;
+ DEBUG_MASK_PRIVATE_DATA *DebugMaskPrivate;
+
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get Protocol from ImageHandle
+ //
+ Status = CoreHandleProtocol (
+ ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ (VOID*)&DebugMaskInterface
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DebugMaskPrivate = DEBUG_MASK_PRIVATE_DATA_FROM_THIS(DebugMaskInterface);
+ //
+ // Remove Protocol from ImageHandle
+ //
+ Status = CoreUninstallProtocolInterface (
+ ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ (VOID*)DebugMaskInterface
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Free Private Data Pool
+ //
+ Status = CoreFreePool(DebugMaskPrivate);
+ return Status;
+}
+
+EFI_STATUS
+InstallCoreDebugMaskProtocol(
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on core.
+
+Arguments:
+
+ ImageHandle - Core handle
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+{
+ EFI_DEBUG_MASK_PROTOCOL *DebugMaskInterface;
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = InstallDebugMaskProtocol(ImageHandle);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Check Image Handle
+ //
+ Status = CoreHandleProtocol (
+ ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ (VOID*)&DebugMaskInterface
+ );
+ if (EFI_ERROR(Status) || (DebugMaskInterface == NULL)) {
+ return Status;
+ }
+ DebugMaskInterface->SetDebugMask = SetCoreDebugMask;
+
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ UpdateDebugMask,
+ mVariableReadyNotify,
+ &Event
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = CoreRegisterProtocolNotify (
+ &gEfiVariableArchProtocolGuid,
+ Event,
+ &mVariableReadyNotify
+ );
+ }
+
+ return Status;
+}
+
+VOID
+UpdateDebugMask (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Event callback function to update the debug mask when the variable service is ready.
+
+Arguments:
+
+ Event - The Event
+ Context - The event's context
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN NoHandles;
+ EFI_STATUS Status;
+ UINTN DebugMask;
+ UINTN Index;
+ UINTN DataSize;
+ EFI_HANDLE *Buffer;
+ EFI_DEBUG_MASK_PROTOCOL *DebugMaskProtocol;
+
+ DataSize = sizeof(UINT32);
+ Status = gRT->GetVariable(
+ L"EFIDebug",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ &DebugMask
+ );
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ Status = CoreLocateHandleBuffer (
+ AllHandles,
+ &gEfiDebugMaskProtocolGuid,
+ NULL,
+ &NoHandles,
+ &Buffer
+ );
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ for (Index = 0; Index < NoHandles; Index ++) {
+ Status = CoreHandleProtocol (
+ Buffer[Index],
+ &gEfiDebugMaskProtocolGuid,
+ &DebugMaskProtocol
+ );
+ if (EFI_ERROR(Status) || (DebugMaskProtocol == NULL)) {
+ continue;
+ }
+ DebugMaskProtocol->SetDebugMask(DebugMaskProtocol, DebugMask);
+ }
+ CoreFreePool(Buffer);
+}
diff --git a/EDK/Foundation/Core/Dxe/Misc/DebugMask.h b/EDK/Foundation/Core/Dxe/Misc/DebugMask.h
new file mode 100644
index 0000000..18dbef5
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Misc/DebugMask.h
@@ -0,0 +1,122 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DebugMask.h
+
+Abstract:
+
+
+--*/
+
+#ifndef __DEBUG_MASK_INFO_H__
+#define __DEBUG_MASK_INFO_H__
+
+#include EFI_PROTOCOL_CONSUMER (DebugMask)
+
+//
+// local type definitions
+//
+#define DEBUGMASK_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('D','M','S','K')
+
+//
+// Private structure used by driver
+//
+typedef struct {
+ UINT32 Signature;
+ UINTN ImageDebugMask;
+ EFI_DEBUG_MASK_PROTOCOL DebugMaskInterface;
+}DEBUG_MASK_PRIVATE_DATA;
+
+#define DEBUG_MASK_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, DEBUG_MASK_PRIVATE_DATA, DebugMaskInterface, DEBUGMASK_PRIVATE_DATA_SIGNATURE)
+
+//
+// Internal DebugMask Procotol Install/Uninstall Function
+//
+EFI_STATUS
+InstallDebugMaskProtocol (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will install on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+;
+
+//
+// Internal DebugMask Procotol Install/Uninstall Function
+//
+EFI_STATUS
+InstallCoreDebugMaskProtocol (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on Dxe Core.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will install on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+;
+
+EFI_STATUS
+UninstallDebugMaskProtocol (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Uninstall debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will uninstall on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_SUCCESS - Debug mask protocol successfully uninstalled
+
+--*/
+;
+
+#endif
diff --git a/EDK/Foundation/Core/Dxe/Misc/InstallConfigurationTable.c b/EDK/Foundation/Core/Dxe/Misc/InstallConfigurationTable.c
new file mode 100644
index 0000000..8aea9bc
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Misc/InstallConfigurationTable.c
@@ -0,0 +1,230 @@
+/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ InstallConfigurationTable.c
+
+
+Abstract:
+
+ Tiano Miscellaneous Services InstallConfigurationTable service
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.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 (EfiCompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) {
+ *Table = gST->ConfigurationTable[Index].VendorTable;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_BOOTSERVICE
+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 (EfiCompareGuid (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;
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // Signal Configuration Table change
+ //
+ CoreNotifySignalList (Guid);
+#endif
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // A match was found and Table is NULL, so this is a delete operation.
+ //
+ gST->NumberOfTableEntries--;
+
+ //
+ // Copy over deleted entry
+ //
+ EfiCommonLibCopyMem (
+ &(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.
+ //
+ EfiCommonLibCopyMem (
+ 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
+ //
+ EfiConfigurationTable[Index].VendorGuid = *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);
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // Signal Configuration Table change
+ //
+ CoreNotifySignalList (Guid);
+#endif
+
+ return EFI_SUCCESS;
+}
diff --git a/EDK/Foundation/Core/Dxe/Misc/SetWatchdogTimer.c b/EDK/Foundation/Core/Dxe/Misc/SetWatchdogTimer.c
new file mode 100644
index 0000000..2146137
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Misc/SetWatchdogTimer.c
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SetWatchdogTimer.c
+
+Abstract:
+
+ Tiano Miscellaneous Services SetWatchdogTimer service implementation
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+#define WATCHDOG_TIMER_CALIBRATE_PER_SECOND 10000000
+
+EFI_BOOTSERVICE
+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/EDK/Foundation/Core/Dxe/Misc/Stall.c b/EDK/Foundation/Core/Dxe/Misc/Stall.c
new file mode 100644
index 0000000..a87f894
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/Misc/Stall.c
@@ -0,0 +1,79 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Stall.c
+
+Abstract:
+
+ Tiano Miscellaneous Services Stall service implementation
+
+--*/
+
+//
+// Include statements
+//
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+EFI_BOOTSERVICE
+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;
+ UINTN 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) DivU64x32 ((Microseconds * 10), (UINTN) 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/EDK/Foundation/Core/Dxe/SectionExtraction/CoreSectionExtraction.c b/EDK/Foundation/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
new file mode 100644
index 0000000..f4e7727
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
@@ -0,0 +1,1387 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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 "Tiano.h"
+#include "DxeCore.h"
+#include "EfiFirmwareFileSystem.h"
+
+//
+// Comsumed protocol
+//
+#include EFI_PROTOCOL_DEFINITION (TianoDecompress)
+#include EFI_PROTOCOL_DEFINITION (GuidedSectionExtraction)
+
+//
+// Produced protocol
+//
+#include EFI_PROTOCOL_DEFINITION (SectionExtraction)
+
+//
+// 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;
+ EFI_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;
+ EFI_LIST_ENTRY Link;
+ UINTN StreamHandle;
+ UINT8 *StreamBuffer;
+ UINTN StreamLength;
+ EFI_LIST 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
+EFI_STATUS
+EFIAPI
+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
+//
+EFI_LIST 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) || (ChildNode == NULL)) {
+ 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;
+ }
+ }
+ EfiCommonLibCopyMem (*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;
+ EFI_LIST *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;
+ }
+
+ //
+ // ReadSection function of the FV protocol (FvReadFileSection) doesn't work for GUID defined sections
+ // (always returns EFI_NOT_FOUND). When this function is called from FvReadFileSection, SectionDefinitionGuid
+ // is always NULL. If SectionDefinitionGuid is NULL, return TRUE (the section type matches).
+ //
+ if (SearchType != EFI_SECTION_GUID_DEFINED || SectionDefinitionGuid == NULL) {
+ return TRUE;
+ }
+ GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);
+ return EfiCompareGuid (&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) || (CurrentChildNode == NULL)) {
+ 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.
+ //
+ EfiCommonLibCopyMem (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, &Decompress);
+ } else {
+ Status = CoreLocateProtocol (&gEfiCustomizedDecompressProtocolGuid, NULL, &Decompress);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status) || (Decompress == NULL)) {
+ //
+ // Failed to locate protocol 'Decompress'
+ //
+ CoreFreePool (Node);
+ CoreFreePool (NewStreamBuffer);
+ return 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, &GuidedExtraction);
+ if (!EFI_ERROR (Status) && (GuidedExtraction != NULL)) {
+ //
+ // 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.
+ //
+ Status = CreateGuidedExtractionRpnEvent (Stream, Node);
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (Node);
+ return Status;
+ }
+ }
+
+ 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
+EFI_STATUS
+EFIAPI
+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:
+ EFI_SUCCESS: Event created successfully
+ EFI_OUT_OF_RESOURCES: Could not allocate needed resources
+
+--*/
+{
+ RPN_EVENT_CONTEXT *Context;
+
+ //
+ // Allocate new event structure and context
+ //
+ Context = CoreAllocateBootServicesPool (sizeof (RPN_EVENT_CONTEXT));
+ ASSERT (Context != NULL);
+ if (Context == NULL) {
+ //
+ // Failed to allocate memory for 'Context'
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Context->ChildNode = ChildNode;
+ Context->ParentStream = ParentStream;
+
+ Context->Event = CoreCreateProtocolNotifyEvent (
+ Context->ChildNode->EncapsulationGuid,
+ EFI_TPL_NOTIFY,
+ NotifyGuidedExtraction,
+ Context,
+ &Context->Registration,
+ FALSE
+ );
+ return EFI_SUCCESS;
+}
+
+
+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, &GuidedExtraction);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status) || (GuidedExtraction == NULL)) {
+ //
+ // Failed to locate protocol 'GuidedExtraction'
+ //
+ CoreCloseEvent (Event);
+ CoreFreePool (Context);
+ return;
+ }
+
+ 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
+ //
+ EfiCommonLibCopyMem (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/EDK/Foundation/Core/Dxe/x64/Processor.h b/EDK/Foundation/Core/Dxe/x64/Processor.h
new file mode 100644
index 0000000..cdf2992
--- /dev/null
+++ b/EDK/Foundation/Core/Dxe/x64/Processor.h
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Processor.h
+
+Abstract:
+ This file contains the x64 processor specific definitions
+
+--*/
+
+#ifndef _PROCESSOR_H_
+#define _PROCESSOR_H_
+
+#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE)
+
+#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE)
+
+#endif