| /** @file | |
| Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR> | |
| 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: | |
| Paging.c | |
| Abstract: | |
| Revision History: | |
| **/ | |
| #include "DxeIpl.h" | |
| #include "HobGeneration.h" | |
| #include "VirtualMemory.h" | |
| #include "Debug.h" | |
| #define EFI_PAGE_SIZE_4K 0x1000 | |
| #define EFI_PAGE_SIZE_4M 0x400000 | |
| // | |
| // Create 4G 4M-page table | |
| // PDE (31:22) : 1024 entries | |
| // | |
| #define EFI_MAX_ENTRY_NUM 1024 | |
| #define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM | |
| #define EFI_PDE_PAGE_NUM 1 | |
| #define EFI_PAGE_NUMBER_4M (EFI_PDE_PAGE_NUM) | |
| // | |
| // Create 4M 4K-page table | |
| // PTE (21:12) : 1024 entries | |
| // | |
| #define EFI_PTE_ENTRY_NUM EFI_MAX_ENTRY_NUM | |
| #define EFI_PTE_PAGE_NUM 1 | |
| #define EFI_PAGE_NUMBER_4K (EFI_PTE_PAGE_NUM) | |
| #define EFI_PAGE_NUMBER (EFI_PAGE_NUMBER_4M + EFI_PAGE_NUMBER_4K) | |
| VOID | |
| EnableNullPointerProtection ( | |
| UINT8 *PageTable | |
| ) | |
| { | |
| IA32_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB; | |
| PageTableEntry4KB = (IA32_PAGE_TABLE_ENTRY_4K *)((UINTN)PageTable + EFI_PAGE_NUMBER_4M * EFI_PAGE_SIZE_4K); | |
| // | |
| // Fill in the Page Table entries | |
| // Mark 0~4K as not present | |
| // | |
| PageTableEntry4KB->Bits.Present = 0; | |
| return ; | |
| } | |
| VOID | |
| Ia32Create4KPageTables ( | |
| UINT8 *PageTable | |
| ) | |
| { | |
| UINT64 PageAddress; | |
| UINTN PTEIndex; | |
| IA32_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4KB; | |
| IA32_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB; | |
| PageAddress = 0; | |
| // | |
| // Page Table structure 2 level 4K. | |
| // | |
| // Page Table 4K : PageDirectoryEntry4K : bits 31-22 | |
| // PageTableEntry : bits 21-12 | |
| // | |
| PageTableEntry4KB = (IA32_PAGE_TABLE_ENTRY_4K *)((UINTN)PageTable + EFI_PAGE_NUMBER_4M * EFI_PAGE_SIZE_4K); | |
| PageDirectoryEntry4KB = (IA32_PAGE_DIRECTORY_ENTRY_4K *)((UINTN)PageTable); | |
| PageDirectoryEntry4KB->Uint32 = (UINT32)(UINTN)PageTableEntry4KB; | |
| PageDirectoryEntry4KB->Bits.ReadWrite = 0; | |
| PageDirectoryEntry4KB->Bits.Present = 1; | |
| PageDirectoryEntry4KB->Bits.MustBeZero = 1; | |
| for (PTEIndex = 0; PTEIndex < EFI_PTE_ENTRY_NUM; PTEIndex++, PageTableEntry4KB++) { | |
| // | |
| // Fill in the Page Table entries | |
| // | |
| PageTableEntry4KB->Uint32 = (UINT32)PageAddress; | |
| PageTableEntry4KB->Bits.ReadWrite = 1; | |
| PageTableEntry4KB->Bits.Present = 1; | |
| PageAddress += EFI_PAGE_SIZE_4K; | |
| } | |
| return ; | |
| } | |
| VOID | |
| Ia32Create4MPageTables ( | |
| UINT8 *PageTable | |
| ) | |
| { | |
| UINT32 PageAddress; | |
| UINT8 *TempPageTable; | |
| UINTN PDEIndex; | |
| IA32_PAGE_TABLE_ENTRY_4M *PageDirectoryEntry4MB; | |
| TempPageTable = PageTable; | |
| PageAddress = 0; | |
| // | |
| // Page Table structure 1 level 4MB. | |
| // | |
| // Page Table 4MB : PageDirectoryEntry4M : bits 31-22 | |
| // | |
| PageDirectoryEntry4MB = (IA32_PAGE_TABLE_ENTRY_4M *)TempPageTable; | |
| for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry4MB++) { | |
| // | |
| // Fill in the Page Directory entries | |
| // | |
| PageDirectoryEntry4MB->Uint32 = (UINT32)PageAddress; | |
| PageDirectoryEntry4MB->Bits.ReadWrite = 1; | |
| PageDirectoryEntry4MB->Bits.Present = 1; | |
| PageDirectoryEntry4MB->Bits.MustBe1 = 1; | |
| PageAddress += EFI_PAGE_SIZE_4M; | |
| } | |
| return ; | |
| } | |
| VOID * | |
| PreparePageTable ( | |
| VOID *PageNumberTop, | |
| UINT8 SizeOfMemorySpace | |
| ) | |
| /*++ | |
| Description: | |
| Generate pagetable below PageNumberTop, | |
| and return the bottom address of pagetable for putting other things later. | |
| --*/ | |
| { | |
| VOID *PageNumberBase; | |
| PageNumberBase = (VOID *)((UINTN)PageNumberTop - EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K); | |
| ZeroMem (PageNumberBase, EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K); | |
| Ia32Create4MPageTables (PageNumberBase); | |
| Ia32Create4KPageTables (PageNumberBase); | |
| // | |
| // Not enable NULL Pointer Protection if using INTX call | |
| // | |
| // EnableNullPointerProtection (PageNumberBase); | |
| return PageNumberBase; | |
| } |