*PageEntry = NewPageEntry;\r
if (CurrentPageEntry != NewPageEntry) {\r
*IsModified = TRUE;\r
- DEBUG ((DEBUG_INFO, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry));\r
- DEBUG ((DEBUG_INFO, "->0x%lx\n", NewPageEntry));\r
+ DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry));\r
+ DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));\r
} else {\r
*IsModified = FALSE;\r
}\r
return Status;\r
}\r
\r
+/**\r
+ Check if Execute Disable feature is enabled or not.\r
+**/\r
+BOOLEAN\r
+IsExecuteDisableEnabled (\r
+ VOID\r
+ )\r
+{\r
+ MSR_CORE_IA32_EFER_REGISTER MsrEfer;\r
+\r
+ MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);\r
+ return (MsrEfer.Bits.NXE == 1);\r
+}\r
+\r
/**\r
Update GCD memory space attributes according to current page table setup.\r
**/\r
UINT64 PageStartAddress;\r
UINT64 Attributes;\r
UINT64 Capabilities;\r
- BOOLEAN DoUpdate;\r
+ UINT64 NewAttributes;\r
UINTN Index;\r
\r
//\r
\r
GetCurrentPagingContext (&PagingContext);\r
\r
- BaseAddress = 0;\r
- PageLength = 0;\r
+ Attributes = 0;\r
+ NewAttributes = 0;\r
+ BaseAddress = 0;\r
+ PageLength = 0;\r
+\r
+ if (IsExecuteDisableEnabled ()) {\r
+ Capabilities = EFI_MEMORY_RO | EFI_MEMORY_RP | EFI_MEMORY_XP;\r
+ } else {\r
+ Capabilities = EFI_MEMORY_RO | EFI_MEMORY_RP;\r
+ }\r
+\r
for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
continue;\r
}\r
\r
+ //\r
+ // Sync the actual paging related capabilities back to GCD service first.\r
+ // As a side effect (good one), this can also help to avoid unnecessary\r
+ // memory map entries due to the different capabilities of the same type\r
+ // memory, such as multiple RT_CODE and RT_DATA entries in memory map,\r
+ // which could cause boot failure of some old Linux distro (before v4.3).\r
+ //\r
+ Status = gDS->SetMemorySpaceCapabilities (\r
+ MemorySpaceMap[Index].BaseAddress,\r
+ MemorySpaceMap[Index].Length,\r
+ MemorySpaceMap[Index].Capabilities | Capabilities\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If we cannot udpate the capabilities, we cannot update its\r
+ // attributes either. So just simply skip current block of memory.\r
+ //\r
+ DEBUG ((\r
+ DEBUG_WARN,\r
+ "Failed to update capability: [%lu] %016lx - %016lx (%016lx -> %016lx)\r\n",\r
+ (UINT64)Index, MemorySpaceMap[Index].BaseAddress,\r
+ MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1,\r
+ MemorySpaceMap[Index].Capabilities,\r
+ MemorySpaceMap[Index].Capabilities | Capabilities\r
+ ));\r
+ continue;\r
+ }\r
+\r
if (MemorySpaceMap[Index].BaseAddress >= (BaseAddress + PageLength)) {\r
//\r
// Current memory space starts at a new page. Resetting PageLength will\r
PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress);\r
}\r
\r
- // Sync real page attributes to GCD\r
+ //\r
+ // Sync actual page attributes to GCD\r
+ //\r
BaseAddress = MemorySpaceMap[Index].BaseAddress;\r
MemorySpaceLength = MemorySpaceMap[Index].Length;\r
while (MemorySpaceLength > 0) {\r
PageStartAddress = (*PageEntry) & (UINT64)PageAttributeToMask(PageAttribute);\r
PageLength = PageAttributeToLength (PageAttribute) - (BaseAddress - PageStartAddress);\r
Attributes = GetAttributesFromPageEntry (PageEntry);\r
-\r
- if (Attributes != (MemorySpaceMap[Index].Attributes & EFI_MEMORY_PAGETYPE_MASK)) {\r
- DoUpdate = TRUE;\r
- Attributes |= (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_PAGETYPE_MASK);\r
- Capabilities = Attributes | MemorySpaceMap[Index].Capabilities;\r
- } else {\r
- DoUpdate = FALSE;\r
- }\r
}\r
\r
Length = MIN (PageLength, MemorySpaceLength);\r
- if (DoUpdate) {\r
- gDS->SetMemorySpaceCapabilities (BaseAddress, Length, Capabilities);\r
- gDS->SetMemorySpaceAttributes (BaseAddress, Length, Attributes);\r
- DEBUG ((DEBUG_INFO, "Update memory space attribute: [%02d] %016lx - %016lx (%08lx -> %08lx)\r\n",\r
- Index, BaseAddress, BaseAddress + Length - 1,\r
- MemorySpaceMap[Index].Attributes, Attributes));\r
+ if (Attributes != (MemorySpaceMap[Index].Attributes &\r
+ EFI_MEMORY_PAGETYPE_MASK)) {\r
+ NewAttributes = (MemorySpaceMap[Index].Attributes &\r
+ ~EFI_MEMORY_PAGETYPE_MASK) | Attributes;\r
+ Status = gDS->SetMemorySpaceAttributes (\r
+ BaseAddress,\r
+ Length,\r
+ NewAttributes\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Updated memory space attribute: [%lu] %016lx - %016lx (%016lx -> %016lx)\r\n",\r
+ (UINT64)Index, BaseAddress, BaseAddress + Length - 1,\r
+ MemorySpaceMap[Index].Attributes,\r
+ NewAttributes\r
+ ));\r
}\r
\r
PageLength -= Length;\r