diff options
author | qhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524> | 2006-11-27 10:14:02 +0000 |
---|---|---|
committer | qhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524> | 2006-11-27 10:14:02 +0000 |
commit | abb26634f230fb703906f46e7e7adebc9124214a (patch) | |
tree | cf08cb43b6a21d52ed620f47c6157f1436da09f9 /EdkModulePkg/Core/DxeIplPeim | |
parent | ad3e8660d37e30ccf2e78aafced1f194e3593a30 (diff) | |
download | edk2-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.h | 7 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa | 51 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/DxeLoad.c | 469 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 2 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c | 2 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S | 296 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.asm | 294 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c | 160 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h | 86 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c | 2 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c | 2 | ||||
-rw-r--r-- | EdkModulePkg/Core/DxeIplPeim/Non-existing.c | 55 |
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);
+}
|