/** @file\r
Ia32-specific functionality for DxeLoad.\r
\r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
0\r
};\r
\r
+/**\r
+ Allocates and fills in the Page Directory and Page Table Entries to\r
+ establish a 4G page table.\r
+\r
+ @param[in] StackBase Stack base address.\r
+ @param[in] StackSize Stack size.\r
+\r
+ @return The address of page table.\r
+\r
+**/\r
+UINTN\r
+Create4GPageTablesIa32Pae (\r
+ IN EFI_PHYSICAL_ADDRESS StackBase,\r
+ IN UINTN StackSize\r
+ )\r
+{ \r
+ UINT8 PhysicalAddressBits;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ UINTN IndexOfPdpEntries;\r
+ UINTN IndexOfPageDirectoryEntries;\r
+ UINT32 NumberOfPdpEntriesNeeded;\r
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;\r
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;\r
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;\r
+ UINTN TotalPagesNum;\r
+ UINTN PageAddress;\r
+\r
+ PhysicalAddressBits = 32;\r
+\r
+ //\r
+ // Calculate the table entries needed.\r
+ //\r
+ NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, (PhysicalAddressBits - 30));\r
+\r
+ TotalPagesNum = NumberOfPdpEntriesNeeded + 1;\r
+ PageAddress = (UINTN) AllocatePages (TotalPagesNum);\r
+ ASSERT (PageAddress != 0);\r
+\r
+ PageMap = (VOID *) PageAddress;\r
+ PageAddress += SIZE_4KB;\r
+\r
+ PageDirectoryPointerEntry = PageMap;\r
+ PhysicalAddress = 0;\r
+\r
+ for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
+ //\r
+ // Each Directory Pointer entries points to a page of Page Directory entires.\r
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
+ // \r
+ PageDirectoryEntry = (VOID *) PageAddress;\r
+ PageAddress += SIZE_4KB;\r
+\r
+ //\r
+ // Fill in a Page Directory Pointer Entries\r
+ //\r
+ PageDirectoryPointerEntry->Uint64 = (UINT64) (UINTN) PageDirectoryEntry;\r
+ PageDirectoryPointerEntry->Bits.Present = 1;\r
+\r
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {\r
+ if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {\r
+ //\r
+ // Need to split this 2M page that covers stack range.\r
+ //\r
+ Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);\r
+ } else {\r
+ //\r
+ // Fill in the Page Directory entries\r
+ //\r
+ PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress;\r
+ PageDirectoryEntry->Bits.ReadWrite = 1;\r
+ PageDirectoryEntry->Bits.Present = 1;\r
+ PageDirectoryEntry->Bits.MustBe1 = 1;\r
+ }\r
+ }\r
+ }\r
+\r
+ for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
+ ZeroMem (\r
+ PageDirectoryPointerEntry,\r
+ sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)\r
+ );\r
+ }\r
+\r
+ return (UINTN) PageMap;\r
+}\r
+\r
+/**\r
+ The function will check if IA32 PAE is supported.\r
+\r
+ @retval TRUE IA32 PAE is supported.\r
+ @retval FALSE IA32 PAE is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+IsIa32PaeSupport (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 RegEax;\r
+ UINT32 RegEdx;\r
+ BOOLEAN Ia32PaeSupport;\r
+\r
+ Ia32PaeSupport = FALSE;\r
+ AsmCpuid (0x0, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x1) {\r
+ AsmCpuid (0x1, NULL, NULL, NULL, &RegEdx);\r
+ if ((RegEdx & BIT6) != 0) {\r
+ Ia32PaeSupport = TRUE;\r
+ }\r
+ }\r
+\r
+ return Ia32PaeSupport;\r
+}\r
+\r
+/**\r
+ The function will check if Execute Disable Bit is available.\r
+\r
+ @retval TRUE Execute Disable Bit is available.\r
+ @retval FALSE Execute Disable Bit is not available.\r
+\r
+**/\r
+BOOLEAN\r
+IsExecuteDisableBitAvailable (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 RegEax;\r
+ UINT32 RegEdx;\r
+ BOOLEAN Available;\r
+\r
+ Available = FALSE;\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000001) {\r
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+ if ((RegEdx & BIT20) != 0) {\r
+ //\r
+ // Bit 20: Execute Disable Bit available.\r
+ //\r
+ Available = TRUE;\r
+ }\r
+ }\r
+\r
+ return Available;\r
+}\r
+\r
/**\r
Transfers control to DxeCore.\r
\r
X64_IDT_TABLE *IdtTableForX64;\r
EFI_VECTOR_HANDOFF_INFO *VectorInfo;\r
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;\r
+ BOOLEAN BuildPageTablesIa32Pae;\r
\r
Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);\r
ASSERT_EFI_ERROR (Status);\r
//\r
// Create page table and save PageMapLevel4 to CR3\r
//\r
- PageTables = CreateIdentityMappingPageTables ();\r
+ PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE);\r
\r
//\r
// End of PEI phase signal\r
TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;\r
TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
\r
+ BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) && IsIa32PaeSupport () && IsExecuteDisableBitAvailable ());\r
+ if (BuildPageTablesIa32Pae) {\r
+ PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);\r
+ EnableExecuteDisableBit ();\r
+ }\r
+\r
//\r
// End of PEI phase signal\r
//\r
Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ if (BuildPageTablesIa32Pae) {\r
+ AsmWriteCr3 (PageTables);\r
+ //\r
+ // Set Physical Address Extension (bit 5 of CR4).\r
+ //\r
+ AsmWriteCr4 (AsmReadCr4 () | BIT5);\r
+ }\r
+\r
//\r
// Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.\r
//\r
//\r
// Transfer the control to the entry point of DxeCore.\r
//\r
- SwitchStack (\r
- (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
- HobList.Raw,\r
- NULL,\r
- (VOID *) (UINTN) TopOfStack\r
- );\r
+ if (BuildPageTablesIa32Pae) {\r
+ AsmEnablePaging32 (\r
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
+ HobList.Raw,\r
+ NULL,\r
+ (VOID *) (UINTN) TopOfStack\r
+ );\r
+ } else {\r
+ SwitchStack (\r
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
+ HobList.Raw,\r
+ NULL,\r
+ (VOID *) (UINTN) TopOfStack\r
+ );\r
+ }\r
}\r
}\r
\r