From 5343eab11a2dfefaef0e332dad7269a65be41e56 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Wed, 12 Jul 2006 23:38:53 +0000 Subject: Add missing files in msa file and add module description in msa file, and reorganize DriverSample and DxeIplX64 module directory. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@927 6f19259b-4bc3-4df7-8a09-765794883524 --- EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa | 2 + EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa | 1 + EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa | 25 +- EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa | 143 --- EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c | 997 --------------- EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c | 53 - EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c | 106 -- EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm | 1350 -------------------- EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c | 434 ------- EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h | 239 ---- EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.dxs | 29 + EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.h | 146 +++ EdkModulePkg/Core/DxeIplX64Peim/DxeIplX64.msa | 145 +++ EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c | 997 +++++++++++++++ EdkModulePkg/Core/DxeIplX64Peim/x64/DxeLoadFunc.c | 53 + EdkModulePkg/Core/DxeIplX64Peim/x64/ImageRead.c | 106 ++ EdkModulePkg/Core/DxeIplX64Peim/x64/LongMode.asm | 1350 ++++++++++++++++++++ .../Core/DxeIplX64Peim/x64/VirtualMemory.c | 434 +++++++ .../Core/DxeIplX64Peim/x64/VirtualMemory.h | 239 ++++ EdkModulePkg/EdkModulePkg.spd | 4 +- .../EdkDxePeCoffLoaderFromHobLib.msa | 4 +- .../EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa | 4 +- .../EdkPeCoffLoaderX64Lib.msa | 4 +- 23 files changed, 3523 insertions(+), 3342 deletions(-) delete mode 100644 EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa delete mode 100644 EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c delete mode 100644 EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c delete mode 100644 EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c delete mode 100644 EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm delete mode 100644 EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c delete mode 100644 EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.dxs create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.h create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/DxeIplX64.msa create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/x64/DxeLoadFunc.c create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/x64/ImageRead.c create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/x64/LongMode.asm create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.c create mode 100644 EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.h diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa index 0d93504..b777845 100644 --- a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa @@ -80,6 +80,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.--> atapi.c ComponentName.c ComponentName.h + DriverConfiguration.c + DriverDiagnostics.h diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa index 8938919..182baa7 100644 --- a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa @@ -93,6 +93,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.--> pcibus.c PciIo.c PciLib.c + LightPciLib.c diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa index eda2981..4bf8413 100644 --- a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa +++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa @@ -1,11 +1,11 @@  - @@ -16,11 +16,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.--> Component description file for DxeIpl module 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. 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, + 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. FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 @@ -78,6 +78,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.--> DxeLoad.c + DxeIpl.h DxeIpl.dxs Ia32/ImageRead.c Ia32/DxeLoadFunc.c diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa deleted file mode 100644 index 80e00fd..0000000 --- a/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa +++ /dev/null @@ -1,143 +0,0 @@ - - - - - DxeIplX64 - PEIM - 0c55bdf7-d71d-4962-8fcb-348773e48929 - 1.0 - Component description file for DxeIplX64 module - The responsibility of this module is to load the DXE Core from a Firmware Volume. This implementation i used to load a 64-bit DXE Core. - Copyright 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. - FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 - - - IA32 X64 IPF EBC - false - DxeIplX64 - - - - DebugLib - - - PeimEntryPoint - - - BaseLib - - - HobLib - - - PerformanceLib - - - PeiServicesLib - - - ReportStatusCodeLib - - - CacheMaintenanceLib - - - EdkPeCoffLoaderLib - - - UefiDecompressLib - - - TianoDecompressLib - - - CustomDecompressLib - - - PeiServicesTablePointerLib - - - BaseMemoryLib - - - MemoryAllocationLib - - - EdkPeCoffLoaderX64Lib - - - - DxeIpl.dxs - DxeLoadX64.c - x64/ImageRead.c - x64/LongMode.asm - x64/DxeLoadFunc.c - x64/VirtualMemory.c - - - - - - - - gEfiDecompressProtocolGuid - - - gEfiTianoDecompressProtocolGuid - - - gEfiCustomizedDecompressProtocolGuid - - - - - gEfiDxeIplPpiGuid - - - gEfiPeiFvFileLoaderPpiGuid - - - gEfiEndOfPeiSignalPpiGuid - - - gEfiPeiRecoveryModulePpiGuid - - - gEfiPeiS3ResumePpiGuid - - - gEfiPeiSectionExtractionPpiGuid - - - gEfiPeiSecurityPpiGuid - - - gPeiInMemoryGuid - - - - - gEfiPeiPeCoffLoaderGuid - - - - EFI_SPECIFICATION_VERSION 0x00020000 - EDK_RELEASE_VERSION 0x00020000 - - PeimInitializeDxeIpl - - - \ No newline at end of file diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c b/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c deleted file mode 100644 index cbb7595..0000000 --- a/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c +++ /dev/null @@ -1,997 +0,0 @@ -/*++ - -Copyright (c) 2006, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - DxeLoad.c - -Abstract: - - Last PEIM. - Responsibility of this module is to load the DXE Core from a Firmware Volume. - ---*/ - -#include - -#pragma warning( disable : 4305 ) - -BOOLEAN gInMemory = FALSE; - -// -// GUID for EM64T -// -#define EFI_PPI_NEEDED_BY_DXE \ - { \ - 0x4d37da42, 0x3a0c, 0x4eda, 0xb9, 0xeb, 0xbc, 0x0e, 0x1d, 0xb4, 0x71, 0x3b \ - } -EFI_GUID mPpiNeededByDxeGuid = EFI_PPI_NEEDED_BY_DXE; - -// -// Module Globals used in the DXE to PEI handoff -// These must be module globals, so the stack can be switched -// -static EFI_DXE_IPL_PPI mDxeIplPpi = { - DxeLoadCore -}; - -static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = { - DxeIplLoadFile -}; - -static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gEfiPeiFvFileLoaderPpiGuid, - &mLoadFilePpi -}; - -static EFI_PEI_PPI_DESCRIPTOR mPpiList = { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gEfiDxeIplPpiGuid, - &mDxeIplPpi -}; - -static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gPeiInMemoryGuid, - NULL -}; - -static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gEfiEndOfPeiSignalPpiGuid, - NULL -}; - -DECOMPRESS_LIBRARY gEfiDecompress = { - UefiDecompressGetInfo, - UefiDecompress -}; - -DECOMPRESS_LIBRARY gTianoDecompress = { - TianoDecompressGetInfo, - TianoDecompress -}; - -DECOMPRESS_LIBRARY gCustomDecompress = { - CustomDecompressGetInfo, - CustomDecompress -}; - -STATIC -UINTN -GetOccupiedSize ( - IN UINTN ActualSize, - IN UINTN Alignment - ) -{ - UINTN OccupiedSize; - - OccupiedSize = ActualSize; - while ((OccupiedSize & (Alignment - 1)) != 0) { - OccupiedSize++; - } - - return OccupiedSize; -} - -EFI_STATUS -EFIAPI -PeimInitializeDxeIpl ( - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN EFI_PEI_SERVICES **PeiServices - ) -/*++ - -Routine Description: - - Initializes the Dxe Ipl PPI - -Arguments: - - FfsHeader - Pointer to FFS file header - PeiServices - General purpose services available to every PEIM. - -Returns: - - EFI_SUCCESS - ---*/ -{ - EFI_STATUS Status; - EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; - EFI_BOOT_MODE BootMode; - - Status = PeiServicesGetBootMode (&BootMode); - - ASSERT_EFI_ERROR (Status); - - Status = PeiServicesLocatePpi ( - &gPeiInMemoryGuid, - 0, - NULL, - NULL - ); - - if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) { - // - // The DxeIpl has not yet been shadowed - // - PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); - - // - // Shadow DxeIpl and then re-run its entry point - // - Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader); - if (EFI_ERROR (Status)) { - return Status; - } - - } else { - if (BootMode != BOOT_ON_S3_RESUME) { - // - // The DxeIpl has been shadowed - // - gInMemory = TRUE; - - // - // Install LoadFile PPI - // - Status = PeiServicesInstallPpi (&mPpiLoadFile); - - if (EFI_ERROR (Status)) { - return Status; - } - } - // - // Install DxeIpl PPI - // - PeiServicesInstallPpi (&mPpiList); - - if (EFI_ERROR (Status)) { - return Status; - } - - } - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -DxeLoadCore ( - IN EFI_DXE_IPL_PPI *This, - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_HOB_POINTERS HobList - ) -/*++ - -Routine Description: - - Main entry point to last PEIM - -Arguments: - - This - Entry point for DXE IPL PPI - PeiServices - General purpose services available to every PEIM. - HobList - Address to the Pei HOB list - -Returns: - - EFI_SUCCESS - DEX core was successfully loaded. - EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core. - ---*/ -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS TopOfStack; - EFI_PHYSICAL_ADDRESS BaseOfStack; - EFI_PHYSICAL_ADDRESS BspStore; - EFI_GUID DxeCoreFileName; - VOID *DxeCorePe32Data; - EFI_PHYSICAL_ADDRESS DxeCoreAddress; - UINT64 DxeCoreSize; - EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; - EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; - EFI_BOOT_MODE BootMode; - EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; - EFI_PEI_S3_RESUME_PPI *S3Resume; - EFI_PHYSICAL_ADDRESS PageTables; - - TopOfStack = 0; - BaseOfStack = 0; - BspStore = 0; - Status = EFI_SUCCESS; - - // - // if in S3 Resume, restore configure - // - Status = PeiServicesGetBootMode (&BootMode); - - if (!EFI_ERROR (Status) && (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 - // -#ifdef EFI_NT_EMULATOR - PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); - ASSERT (PeiEfiPeiPeCoffLoader != NULL); -#else - PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderX64Protocol (); -#endif - -#if 0 - Status = InstallEfiPeiPeCoffLoader64 (PeiServices, &PeiEfiPeiPeCoffLoader, NULL); - ASSERT_EFI_ERROR (Status); -#endif - // - // Allocate 128KB for the Stack - // - PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); - ASSERT (BaseOfStack != 0); - - // - // Compute the top of the stack we were allocated. Pre-allocate a 32 bytes - // for safety (PpisNeededByDxe and DxeCore). - // - TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; - - // - // Add architecture-specifc HOBs (including the BspStore HOB) - // - Status = CreateArchSpecificHobs (&BspStore); - ASSERT_EFI_ERROR (Status); - - // - // See if we are in crisis recovery - // - Status = PeiServicesGetBootMode (&BootMode); - if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) { - Status = PeiServicesLocatePpi ( - &gEfiPeiRecoveryModulePpiGuid, - 0, - NULL, - (VOID **)&PeiRecovery - ); - - ASSERT_EFI_ERROR (Status); - Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); - ASSERT_EFI_ERROR (Status); - } - - // - // Find the DXE Core in a Firmware Volume - // - Status = PeiFindFile ( - EFI_FV_FILETYPE_DXE_CORE, - EFI_SECTION_PE32, - &DxeCoreFileName, - &DxeCorePe32Data - ); - ASSERT_EFI_ERROR (Status); - - // - // Transfer control to the DXE Core - // The handoff state is simply a pointer to the HOB list - // - // PEI_PERF_END (PeiServices, L"DxeIpl", NULL, 0); - - Status = PeiServicesInstallPpi (&mPpiSignal); - ASSERT_EFI_ERROR (Status); - - // - // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \ - // memory, it may be corrupted when copying FV to high-end memory - LoadGo64Gdt(); - - // - // Limit to 36 bits of addressing for debug. Should get it from CPU - // - PageTables = CreateIdentityMappingPageTables (36); - - - // - // Load the DXE Core from a Firmware Volume - // - Status = PeiLoadx64File ( - PeiEfiPeiPeCoffLoader, - DxeCorePe32Data, - EfiBootServicesData, - &DxeCoreAddress, - &DxeCoreSize, - &DxeCoreEntryPoint - ); - ASSERT_EFI_ERROR (Status); - - // - // - // Add HOB for the DXE Core - // - BuildModuleHob ( - &DxeCoreFileName, - DxeCoreAddress, - DxeCoreSize, - DxeCoreEntryPoint - ); - - // - // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT - ); - - DEBUG ((EFI_D_INFO, "DXE Core Entry\n")); - // - // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded. - // Call x64 drivers passing in single argument, a pointer to the HOBs. - // - ActivateLongMode ( - PageTables, - (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), - TopOfStack, - 0x00000000, - DxeCoreEntryPoint - ); - - // - // If we get here, then the DXE Core returned. This is an error - // - ASSERT_EFI_ERROR (Status); - - return EFI_OUT_OF_RESOURCES; -} - -EFI_STATUS -PeiFindFile ( - IN UINT8 Type, - IN UINT16 SectionType, - OUT EFI_GUID *FileName, - OUT VOID **Pe32Data - ) -/*++ - -Routine Description: - - Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes - described in the HOB list. Able to search in a compression set in a FFS file. - But only one level of compression is supported, that is, not able to search - in a compression set that is within another compression set. - -Arguments: - - Type - The Type of file to retrieve - - SectionType - The type of section to retrieve from a file - - FileName - The name of the file found in the Firmware Volume - - Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume - -Returns: - - EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to - the PE/COFF image is returned in Pe32Data - - EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List - ---*/ -{ - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FFS_FILE_HEADER *FfsFileHeader; - VOID *SectionData; - EFI_STATUS Status; - EFI_PEI_HOB_POINTERS Hob; - - - FwVolHeader = NULL; - FfsFileHeader = NULL; - SectionData = NULL; - - // - // Foreach Firmware Volume, look for a specified type - // of file and break out when one is found - // - Hob.Raw = GetHobList (); - while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) { - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress); - Status = PeiServicesFfsFindNextFile ( - Type, - FwVolHeader, - &FfsFileHeader - ); - if (!EFI_ERROR (Status)) { - Status = PeiProcessFile ( - SectionType, - &FfsFileHeader, - Pe32Data - ); - CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID)); - return Status; - } - Hob.Raw = GET_NEXT_HOB (Hob); - } - return EFI_NOT_FOUND; -} - -EFI_STATUS -PeiLoadx64File ( - IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, - IN VOID *Pe32Data, - IN EFI_MEMORY_TYPE MemoryType, - OUT EFI_PHYSICAL_ADDRESS *ImageAddress, - OUT UINT64 *ImageSize, - OUT EFI_PHYSICAL_ADDRESS *EntryPoint - ) -/*++ - -Routine Description: - - Loads and relocates a PE/COFF image into memory. - -Arguments: - - PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol - - Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated - - ImageAddress - The base address of the relocated PE/COFF image - - ImageSize - The size of the relocated PE/COFF image - - EntryPoint - The entry point of the relocated PE/COFF image - -Returns: - - EFI_SUCCESS - The file was loaded and relocated - EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file - ---*/ -{ - EFI_STATUS Status; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; - EFI_PHYSICAL_ADDRESS MemoryBuffer; - - ZeroMem (&ImageContext, sizeof (ImageContext)); - ImageContext.Handle = Pe32Data; - Status = GetImageReadFunction (&ImageContext); - - ASSERT_EFI_ERROR (Status); - - Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Allocate Memory for the image - // - // - // Allocate Memory for the image - // - PeiServicesAllocatePages (MemoryType, EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), &MemoryBuffer); - ImageContext.ImageAddress = MemoryBuffer; - ASSERT (ImageContext.ImageAddress != 0); - - // - // Load the image to our new buffer - // - - Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Relocate the image in our new buffer - // - Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Flush the instruction cache so the image data is written before we execute it - // - InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); - - *ImageAddress = ImageContext.ImageAddress; - *ImageSize = ImageContext.ImageSize; - *EntryPoint = ImageContext.EntryPoint; - - return EFI_SUCCESS; -} - -EFI_STATUS -ShadowDxeIpl ( - IN EFI_FFS_FILE_HEADER *DxeIplFileHeader, - IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader - ) -/*++ - -Routine Description: - - Shadow the DXE IPL to a different memory location. This occurs after permanent - memory has been discovered. - -Arguments: - - DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver - - PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol - -Returns: - - EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location. - - EFI_ ERROR - The shadow was unsuccessful. - - ---*/ -{ - UINTN SectionLength; - UINTN OccupiedSectionLength; - EFI_PHYSICAL_ADDRESS DxeIplAddress; - UINT64 DxeIplSize; - EFI_PHYSICAL_ADDRESS DxeIplEntryPoint; - EFI_STATUS Status; - EFI_COMMON_SECTION_HEADER *Section; - - Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1); - - while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) { - SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; - OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); - Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); - } - - // - // Relocate DxeIpl into memory by using loadfile service - // - Status = PeiLoadx64File ( - PeiEfiPeiPeCoffLoader, - (VOID *) (Section + 1), - EfiBootServicesData, - &DxeIplAddress, - &DxeIplSize, - &DxeIplEntryPoint - ); - - if (Status == EFI_SUCCESS) { - // - // Install PeiInMemory to indicate the Dxeipl is shadowed - // - Status = PeiServicesInstallPpi (&mPpiPeiInMemory); - - if (EFI_ERROR (Status)) { - return Status; - } - - Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer()); - } - - return Status; -} - -EFI_STATUS -EFIAPI -DxeIplLoadFile ( - IN EFI_PEI_FV_FILE_LOADER_PPI *This, - IN EFI_FFS_FILE_HEADER *FfsHeader, - OUT EFI_PHYSICAL_ADDRESS *ImageAddress, - OUT UINT64 *ImageSize, - OUT EFI_PHYSICAL_ADDRESS *EntryPoint - ) -/*++ - -Routine Description: - - Given a pointer to an FFS file containing a PE32 image, get the - information on the PE32 image, and then "load" it so that it - can be executed. - -Arguments: - - This - pointer to our file loader protocol - FfsHeader - pointer to the FFS file header of the FFS file that - contains the PE32 image we want to load - ImageAddress - returned address where the PE32 image is loaded - ImageSize - returned size of the loaded PE32 image - EntryPoint - entry point to the loaded PE32 image - -Returns: - - EFI_SUCCESS - The FFS file was successfully loaded. - EFI_ERROR - Unable to load the FFS file. - ---*/ -{ - EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; - EFI_STATUS Status; - VOID *Pe32Data; - - Pe32Data = NULL; - PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); - - // - // Preprocess the FFS file to get a pointer to the PE32 information - // in the enclosed PE32 image. - // - Status = PeiProcessFile ( - EFI_SECTION_PE32, - &FfsHeader, - &Pe32Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Load the PE image from the FFS file - // - Status = PeiLoadx64File ( - PeiEfiPeiPeCoffLoader, - Pe32Data, - EfiBootServicesData, - ImageAddress, - ImageSize, - EntryPoint - ); - - return Status; -} - -EFI_STATUS -PeiProcessFile ( - IN UINT16 SectionType, - IN OUT EFI_FFS_FILE_HEADER **RealFfsFileHeader, - OUT VOID **Pe32Data - ) -/*++ - -Routine Description: - -Arguments: - - SectionType - The type of section in the FFS file to process. - - FfsFileHeader - Pointer to the FFS file to process, looking for the - specified SectionType - - Pe32Data - returned pointer to the start of the PE32 image found - in the FFS file. - -Returns: - - EFI_SUCCESS - found the PE32 section in the FFS file - ---*/ -{ - EFI_STATUS Status; - VOID *SectionData; - DECOMPRESS_LIBRARY *DecompressLibrary; - UINT8 *DstBuffer; - UINT8 *ScratchBuffer; - UINT32 DstBufferSize; - UINT32 ScratchBufferSize; - EFI_COMMON_SECTION_HEADER *CmpSection; - UINTN CmpSectionLength; - UINTN OccupiedCmpSectionLength; - VOID *CmpFileData; - UINTN CmpFileSize; - EFI_COMMON_SECTION_HEADER *Section; - UINTN SectionLength; - UINTN OccupiedSectionLength; - UINT64 FileSize; - EFI_GUID_DEFINED_SECTION *GuidedSectionHeader; - UINT32 AuthenticationStatus; - EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract; - UINT32 BufferSize; - UINT8 *Buffer; - EFI_PEI_SECURITY_PPI *Security; - BOOLEAN StartCrisisRecovery; - EFI_GUID TempGuid; - EFI_FIRMWARE_VOLUME_HEADER *FvHeader; - EFI_COMPRESSION_SECTION *CompressionSection; - EFI_FFS_FILE_HEADER *FfsFileHeader; - - FfsFileHeader = *RealFfsFileHeader; - - Status = PeiServicesFfsFindSectionData ( - EFI_SECTION_COMPRESSION, - FfsFileHeader, - &SectionData - ); - - // - // Upon finding a DXE Core file, see if there is first a compression section - // - if (!EFI_ERROR (Status)) { - // - // Yes, there is a compression section, so extract the contents - // Decompress the image here - // - Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER)); - - do { - SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; - OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); - - // - // Was the DXE Core file encapsulated in a GUID'd section? - // - if (Section->Type == EFI_SECTION_GUID_DEFINED) { - // - // Locate the GUID'd Section Extractor - // - GuidedSectionHeader = (VOID *) (Section + 1); - - // - // This following code constitutes the addition of the security model - // to the DXE IPL. - // - // - // Set a default authenticatino state - // - AuthenticationStatus = 0; - - Status = PeiServicesLocatePpi ( - &gEfiPeiSectionExtractionPpiGuid, - 0, - NULL, - (VOID **)&SectionExtract - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Verify Authentication State - // - CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID)); - - Status = SectionExtract->PeiGetSection ( - GetPeiServicesTablePointer(), - SectionExtract, - (EFI_SECTION_TYPE *) &SectionType, - &TempGuid, - 0, - (VOID **) &Buffer, - &BufferSize, - &AuthenticationStatus - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // If not ask the Security PPI, if exists, for disposition - // - // - Status = PeiServicesLocatePpi ( - &gEfiPeiSecurityPpiGuid, - 0, - NULL, - (VOID **)&Security - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Security->AuthenticationState ( - GetPeiServicesTablePointer(), - (struct _EFI_PEI_SECURITY_PPI *) Security, - AuthenticationStatus, - FfsFileHeader, - &StartCrisisRecovery - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // If there is a security violation, report to caller and have - // the upper-level logic possible engender a crisis recovery - // - if (StartCrisisRecovery) { - return EFI_SECURITY_VIOLATION; - } - } - - if (Section->Type == EFI_SECTION_PE32) { - // - // This is what we want - // - *Pe32Data = (VOID *) (Section + 1); - return EFI_SUCCESS; - } else if (Section->Type == EFI_SECTION_COMPRESSION) { - // - // This is a compression set, expand it - // - CompressionSection = (EFI_COMPRESSION_SECTION *) Section; - - switch (CompressionSection->CompressionType) { - case EFI_STANDARD_COMPRESSION: - DecompressLibrary = &gTianoDecompress; - break; - - case EFI_CUSTOMIZED_COMPRESSION: - // - // Load user customized compression protocol. - // - DecompressLibrary = &gCustomDecompress; - break; - - case EFI_NOT_COMPRESSED: - default: - // - // Need to support not compressed file - // - ASSERT_EFI_ERROR (Status); - return EFI_NOT_FOUND; - } - - Status = DecompressLibrary->GetInfo ( - (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), - (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), - &DstBufferSize, - &ScratchBufferSize - ); - if (EFI_ERROR (Status)) { - // - // GetInfo failed - // - return EFI_NOT_FOUND; - } - - // - // Allocate scratch buffer - // - ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); - if (ScratchBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Allocate destination buffer - // - DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); - if (DstBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Call decompress function - // - Status = DecompressLibrary->Decompress ( - (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), - DstBuffer, - ScratchBuffer - ); - - CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer; - if (CmpSection->Type == EFI_SECTION_RAW) { - // - // Skip the section header and - // adjust the pointer alignment to 16 - // - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16); - - if (FvHeader->Signature == EFI_FVH_SIGNATURE) { - FfsFileHeader = NULL; - BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength); - Status = PeiServicesFfsFindNextFile ( - EFI_FV_FILETYPE_DXE_CORE, - FvHeader, - &FfsFileHeader - ); - - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - // - // Reture the FfsHeader that contain Pe32Data. - // - *RealFfsFileHeader = FfsFileHeader; - return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data); - } - } - // - // Decompress successfully. - // Loop the decompressed data searching for expected section. - // - CmpFileData = (VOID *) DstBuffer; - CmpFileSize = DstBufferSize; - do { - CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff; - if (CmpSection->Type == EFI_SECTION_PE32) { - // - // This is what we want - // - *Pe32Data = (VOID *) (CmpSection + 1); - return EFI_SUCCESS; - } - - OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4); - CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength); - } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize); - } - - Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); - FileSize = FfsFileHeader->Size[0] & 0xFF; - FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00; - FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000; - FileSize &= 0x00FFFFFF; - } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize); - - // - // End of the decompression activity - // - } else { - - Status = PeiServicesFfsFindSectionData ( - EFI_SECTION_PE32, - FfsFileHeader, - &SectionData - ); - - if (EFI_ERROR (Status)) { - Status = PeiServicesFfsFindSectionData ( - EFI_SECTION_TE, - FfsFileHeader, - &SectionData - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - } - - *Pe32Data = SectionData; - - return EFI_SUCCESS; -} \ No newline at end of file diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c deleted file mode 100644 index c93c7e1..0000000 --- a/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c +++ /dev/null @@ -1,53 +0,0 @@ -/*++ - -Copyright (c) 2006, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - DxeLoadFunc.c - -Abstract: - - Ia32-specifc functionality for DxeLoad X64 Lakeport. - ---*/ - -#include - -EFI_STATUS -CreateArchSpecificHobs ( - OUT EFI_PHYSICAL_ADDRESS *BspStore - ) -/*++ - -Routine Description: - - Creates architecture-specific HOBs. - - Note: New parameters should NOT be added for any HOBs that are added to this - function. BspStore is a special case because it is required for the - call to SwitchStacks() in DxeLoad(). - -Arguments: - - PeiServices - General purpose services available to every PEIM. - BspStore - The address of the BSP Store for those architectures that need - it. Otherwise 0. - -Returns: - - EFI_SUCCESS - The HOBs were created successfully. - ---*/ -{ - *BspStore = 0; - - return EFI_SUCCESS; -} diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c deleted file mode 100644 index dd977f2..0000000 --- a/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c +++ /dev/null @@ -1,106 +0,0 @@ -/*++ - -Copyright (c) 2006, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - ImageRead.c - -Abstract: - ---*/ - -#include - -EFI_STATUS -EFIAPI -PeiImageRead ( - IN VOID *FileHandle, - IN UINTN FileOffset, - IN OUT UINTN *ReadSize, - OUT VOID *Buffer - ) -/*++ - -Routine Description: - - Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file - -Arguments: - - FileHandle - The handle to the PE/COFF file - - FileOffset - The offset, in bytes, into the file to read - - ReadSize - The number of bytes to read from the file starting at FileOffset - - Buffer - A pointer to the buffer to read the data into. - -Returns: - - EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset - ---*/ -{ - CHAR8 *Destination8; - CHAR8 *Source8; - UINTN Length; - - Destination8 = Buffer; - Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); - Length = *ReadSize; - while (Length--) { - *(Destination8++) = *(Source8++); - } - - return EFI_SUCCESS; -} - -EFI_STATUS -GetImageReadFunction ( - IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext - ) -/*++ - -Routine Description: - - Support routine to return the PE32 Image Reader. - If the PeiImageRead() function is less than a page - in legnth. If the function is more than a page the DXE IPL will crash!!!! - -Arguments: - ImageContext - The context of the image being loaded - -Returns: - - EFI_SUCCESS - If Image function location is found - ---*/ -{ - VOID *MemoryBuffer; - - if (gInMemory) { - ImageContext->ImageRead = PeiImageRead; - return EFI_SUCCESS; - } - - // - // BugBug; This code assumes PeiImageRead() is less than a page in size! - // Allocate a page so we can shaddow the read function from FLASH into - // memory to increase performance. - // - - MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead); - ASSERT (MemoryBuffer != NULL); - - ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; - - return EFI_SUCCESS; -} diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm b/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm deleted file mode 100644 index ae87bd8..0000000 --- a/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm +++ /dev/null @@ -1,1350 +0,0 @@ - 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: - -; -; -;------------------------------------------------------------------------------ -; Generic IDT Vector Handlers for the Host. They are all the same so they -; will compress really well. -; -; By knowing the return address for Vector 00 you can can calculate the -; vector number by looking at the call CommonInterruptEntry return address. -; (return address - AsmIdtVector00Base)/8 == IDT index -; -;------------------------------------------------------------------------------ - -_AsmIdtVector00 PROC NEAR PUBLIC - call CommonInterruptEntry -_AsmIdtVector00 ENDP -AsmIdtVector00Base PROC NEAR PUBLIC - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop -AsmIdtVector00Base ENDP - - -;---------------------------------------; -; CommonInterruptEntry ; -;---------------------------------------; -; The follow algorithm is used for the common interrupt routine. -; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition -; -; -CommonInterruptEntry PROC NEAR PUBLIC - cli - jmp $ - iret - -CommonInterruptEntry ENDP - -END - diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c deleted file mode 100644 index 40eaed2..0000000 --- a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c +++ /dev/null @@ -1,434 +0,0 @@ -/*++ - -Copyright (c) 2006, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - VirtualMemory.c - -Abstract: - - x64 Virtual Memory Management Services in the form of an IA-32 driver. - Used to establish a 1:1 Virtual to Physical Mapping that is required to - enter Long Mode (x64 64-bit mode). - - While we make a 1:1 mapping (identity mapping) for all physical pages - we still need to use the MTRR's to ensure that the cachability attirbutes - for all memory regions is correct. - - The basic idea is to use 2MB page table entries where ever possible. If - more granularity of cachability is required then 4K page tables are used. - - References: - 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel - 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel - 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel - ---*/ - -#include "VirtualMemory.h" - -x64_MTRR_VARIABLE_RANGE *mMTRRVariableRange; -x64_MTRR_FIXED_RANGE mMTRRFixedRange; - - -// -// Physial memory limit values for each of the 11 fixed MTRRs -// -UINTN mFixedRangeLimit[] = { - 0x7FFFF, // Fixed MTRR #0 describes 0x00000..0x7FFFF - 0x9FFFF, // Fixed MTRR #1 describes 0x80000..0x9FFFF - 0xBFFFF, // Fixed MTRR #2 describes 0xA0000..0xBFFFF - 0xC7FFF, // Fixed MTRR #3 describes 0xC0000..0xC7FFF - 0xCFFFF, // Fixed MTRR #4 describes 0xC8000..0xCFFFF - 0xD7FFF, // Fixed MTRR #5 describes 0xD0000..0xD7FFF - 0xDFFFF, // Fixed MTRR #6 describes 0xD8000..0xDFFFF - 0xE7FFF, // Fixed MTRR #7 describes 0xE0000..0xE7FFF - 0xEFFFF, // Fixed MTRR #8 describes 0xE8000..0xEFFFF - 0xF7FFF, // Fixed MTRR #9 describes 0xF0000..0xF7FFF - 0xFFFFF // Fixed MTRR #10 describes 0xF8000..0xFFFFF -}; - -// -// The size, in bits, of each of the 11 fixed MTRR. -// -UINTN mFixedRangeShift[] = { - 16, // Fixed MTRR #0 describes 8, 64 KB ranges - 14, // Fixed MTRR #1 describes 8, 16 KB ranges - 14, // Fixed MTRR #2 describes 8, 16 KB ranges - 12, // Fixed MTRR #3 describes 8, 4 KB ranges - 12, // Fixed MTRR #4 describes 8, 4 KB ranges - 12, // Fixed MTRR #5 describes 8, 4 KB ranges - 12, // Fixed MTRR #6 describes 8, 4 KB ranges - 12, // Fixed MTRR #7 describes 8, 4 KB ranges - 12, // Fixed MTRR #8 describes 8, 4 KB ranges - 12, // Fixed MTRR #9 describes 8, 4 KB ranges - 12 // Fixed MTRR #10 describes 8, 4 KB ranges -}; - - -UINTN mPowerOf2[] = { - 1, - 2, - 4, - 8, - 16, - 32, - 64, - 128, - 256, - 512 -}; - -x64_MTRR_MEMORY_TYPE -EfiGetMTRRMemoryType ( - IN EFI_PHYSICAL_ADDRESS Address - ) -/*++ - -Routine Description: - - Retrieves the memory type from the MTRR that describes a physical address. - -Arguments: - - VariableRange - Set of Variable MTRRs - - FixedRange - Set of Fixed MTRRs - - Address - The physical address for which the MTRR memory type is being retrieved - -Returns: - - The MTRR Memory Type for the physical memory specified by Address. - ---*/ -{ - UINTN Index; - UINTN TypeIndex; - BOOLEAN Found; - x64_MTRR_MEMORY_TYPE VariableType; - EFI_PHYSICAL_ADDRESS MaskBase; - EFI_PHYSICAL_ADDRESS PhysMask; - - // - // If the MTRRs are disabled, then return the Uncached Memory Type - // - if (mMTRRFixedRange.DefaultType.Bits.E == 0) { - return Uncached; - } - - // - // If the CPU supports Fixed MTRRs and the Fixed MTRRs are enabled, then - // see if Address falls into one of the Fixed MTRRs - // - if (mMTRRFixedRange.Capabilities.Bits.FIX && mMTRRFixedRange.DefaultType.Bits.FE) { - // - // Loop though 11 fixed MTRRs - // - for (Index = 0; Index < 11; Index++) { - // - // Check for a matching range - // - if (Address <= mFixedRangeLimit[Index]) { - // - // Compute the offset address into the MTRR bu subtrating the base address of the MTRR - // - if (Index > 0) { - Address = Address - (mFixedRangeLimit[Index-1] + 1); - } - // - // Retrieve the index into the MTRR to extract the memory type. The range is 0..7 - // - TypeIndex = (UINTN)RShiftU64 (Address, mFixedRangeShift[Index]); - - // - // Retrieve and return the memory type for the matching range - // - return mMTRRFixedRange.Fixed[Index].Type[TypeIndex]; - } - } - } - - // - // If Address was not found in a Fixed MTRR, then search the Variable MTRRs - // - for (Index = 0, Found = FALSE, VariableType = WriteBack; Index < mMTRRFixedRange.Capabilities.Bits.VCNT; Index++) { - // - // BugBug: __aullshr complier error - // - if ((mMTRRVariableRange[Index].PhysMask.Uint64 & 0x800) == 0x800) { - //if (mMTRRVariableRange[Index].PhysMask.Bits.Valid == 1) { - PhysMask = mMTRRVariableRange[Index].PhysMask.Uint64 & ~0xfff; - MaskBase = PhysMask & (mMTRRVariableRange[Index].PhysBase.Uint64 & ~0xfff); - if (MaskBase == (PhysMask & Address)) { - // - // Check to see how many matches we find - // - Found = TRUE; - if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == Uncached) || (VariableType == Uncached)) { - // - // If any matching region uses UC, the memory region is UC - // - VariableType = Uncached; - } else if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == WriteThrough) || (VariableType == WriteThrough)){ - // - // If it's WT and WB then set it to WT. If it's WT and other type it's undefined - // - VariableType = WriteThrough; - } else { - VariableType = mMTRRVariableRange[Index].PhysBase.Bits.Type; - } - } - } - } - - if (Found) { - return VariableType; - } - - // - // Address was not found in the Fixed or Variable MTRRs, so return the default memory type - // - return mMTRRFixedRange.DefaultType.Bits.Type; -} - - -BOOLEAN -CanNotUse2MBPage ( - IN EFI_PHYSICAL_ADDRESS BaseAddress - ) -/*++ - -Routine Description: - Test to see if a 2MB aligned page has all the same attributes. If a 2MB page - has more than one attibute type it needs to be split into multiple 4K pages. - -Arguments: - BaseAddress - 2MB aligned address to check out - -Returns: - TRUE - This 2MB address range (BaseAddress) can NOT be mapped by a 2MB page - FALSE - This 2MB address range can be mapped by a 2MB page - ---*/ -{ - UINTN Index; - x64_MTRR_MEMORY_TYPE MemoryType; - x64_MTRR_MEMORY_TYPE PreviousMemoryType; - - // - // Address needs to be 2MB aligned - // - ASSERT ((BaseAddress & 0x1fffff) == 0); - - PreviousMemoryType = -1; - for (Index = 0; Index < 512; Index++, BaseAddress += 0x1000) { - MemoryType = EfiGetMTRRMemoryType (BaseAddress); - if ((Index != 0) && (MemoryType != PreviousMemoryType)) { - return TRUE; - } - - PreviousMemoryType = MemoryType; - } - - // - // All the pages had the same type - // - return FALSE; -} - - - - -VOID -Convert2MBPageTo4KPages ( - IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB, - IN EFI_PHYSICAL_ADDRESS PageAddress - ) -/*++ - -Routine Description: - Convert a single 2MB page entry to 512 4K page entries. The attributes for - the 4K pages are read from the MTRR registers. - -Arguments: - PageDirectoryEntry2MB - Page directory entry for PageAddress - PageAddress - 2MB algined address of region to convert - -Returns: - None - ---*/ -{ - EFI_PHYSICAL_ADDRESS Address; - x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k; - x64_PAGE_TABLE_ENTRY_4K *PageTableEntry; - UINTN Index1; - - // - // Allocate the page table entry for the 4K pages - // - PageTableEntry = (x64_PAGE_TABLE_ENTRY_4K *) AllocatePages (1); - - ASSERT (PageTableEntry != NULL); - - // - // Convert PageDirectoryEntry2MB into a 4K Page Directory - // - PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *)PageDirectoryEntry2MB; - PageDirectoryEntry2MB->Uint64 = (UINT64)PageTableEntry; - PageDirectoryEntry2MB->Bits.ReadWrite = 1; - PageDirectoryEntry2MB->Bits.Present = 1; - - // - // Fill in the 4K page entries with the attributes from the MTRRs - // - for (Index1 = 0, Address = PageAddress; Index1 < 512; Index1++, PageTableEntry++, Address += 0x1000) { - PageTableEntry->Uint64 = (UINT64)Address; - PageTableEntry->Bits.ReadWrite = 1; - PageTableEntry->Bits.Present = 1; - } -} - - -EFI_PHYSICAL_ADDRESS -CreateIdentityMappingPageTables ( - IN UINT32 NumberOfProcessorPhysicalAddressBits - ) -/*++ - -Routine Description: - - Allocates and fills in the Page Directory and Page Table Entries to - establish a 1:1 Virtual to Physical mapping for physical memory from - 0 to 4GB. Memory above 4GB is not mapped. The MTRRs are used to - determine the cachability of the physical memory regions - -Arguments: - - NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use. - Limits the number of page table entries - to the physical address space. - -Returns: - EFI_OUT_OF_RESOURCES There are not enough resources to allocate the Page Tables - - EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created - ---*/ -{ - EFI_PHYSICAL_ADDRESS PageAddress; - UINTN Index; - UINTN MaxBitsSupported; - UINTN Index1; - UINTN Index2; - x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; - x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMap; - x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; - x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; - - - // - // Page Table structure 4 level 4K, 3 level 2MB. - // - // PageMapLevel4Entry : bits 47-39 - // PageDirectoryPointerEntry : bits 38-30 - // Page Table 2MB : PageDirectoryEntry2M : bits 29-21 - // Page Table 4K : PageDirectoryEntry4K : bits 29 - 21 - // PageTableEntry : bits 20 - 12 - // - // Strategy is to map every thing in the processor address space using - // 2MB pages. If more granularity is required the 2MB page will get - // converted to set of 4K pages. - // - - // - // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it. - // - PageMap = PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1); - ASSERT (PageMap != NULL); - PageAddress = 0; - - // - // The number of page-map Level-4 Offset entries is based on the number of - // physical address bits. Less than equal to 38 bits only takes one entry. - // 512 entries represents 48 address bits. - // - if (NumberOfProcessorPhysicalAddressBits <= 38) { - MaxBitsSupported = 1; - } else { - MaxBitsSupported = mPowerOf2[NumberOfProcessorPhysicalAddressBits - 39]; - } - - for (Index = 0; Index < MaxBitsSupported; Index++, PageMapLevel4Entry++) { - // - // Each PML4 entry points to a page of Page Directory Pointer entires. - // So lets allocate space for them and fill them in in the Index1 loop. - // - PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1); - ASSERT (PageDirectoryPointerEntry != NULL); - - // - // Make a PML4 Entry - // - PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry; - PageMapLevel4Entry->Bits.ReadWrite = 1; - PageMapLevel4Entry->Bits.Present = 1; - - for (Index1 = 0; Index1 < 512; Index1++, PageDirectoryPointerEntry++) { - // - // Each Directory Pointer entries points to a page of Page Directory entires. - // So lets allocate space for them and fill them in in the Index2 loop. - // - PageDirectoryEntry2MB = (x64_PAGE_TABLE_ENTRY_2M *) AllocatePages (1); - ASSERT (PageDirectoryEntry2MB != NULL); - - // - // Fill in a Page Directory Pointer Entries - // - PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry2MB; - PageDirectoryPointerEntry->Bits.ReadWrite = 1; - PageDirectoryPointerEntry->Bits.Present = 1; - - for (Index2 = 0; Index2 < 512; Index2++, PageDirectoryEntry2MB++, PageAddress += 0x200000) { - // - // Fill in the Page Directory entries - // - PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress; - PageDirectoryEntry2MB->Bits.ReadWrite = 1; - PageDirectoryEntry2MB->Bits.Present = 1; - PageDirectoryEntry2MB->Bits.MustBe1 = 1; - - if (CanNotUse2MBPage (PageAddress)) { - // - // Check to see if all 2MB has the same mapping. If not convert - // to 4K pages by adding the 4th level of page table entries - // - Convert2MBPageTo4KPages (PageDirectoryEntry2MB, PageAddress); - } - } - } - } - - // - // For the PML4 entries we are not using fill in a null entry. - // for now we just copy the first entry. - // - for (; Index < 512; Index++, PageMapLevel4Entry++) { - // EfiCopyMem (PageMapLevel4Entry, PageMap, sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K)); - CopyMem (PageMapLevel4Entry, - PageMap, - sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K) - ); - } - - return (EFI_PHYSICAL_ADDRESS)PageMap; -} - diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h deleted file mode 100644 index 8133ad4..0000000 --- a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h +++ /dev/null @@ -1,239 +0,0 @@ -/*++ - -Copyright (c) 2006, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - VirtualMemory.h - -Abstract: - - x64 Long Mode Virtual Memory Management Definitions - - References: - 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel - 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel - 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel - 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming ---*/ -#ifndef _VIRTUAL_MEMORY_H_ -#define _VIRTUAL_MEMORY_H_ - - -#pragma pack(1) - -// -// Page-Map Level-4 Offset (PML4) and -// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB -// - -typedef union { - struct { - UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory - UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write - UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User - UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching - UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached - UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) - UINT64 Reserved:1; // Reserved - UINT64 MustBeZero:2; // Must Be Zero - UINT64 Available:3; // Available for use by system software - UINT64 PageTableBaseAddress:40; // Page Table Base Address - UINT64 AvabilableHigh:11; // Available for use by system software - UINT64 Nx:1; // No Execute bit - } Bits; - UINT64 Uint64; -} x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; - -// -// Page-Directory Offset 4K -// -typedef union { - struct { - UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory - UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write - UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User - UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching - UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached - UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) - UINT64 Reserved:1; // Reserved - UINT64 MustBeZero:1; // Must Be Zero - UINT64 Reserved2:1; // Reserved - UINT64 Available:3; // Available for use by system software - UINT64 PageTableBaseAddress:40; // Page Table Base Address - UINT64 AvabilableHigh:11; // Available for use by system software - UINT64 Nx:1; // No Execute bit - } Bits; - UINT64 Uint64; -} x64_PAGE_DIRECTORY_ENTRY_4K; - -// -// Page Table Entry 4K -// -typedef union { - struct { - UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory - UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write - UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User - UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching - UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached - UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) - UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page - UINT64 PAT:1; // 0 = Ignore Page Attribute Table - UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write - UINT64 Available:3; // Available for use by system software - UINT64 PageTableBaseAddress:40; // Page Table Base Address - UINT64 AvabilableHigh:11; // Available for use by system software - UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution - } Bits; - UINT64 Uint64; -} x64_PAGE_TABLE_ENTRY_4K; - - -// -// Page Table Entry 2MB -// -typedef union { - struct { - UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory - UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write - UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User - UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching - UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached - UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) - UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page - UINT64 MustBe1:1; // Must be 1 - UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write - UINT64 Available:3; // Available for use by system software - UINT64 PAT:1; // - UINT64 MustBeZero:8; // Must be zero; - UINT64 PageTableBaseAddress:31; // Page Table Base Address - UINT64 AvabilableHigh:11; // Available for use by system software - UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution - } Bits; - UINT64 Uint64; -} x64_PAGE_TABLE_ENTRY_2M; - -typedef union { - UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory - UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write - UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User - UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching - UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached - UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) - UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page - UINT64 Reserved:57; -} x64_PAGE_TABLE_ENTRY_COMMON; - -typedef union { - x64_PAGE_TABLE_ENTRY_4K Page4k; - x64_PAGE_TABLE_ENTRY_2M Page2Mb; - x64_PAGE_TABLE_ENTRY_COMMON Common; -} x64_PAGE_TABLE_ENTRY; - -// -// MTRR Definitions -// -typedef enum { - Uncached = 0, - WriteCombining = 1, - WriteThrough = 4, - WriteProtected = 5, - WriteBack = 6 -} x64_MTRR_MEMORY_TYPE; - -typedef union { - struct { - UINT32 VCNT:8; // The number of Variable Range MTRRs - UINT32 FIX:1; // 1=Fixed Range MTRRs supported. 0=Fixed Range MTRRs not supported - UINT32 Reserved_0; // Reserved - UINT32 WC:1; // Write combining memory type supported - UINT32 Reserved_1:21; // Reserved - UINT32 Reserved_2:32; // Reserved - } Bits; - UINT64 Uint64; -} x64_MTRRCAP_MSR; - -typedef union { - struct { - UINT32 Type:8; // Default Memory Type - UINT32 Reserved_0:2; // Reserved - UINT32 FE:1; // 1=Fixed Range MTRRs enabled. 0=Fixed Range MTRRs disabled - UINT32 E:1; // 1=MTRRs enabled, 0=MTRRs disabled - UINT32 Reserved_1:20; // Reserved - UINT32 Reserved_2:32; // Reserved - } Bits; - UINT64 Uint64; -} x64_MTRR_DEF_TYPE_MSR; - -typedef union { - UINT8 Type[8]; // The 8 Memory Type values in the 64-bit MTRR - UINT64 Uint64; // The full 64-bit MSR -} x64_MTRR_FIXED_RANGE_MSR; - -typedef struct { - x64_MTRRCAP_MSR Capabilities; // MTRR Capabilities MSR value - x64_MTRR_DEF_TYPE_MSR DefaultType; // Default Memory Type MSR Value - x64_MTRR_FIXED_RANGE_MSR Fixed[11]; // The 11 Fixed MTRR MSR Values -} x64_MTRR_FIXED_RANGE; - - -typedef union { - struct { - UINT64 Type:8; // Memory Type - UINT64 Reserved0:4; // Reserved - UINT64 PhysBase:40; // The physical base address(bits 35..12) of the MTRR - UINT64 Reserved1:12 ; // Reserved - } Bits; - UINT64 Uint64; -} x64_MTRR_PHYSBASE_MSR; - -typedef union { - struct { - UINT64 Reserved0:11; // Reserved - UINT64 Valid:1; // 1=MTRR is valid, 0=MTRR is not valid - UINT64 PhysMask:40; // The physical address mask (bits 35..12) of the MTRR - UINT64 Reserved1:12; // Reserved - } Bits; - UINT64 Uint64; -} x64_MTRR_PHYSMASK_MSR; - -typedef struct { - x64_MTRR_PHYSBASE_MSR PhysBase; // Variable MTRR Physical Base MSR - x64_MTRR_PHYSMASK_MSR PhysMask; // Variable MTRR Physical Mask MSR -} x64_MTRR_VARIABLE_RANGE; - -#pragma pack() - -x64_MTRR_MEMORY_TYPE -EfiGetMTRRMemoryType ( - IN EFI_PHYSICAL_ADDRESS Address - ) -; - -BOOLEAN -CanNotUse2MBPage ( - IN EFI_PHYSICAL_ADDRESS BaseAddress - ) -; - -VOID -Convert2MBPageTo4KPages ( - IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB, - IN EFI_PHYSICAL_ADDRESS PageAddress - ) -; - -EFI_PHYSICAL_ADDRESS -CreateIdentityMappingPageTables ( - IN UINT32 NumberOfProcessorPhysicalAddressBits - ) -; - -#endif diff --git a/EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.dxs b/EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.dxs new file mode 100644 index 0000000..6370d86 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.dxs @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeIpl.dxs + +Abstract: + + Dependency expression file for DXE Initial Program Loader PEIM. + +--*/ + +#include +#include + +DEPENDENCY_START + EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID +DEPENDENCY_END + + diff --git a/EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.h b/EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.h new file mode 100644 index 0000000..5e35042 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/DxeIpl.h @@ -0,0 +1,146 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeIpl.h + +Abstract: + +--*/ + +#ifndef __PEI_DXEIPL_H__ +#define __PEI_DXEIPL_H__ + +#define STACK_SIZE 0x20000 +#define BSP_STORE_SIZE 0x4000 + +extern BOOLEAN gInMemory; + +VOID +SwitchIplStacks ( + VOID *EntryPoint, + UINTN Parameter1, + UINTN Parameter2, + VOID *NewStack, + VOID *NewBsp + ) +; + +EFI_STATUS +PeiFindFile ( + IN UINT8 Type, + IN UINT16 SectionType, + OUT EFI_GUID *FileName, + OUT VOID **Pe32Data + ) +; + +EFI_STATUS +PeiLoadFile ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +; + + +EFI_STATUS +CreateArchSpecificHobs ( + OUT EFI_PHYSICAL_ADDRESS *BspStore + ) +; + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +EFI_STATUS +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +; + +EFI_STATUS +EFIAPI +DxeIplLoadFile ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +EFI_STATUS +ShadowDxeIpl ( + IN EFI_FFS_FILE_HEADER *DxeIpl, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader + ); + +EFI_STATUS +EFIAPI +DxeLoadCore ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ); + +EFI_STATUS +PeiProcessFile ( + IN UINT16 SectionType, + IN OUT EFI_FFS_FILE_HEADER **RealFfsFileHeader, + OUT VOID **Pe32Data + ); + +EFI_STATUS +EFIAPI +PeimInitializeDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +PeiLoadx64File ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + IN EFI_MEMORY_TYPE MemoryType, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +; + +EFI_PHYSICAL_ADDRESS +CreateIdentityMappingPageTables ( + IN UINT32 NumberOfProcessorPhysicalAddressBits + ) +; + +VOID +ActivateLongMode ( + IN EFI_PHYSICAL_ADDRESS PageTables, + IN EFI_PHYSICAL_ADDRESS HobStart, + IN EFI_PHYSICAL_ADDRESS Stack, + IN EFI_PHYSICAL_ADDRESS CodeEntryPoint1, + IN EFI_PHYSICAL_ADDRESS CodeEntryPoint2 + ); + +VOID +LoadGo64Gdt(); + +#endif diff --git a/EdkModulePkg/Core/DxeIplX64Peim/DxeIplX64.msa b/EdkModulePkg/Core/DxeIplX64Peim/DxeIplX64.msa new file mode 100644 index 0000000..929a627 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/DxeIplX64.msa @@ -0,0 +1,145 @@ + + + + + DxeIplX64 + PEIM + 0c55bdf7-d71d-4962-8fcb-348773e48929 + 1.0 + Component description file for DxeIplX64 module + The responsibility of this module is to load the DXE Core from a Firmware Volume. This implementation i used to load a 64-bit DXE Core. + Copyright 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. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 + false + DxeIplX64 + + + + DebugLib + + + PeimEntryPoint + + + BaseLib + + + HobLib + + + PerformanceLib + + + PeiServicesLib + + + ReportStatusCodeLib + + + CacheMaintenanceLib + + + EdkPeCoffLoaderLib + + + UefiDecompressLib + + + TianoDecompressLib + + + CustomDecompressLib + + + PeiServicesTablePointerLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + EdkPeCoffLoaderX64Lib + + + + DxeIpl.dxs + DxeIpl.h + DxeLoadX64.c + x64/ImageRead.c + x64/LongMode.asm + x64/DxeLoadFunc.c + x64/VirtualMemory.h + x64/VirtualMemory.c + + + + + + + + gEfiDecompressProtocolGuid + + + gEfiTianoDecompressProtocolGuid + + + gEfiCustomizedDecompressProtocolGuid + + + + + gEfiDxeIplPpiGuid + + + gEfiPeiFvFileLoaderPpiGuid + + + gEfiEndOfPeiSignalPpiGuid + + + gEfiPeiRecoveryModulePpiGuid + + + gEfiPeiS3ResumePpiGuid + + + gEfiPeiSectionExtractionPpiGuid + + + gEfiPeiSecurityPpiGuid + + + gPeiInMemoryGuid + + + + + gEfiPeiPeCoffLoaderGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + PeimInitializeDxeIpl + + + \ No newline at end of file diff --git a/EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c b/EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c new file mode 100644 index 0000000..cbb7595 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c @@ -0,0 +1,997 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeLoad.c + +Abstract: + + Last PEIM. + Responsibility of this module is to load the DXE Core from a Firmware Volume. + +--*/ + +#include + +#pragma warning( disable : 4305 ) + +BOOLEAN gInMemory = FALSE; + +// +// GUID for EM64T +// +#define EFI_PPI_NEEDED_BY_DXE \ + { \ + 0x4d37da42, 0x3a0c, 0x4eda, 0xb9, 0xeb, 0xbc, 0x0e, 0x1d, 0xb4, 0x71, 0x3b \ + } +EFI_GUID mPpiNeededByDxeGuid = EFI_PPI_NEEDED_BY_DXE; + +// +// Module Globals used in the DXE to PEI handoff +// These must be module globals, so the stack can be switched +// +static EFI_DXE_IPL_PPI mDxeIplPpi = { + DxeLoadCore +}; + +static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = { + DxeIplLoadFile +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiFvFileLoaderPpiGuid, + &mLoadFilePpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiDxeIplPpiGuid, + &mDxeIplPpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiInMemoryGuid, + NULL +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + NULL +}; + +DECOMPRESS_LIBRARY gEfiDecompress = { + UefiDecompressGetInfo, + UefiDecompress +}; + +DECOMPRESS_LIBRARY gTianoDecompress = { + TianoDecompressGetInfo, + TianoDecompress +}; + +DECOMPRESS_LIBRARY gCustomDecompress = { + CustomDecompressGetInfo, + CustomDecompress +}; + +STATIC +UINTN +GetOccupiedSize ( + IN UINTN ActualSize, + IN UINTN Alignment + ) +{ + UINTN OccupiedSize; + + OccupiedSize = ActualSize; + while ((OccupiedSize & (Alignment - 1)) != 0) { + OccupiedSize++; + } + + return OccupiedSize; +} + +EFI_STATUS +EFIAPI +PeimInitializeDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Initializes the Dxe Ipl PPI + +Arguments: + + FfsHeader - Pointer to FFS file header + PeiServices - General purpose services available to every PEIM. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + + Status = PeiServicesGetBootMode (&BootMode); + + ASSERT_EFI_ERROR (Status); + + Status = PeiServicesLocatePpi ( + &gPeiInMemoryGuid, + 0, + NULL, + NULL + ); + + if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) { + // + // The DxeIpl has not yet been shadowed + // + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Shadow DxeIpl and then re-run its entry point + // + Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader); + if (EFI_ERROR (Status)) { + return Status; + } + + } else { + if (BootMode != BOOT_ON_S3_RESUME) { + // + // The DxeIpl has been shadowed + // + gInMemory = TRUE; + + // + // Install LoadFile PPI + // + Status = PeiServicesInstallPpi (&mPpiLoadFile); + + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // Install DxeIpl PPI + // + PeiServicesInstallPpi (&mPpiList); + + if (EFI_ERROR (Status)) { + return Status; + } + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DxeLoadCore ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ) +/*++ + +Routine Description: + + Main entry point to last PEIM + +Arguments: + + This - Entry point for DXE IPL PPI + PeiServices - General purpose services available to every PEIM. + HobList - Address to the Pei HOB list + +Returns: + + EFI_SUCCESS - DEX core was successfully loaded. + EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TopOfStack; + EFI_PHYSICAL_ADDRESS BaseOfStack; + EFI_PHYSICAL_ADDRESS BspStore; + EFI_GUID DxeCoreFileName; + VOID *DxeCorePe32Data; + EFI_PHYSICAL_ADDRESS DxeCoreAddress; + UINT64 DxeCoreSize; + EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; + EFI_PEI_S3_RESUME_PPI *S3Resume; + EFI_PHYSICAL_ADDRESS PageTables; + + TopOfStack = 0; + BaseOfStack = 0; + BspStore = 0; + Status = EFI_SUCCESS; + + // + // if in S3 Resume, restore configure + // + Status = PeiServicesGetBootMode (&BootMode); + + if (!EFI_ERROR (Status) && (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 + // +#ifdef EFI_NT_EMULATOR + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + ASSERT (PeiEfiPeiPeCoffLoader != NULL); +#else + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderX64Protocol (); +#endif + +#if 0 + Status = InstallEfiPeiPeCoffLoader64 (PeiServices, &PeiEfiPeiPeCoffLoader, NULL); + ASSERT_EFI_ERROR (Status); +#endif + // + // Allocate 128KB for the Stack + // + PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); + ASSERT (BaseOfStack != 0); + + // + // Compute the top of the stack we were allocated. Pre-allocate a 32 bytes + // for safety (PpisNeededByDxe and DxeCore). + // + TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; + + // + // Add architecture-specifc HOBs (including the BspStore HOB) + // + Status = CreateArchSpecificHobs (&BspStore); + ASSERT_EFI_ERROR (Status); + + // + // See if we are in crisis recovery + // + Status = PeiServicesGetBootMode (&BootMode); + if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) { + Status = PeiServicesLocatePpi ( + &gEfiPeiRecoveryModulePpiGuid, + 0, + NULL, + (VOID **)&PeiRecovery + ); + + ASSERT_EFI_ERROR (Status); + Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); + ASSERT_EFI_ERROR (Status); + } + + // + // Find the DXE Core in a Firmware Volume + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_DXE_CORE, + EFI_SECTION_PE32, + &DxeCoreFileName, + &DxeCorePe32Data + ); + ASSERT_EFI_ERROR (Status); + + // + // Transfer control to the DXE Core + // The handoff state is simply a pointer to the HOB list + // + // PEI_PERF_END (PeiServices, L"DxeIpl", NULL, 0); + + Status = PeiServicesInstallPpi (&mPpiSignal); + ASSERT_EFI_ERROR (Status); + + // + // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \ + // memory, it may be corrupted when copying FV to high-end memory + LoadGo64Gdt(); + + // + // Limit to 36 bits of addressing for debug. Should get it from CPU + // + PageTables = CreateIdentityMappingPageTables (36); + + + // + // Load the DXE Core from a Firmware Volume + // + Status = PeiLoadx64File ( + PeiEfiPeiPeCoffLoader, + DxeCorePe32Data, + EfiBootServicesData, + &DxeCoreAddress, + &DxeCoreSize, + &DxeCoreEntryPoint + ); + ASSERT_EFI_ERROR (Status); + + // + // + // Add HOB for the DXE Core + // + BuildModuleHob ( + &DxeCoreFileName, + DxeCoreAddress, + DxeCoreSize, + DxeCoreEntryPoint + ); + + // + // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT + ); + + DEBUG ((EFI_D_INFO, "DXE Core Entry\n")); + // + // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded. + // Call x64 drivers passing in single argument, a pointer to the HOBs. + // + ActivateLongMode ( + PageTables, + (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), + TopOfStack, + 0x00000000, + DxeCoreEntryPoint + ); + + // + // If we get here, then the DXE Core returned. This is an error + // + ASSERT_EFI_ERROR (Status); + + return EFI_OUT_OF_RESOURCES; +} + +EFI_STATUS +PeiFindFile ( + IN UINT8 Type, + IN UINT16 SectionType, + OUT EFI_GUID *FileName, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + + Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes + described in the HOB list. Able to search in a compression set in a FFS file. + But only one level of compression is supported, that is, not able to search + in a compression set that is within another compression set. + +Arguments: + + Type - The Type of file to retrieve + + SectionType - The type of section to retrieve from a file + + FileName - The name of the file found in the Firmware Volume + + Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume + +Returns: + + EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to + the PE/COFF image is returned in Pe32Data + + EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + VOID *SectionData; + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + + + FwVolHeader = NULL; + FfsFileHeader = NULL; + SectionData = NULL; + + // + // Foreach Firmware Volume, look for a specified type + // of file and break out when one is found + // + Hob.Raw = GetHobList (); + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) { + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress); + Status = PeiServicesFfsFindNextFile ( + Type, + FwVolHeader, + &FfsFileHeader + ); + if (!EFI_ERROR (Status)) { + Status = PeiProcessFile ( + SectionType, + &FfsFileHeader, + Pe32Data + ); + CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID)); + return Status; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +PeiLoadx64File ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + IN EFI_MEMORY_TYPE MemoryType, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Loads and relocates a PE/COFF image into memory. + +Arguments: + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + + Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + + ImageAddress - The base address of the relocated PE/COFF image + + ImageSize - The size of the relocated PE/COFF image + + EntryPoint - The entry point of the relocated PE/COFF image + +Returns: + + EFI_SUCCESS - The file was loaded and relocated + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_PHYSICAL_ADDRESS MemoryBuffer; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + Status = GetImageReadFunction (&ImageContext); + + ASSERT_EFI_ERROR (Status); + + Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + // + // Allocate Memory for the image + // + PeiServicesAllocatePages (MemoryType, EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), &MemoryBuffer); + ImageContext.ImageAddress = MemoryBuffer; + ASSERT (ImageContext.ImageAddress != 0); + + // + // Load the image to our new buffer + // + + Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return EFI_SUCCESS; +} + +EFI_STATUS +ShadowDxeIpl ( + IN EFI_FFS_FILE_HEADER *DxeIplFileHeader, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader + ) +/*++ + +Routine Description: + + Shadow the DXE IPL to a different memory location. This occurs after permanent + memory has been discovered. + +Arguments: + + DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + +Returns: + + EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location. + + EFI_ ERROR - The shadow was unsuccessful. + + +--*/ +{ + UINTN SectionLength; + UINTN OccupiedSectionLength; + EFI_PHYSICAL_ADDRESS DxeIplAddress; + UINT64 DxeIplSize; + EFI_PHYSICAL_ADDRESS DxeIplEntryPoint; + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1); + + while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + } + + // + // Relocate DxeIpl into memory by using loadfile service + // + Status = PeiLoadx64File ( + PeiEfiPeiPeCoffLoader, + (VOID *) (Section + 1), + EfiBootServicesData, + &DxeIplAddress, + &DxeIplSize, + &DxeIplEntryPoint + ); + + if (Status == EFI_SUCCESS) { + // + // Install PeiInMemory to indicate the Dxeipl is shadowed + // + Status = PeiServicesInstallPpi (&mPpiPeiInMemory); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer()); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DxeIplLoadFile ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Given a pointer to an FFS file containing a PE32 image, get the + information on the PE32 image, and then "load" it so that it + can be executed. + +Arguments: + + This - pointer to our file loader protocol + FfsHeader - pointer to the FFS file header of the FFS file that + contains the PE32 image we want to load + ImageAddress - returned address where the PE32 image is loaded + ImageSize - returned size of the loaded PE32 image + EntryPoint - entry point to the loaded PE32 image + +Returns: + + EFI_SUCCESS - The FFS file was successfully loaded. + EFI_ERROR - Unable to load the FFS file. + +--*/ +{ + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_STATUS Status; + VOID *Pe32Data; + + Pe32Data = NULL; + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Preprocess the FFS file to get a pointer to the PE32 information + // in the enclosed PE32 image. + // + Status = PeiProcessFile ( + EFI_SECTION_PE32, + &FfsHeader, + &Pe32Data + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Load the PE image from the FFS file + // + Status = PeiLoadx64File ( + PeiEfiPeiPeCoffLoader, + Pe32Data, + EfiBootServicesData, + ImageAddress, + ImageSize, + EntryPoint + ); + + return Status; +} + +EFI_STATUS +PeiProcessFile ( + IN UINT16 SectionType, + IN OUT EFI_FFS_FILE_HEADER **RealFfsFileHeader, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + +Arguments: + + SectionType - The type of section in the FFS file to process. + + FfsFileHeader - Pointer to the FFS file to process, looking for the + specified SectionType + + Pe32Data - returned pointer to the start of the PE32 image found + in the FFS file. + +Returns: + + EFI_SUCCESS - found the PE32 section in the FFS file + +--*/ +{ + EFI_STATUS Status; + VOID *SectionData; + DECOMPRESS_LIBRARY *DecompressLibrary; + UINT8 *DstBuffer; + UINT8 *ScratchBuffer; + UINT32 DstBufferSize; + UINT32 ScratchBufferSize; + EFI_COMMON_SECTION_HEADER *CmpSection; + UINTN CmpSectionLength; + UINTN OccupiedCmpSectionLength; + VOID *CmpFileData; + UINTN CmpFileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN SectionLength; + UINTN OccupiedSectionLength; + UINT64 FileSize; + EFI_GUID_DEFINED_SECTION *GuidedSectionHeader; + UINT32 AuthenticationStatus; + EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract; + UINT32 BufferSize; + UINT8 *Buffer; + EFI_PEI_SECURITY_PPI *Security; + BOOLEAN StartCrisisRecovery; + EFI_GUID TempGuid; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_COMPRESSION_SECTION *CompressionSection; + EFI_FFS_FILE_HEADER *FfsFileHeader; + + FfsFileHeader = *RealFfsFileHeader; + + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_COMPRESSION, + FfsFileHeader, + &SectionData + ); + + // + // Upon finding a DXE Core file, see if there is first a compression section + // + if (!EFI_ERROR (Status)) { + // + // Yes, there is a compression section, so extract the contents + // Decompress the image here + // + Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER)); + + do { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); + + // + // Was the DXE Core file encapsulated in a GUID'd section? + // + if (Section->Type == EFI_SECTION_GUID_DEFINED) { + // + // Locate the GUID'd Section Extractor + // + GuidedSectionHeader = (VOID *) (Section + 1); + + // + // This following code constitutes the addition of the security model + // to the DXE IPL. + // + // + // Set a default authenticatino state + // + AuthenticationStatus = 0; + + Status = PeiServicesLocatePpi ( + &gEfiPeiSectionExtractionPpiGuid, + 0, + NULL, + (VOID **)&SectionExtract + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Verify Authentication State + // + CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID)); + + Status = SectionExtract->PeiGetSection ( + GetPeiServicesTablePointer(), + SectionExtract, + (EFI_SECTION_TYPE *) &SectionType, + &TempGuid, + 0, + (VOID **) &Buffer, + &BufferSize, + &AuthenticationStatus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If not ask the Security PPI, if exists, for disposition + // + // + Status = PeiServicesLocatePpi ( + &gEfiPeiSecurityPpiGuid, + 0, + NULL, + (VOID **)&Security + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Security->AuthenticationState ( + GetPeiServicesTablePointer(), + (struct _EFI_PEI_SECURITY_PPI *) Security, + AuthenticationStatus, + FfsFileHeader, + &StartCrisisRecovery + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If there is a security violation, report to caller and have + // the upper-level logic possible engender a crisis recovery + // + if (StartCrisisRecovery) { + return EFI_SECURITY_VIOLATION; + } + } + + if (Section->Type == EFI_SECTION_PE32) { + // + // This is what we want + // + *Pe32Data = (VOID *) (Section + 1); + return EFI_SUCCESS; + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + // + // This is a compression set, expand it + // + CompressionSection = (EFI_COMPRESSION_SECTION *) Section; + + switch (CompressionSection->CompressionType) { + case EFI_STANDARD_COMPRESSION: + DecompressLibrary = &gTianoDecompress; + break; + + case EFI_CUSTOMIZED_COMPRESSION: + // + // Load user customized compression protocol. + // + DecompressLibrary = &gCustomDecompress; + break; + + case EFI_NOT_COMPRESSED: + default: + // + // Need to support not compressed file + // + ASSERT_EFI_ERROR (Status); + return EFI_NOT_FOUND; + } + + Status = DecompressLibrary->GetInfo ( + (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), + &DstBufferSize, + &ScratchBufferSize + ); + if (EFI_ERROR (Status)) { + // + // GetInfo failed + // + return EFI_NOT_FOUND; + } + + // + // Allocate scratch buffer + // + ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); + if (ScratchBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Allocate destination buffer + // + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Call decompress function + // + Status = DecompressLibrary->Decompress ( + (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + DstBuffer, + ScratchBuffer + ); + + CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer; + if (CmpSection->Type == EFI_SECTION_RAW) { + // + // Skip the section header and + // adjust the pointer alignment to 16 + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16); + + if (FvHeader->Signature == EFI_FVH_SIGNATURE) { + FfsFileHeader = NULL; + BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength); + Status = PeiServicesFfsFindNextFile ( + EFI_FV_FILETYPE_DXE_CORE, + FvHeader, + &FfsFileHeader + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Reture the FfsHeader that contain Pe32Data. + // + *RealFfsFileHeader = FfsFileHeader; + return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data); + } + } + // + // Decompress successfully. + // Loop the decompressed data searching for expected section. + // + CmpFileData = (VOID *) DstBuffer; + CmpFileSize = DstBufferSize; + do { + CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff; + if (CmpSection->Type == EFI_SECTION_PE32) { + // + // This is what we want + // + *Pe32Data = (VOID *) (CmpSection + 1); + return EFI_SUCCESS; + } + + OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4); + CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength); + } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize); + } + + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + FileSize = FfsFileHeader->Size[0] & 0xFF; + FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00; + FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000; + FileSize &= 0x00FFFFFF; + } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize); + + // + // End of the decompression activity + // + } else { + + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_PE32, + FfsFileHeader, + &SectionData + ); + + if (EFI_ERROR (Status)) { + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_TE, + FfsFileHeader, + &SectionData + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + *Pe32Data = SectionData; + + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/EdkModulePkg/Core/DxeIplX64Peim/x64/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplX64Peim/x64/DxeLoadFunc.c new file mode 100644 index 0000000..c93c7e1 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/x64/DxeLoadFunc.c @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeLoadFunc.c + +Abstract: + + Ia32-specifc functionality for DxeLoad X64 Lakeport. + +--*/ + +#include + +EFI_STATUS +CreateArchSpecificHobs ( + OUT EFI_PHYSICAL_ADDRESS *BspStore + ) +/*++ + +Routine Description: + + Creates architecture-specific HOBs. + + Note: New parameters should NOT be added for any HOBs that are added to this + function. BspStore is a special case because it is required for the + call to SwitchStacks() in DxeLoad(). + +Arguments: + + PeiServices - General purpose services available to every PEIM. + BspStore - The address of the BSP Store for those architectures that need + it. Otherwise 0. + +Returns: + + EFI_SUCCESS - The HOBs were created successfully. + +--*/ +{ + *BspStore = 0; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplX64Peim/x64/ImageRead.c b/EdkModulePkg/Core/DxeIplX64Peim/x64/ImageRead.c new file mode 100644 index 0000000..dd977f2 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/x64/ImageRead.c @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ImageRead.c + +Abstract: + +--*/ + +#include + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Support routine to return the PE32 Image Reader. + If the PeiImageRead() function is less than a page + in legnth. If the function is more than a page the DXE IPL will crash!!!! + +Arguments: + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS - If Image function location is found + +--*/ +{ + VOID *MemoryBuffer; + + if (gInMemory) { + ImageContext->ImageRead = PeiImageRead; + return EFI_SUCCESS; + } + + // + // BugBug; This code assumes PeiImageRead() is less than a page in size! + // Allocate a page so we can shaddow the read function from FLASH into + // memory to increase performance. + // + + MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead); + ASSERT (MemoryBuffer != NULL); + + ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplX64Peim/x64/LongMode.asm b/EdkModulePkg/Core/DxeIplX64Peim/x64/LongMode.asm new file mode 100644 index 0000000..ae87bd8 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/x64/LongMode.asm @@ -0,0 +1,1350 @@ + 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: + +; +; +;------------------------------------------------------------------------------ +; Generic IDT Vector Handlers for the Host. They are all the same so they +; will compress really well. +; +; By knowing the return address for Vector 00 you can can calculate the +; vector number by looking at the call CommonInterruptEntry return address. +; (return address - AsmIdtVector00Base)/8 == IDT index +; +;------------------------------------------------------------------------------ + +_AsmIdtVector00 PROC NEAR PUBLIC + call CommonInterruptEntry +_AsmIdtVector00 ENDP +AsmIdtVector00Base PROC NEAR PUBLIC + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop +AsmIdtVector00Base ENDP + + +;---------------------------------------; +; CommonInterruptEntry ; +;---------------------------------------; +; The follow algorithm is used for the common interrupt routine. +; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition +; +; +CommonInterruptEntry PROC NEAR PUBLIC + cli + jmp $ + iret + +CommonInterruptEntry ENDP + +END + diff --git a/EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.c b/EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.c new file mode 100644 index 0000000..40eaed2 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.c @@ -0,0 +1,434 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.c + +Abstract: + + x64 Virtual Memory Management Services in the form of an IA-32 driver. + Used to establish a 1:1 Virtual to Physical Mapping that is required to + enter Long Mode (x64 64-bit mode). + + While we make a 1:1 mapping (identity mapping) for all physical pages + we still need to use the MTRR's to ensure that the cachability attirbutes + for all memory regions is correct. + + The basic idea is to use 2MB page table entries where ever possible. If + more granularity of cachability is required then 4K page tables are used. + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + +--*/ + +#include "VirtualMemory.h" + +x64_MTRR_VARIABLE_RANGE *mMTRRVariableRange; +x64_MTRR_FIXED_RANGE mMTRRFixedRange; + + +// +// Physial memory limit values for each of the 11 fixed MTRRs +// +UINTN mFixedRangeLimit[] = { + 0x7FFFF, // Fixed MTRR #0 describes 0x00000..0x7FFFF + 0x9FFFF, // Fixed MTRR #1 describes 0x80000..0x9FFFF + 0xBFFFF, // Fixed MTRR #2 describes 0xA0000..0xBFFFF + 0xC7FFF, // Fixed MTRR #3 describes 0xC0000..0xC7FFF + 0xCFFFF, // Fixed MTRR #4 describes 0xC8000..0xCFFFF + 0xD7FFF, // Fixed MTRR #5 describes 0xD0000..0xD7FFF + 0xDFFFF, // Fixed MTRR #6 describes 0xD8000..0xDFFFF + 0xE7FFF, // Fixed MTRR #7 describes 0xE0000..0xE7FFF + 0xEFFFF, // Fixed MTRR #8 describes 0xE8000..0xEFFFF + 0xF7FFF, // Fixed MTRR #9 describes 0xF0000..0xF7FFF + 0xFFFFF // Fixed MTRR #10 describes 0xF8000..0xFFFFF +}; + +// +// The size, in bits, of each of the 11 fixed MTRR. +// +UINTN mFixedRangeShift[] = { + 16, // Fixed MTRR #0 describes 8, 64 KB ranges + 14, // Fixed MTRR #1 describes 8, 16 KB ranges + 14, // Fixed MTRR #2 describes 8, 16 KB ranges + 12, // Fixed MTRR #3 describes 8, 4 KB ranges + 12, // Fixed MTRR #4 describes 8, 4 KB ranges + 12, // Fixed MTRR #5 describes 8, 4 KB ranges + 12, // Fixed MTRR #6 describes 8, 4 KB ranges + 12, // Fixed MTRR #7 describes 8, 4 KB ranges + 12, // Fixed MTRR #8 describes 8, 4 KB ranges + 12, // Fixed MTRR #9 describes 8, 4 KB ranges + 12 // Fixed MTRR #10 describes 8, 4 KB ranges +}; + + +UINTN mPowerOf2[] = { + 1, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 512 +}; + +x64_MTRR_MEMORY_TYPE +EfiGetMTRRMemoryType ( + IN EFI_PHYSICAL_ADDRESS Address + ) +/*++ + +Routine Description: + + Retrieves the memory type from the MTRR that describes a physical address. + +Arguments: + + VariableRange - Set of Variable MTRRs + + FixedRange - Set of Fixed MTRRs + + Address - The physical address for which the MTRR memory type is being retrieved + +Returns: + + The MTRR Memory Type for the physical memory specified by Address. + +--*/ +{ + UINTN Index; + UINTN TypeIndex; + BOOLEAN Found; + x64_MTRR_MEMORY_TYPE VariableType; + EFI_PHYSICAL_ADDRESS MaskBase; + EFI_PHYSICAL_ADDRESS PhysMask; + + // + // If the MTRRs are disabled, then return the Uncached Memory Type + // + if (mMTRRFixedRange.DefaultType.Bits.E == 0) { + return Uncached; + } + + // + // If the CPU supports Fixed MTRRs and the Fixed MTRRs are enabled, then + // see if Address falls into one of the Fixed MTRRs + // + if (mMTRRFixedRange.Capabilities.Bits.FIX && mMTRRFixedRange.DefaultType.Bits.FE) { + // + // Loop though 11 fixed MTRRs + // + for (Index = 0; Index < 11; Index++) { + // + // Check for a matching range + // + if (Address <= mFixedRangeLimit[Index]) { + // + // Compute the offset address into the MTRR bu subtrating the base address of the MTRR + // + if (Index > 0) { + Address = Address - (mFixedRangeLimit[Index-1] + 1); + } + // + // Retrieve the index into the MTRR to extract the memory type. The range is 0..7 + // + TypeIndex = (UINTN)RShiftU64 (Address, mFixedRangeShift[Index]); + + // + // Retrieve and return the memory type for the matching range + // + return mMTRRFixedRange.Fixed[Index].Type[TypeIndex]; + } + } + } + + // + // If Address was not found in a Fixed MTRR, then search the Variable MTRRs + // + for (Index = 0, Found = FALSE, VariableType = WriteBack; Index < mMTRRFixedRange.Capabilities.Bits.VCNT; Index++) { + // + // BugBug: __aullshr complier error + // + if ((mMTRRVariableRange[Index].PhysMask.Uint64 & 0x800) == 0x800) { + //if (mMTRRVariableRange[Index].PhysMask.Bits.Valid == 1) { + PhysMask = mMTRRVariableRange[Index].PhysMask.Uint64 & ~0xfff; + MaskBase = PhysMask & (mMTRRVariableRange[Index].PhysBase.Uint64 & ~0xfff); + if (MaskBase == (PhysMask & Address)) { + // + // Check to see how many matches we find + // + Found = TRUE; + if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == Uncached) || (VariableType == Uncached)) { + // + // If any matching region uses UC, the memory region is UC + // + VariableType = Uncached; + } else if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == WriteThrough) || (VariableType == WriteThrough)){ + // + // If it's WT and WB then set it to WT. If it's WT and other type it's undefined + // + VariableType = WriteThrough; + } else { + VariableType = mMTRRVariableRange[Index].PhysBase.Bits.Type; + } + } + } + } + + if (Found) { + return VariableType; + } + + // + // Address was not found in the Fixed or Variable MTRRs, so return the default memory type + // + return mMTRRFixedRange.DefaultType.Bits.Type; +} + + +BOOLEAN +CanNotUse2MBPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +/*++ + +Routine Description: + Test to see if a 2MB aligned page has all the same attributes. If a 2MB page + has more than one attibute type it needs to be split into multiple 4K pages. + +Arguments: + BaseAddress - 2MB aligned address to check out + +Returns: + TRUE - This 2MB address range (BaseAddress) can NOT be mapped by a 2MB page + FALSE - This 2MB address range can be mapped by a 2MB page + +--*/ +{ + UINTN Index; + x64_MTRR_MEMORY_TYPE MemoryType; + x64_MTRR_MEMORY_TYPE PreviousMemoryType; + + // + // Address needs to be 2MB aligned + // + ASSERT ((BaseAddress & 0x1fffff) == 0); + + PreviousMemoryType = -1; + for (Index = 0; Index < 512; Index++, BaseAddress += 0x1000) { + MemoryType = EfiGetMTRRMemoryType (BaseAddress); + if ((Index != 0) && (MemoryType != PreviousMemoryType)) { + return TRUE; + } + + PreviousMemoryType = MemoryType; + } + + // + // All the pages had the same type + // + return FALSE; +} + + + + +VOID +Convert2MBPageTo4KPages ( + IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB, + IN EFI_PHYSICAL_ADDRESS PageAddress + ) +/*++ + +Routine Description: + Convert a single 2MB page entry to 512 4K page entries. The attributes for + the 4K pages are read from the MTRR registers. + +Arguments: + PageDirectoryEntry2MB - Page directory entry for PageAddress + PageAddress - 2MB algined address of region to convert + +Returns: + None + +--*/ +{ + EFI_PHYSICAL_ADDRESS Address; + x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k; + x64_PAGE_TABLE_ENTRY_4K *PageTableEntry; + UINTN Index1; + + // + // Allocate the page table entry for the 4K pages + // + PageTableEntry = (x64_PAGE_TABLE_ENTRY_4K *) AllocatePages (1); + + ASSERT (PageTableEntry != NULL); + + // + // Convert PageDirectoryEntry2MB into a 4K Page Directory + // + PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *)PageDirectoryEntry2MB; + PageDirectoryEntry2MB->Uint64 = (UINT64)PageTableEntry; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + + // + // Fill in the 4K page entries with the attributes from the MTRRs + // + for (Index1 = 0, Address = PageAddress; Index1 < 512; Index1++, PageTableEntry++, Address += 0x1000) { + PageTableEntry->Uint64 = (UINT64)Address; + PageTableEntry->Bits.ReadWrite = 1; + PageTableEntry->Bits.Present = 1; + } +} + + +EFI_PHYSICAL_ADDRESS +CreateIdentityMappingPageTables ( + IN UINT32 NumberOfProcessorPhysicalAddressBits + ) +/*++ + +Routine Description: + + Allocates and fills in the Page Directory and Page Table Entries to + establish a 1:1 Virtual to Physical mapping for physical memory from + 0 to 4GB. Memory above 4GB is not mapped. The MTRRs are used to + determine the cachability of the physical memory regions + +Arguments: + + NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use. + Limits the number of page table entries + to the physical address space. + +Returns: + EFI_OUT_OF_RESOURCES There are not enough resources to allocate the Page Tables + + EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created + +--*/ +{ + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN Index; + UINTN MaxBitsSupported; + UINTN Index1; + UINTN Index2; + x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; + x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMap; + x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; + x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; + + + // + // Page Table structure 4 level 4K, 3 level 2MB. + // + // PageMapLevel4Entry : bits 47-39 + // PageDirectoryPointerEntry : bits 38-30 + // Page Table 2MB : PageDirectoryEntry2M : bits 29-21 + // Page Table 4K : PageDirectoryEntry4K : bits 29 - 21 + // PageTableEntry : bits 20 - 12 + // + // Strategy is to map every thing in the processor address space using + // 2MB pages. If more granularity is required the 2MB page will get + // converted to set of 4K pages. + // + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it. + // + PageMap = PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1); + ASSERT (PageMap != NULL); + PageAddress = 0; + + // + // The number of page-map Level-4 Offset entries is based on the number of + // physical address bits. Less than equal to 38 bits only takes one entry. + // 512 entries represents 48 address bits. + // + if (NumberOfProcessorPhysicalAddressBits <= 38) { + MaxBitsSupported = 1; + } else { + MaxBitsSupported = mPowerOf2[NumberOfProcessorPhysicalAddressBits - 39]; + } + + for (Index = 0; Index < MaxBitsSupported; Index++, PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // So lets allocate space for them and fill them in in the Index1 loop. + // + PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1); + ASSERT (PageDirectoryPointerEntry != NULL); + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry; + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (Index1 = 0; Index1 < 512; Index1++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So lets allocate space for them and fill them in in the Index2 loop. + // + PageDirectoryEntry2MB = (x64_PAGE_TABLE_ENTRY_2M *) AllocatePages (1); + ASSERT (PageDirectoryEntry2MB != NULL); + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry2MB; + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (Index2 = 0; Index2 < 512; Index2++, PageDirectoryEntry2MB++, PageAddress += 0x200000) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + PageDirectoryEntry2MB->Bits.MustBe1 = 1; + + if (CanNotUse2MBPage (PageAddress)) { + // + // Check to see if all 2MB has the same mapping. If not convert + // to 4K pages by adding the 4th level of page table entries + // + Convert2MBPageTo4KPages (PageDirectoryEntry2MB, PageAddress); + } + } + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // for now we just copy the first entry. + // + for (; Index < 512; Index++, PageMapLevel4Entry++) { + // EfiCopyMem (PageMapLevel4Entry, PageMap, sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K)); + CopyMem (PageMapLevel4Entry, + PageMap, + sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K) + ); + } + + return (EFI_PHYSICAL_ADDRESS)PageMap; +} + diff --git a/EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.h b/EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.h new file mode 100644 index 0000000..8133ad4 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplX64Peim/x64/VirtualMemory.h @@ -0,0 +1,239 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.h + +Abstract: + + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming +--*/ +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; + +// +// Page-Directory Offset 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:1; // Must Be Zero + UINT64 Reserved2:1; // Reserved + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} x64_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // 0 = Ignore Page Attribute Table + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} x64_PAGE_TABLE_ENTRY_4K; + + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} x64_PAGE_TABLE_ENTRY_2M; + +typedef union { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 Reserved:57; +} x64_PAGE_TABLE_ENTRY_COMMON; + +typedef union { + x64_PAGE_TABLE_ENTRY_4K Page4k; + x64_PAGE_TABLE_ENTRY_2M Page2Mb; + x64_PAGE_TABLE_ENTRY_COMMON Common; +} x64_PAGE_TABLE_ENTRY; + +// +// MTRR Definitions +// +typedef enum { + Uncached = 0, + WriteCombining = 1, + WriteThrough = 4, + WriteProtected = 5, + WriteBack = 6 +} x64_MTRR_MEMORY_TYPE; + +typedef union { + struct { + UINT32 VCNT:8; // The number of Variable Range MTRRs + UINT32 FIX:1; // 1=Fixed Range MTRRs supported. 0=Fixed Range MTRRs not supported + UINT32 Reserved_0; // Reserved + UINT32 WC:1; // Write combining memory type supported + UINT32 Reserved_1:21; // Reserved + UINT32 Reserved_2:32; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRRCAP_MSR; + +typedef union { + struct { + UINT32 Type:8; // Default Memory Type + UINT32 Reserved_0:2; // Reserved + UINT32 FE:1; // 1=Fixed Range MTRRs enabled. 0=Fixed Range MTRRs disabled + UINT32 E:1; // 1=MTRRs enabled, 0=MTRRs disabled + UINT32 Reserved_1:20; // Reserved + UINT32 Reserved_2:32; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRR_DEF_TYPE_MSR; + +typedef union { + UINT8 Type[8]; // The 8 Memory Type values in the 64-bit MTRR + UINT64 Uint64; // The full 64-bit MSR +} x64_MTRR_FIXED_RANGE_MSR; + +typedef struct { + x64_MTRRCAP_MSR Capabilities; // MTRR Capabilities MSR value + x64_MTRR_DEF_TYPE_MSR DefaultType; // Default Memory Type MSR Value + x64_MTRR_FIXED_RANGE_MSR Fixed[11]; // The 11 Fixed MTRR MSR Values +} x64_MTRR_FIXED_RANGE; + + +typedef union { + struct { + UINT64 Type:8; // Memory Type + UINT64 Reserved0:4; // Reserved + UINT64 PhysBase:40; // The physical base address(bits 35..12) of the MTRR + UINT64 Reserved1:12 ; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRR_PHYSBASE_MSR; + +typedef union { + struct { + UINT64 Reserved0:11; // Reserved + UINT64 Valid:1; // 1=MTRR is valid, 0=MTRR is not valid + UINT64 PhysMask:40; // The physical address mask (bits 35..12) of the MTRR + UINT64 Reserved1:12; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRR_PHYSMASK_MSR; + +typedef struct { + x64_MTRR_PHYSBASE_MSR PhysBase; // Variable MTRR Physical Base MSR + x64_MTRR_PHYSMASK_MSR PhysMask; // Variable MTRR Physical Mask MSR +} x64_MTRR_VARIABLE_RANGE; + +#pragma pack() + +x64_MTRR_MEMORY_TYPE +EfiGetMTRRMemoryType ( + IN EFI_PHYSICAL_ADDRESS Address + ) +; + +BOOLEAN +CanNotUse2MBPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +; + +VOID +Convert2MBPageTo4KPages ( + IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB, + IN EFI_PHYSICAL_ADDRESS PageAddress + ) +; + +EFI_PHYSICAL_ADDRESS +CreateIdentityMappingPageTables ( + IN UINT32 NumberOfProcessorPhysicalAddressBits + ) +; + +#endif diff --git a/EdkModulePkg/EdkModulePkg.spd b/EdkModulePkg/EdkModulePkg.spd index 15ec1d8..96af0e1 100644 --- a/EdkModulePkg/EdkModulePkg.spd +++ b/EdkModulePkg/EdkModulePkg.spd @@ -96,7 +96,7 @@ Bus/Usb/UsbMouse/Dxe/UsbMouse.msa Core/Dxe/DxeMain.msa Core/DxeIplPeim/DxeIpl.msa - Core/DxeIplPeim/DxeIplX64.msa + Core/DxeIplX64Peim/DxeIplX64.msa Core/Pei/PeiMain.msa Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.msa Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.msa @@ -151,7 +151,7 @@ Universal/Security/SecurityStub/Dxe/SecurityStub.msa Universal/StatusCode/RuntimeDxe/StatusCode.msa Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa - Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.msa + Universal/UserInterface/DriverSample/DriverSample.msa Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.msa Universal/Variable/Pei/Variable.msa Universal/EmuVariable/RuntimeDxe/EmuVariable.msa diff --git a/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa index 2d0c7d2..fda12ff 100644 --- a/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa +++ b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa @@ -5,8 +5,8 @@ DXE_DRIVER ed3de5c8-c389-44f2-a35e-2ebdc9802a49 1.0 - Component description file for the PEI library. - FIX ME! + EdkPeCoffLoaderLib library instance + This library gets PeCoffLoader Protocol from Hob List 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 diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa index b8d24d7..66555bd 100644 --- a/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa +++ b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa @@ -5,8 +5,8 @@ PEIM 858bbbc9-474f-4556-a361-0ae52a44ffa5 1.0 - Component description file for the PEI library. - FIX ME! + EdkPeCoffLoaderLib library instance + This library provides PeCoffLoader protocol based on PeCoffLib functions. 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 diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa index 50f69b8..aa79f20 100644 --- a/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa +++ b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa @@ -5,8 +5,8 @@ PEIM 6aac37f2-7b46-4ef3-8645-c24800a3d410 1.0 - Component description file for the PEI library. - FIX ME! + EdkPeCoffLoaderX64Lib library instance + This library provides PeCoffLoader protocol to support PE64 image. 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 -- cgit v1.1