From 95276127e373f2e2fb2a208ff77267422a197d9f Mon Sep 17 00:00:00 2001 From: xgu3 Date: Thu, 5 Jul 2007 07:05:28 +0000 Subject: Check in following modules, DxeIpl ConPlatform ConSplitter GraphicsConsole Terminal DevicePath git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3069 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 136 +++++++++++++++++ MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c | 117 +++++++++++++++ MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c | 173 ++++++++++++++++++++++ MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h | 112 ++++++++++++++ 4 files changed, 538 insertions(+) create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h (limited to 'MdeModulePkg/Core/DxeIplPeim/Ia32') diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c new file mode 100644 index 0000000000..d3fbcb2e08 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c @@ -0,0 +1,136 @@ +/*++ + +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. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" +#include "VirtualMemory.h" + +// +// Global Descriptor Table (GDT) +// +GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries [] = { +/* selector { Global Segment Descriptor } */ +/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor +/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor +/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor +/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor +/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor +/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor +/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor +/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor +/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor +}; + +// +// IA32 Gdt register +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = { + sizeof (gGdtEntries) - 1, + (UINTN) gGdtEntries + }; + +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList, + IN EFI_PEI_PPI_DESCRIPTOR *EndOfPeiSignal + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS BaseOfStack; + EFI_PHYSICAL_ADDRESS TopOfStack; + UINTN PageTables; + + Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); + ASSERT_EFI_ERROR (Status); + + if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) { + // + // Compute the top of the stack we were allocated, which is used to load X64 dxe core. + // Pre-allocate a 32 bytes which confroms to x64 calling convention. + // + // The first four parameters to a function are passed in rcx, rdx, r8 and r9. + // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the + // register parameters is reserved on the stack, in case the called function + // wants to spill them; this is important if the function is variadic. + // + TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; + + // + // X64 Calling Conventions requires that the stack must be aligned to 16 bytes + // + TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16); + + // + // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA + // memory, it may be corrupted when copying FV to high-end memory + // + AsmWriteGdtr (&gGdt); + // + // Create page table and save PageMapLevel4 to CR3 + // + PageTables = CreateIdentityMappingPageTables (); + + // + // End of PEI phase singal + // + Status = PeiServicesInstallPpi (EndOfPeiSignal); + ASSERT_EFI_ERROR (Status); + + AsmWriteCr3 (PageTables); + // + // 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. + // + AsmEnablePaging64 ( + SYS_CODE64_SEL, + DxeCoreEntryPoint, + (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), + 0, + TopOfStack + ); + } else { + // + // Compute the top of the stack we were allocated. Pre-allocate a UINTN + // for safety. + // + TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT; + TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + // + // End of PEI phase singal + // + Status = PeiServicesInstallPpi (EndOfPeiSignal); + ASSERT_EFI_ERROR (Status); + + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + HobList.Raw, + NULL, + (VOID *) (UINTN) TopOfStack + ); + } +} + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c new file mode 100644 index 0000000000..f7bef7eb3e --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c @@ -0,0 +1,117 @@ +/*++ + +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 common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" + +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 + +--*/ +{ + UINT8 *Destination32; + UINT8 *Source32; + UINTN Length; + + + Destination32 = Buffer; + Source32 = (UINT8 *) ((UINTN) FileHandle + FileOffset); + + // + // This function assumes 32-bit alignment to increase performance + // +// ASSERT (ALIGN_POINTER (Destination32, sizeof (UINT32)) == Destination32); +// ASSERT (ALIGN_POINTER (Source32, sizeof (UINT32)) == Source32); + + Length = *ReadSize; + while (Length--) { + *(Destination32++) = *(Source32++); + } + + 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/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c new file mode 100644 index 0000000000..f4a6a4faba --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c @@ -0,0 +1,173 @@ +/*++ + +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 common header file for this module. +// +#include "CommonHeader.h" + +#include "VirtualMemory.h" + +UINTN +CreateIdentityMappingPageTables ( + VOID + ) +/*++ + +Routine Description: + + Allocates and fills in the Page Directory and Page Table Entries to + establish a 1:1 Virtual to Physical mapping. + +Arguments: + + NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use. + Limits the number of page table entries + to the physical address space. + +Returns: + + EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created + +--*/ +{ + UINT8 PhysicalAddressBits; + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN IndexOfPml4Entries; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + UINTN NumberOfPml4EntriesNeeded; + UINTN NumberOfPdpEntriesNeeded; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINTN TotalPagesNum; + UINTN BigPageAddress; + VOID *Hob; + + // + // Get physical address bits supported from CPU HOB. + // + PhysicalAddressBits = 36; + + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } + + // + // Calculate the table entries needed. + // + if (PhysicalAddressBits <= 39 ) { + NumberOfPml4EntriesNeeded = 1; + NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30); + } else { + NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39); + NumberOfPdpEntriesNeeded = 512; + } + + // + // Pre-allocate big pages to avoid later allocations. + // + TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1; + BigPageAddress = (UINTN) AllocatePages (TotalPagesNum); + ASSERT (BigPageAddress != 0); + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // + PageMap = (VOID *) BigPageAddress; + BigPageAddress += EFI_PAGE_SIZE; + + PageMapLevel4Entry = PageMap; + PageAddress = 0; + for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop. + // + PageDirectoryPointerEntry = (VOID *) BigPageAddress; + BigPageAddress += EFI_PAGE_SIZE; + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry; + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. + // + PageDirectoryEntry = (VOID *) BigPageAddress; + BigPageAddress += EFI_PAGE_SIZE; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry; + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + + } + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // For now we just copy the first entry. + // + for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) { + CopyMem ( + PageMapLevel4Entry, + PageMap, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); + } + + return (UINTN)PageMap; // FIXME +} + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h new file mode 100644 index 0000000000..4e6614ecfb --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h @@ -0,0 +1,112 @@ +/*++ + +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_ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#define SYS_CODE64_SEL 0x38 + +#pragma pack(1) + +typedef union { + struct { + UINT32 LimitLow : 16; + UINT32 BaseLow : 16; + UINT32 BaseMid : 8; + UINT32 Type : 4; + UINT32 System : 1; + UINT32 Dpl : 2; + UINT32 Present : 1; + UINT32 LimitHigh : 4; + UINT32 Software : 1; + UINT32 Reserved : 1; + UINT32 DefaultSize : 1; + UINT32 Granularity : 1; + UINT32 BaseHigh : 8; + } Bits; + UINT64 Uint64; +} IA32_GDT; + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_ENTRY; + +#pragma pack() + +UINTN +CreateIdentityMappingPageTables ( + VOID + ) +; + +#endif -- cgit v1.2.3