USB Keyboard driver should add F11, F12 support DxeIpl should not hardcode 36bit address git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2543 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			169 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| 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"
 | |
| 
 | |
| 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
 | |
| }
 | |
| 
 |