mirror of https://github.com/acidanthera/audk.git
MdeModulePkg DxeIpl: Add stack NX support
This feature is added for UEFI spec that says "Stack may be marked as non-executable in identity mapped page tables". A PCD PcdSetNxForStack is added to turn on/off this feature, and it is FALSE by default. Cc: Jiewen Yao <jiewen.yao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: "Yao, Jiewen" <Jiewen.yao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18166 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
edaea0e7bf
commit
5630cdfe9f
|
@ -5,7 +5,7 @@
|
||||||
# PPI to discover and dispatch the DXE Foundation and components that are
|
# PPI to discover and dispatch the DXE Foundation and components that are
|
||||||
# needed to run the DXE Foundation.
|
# needed to run the DXE Foundation.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
# This program and the accompanying materials
|
# This program and the accompanying materials
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
# 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
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -104,6 +104,7 @@
|
||||||
|
|
||||||
[Pcd.IA32,Pcd.X64]
|
[Pcd.IA32,Pcd.X64]
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiLoadFilePpiGuid AND gEfiPeiMasterBootModePpiGuid
|
gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiLoadFilePpiGuid AND gEfiPeiMasterBootModePpiGuid
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/** @file
|
/** @file
|
||||||
Ia32-specific functionality for DxeLoad.
|
Ia32-specific functionality for DxeLoad.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -56,6 +56,151 @@ GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocates and fills in the Page Directory and Page Table Entries to
|
||||||
|
establish a 4G page table.
|
||||||
|
|
||||||
|
@param[in] StackBase Stack base address.
|
||||||
|
@param[in] StackSize Stack size.
|
||||||
|
|
||||||
|
@return The address of page table.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
Create4GPageTablesIa32Pae (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS StackBase,
|
||||||
|
IN UINTN StackSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 PhysicalAddressBits;
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalAddress;
|
||||||
|
UINTN IndexOfPdpEntries;
|
||||||
|
UINTN IndexOfPageDirectoryEntries;
|
||||||
|
UINT32 NumberOfPdpEntriesNeeded;
|
||||||
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
|
||||||
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
|
||||||
|
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
||||||
|
UINTN TotalPagesNum;
|
||||||
|
UINTN PageAddress;
|
||||||
|
|
||||||
|
PhysicalAddressBits = 32;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calculate the table entries needed.
|
||||||
|
//
|
||||||
|
NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, (PhysicalAddressBits - 30));
|
||||||
|
|
||||||
|
TotalPagesNum = NumberOfPdpEntriesNeeded + 1;
|
||||||
|
PageAddress = (UINTN) AllocatePages (TotalPagesNum);
|
||||||
|
ASSERT (PageAddress != 0);
|
||||||
|
|
||||||
|
PageMap = (VOID *) PageAddress;
|
||||||
|
PageAddress += SIZE_4KB;
|
||||||
|
|
||||||
|
PageDirectoryPointerEntry = PageMap;
|
||||||
|
PhysicalAddress = 0;
|
||||||
|
|
||||||
|
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 *) PageAddress;
|
||||||
|
PageAddress += SIZE_4KB;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill in a Page Directory Pointer Entries
|
||||||
|
//
|
||||||
|
PageDirectoryPointerEntry->Uint64 = (UINT64) (UINTN) PageDirectoryEntry;
|
||||||
|
PageDirectoryPointerEntry->Bits.Present = 1;
|
||||||
|
|
||||||
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
|
||||||
|
if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {
|
||||||
|
//
|
||||||
|
// Need to split this 2M page that covers stack range.
|
||||||
|
//
|
||||||
|
Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Fill in the Page Directory entries
|
||||||
|
//
|
||||||
|
PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress;
|
||||||
|
PageDirectoryEntry->Bits.ReadWrite = 1;
|
||||||
|
PageDirectoryEntry->Bits.Present = 1;
|
||||||
|
PageDirectoryEntry->Bits.MustBe1 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
||||||
|
ZeroMem (
|
||||||
|
PageDirectoryPointerEntry,
|
||||||
|
sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (UINTN) PageMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function will check if IA32 PAE is supported.
|
||||||
|
|
||||||
|
@retval TRUE IA32 PAE is supported.
|
||||||
|
@retval FALSE IA32 PAE is not supported.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsIa32PaeSupport (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 RegEax;
|
||||||
|
UINT32 RegEdx;
|
||||||
|
BOOLEAN Ia32PaeSupport;
|
||||||
|
|
||||||
|
Ia32PaeSupport = FALSE;
|
||||||
|
AsmCpuid (0x0, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x1) {
|
||||||
|
AsmCpuid (0x1, NULL, NULL, NULL, &RegEdx);
|
||||||
|
if ((RegEdx & BIT6) != 0) {
|
||||||
|
Ia32PaeSupport = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ia32PaeSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function will check if Execute Disable Bit is available.
|
||||||
|
|
||||||
|
@retval TRUE Execute Disable Bit is available.
|
||||||
|
@retval FALSE Execute Disable Bit is not available.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsExecuteDisableBitAvailable (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 RegEax;
|
||||||
|
UINT32 RegEdx;
|
||||||
|
BOOLEAN Available;
|
||||||
|
|
||||||
|
Available = FALSE;
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000001) {
|
||||||
|
AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
||||||
|
if ((RegEdx & BIT20) != 0) {
|
||||||
|
//
|
||||||
|
// Bit 20: Execute Disable Bit available.
|
||||||
|
//
|
||||||
|
Available = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Available;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Transfers control to DxeCore.
|
Transfers control to DxeCore.
|
||||||
|
|
||||||
|
@ -85,6 +230,7 @@ HandOffToDxeCore (
|
||||||
X64_IDT_TABLE *IdtTableForX64;
|
X64_IDT_TABLE *IdtTableForX64;
|
||||||
EFI_VECTOR_HANDOFF_INFO *VectorInfo;
|
EFI_VECTOR_HANDOFF_INFO *VectorInfo;
|
||||||
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
|
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
|
||||||
|
BOOLEAN BuildPageTablesIa32Pae;
|
||||||
|
|
||||||
Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
|
Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
@ -114,7 +260,7 @@ HandOffToDxeCore (
|
||||||
//
|
//
|
||||||
// Create page table and save PageMapLevel4 to CR3
|
// Create page table and save PageMapLevel4 to CR3
|
||||||
//
|
//
|
||||||
PageTables = CreateIdentityMappingPageTables ();
|
PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// End of PEI phase signal
|
// End of PEI phase signal
|
||||||
|
@ -215,12 +361,26 @@ HandOffToDxeCore (
|
||||||
TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;
|
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);
|
TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
|
||||||
|
|
||||||
|
BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) && IsIa32PaeSupport () && IsExecuteDisableBitAvailable ());
|
||||||
|
if (BuildPageTablesIa32Pae) {
|
||||||
|
PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
|
||||||
|
EnableExecuteDisableBit ();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// End of PEI phase signal
|
// End of PEI phase signal
|
||||||
//
|
//
|
||||||
Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
|
Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
if (BuildPageTablesIa32Pae) {
|
||||||
|
AsmWriteCr3 (PageTables);
|
||||||
|
//
|
||||||
|
// Set Physical Address Extension (bit 5 of CR4).
|
||||||
|
//
|
||||||
|
AsmWriteCr4 (AsmReadCr4 () | BIT5);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
|
// Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
|
||||||
//
|
//
|
||||||
|
@ -229,6 +389,14 @@ HandOffToDxeCore (
|
||||||
//
|
//
|
||||||
// Transfer the control to the entry point of DxeCore.
|
// Transfer the control to the entry point of DxeCore.
|
||||||
//
|
//
|
||||||
|
if (BuildPageTablesIa32Pae) {
|
||||||
|
AsmEnablePaging32 (
|
||||||
|
(SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
|
||||||
|
HobList.Raw,
|
||||||
|
NULL,
|
||||||
|
(VOID *) (UINTN) TopOfStack
|
||||||
|
);
|
||||||
|
} else {
|
||||||
SwitchStack (
|
SwitchStack (
|
||||||
(SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
|
(SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
|
||||||
HobList.Raw,
|
HobList.Raw,
|
||||||
|
@ -237,4 +405,5 @@ HandOffToDxeCore (
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/** @file
|
/** @file
|
||||||
x64-specifc functionality for DxeLoad.
|
x64-specifc functionality for DxeLoad.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -84,7 +84,13 @@ HandOffToDxeCore (
|
||||||
//
|
//
|
||||||
// Create page table and save PageMapLevel4 to CR3
|
// Create page table and save PageMapLevel4 to CR3
|
||||||
//
|
//
|
||||||
PageTables = CreateIdentityMappingPageTables ();
|
PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE
|
||||||
|
// for the DxeIpl and the DxeCore are both X64.
|
||||||
|
//
|
||||||
|
ASSERT (PcdGetBool (PcdSetNxForStack) == FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
|
2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
|
||||||
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
||||||
|
|
||||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -29,21 +29,126 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#include "DxeIpl.h"
|
#include "DxeIpl.h"
|
||||||
#include "VirtualMemory.h"
|
#include "VirtualMemory.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable Execute Disable Bit.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EnableExecuteDisableBit (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT64 MsrRegisters;
|
||||||
|
|
||||||
|
MsrRegisters = AsmReadMsr64 (0xC0000080);
|
||||||
|
MsrRegisters |= BIT11;
|
||||||
|
AsmWriteMsr64 (0xC0000080, MsrRegisters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Split 2M page to 4K.
|
||||||
|
|
||||||
|
@param[in] PhysicalAddress Start physical address the 2M page covered.
|
||||||
|
@param[in, out] PageEntry2M Pointer to 2M page entry.
|
||||||
|
@param[in] StackBase Stack base address.
|
||||||
|
@param[in] StackSize Stack size.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
Split2MPageTo4K (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
|
IN OUT UINT64 *PageEntry2M,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS StackBase,
|
||||||
|
IN UINTN StackSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalAddress4K;
|
||||||
|
UINTN IndexOfPageTableEntries;
|
||||||
|
PAGE_TABLE_4K_ENTRY *PageTableEntry;
|
||||||
|
|
||||||
|
PageTableEntry = AllocatePages (1);
|
||||||
|
//
|
||||||
|
// Fill in 2M page entry.
|
||||||
|
//
|
||||||
|
*PageEntry2M = (UINT64) (UINTN) PageTableEntry | IA32_PG_P | IA32_PG_RW;
|
||||||
|
|
||||||
|
PhysicalAddress4K = PhysicalAddress;
|
||||||
|
for (IndexOfPageTableEntries = 0; IndexOfPageTableEntries < 512; IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K += SIZE_4KB) {
|
||||||
|
//
|
||||||
|
// Fill in the Page Table entries
|
||||||
|
//
|
||||||
|
PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K;
|
||||||
|
PageTableEntry->Bits.ReadWrite = 1;
|
||||||
|
PageTableEntry->Bits.Present = 1;
|
||||||
|
if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {
|
||||||
|
//
|
||||||
|
// Set Nx bit for stack.
|
||||||
|
//
|
||||||
|
PageTableEntry->Bits.Nx = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Split 1G page to 2M.
|
||||||
|
|
||||||
|
@param[in] PhysicalAddress Start physical address the 1G page covered.
|
||||||
|
@param[in, out] PageEntry1G Pointer to 1G page entry.
|
||||||
|
@param[in] StackBase Stack base address.
|
||||||
|
@param[in] StackSize Stack size.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
Split1GPageTo2M (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
|
IN OUT UINT64 *PageEntry1G,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS StackBase,
|
||||||
|
IN UINTN StackSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalAddress2M;
|
||||||
|
UINTN IndexOfPageDirectoryEntries;
|
||||||
|
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
||||||
|
|
||||||
|
PageDirectoryEntry = AllocatePages (1);
|
||||||
|
//
|
||||||
|
// Fill in 1G page entry.
|
||||||
|
//
|
||||||
|
*PageEntry1G = (UINT64) (UINTN) PageDirectoryEntry | IA32_PG_P | IA32_PG_RW;
|
||||||
|
|
||||||
|
PhysicalAddress2M = PhysicalAddress;
|
||||||
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
|
||||||
|
if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
|
||||||
|
//
|
||||||
|
// Need to split this 2M page that covers stack range.
|
||||||
|
//
|
||||||
|
Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Fill in the Page Directory entries
|
||||||
|
//
|
||||||
|
PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M;
|
||||||
|
PageDirectoryEntry->Bits.ReadWrite = 1;
|
||||||
|
PageDirectoryEntry->Bits.Present = 1;
|
||||||
|
PageDirectoryEntry->Bits.MustBe1 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Allocates and fills in the Page Directory and Page Table Entries to
|
Allocates and fills in the Page Directory and Page Table Entries to
|
||||||
establish a 1:1 Virtual to Physical mapping.
|
establish a 1:1 Virtual to Physical mapping.
|
||||||
|
|
||||||
@param NumberOfProcessorPhysicalAddressBits Number of processor address bits
|
@param[in] StackBase Stack base address.
|
||||||
to use. Limits the number of page
|
@param[in] StackSize Stack size.
|
||||||
table entries to the physical
|
|
||||||
address space.
|
|
||||||
|
|
||||||
@return The address of 4 level page map.
|
@return The address of 4 level page map.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
UINTN
|
UINTN
|
||||||
CreateIdentityMappingPageTables (
|
CreateIdentityMappingPageTables (
|
||||||
VOID
|
IN EFI_PHYSICAL_ADDRESS StackBase,
|
||||||
|
IN UINTN StackSize
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT32 RegEax;
|
UINT32 RegEax;
|
||||||
|
@ -149,6 +254,9 @@ CreateIdentityMappingPageTables (
|
||||||
PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
|
PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
|
||||||
|
|
||||||
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
|
||||||
|
if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase)) {
|
||||||
|
Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
|
||||||
|
} else {
|
||||||
//
|
//
|
||||||
// Fill in the Page Directory entries
|
// Fill in the Page Directory entries
|
||||||
//
|
//
|
||||||
|
@ -157,6 +265,7 @@ CreateIdentityMappingPageTables (
|
||||||
PageDirectory1GEntry->Bits.Present = 1;
|
PageDirectory1GEntry->Bits.Present = 1;
|
||||||
PageDirectory1GEntry->Bits.MustBe1 = 1;
|
PageDirectory1GEntry->Bits.MustBe1 = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
||||||
//
|
//
|
||||||
|
@ -174,6 +283,12 @@ CreateIdentityMappingPageTables (
|
||||||
PageDirectoryPointerEntry->Bits.Present = 1;
|
PageDirectoryPointerEntry->Bits.Present = 1;
|
||||||
|
|
||||||
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
|
||||||
|
if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) {
|
||||||
|
//
|
||||||
|
// Need to split this 2M page that covers stack range.
|
||||||
|
//
|
||||||
|
Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
|
||||||
|
} else {
|
||||||
//
|
//
|
||||||
// Fill in the Page Directory entries
|
// Fill in the Page Directory entries
|
||||||
//
|
//
|
||||||
|
@ -183,6 +298,7 @@ CreateIdentityMappingPageTables (
|
||||||
PageDirectoryEntry->Bits.MustBe1 = 1;
|
PageDirectoryEntry->Bits.MustBe1 = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
||||||
ZeroMem (
|
ZeroMem (
|
||||||
|
@ -203,6 +319,10 @@ CreateIdentityMappingPageTables (
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PcdGetBool (PcdSetNxForStack)) {
|
||||||
|
EnableExecuteDisableBit ();
|
||||||
|
}
|
||||||
|
|
||||||
return (UINTN)PageMap;
|
return (UINTN)PageMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
||||||
4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
|
4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
|
||||||
|
|
||||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -73,6 +73,28 @@ typedef union {
|
||||||
UINT64 Uint64;
|
UINT64 Uint64;
|
||||||
} PAGE_MAP_AND_DIRECTORY_POINTER;
|
} PAGE_MAP_AND_DIRECTORY_POINTER;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Page Table Entry 4KB
|
||||||
|
//
|
||||||
|
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 PAT: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 PageTableBaseAddress:40; // 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_4K_ENTRY;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Page Table Entry 2MB
|
// Page Table Entry 2MB
|
||||||
//
|
//
|
||||||
|
@ -123,22 +145,49 @@ typedef union {
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
#define IA32_PG_P BIT0
|
||||||
|
#define IA32_PG_RW BIT1
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable Execute Disable Bit.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EnableExecuteDisableBit (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Split 2M page to 4K.
|
||||||
|
|
||||||
|
@param[in] PhysicalAddress Start physical address the 2M page covered.
|
||||||
|
@param[in, out] PageEntry2M Pointer to 2M page entry.
|
||||||
|
@param[in] StackBase Stack base address.
|
||||||
|
@param[in] StackSize Stack size.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
Split2MPageTo4K (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
|
IN OUT UINT64 *PageEntry2M,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS StackBase,
|
||||||
|
IN UINTN StackSize
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Allocates and fills in the Page Directory and Page Table Entries to
|
Allocates and fills in the Page Directory and Page Table Entries to
|
||||||
establish a 1:1 Virtual to Physical mapping.
|
establish a 1:1 Virtual to Physical mapping.
|
||||||
|
|
||||||
@param NumberOfProcessorPhysicalAddressBits Number of processor address bits
|
@param[in] StackBase Stack base address.
|
||||||
to use. Limits the number of page
|
@param[in] StackSize Stack size.
|
||||||
table entries to the physical
|
|
||||||
address space.
|
|
||||||
|
|
||||||
@return The address of 4 level page map.
|
@return The address of 4 level page map.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
UINTN
|
UINTN
|
||||||
CreateIdentityMappingPageTables (
|
CreateIdentityMappingPageTables (
|
||||||
VOID
|
IN EFI_PHYSICAL_ADDRESS StackBase,
|
||||||
|
IN UINTN StackSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -961,6 +961,15 @@
|
||||||
# @Prompt Serial Port Register Stride in Bytes
|
# @Prompt Serial Port Register Stride in Bytes
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1|UINT32|0x0001006d
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1|UINT32|0x0001006d
|
||||||
|
|
||||||
|
## Indicates if to set NX for stack.<BR><BR>
|
||||||
|
# For the DxeIpl and the DxeCore are both X64, set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE.<BR>
|
||||||
|
# For the DxeIpl and the DxeCore are both IA32 (PcdDxeIplSwitchToLongMode is FALSE), set NX for stack feature also require
|
||||||
|
# IA32 PAE is supported and Execute Disable Bit is available.<BR>
|
||||||
|
# TRUE - to set NX for stack.<BR>
|
||||||
|
# FALSE - Not to set NX for stack.<BR>
|
||||||
|
# @Prompt Set NX for stack.
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE|BOOLEAN|0x0001006f
|
||||||
|
|
||||||
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
|
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
|
||||||
## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
|
## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
|
||||||
# This PCD could be set to 0 then console output would be at max column and max row.
|
# This PCD could be set to 0 then console output would be at max column and max row.
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue