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