summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Core/DxeIplPeim
diff options
context:
space:
mode:
authorqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>2006-11-27 10:14:02 +0000
committerqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>2006-11-27 10:14:02 +0000
commitabb26634f230fb703906f46e7e7adebc9124214a (patch)
treecf08cb43b6a21d52ed620f47c6157f1436da09f9 /EdkModulePkg/Core/DxeIplPeim
parentad3e8660d37e30ccf2e78aafced1f194e3593a30 (diff)
downloadedk2-platforms-abb26634f230fb703906f46e7e7adebc9124214a.tar.xz
Introduce PcdDxeIplSwitchToLongMode to DxeIplPeim and remove DxeIplX64Peim.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2018 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Core/DxeIplPeim')
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIpl.h7
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa51
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/DxeLoad.c469
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c2
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c2
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S296
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.asm294
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c160
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h86
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c2
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c2
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Non-existing.c55
12 files changed, 1187 insertions, 239 deletions
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h
index 9e626a7dc7..f8fd8766ab 100644
--- a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h
@@ -23,6 +23,8 @@ Abstract:
#define STACK_SIZE 0x20000
#define BSP_STORE_SIZE 0x4000
+#define GET_OCCUPIED_SIZE(ActualSize, Alignment) ((ActualSize + (Alignment - 1)) & ~(Alignment - 1))
+
extern BOOLEAN gInMemory;
/**
@@ -125,8 +127,9 @@ DxeLoadCore (
EFI_STATUS
PeiProcessFile (
IN UINT16 SectionType,
- IN OUT EFI_FFS_FILE_HEADER **RealFfsFileHeader,
- OUT VOID **Pe32Data
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ OUT VOID **Pe32Data,
+ IN EFI_PEI_HOB_POINTERS *OrigHob
);
EFI_STATUS
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa
index c3042e1186..31b7b358ee 100644
--- a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0">
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MsaHeader>
<ModuleName>DxeIpl</ModuleName>
<ModuleType>PEIM</ModuleType>
@@ -8,11 +8,11 @@
<Abstract>Component description file for DxeIpl module</Abstract>
<Description>The responsibility of this module is to load the DXE Core from a Firmware Volume. This implementation i used to load a 32-bit DXE Core.</Description>
<Copyright>Copyright (c) 2006, Intel Corporation</Copyright>
- <License>All rights reserved. This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
</MsaHeader>
@@ -67,6 +67,9 @@
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>MemoryAllocationLib</Keyword>
</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PcdLib</Keyword>
+ </LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>DxeLoad.c</Filename>
@@ -74,12 +77,17 @@
<Filename>DxeIpl.dxs</Filename>
<Filename SupArchList="IA32">Ia32/ImageRead.c</Filename>
<Filename SupArchList="IA32">Ia32/DxeLoadFunc.c</Filename>
+ <Filename SupArchList="IA32">Ia32/LongMode.asm</Filename>
+ <Filename ToolChainFamily="GCC" SupArchList="IA32">Ia32/LongMode.S</Filename>
+ <Filename SupArchList="IA32">Ia32/VirtualMemory.c</Filename>
+ <Filename SupArchList="IA32">Ia32/VirtualMemory.h</Filename>
<Filename SupArchList="X64">Ia32/ImageRead.c</Filename>
<Filename SupArchList="X64">Ia32/DxeLoadFunc.c</Filename>
<Filename SupArchList="IPF">ipf/ImageRead.c</Filename>
<Filename SupArchList="IPF">ipf/DxeLoadFunc.c</Filename>
<Filename SupArchList="EBC">Ia32/ImageRead.c</Filename>
<Filename SupArchList="EBC">Ia32/DxeLoadFunc.c</Filename>
+ <Filename SupArchList="X64 IPF EBC">Non-existing.c</Filename>
</SourceFiles>
<PackageDependencies>
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
@@ -118,9 +126,6 @@
<Ppi Usage="SOMETIMES_CONSUMED">
<PpiCName>gEfiPeiSecurityPpiGuid</PpiCName>
</Ppi>
- <Ppi Usage="PRIVATE">
- <PpiCName>gPeiInMemoryGuid</PpiCName>
- </Ppi>
</PPIs>
<Guids>
<GuidCNames Usage="SOMETIMES_CONSUMED">
@@ -134,4 +139,30 @@
<ModuleEntryPoint>PeimInitializeDxeIpl</ModuleEntryPoint>
</Extern>
</Externs>
+ <PcdCoded>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdDxeIplSwitchToLongMode</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>FALSE</DefaultValue>
+ <HelpText>If this feature is enabled, then the DXE IPL will load a 64-bit DxeCore.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdDxeIplSupportEfiDecompress</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>TRUE</DefaultValue>
+ <HelpText>If this feature is enabled, then the DXE IPL must support decompressing files compressed with the EFI Compression algorithm</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdDxeIplSupportTianoDecompress</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>TRUE</DefaultValue>
+ <HelpText>If this feature is enabled, then the DXE IPL must support decompressing files compressed with the Tiano Compression algorithm</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdDxeIplSupportCustomDecompress</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <DefaultValue>TRUE</DefaultValue>
+ <HelpText>If this feature is enabled, then the DXE IPL must support decompressing files compressed with the Custom Compression algorithm</HelpText>
+ </PcdEntry>
+ </PcdCoded>
</ModuleSurfaceArea> \ No newline at end of file
diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c b/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
index fdd6c24b2e..8c3de0522d 100644
--- a/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
+++ b/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -20,7 +20,11 @@ Abstract:
--*/
-#include <DxeIpl.h>
+#include "DxeIpl.h"
+
+#ifndef __GNUC__
+#pragma warning( disable : 4305 )
+#endif
BOOLEAN gInMemory = FALSE;
@@ -36,22 +40,17 @@ static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {
DxeIplLoadFile
};
-static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
&gEfiPeiFvFileLoaderPpiGuid,
&mLoadFilePpi
-};
-
-static EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ },
+ {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiDxeIplPpiGuid,
&mDxeIplPpi
-};
-
-static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gPeiInMemoryGuid,
- NULL
+ }
};
static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {
@@ -60,38 +59,21 @@ static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {
NULL
};
-DECOMPRESS_LIBRARY gEfiDecompress = {
+GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress = {
UefiDecompressGetInfo,
UefiDecompress
};
-DECOMPRESS_LIBRARY gTianoDecompress = {
+GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress = {
TianoDecompressGetInfo,
TianoDecompress
};
-DECOMPRESS_LIBRARY gCustomDecompress = {
+GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress = {
CustomDecompressGetInfo,
CustomDecompress
};
-STATIC
-UINTN
-GetOccupiedSize (
- IN UINTN ActualSize,
- IN UINTN Alignment
- )
-{
- UINTN OccupiedSize;
-
- OccupiedSize = ActualSize;
- while ((OccupiedSize & (Alignment - 1)) != 0) {
- OccupiedSize++;
- }
-
- return OccupiedSize;
-}
-
EFI_STATUS
EFIAPI
PeimInitializeDxeIpl (
@@ -120,17 +102,9 @@ Returns:
EFI_BOOT_MODE BootMode;
Status = PeiServicesGetBootMode (&BootMode);
-
ASSERT_EFI_ERROR (Status);
- Status = PeiServicesLocatePpi (
- &gPeiInMemoryGuid,
- 0,
- NULL,
- NULL
- );
-
- if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) {
+ if (!gInMemory && (BootMode != BOOT_ON_S3_RESUME)) {
//
// The DxeIpl has not yet been shadowed
//
@@ -140,38 +114,15 @@ Returns:
// Shadow DxeIpl and then re-run its entry point
//
Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
} else {
- if (BootMode != BOOT_ON_S3_RESUME) {
//
- // The DxeIpl has been shadowed
+ // Install FvFileLoader and DxeIpl PPIs.
//
- gInMemory = TRUE;
-
- //
- // Install LoadFile PPI
- //
- Status = PeiServicesInstallPpi (&mPpiLoadFile);
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
- //
- // Install DxeIpl PPI
- //
- PeiServicesInstallPpi (&mPpiList);
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
+ Status = PeiServicesInstallPpi (mPpiList);
+ ASSERT_EFI_ERROR(Status);
}
-
- return EFI_SUCCESS;
+
+ return Status;
}
EFI_STATUS
@@ -200,12 +151,13 @@ Returns:
--*/
{
EFI_STATUS Status;
- VOID *TopOfStack;
- VOID *BaseOfStack;
+ EFI_PHYSICAL_ADDRESS TopOfStack;
+ EFI_PHYSICAL_ADDRESS BaseOfStack;
EFI_PHYSICAL_ADDRESS BspStore;
EFI_GUID DxeCoreFileName;
EFI_GUID FirmwareFileName;
VOID *Pe32Data;
+ VOID *FvImageData;
EFI_PHYSICAL_ADDRESS DxeCoreAddress;
UINT64 DxeCoreSize;
EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;
@@ -213,104 +165,32 @@ Returns:
EFI_BOOT_MODE BootMode;
EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;
EFI_PEI_S3_RESUME_PPI *S3Resume;
+ EFI_PHYSICAL_ADDRESS PageTables;
// PERF_START (PeiServices, L"DxeIpl", NULL, 0);
- TopOfStack = NULL;
- BaseOfStack = NULL;
+ TopOfStack = 0;
+ BaseOfStack = 0;
BspStore = 0;
- Status = EFI_SUCCESS;
+ PageTables = 0;
//
// if in S3 Resume, restore configure
//
Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR(Status);
- if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {
+ if (BootMode == BOOT_ON_S3_RESUME) {
Status = PeiServicesLocatePpi (
&gEfiPeiS3ResumePpiGuid,
0,
NULL,
(VOID **)&S3Resume
);
-
ASSERT_EFI_ERROR (Status);
Status = S3Resume->S3RestoreConfig (PeiServices);
-
ASSERT_EFI_ERROR (Status);
- }
-
- Status = EFI_SUCCESS;
-
- //
- // Install the PEI Protocols that are shared between PEI and DXE
- //
- PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
- ASSERT (PeiEfiPeiPeCoffLoader != NULL);
-
-
- //
- // Allocate 128KB for the Stack
- //
- BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
- ASSERT (BaseOfStack != NULL);
-
- //
- // Compute the top of the stack we were allocated. Pre-allocate a UINTN
- // for safety.
- //
- TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
- TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
-
- //
- // Add architecture-specifc HOBs (including the BspStore HOB)
- //
- Status = CreateArchSpecificHobs (&BspStore);
-
- ASSERT_EFI_ERROR (Status);
-
- //
- // Add HOB for the EFI Decompress Protocol
- //
- BuildGuidDataHob (
- &gEfiDecompressProtocolGuid,
- (VOID *)&gEfiDecompress,
- sizeof (gEfiDecompress)
- );
-
- //
- // Add HOB for the Tiano Decompress Protocol
- //
- BuildGuidDataHob (
- &gEfiTianoDecompressProtocolGuid,
- (VOID *)&gTianoDecompress,
- sizeof (gTianoDecompress)
- );
-
- //
- // Add HOB for the user customized Decompress Protocol
- //
- BuildGuidDataHob (
- &gEfiCustomizedDecompressProtocolGuid,
- (VOID *)&gCustomDecompress,
- sizeof (gCustomDecompress)
- );
-
- //
- // Add HOB for the PE/COFF Loader Protocol
- //
- BuildGuidDataHob (
- &gEfiPeiPeCoffLoaderGuid,
- (VOID *)&PeiEfiPeiPeCoffLoader,
- sizeof (VOID *)
- );
-
- //
- // See if we are in crisis recovery
- //
- Status = PeiServicesGetBootMode (&BootMode);
-
- if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) {
+ } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
Status = PeiServicesLocatePpi (
&gEfiPeiRecoveryModulePpiGuid,
@@ -318,8 +198,8 @@ Returns:
NULL,
(VOID **)&PeiRecovery
);
-
ASSERT_EFI_ERROR (Status);
+
Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
@@ -332,19 +212,34 @@ Returns:
}
//
- // Find the EFI_FV_FILETYPE_RAW type compressed Firmware Volume file in FTW spare block
+ // Install the PEI Protocols that are shared between PEI and DXE
+ //
+ PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
+ ASSERT (PeiEfiPeiPeCoffLoader != NULL);
+
+ //
+ // Allocate 128KB for the Stack
+ //
+ PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
+ ASSERT (BaseOfStack != 0);
+
+ //
+ // Add architecture-specifc HOBs (including the BspStore HOB)
+ //
+ Status = CreateArchSpecificHobs (&BspStore);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
// The file found will be processed by PeiProcessFile: It will first be decompressed to
- // a normal FV, then a corresponding FV type hob will be built which is provided for DXE
- // core to find and dispatch drivers in this FV. Because PeiProcessFile typically checks
- // for EFI_FV_FILETYPE_DXE_CORE type file, in this condition we need not check returned
- // status
+ // a normal FV, then a corresponding FV type hob will be built.
//
Status = PeiFindFile (
- EFI_FV_FILETYPE_RAW,
- EFI_SECTION_PE32,
- &FirmwareFileName,
- &Pe32Data
- );
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
+ EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+ &FirmwareFileName,
+ &FvImageData
+ );
//
// Find the DXE Core in a Firmware Volume
@@ -355,20 +250,18 @@ Returns:
&DxeCoreFileName,
&Pe32Data
);
-
ASSERT_EFI_ERROR (Status);
//
// Load the DXE Core from a Firmware Volume
//
Status = PeiLoadFile (
- PeiEfiPeiPeCoffLoader,
- Pe32Data,
- &DxeCoreAddress,
- &DxeCoreSize,
- &DxeCoreEntryPoint
- );
-
+ PeiEfiPeiPeCoffLoader,
+ Pe32Data,
+ &DxeCoreAddress,
+ &DxeCoreSize,
+ &DxeCoreEntryPoint
+ );
ASSERT_EFI_ERROR (Status);
//
@@ -377,7 +270,6 @@ Returns:
//
Status = PeiServicesInstallPpi (&mPpiSignal);
-
ASSERT_EFI_ERROR (Status);
//
@@ -399,14 +291,93 @@ Returns:
);
DEBUG ((EFI_D_INFO, "DXE Core Entry\n"));
- SwitchIplStacks (
- (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
- HobList.Raw,
- NULL,
- TopOfStack,
- (VOID *) (UINTN) BspStore
- );
+ if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {
+ //
+ // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
+ // Pre-allocate a 32 bytes which confroms to x64 calling convention.
+ //
+ // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
+ // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
+ // register parameters is reserved on the stack, in case the called function
+ // wants to spill them; this is important if the function is variadic.
+ //
+ TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;
+
+ //
+ // X64 Calling Conventions requires that the stack must be aligned to 16 bytes
+ //
+ TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);
+ //
+ // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
+ // memory, it may be corrupted when copying FV to high-end memory
+ //
+ LoadGo64Gdt();
+ //
+ // Limit to 36 bits of addressing for debug. Should get it from CPU
+ //
+ PageTables = CreateIdentityMappingPageTables (36);
+ //
+ // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
+ // Call x64 drivers passing in single argument, a pointer to the HOBs.
+ //
+ ActivateLongMode (
+ PageTables,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),
+ TopOfStack,
+ 0x00000000,
+ DxeCoreEntryPoint
+ );
+ } else {
+ //
+ // Add HOB for the EFI Decompress Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiDecompressProtocolGuid,
+ (VOID *)&gEfiDecompress,
+ sizeof (gEfiDecompress)
+ );
+ //
+ // Add HOB for the Tiano Decompress Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiTianoDecompressProtocolGuid,
+ (VOID *)&gTianoDecompress,
+ sizeof (gTianoDecompress)
+ );
+
+ //
+ // Add HOB for the user customized Decompress Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiCustomizedDecompressProtocolGuid,
+ (VOID *)&gCustomDecompress,
+ sizeof (gCustomDecompress)
+ );
+
+ //
+ // Add HOB for the PE/COFF Loader Protocol
+ //
+ BuildGuidDataHob (
+ &gEfiPeiPeCoffLoaderGuid,
+ (VOID *)&PeiEfiPeiPeCoffLoader,
+ sizeof (VOID *)
+ );
+ //
+ // Compute the top of the stack we were allocated. Pre-allocate a UINTN
+ // for safety.
+ //
+ TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;
+ TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
+
+ SwitchIplStacks (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
+ HobList.Raw,
+ NULL,
+ (VOID *) (UINTN) TopOfStack,
+ (VOID *) (UINTN) BspStore
+ );
+ }
//
// If we get here, then the DXE Core returned. This is an error
// Dxe Core should not return.
@@ -462,10 +433,11 @@ Returns:
FwVolHeader = NULL;
FfsFileHeader = NULL;
SectionData = NULL;
+ Status = EFI_SUCCESS;
//
- // Foreach Firmware Volume, look for a specified type
- // of file and break out when one is found
+ // For each Firmware Volume, look for a specified type
+ // of file and break out until no one is found
//
Hob.Raw = GetHobList ();
while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {
@@ -478,11 +450,14 @@ Returns:
if (!EFI_ERROR (Status)) {
Status = PeiProcessFile (
SectionType,
- &FfsFileHeader,
- Pe32Data
+ FfsFileHeader,
+ Pe32Data,
+ &Hob
);
CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));
- return Status;
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
}
Hob.Raw = GET_NEXT_HOB (Hob);
}
@@ -608,7 +583,7 @@ Returns:
while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) {
SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
- OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
+ OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
}
//
@@ -624,14 +599,9 @@ Returns:
if (Status == EFI_SUCCESS) {
//
- // Install PeiInMemory to indicate the Dxeipl is shadowed
+ // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.
//
- Status = PeiServicesInstallPpi (&mPpiPeiInMemory);
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
+ *(BOOLEAN *) ((UINTN) &gInMemory + (UINTN) DxeIplEntryPoint - (UINTN) _ModuleEntryPoint) = TRUE;
Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());
}
@@ -689,8 +659,9 @@ Returns:
//
Status = PeiProcessFile (
EFI_SECTION_PE32,
- &FfsHeader,
- &Pe32Data
+ FfsHeader,
+ &Pe32Data,
+ NULL
);
if (EFI_ERROR (Status)) {
@@ -713,8 +684,9 @@ Returns:
EFI_STATUS
PeiProcessFile (
IN UINT16 SectionType,
- IN OUT EFI_FFS_FILE_HEADER **RealFfsFileHeader,
- OUT VOID **Pe32Data
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ OUT VOID **Pe32Data,
+ IN EFI_PEI_HOB_POINTERS *OrigHob
)
/*++
@@ -762,9 +734,7 @@ Returns:
EFI_GUID TempGuid;
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
EFI_COMPRESSION_SECTION *CompressionSection;
- EFI_FFS_FILE_HEADER *FfsFileHeader;
-
- FfsFileHeader = *RealFfsFileHeader;
+ UINT32 FvAlignment;
Status = PeiServicesFfsFindSectionData (
EFI_SECTION_COMPRESSION,
@@ -773,7 +743,7 @@ Returns:
);
//
- // Upon finding a DXE Core file, see if there is first a compression section
+ // First process the compression section
//
if (!EFI_ERROR (Status)) {
//
@@ -784,7 +754,7 @@ Returns:
do {
SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
- OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
+ OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
//
// Was the DXE Core file encapsulated in a GUID'd section?
@@ -881,14 +851,24 @@ Returns:
switch (CompressionSection->CompressionType) {
case EFI_STANDARD_COMPRESSION:
- DecompressLibrary = &gTianoDecompress;
+ if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) {
+ DecompressLibrary = &gTianoDecompress;
+ } else {
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
break;
case EFI_CUSTOMIZED_COMPRESSION:
//
// Load user customized compression protocol.
//
- DecompressLibrary = &gCustomDecompress;
+ if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) {
+ DecompressLibrary = &gCustomDecompress;
+ } else {
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
break;
case EFI_NOT_COMPRESSED:
@@ -939,31 +919,64 @@ Returns:
);
CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;
- if (CmpSection->Type == EFI_SECTION_RAW) {
- //
- // Skip the section header and
- // adjust the pointer alignment to 16
+ if (CmpSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
+ //
+ // Firmware Volume Image in this Section
+ // Skip the section header to get FvHeader
//
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16);
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);
- if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
- FfsFileHeader = NULL;
+ if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
+ //
+ // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
+ //
+
+ //
+ // When FvImage support Alignment, we need to check whether
+ // its alignment is correct.
+ //
+ if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) {
+
+ //
+ // Calculate the mini alignment for this FvImage
+ //
+ FvAlignment = 1 << (LowBitSet32 (FvHeader->Attributes >> 16) + 1);
+
+ //
+ // If current FvImage base address doesn't meet the its alignment,
+ // we need to reload this FvImage to another correct memory address.
+ //
+ if (((UINTN) FvHeader % FvAlignment) != 0) {
+ DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), FvAlignment);
+ if (DstBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (DstBuffer, FvHeader, (UINTN) FvHeader->FvLength);
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;
+ }
+ }
+ //
+ // Build new FvHob for new decompressed Fv image.
+ //
BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);
- Status = PeiServicesFfsFindNextFile (
- EFI_FV_FILETYPE_DXE_CORE,
- FvHeader,
- &FfsFileHeader
- );
-
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
+
+ //
+ // Set the original FvHob to unused.
+ //
+ if (OrigHob != NULL) {
+ OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;
}
-
+
//
- // Reture the FfsHeader that contain Pe32Data.
+ // when search FvImage Section return true.
//
- *RealFfsFileHeader = FfsFileHeader;
- return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data);
+ if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
+ *Pe32Data = (VOID *) FvHeader;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+
}
}
//
@@ -982,10 +995,13 @@ Returns:
return EFI_SUCCESS;
}
- OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4);
+ OccupiedCmpSectionLength = GET_OCCUPIED_SIZE (CmpSectionLength, 4);
CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);
} while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);
}
+ //
+ // End of the decompression activity
+ //
Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
FileSize = FfsFileHeader->Size[0] & 0xFF;
@@ -993,11 +1009,17 @@ Returns:
FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;
FileSize &= 0x00FFFFFF;
} while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);
-
+
//
- // End of the decompression activity
+ // search all sections (compression and non compression) in this FFS, don't
+ // find expected section.
//
+ return EFI_NOT_FOUND;
} else {
+ //
+ // For those FFS that doesn't contain compression section, directly search
+ // PE or TE section in this FFS.
+ //
Status = PeiServicesFfsFindSectionData (
EFI_SECTION_PE32,
@@ -1021,3 +1043,4 @@ Returns:
return EFI_SUCCESS;
}
+
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index 0aa323ec2f..28e980517a 100644
--- a/EdkModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/EdkModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -19,7 +19,7 @@ Abstract:
--*/
-#include <DxeIpl.h>
+#include "DxeIpl.h"
EFI_STATUS
CreateArchSpecificHobs (
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c
index fe07608290..b4bd64067c 100644
--- a/EdkModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c
+++ b/EdkModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c
@@ -17,7 +17,7 @@ Abstract:
--*/
-#include <DxeIpl.h>
+#include "DxeIpl.h"
EFI_STATUS
EFIAPI
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S b/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S
new file mode 100644
index 0000000000..273b3d5bc2
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S
@@ -0,0 +1,296 @@
+#------------------------------------------------------------------------------
+#*
+#* Copyright (c) 2006, Intel Corporation
+#* All rights reserved. This program and the accompanying materials
+#* are licensed and made available under the terms and conditions of the BSD License
+#* which accompanies this distribution. The full text of the license may be found at
+#* http://opensource.org/licenses/bsd-license.php
+#*
+#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#*
+#* LongMode.S
+#*
+#* Abstract:
+#*
+#* Transition from 32-bit protected mode EFI environment into x64
+#* 64-bit bit long mode.
+#*
+#* This file is not fully ported or operational.
+#*
+#------------------------------------------------------------------------------
+
+.686p:
+#.MODEL flat
+
+#
+# Create the exception handler code in IA32 C code
+#
+
+.code:
+.stack:
+.MMX:
+.XMM:
+
+.global _LoadGo64Gdt;
+_LoadGo64Gdt:
+ pushl %ebp # C prolog
+ pushl %edi
+ movl %esp, %ebp
+ #
+ # Disable interrupts
+ #
+ cli
+ #
+ # Reload the selectors
+ # Note:
+ # Make the Selectors 64-bit ready
+ #
+ movl gdtr, %edi # Load GDT register
+ movw %cs, %ax # Get the selector data from our code image
+ mov %ax, %es
+# FIXME MISMATCH: " lgdt FWORD PTR es:[edi] "
+
+ .byte 0x67
+ .byte 0xea # Far Jump Offset:Selector to reload CS
+# FIXME MISMATCH: " dd OFFSET DataSelectorRld"
+# FIXME MISMATCH: " dw LINEAR_CODE_SEL "
+DataSelectorRld:
+ movw SYS_DATA_SEL, %ax # Update the Base for the new selectors, too
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ popl %edi
+ popl %ebp
+ ret
+#_LoadGo64Gdt ENDP
+
+
+# VOID
+# ActivateLongMode (
+# IN EFI_PHYSICAL_ADDRESS PageTables,
+# IN EFI_PHYSICAL_ADDRESS HobStart,
+# IN EFI_PHYSICAL_ADDRESS Stack,
+# IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint,
+# IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
+# )
+#
+# Input: [ebp][0h] = Original ebp
+# [ebp][4h] = Return address
+# [ebp][8h] = PageTables
+# [ebp][10h] = HobStart
+# [ebp][18h] = Stack
+# [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer)
+# [ebp][28h] = CodeEntryPoint2 <--- Call this second
+#
+#
+.global _ActivateLongMode;
+_ActivateLongMode:
+ pushl %ebp # C prolog
+ movl %esp, %ebp
+
+ #
+ # Use CPUID to determine if the processor supports long mode.
+ #
+ movl $0x80000000, %eax # Extended-function code 8000000h.
+ cpuid # Is largest extended function
+ cmpl $0x80000000, %eax # any function > 80000000h?
+ jbe no_long_mode # If not, no long mode.
+ movl $0x80000001, %eax # Extended-function code 8000001h.
+ cpuid # Now EDX = extended-features flags.
+ btl $29, %edx # Test if long mode is supported.
+ jnc no_long_mode # Exit if not supported.
+
+ #
+ # Enable the 64-bit page-translation-table entries by
+ # setting CR4.PAE=1 (this is _required_ before activating
+ # long mode). Paging is not enabled until after long mode
+ # is enabled.
+ #
+ movl %cr4, %eax
+ btsl $5, %eax
+ movl %eax, %cr4
+
+ #
+ # Get the long-mode page tables, and initialize the
+ # 64-bit CR3 (page-table base address) to point to the base
+ # of the PML4 page table. The PML4 page table must be located
+ # below 4 Gbytes because only 32 bits of CR3 are loaded when
+ # the processor is not in 64-bit mode.
+ #
+ movl 0x8(%ebp), %eax # Get Page Tables
+ movl %eax, %cr3 # Initialize CR3 with PML4 base.
+
+ #
+ # Enable long mode (set EFER.LME=1).
+ #
+ movl $0xc0000080, %ecx # EFER MSR number.
+ rdmsr # Read EFER.
+ btsl $8, %eax # Set LME=1.
+ wrmsr # Write EFER.
+
+ #
+ # Enable paging to activate long mode (set CR0.PG=1)
+ #
+
+
+ movl %cr0, %eax # Read CR0.
+ btsl $31, %eax # Set PG=1.
+ movl %eax, %cr0 # Write CR0.
+ jmp go_to_long_mode
+go_to_long_mode:
+
+ #
+ # This is the next instruction after enabling paging. Jump to long mode
+ #
+ .byte 0x67
+ .byte 0xea # Far Jump Offset:Selector to reload CS
+#FIXME MISMATCH: " dd OFFSET in_long_mode"
+#FIXME MISMATCH: " dw SYS_CODE64_SEL "
+in_long_mode:
+ movw SYS_DATA64_SEL, %ax
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %ds
+ jmp .
+
+
+ #
+ # We're in long mode, so marshall the arguments to call the
+ # passed in function pointers
+ # Recall
+ # [ebp][10h] = HobStart
+ # [ebp][18h] = Stack
+ # [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
+ # [ebp][28h] = DxeCoreEntryPoint <--- Call this second
+ #
+ .byte 0x48
+ movl 0x18(%ebp), %ebx # Setup the stack
+ .byte 0x48
+ movl %ebx, %esp # On a new stack now
+
+
+## 00000905 FF D0 call rax
+
+ .byte 0x48
+ movl 0x10(%ebp), %ecx # Pass Hob Start in RCX
+ .byte 0x48
+ movl 0x28(%ebp), %eax # Get the function pointer for
+ # DxeCoreEntryPoint into EAX
+
+## 00000905 FF D0 call rax
+ .byte 0xff
+ .byte 0xd0
+
+ #
+ # WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
+ #
+no_long_mode:
+ jmp no_long_mode
+#_ActivateLongMode ENDP
+
+ .align 16
+
+gdtr: #FIXME MISMATCH: "gdtr dw _GDT_END - _GDT_BASE - 1 "
+#FIXME MISMATCH: " dd OFFSET _GDT_BASE "
+
+#-----------------------------------------------------------------------------;
+# global descriptor table (GDT)
+#-----------------------------------------------------------------------------;
+
+ .align 16
+
+.global _GDT_BASE
+_GDT_BASE:
+# null descriptor
+.equ NULL_SEL, .-_GDT_BASE # Selector [0]
+ .word 0 # limit 15:0
+ .word 0 # base 15:0
+ .byte 0 # base 23:16
+ .byte 0 # type
+ .byte 0 # limit 19:16, flags
+ .byte 0 # base 31:24
+
+# linear data segment descriptor
+.equ LINEAR_SEL, .-_GDT_BASE # Selector [0x8]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# linear code segment descriptor
+.equ LINEAR_CODE_SEL, .-_GDT_BASE # Selector [0x10]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9F # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system data segment descriptor
+.equ SYS_DATA_SEL, .-_GDT_BASE # Selector [0x18]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x93 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system code segment descriptor
+.equ SYS_CODE_SEL, .-_GDT_BASE # Selector [0x20]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+.equ SPARE3_SEL, .-_GDT_BASE # Selector [0x28]
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+#
+# system data segment descriptor
+#
+.equ SYS_DATA64_SEL, .-_GDT_BASE # Selector [0x30]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # P | DPL [1..2] | 1 | 1 | C | R | A
+ .byte 0xCF # G | D | L | AVL | Segment [19..16]
+ .byte 0
+
+#
+# system code segment descriptor
+#
+.equ SYS_CODE64_SEL, .-_GDT_BASE # Selector [0x38]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # P | DPL [1..2] | 1 | 1 | C | R | A
+ .byte 0xAF # G | D | L | AVL | Segment [19..16]
+ .byte 0
+
+# spare segment descriptor
+.equ SPARE4_SEL, .-_GDT_BASE # Selector [0x40]
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+_GDT_END:
+
+
+
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.asm b/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.asm
new file mode 100644
index 0000000000..a241273048
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.asm
@@ -0,0 +1,294 @@
+ TITLE LongMode.asm: Assembly code for the entering long mode
+
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2006, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* LongMode.asm
+;*
+;* Abstract:
+;*
+;* Transition from 32-bit protected mode EFI environment into x64
+;* 64-bit bit long mode.
+;*
+;------------------------------------------------------------------------------
+
+.686p
+.model flat
+
+;
+; Create the exception handler code in IA32 C code
+;
+
+.code
+.stack
+.MMX
+.XMM
+
+_LoadGo64Gdt PROC Near Public
+ push ebp ; C prolog
+ push edi
+ mov ebp, esp
+ ;
+ ; Disable interrupts
+ ;
+ cli
+ ;
+ ; Reload the selectors
+ ; Note:
+ ; Make the Selectors 64-bit ready
+ ;
+ mov edi, OFFSET gdtr ; Load GDT register
+ mov ax,cs ; Get the selector data from our code image
+ mov es,ax
+ lgdt FWORD PTR es:[edi] ; and update the GDTR
+
+ db 067h
+ db 0eah ; Far Jump Offset:Selector to reload CS
+ dd OFFSET DataSelectorRld; Offset is ensuing instruction boundary
+ dw LINEAR_CODE_SEL ; Selector is our code selector, 10h
+DataSelectorRld::
+ mov ax, SYS_DATA_SEL ; Update the Base for the new selectors, too
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ pop edi
+ pop ebp
+ ret
+_LoadGo64Gdt endp
+
+
+; VOID
+; ActivateLongMode (
+; IN EFI_PHYSICAL_ADDRESS PageTables,
+; IN EFI_PHYSICAL_ADDRESS HobStart,
+; IN EFI_PHYSICAL_ADDRESS Stack,
+; IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint,
+; IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
+; )
+;
+; Input: [ebp][0h] = Original ebp
+; [ebp][4h] = Return address
+; [ebp][8h] = PageTables
+; [ebp][10h] = HobStart
+; [ebp][18h] = Stack
+; [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer)
+; [ebp][28h] = CodeEntryPoint2 <--- Call this second
+;
+;
+_ActivateLongMode PROC Near Public
+ push ebp ; C prolog
+ mov ebp, esp
+
+ ;
+ ; Use CPUID to determine if the processor supports long mode.
+ ;
+ mov eax, 80000000h ; Extended-function code 8000000h.
+ cpuid ; Is largest extended function
+ cmp eax, 80000000h ; any function > 80000000h?
+ jbe no_long_mode ; If not, no long mode.
+ mov eax, 80000001h ; Extended-function code 8000001h.
+ cpuid ; Now EDX = extended-features flags.
+ bt edx, 29 ; Test if long mode is supported.
+ jnc no_long_mode ; Exit if not supported.
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ mov eax, cr4
+ bts eax, 5
+ mov cr4, eax
+
+ ;
+ ; Get the long-mode page tables, and initialize the
+ ; 64-bit CR3 (page-table base address) to point to the base
+ ; of the PML4 page table. The PML4 page table must be located
+ ; below 4 Gbytes because only 32 bits of CR3 are loaded when
+ ; the processor is not in 64-bit mode.
+ ;
+ mov eax, [ebp+8h] ; Get Page Tables
+ mov cr3, eax ; Initialize CR3 with PML4 base.
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ mov ecx, 0c0000080h ; EFER MSR number.
+ rdmsr ; Read EFER.
+ bts eax, 8 ; Set LME=1.
+ wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+
+
+ mov eax, cr0 ; Read CR0.
+ bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp go_to_long_mode
+go_to_long_mode:
+
+ ;
+ ; This is the next instruction after enabling paging. Jump to long mode
+ ;
+ db 067h
+ db 0eah ; Far Jump Offset:Selector to reload CS
+ dd OFFSET in_long_mode; Offset is ensuing instruction boundary
+ dw SYS_CODE64_SEL ; Selector is our code selector, 10h
+in_long_mode::
+ mov ax, SYS_DATA64_SEL
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+;; jmp $
+
+
+ ;
+ ; We're in long mode, so marshall the arguments to call the
+ ; passed in function pointers
+ ; Recall
+ ; [ebp][10h] = HobStart
+ ; [ebp][18h] = Stack
+ ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
+ ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second
+ ;
+ db 48h
+ mov ebx, [ebp+18h] ; Setup the stack
+ db 48h
+ mov esp, ebx ; On a new stack now
+
+
+;; 00000905 FF D0 call rax
+
+ db 48h
+ mov ecx, [ebp+10h] ; Pass Hob Start in RCX
+ db 48h
+ mov eax, [ebp+28h] ; Get the function pointer for
+ ; DxeCoreEntryPoint into EAX
+
+;; 00000905 FF D0 call rax
+ db 0ffh
+ db 0d0h
+
+ ;
+ ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
+ ;
+no_long_mode:
+ jmp no_long_mode
+_ActivateLongMode endp
+
+ align 16
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd OFFSET GDT_BASE ; (GDT base gets set above)
+
+;-----------------------------------------------------------------------------;
+; global descriptor table (GDT)
+;-----------------------------------------------------------------------------;
+
+ align 16
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Fh ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 093h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+END
+
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c b/EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c
new file mode 100644
index 0000000000..ef9c3b61ae
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c
@@ -0,0 +1,160 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ VirtualMemory.c
+
+Abstract:
+
+ x64 Virtual Memory Management Services in the form of an IA-32 driver.
+ Used to establish a 1:1 Virtual to Physical Mapping that is required to
+ enter Long Mode (x64 64-bit mode).
+
+ While we make a 1:1 mapping (identity mapping) for all physical pages
+ we still need to use the MTRR's to ensure that the cachability attirbutes
+ for all memory regions is correct.
+
+ The basic idea is to use 2MB page table entries where ever possible. If
+ more granularity of cachability is required then 4K page tables are used.
+
+ References:
+ 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+
+--*/
+
+#include "VirtualMemory.h"
+
+EFI_PHYSICAL_ADDRESS
+CreateIdentityMappingPageTables (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocates and fills in the Page Directory and Page Table Entries to
+ establish a 1:1 Virtual to Physical mapping.
+
+Arguments:
+
+ NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use.
+ Limits the number of page table entries
+ to the physical address space.
+
+Returns:
+
+ EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created
+
+--*/
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN IndexOfPml4Entries;
+ UINTN IndexOfPdpEntries;
+ UINTN IndexOfPageDirectoryEntries;
+ UINTN NumberOfPml4EntriesNeeded;
+ UINTN NumberOfPdpEntriesNeeded;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+
+ //
+ // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
+ //
+ PageMap = AllocatePages (1);
+ ASSERT (PageMap != NULL);
+
+ //
+ // Get physical address bits supported.
+ //
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+
+ //
+ // Calculate the table entries needed.
+ //
+ if (PhysicalAddressBits <= 39 ) {
+ NumberOfPml4EntriesNeeded = 1;
+ NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30);
+ } else {
+ NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39);
+ NumberOfPdpEntriesNeeded = 512;
+ }
+
+ PageMapLevel4Entry = PageMap;
+ PageAddress = 0;
+ for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {
+ //
+ // Each PML4 entry points to a page of Page Directory Pointer entires.
+ // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
+ //
+ PageDirectoryPointerEntry = AllocatePages (1);
+ ASSERT (PageDirectoryPointerEntry != NULL);
+
+ //
+ // Make a PML4 Entry
+ //
+ PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
+ PageMapLevel4Entry->Bits.ReadWrite = 1;
+ PageMapLevel4Entry->Bits.Present = 1;
+
+ for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ //
+ // Each Directory Pointer entries points to a page of Page Directory entires.
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
+ //
+ PageDirectoryEntry = AllocatePages (1);
+ ASSERT (PageDirectoryEntry != NULL);
+
+ //
+ // Fill in a Page Directory Pointer Entries
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+
+ }
+ }
+ }
+
+ //
+ // For the PML4 entries we are not using fill in a null entry.
+ // For now we just copy the first entry.
+ //
+ for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) {
+ CopyMem (
+ PageMapLevel4Entry,
+ PageMap,
+ sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
+ );
+ }
+
+ return (EFI_PHYSICAL_ADDRESS) (UINTN)PageMap; // FIXME
+}
+
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h b/EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h
new file mode 100644
index 0000000000..ddb504acf7
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h
@@ -0,0 +1,86 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ VirtualMemory.h
+
+Abstract:
+
+ x64 Long Mode Virtual Memory Management Definitions
+
+ References:
+ 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+ 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
+--*/
+#ifndef _VIRTUAL_MEMORY_H_
+#define _VIRTUAL_MEMORY_H_
+
+
+#pragma pack(1)
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} PAGE_MAP_AND_DIRECTORY_POINTER;
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_ENTRY;
+
+#pragma pack()
+
+EFI_PHYSICAL_ADDRESS
+CreateIdentityMappingPageTables (
+ VOID
+ )
+;
+
+#endif
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c
index cdc418f6f3..079ae924da 100644
--- a/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c
+++ b/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c
@@ -19,7 +19,7 @@ Abstract:
--*/
-#include <DxeIpl.h>
+#include "DxeIpl.h"
EFI_STATUS
CreateArchSpecificHobs (
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c
index 16b44b24d8..3131533b2a 100644
--- a/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c
+++ b/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c
@@ -17,7 +17,7 @@ Abstract:
--*/
-#include <DxeIpl.h>
+#include "DxeIpl.h"
EFI_STATUS
PeiImageRead (
diff --git a/EdkModulePkg/Core/DxeIplPeim/Non-existing.c b/EdkModulePkg/Core/DxeIplPeim/Non-existing.c
new file mode 100644
index 0000000000..f9f7df769c
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Non-existing.c
@@ -0,0 +1,55 @@
+/** @file
+ Non-existing functions other than Ia32 architecture.
+
+ 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: Non-existing.c
+
+**/
+
+#include "DxeIpl.h"
+
+EFI_PHYSICAL_ADDRESS
+CreateIdentityMappingPageTables (
+ IN UINT32 NumberOfProcessorPhysicalAddressBits
+ )
+{
+ //
+ // This function cannot work on non-Ia32 architecture.
+ //
+ ASSERT (FALSE);
+ return 0;
+}
+
+VOID
+ActivateLongMode (
+ IN EFI_PHYSICAL_ADDRESS PageTables,
+ IN EFI_PHYSICAL_ADDRESS HobStart,
+ IN EFI_PHYSICAL_ADDRESS Stack,
+ IN EFI_PHYSICAL_ADDRESS CodeEntryPoint1,
+ IN EFI_PHYSICAL_ADDRESS CodeEntryPoint2
+ )
+{
+ //
+ // This function cannot work on non-Ia32 architecture.
+ //
+ ASSERT (FALSE);
+}
+
+VOID
+LoadGo64Gdt(
+ VOID
+ )
+{
+ //
+ // This function cannot work on non-Ia32 architecture.
+ //
+ ASSERT (FALSE);
+}