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
This commit is contained in:
qhuang8
2006-11-27 10:14:02 +00:00
parent ad3e8660d3
commit abb26634f2
20 changed files with 488 additions and 1913 deletions

View File

@@ -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

View File

@@ -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>

View File

@@ -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) {
if (CmpSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
//
// Firmware Volume Image in this Section
// Skip the section header to get FvHeader
//
// Skip the section header and
// adjust the pointer alignment to 16
//
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)) {
//
// Set the original FvHob to unused.
//
if (OrigHob != NULL) {
OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;
}
//
// when search FvImage Section return true.
//
if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
*Pe32Data = (VOID *) FvHeader;
return EFI_SUCCESS;
} else {
return EFI_NOT_FOUND;
}
//
// Reture the FfsHeader that contain Pe32Data.
//
*RealFfsFileHeader = FfsFileHeader;
return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data);
}
}
//
@@ -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;
}

View File

@@ -19,7 +19,7 @@ Abstract:
--*/
#include <DxeIpl.h>
#include "DxeIpl.h"
EFI_STATUS
CreateArchSpecificHobs (

View File

@@ -17,7 +17,7 @@ Abstract:
--*/
#include <DxeIpl.h>
#include "DxeIpl.h"
EFI_STATUS
EFIAPI

View File

@@ -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:

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -19,7 +19,7 @@ Abstract:
--*/
#include <DxeIpl.h>
#include "DxeIpl.h"
EFI_STATUS
CreateArchSpecificHobs (

View File

@@ -17,7 +17,7 @@ Abstract:
--*/
#include <DxeIpl.h>
#include "DxeIpl.h"
EFI_STATUS
PeiImageRead (

View File

@@ -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);
}