summaryrefslogtreecommitdiffstats
path: root/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
diff options
context:
space:
mode:
authorTaylor Beebe <tabeebe@microsoft.com>2023-06-29 09:17:56 -0700
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-07-03 14:29:32 +0000
commit1b25a7049c4a2621da48d19817b2053217e65478 (patch)
tree8baa2f15f006012e8f506201b287c88c50d6f748 /ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
parentcdbdd1246005669d5b4f66dff692c398920c3c2b (diff)
downloadedk2-1b25a7049c4a2621da48d19817b2053217e65478.tar.gz
edk2-1b25a7049c4a2621da48d19817b2053217e65478.tar.bz2
edk2-1b25a7049c4a2621da48d19817b2053217e65478.zip
ArmPkg: Update GetMemoryRegion() to Handle No mapping
This patch updates the GetMemoryRegion() function to handle the case where there is no mapping for the requested address. The original logic for the ARM would hit an ASSERT after GetMemoryRegionPage() returned EFI_SUCCESS but did not update The RegionLength parameter. The original logic for the AARCH64 would never initialize the RegionLength parameter to zero and return EFI_SUCCESS after traversing an unknown number of pages. To fix this, update the logic for both architecture to return EFI_NO_MAPPING if the BaseAddress being checked is unmapped. Signed-off-by: Taylor Beebe <t@taylorbeebe.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'ArmPkg/Drivers/CpuDxe/Arm/Mmu.c')
-rw-r--r--ArmPkg/Drivers/CpuDxe/Arm/Mmu.c65
1 files changed, 42 insertions, 23 deletions
diff --git a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
index afd6aab602..268c0bf3f9 100644
--- a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
+++ b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
@@ -427,17 +427,20 @@ EfiAttributeToArmAttribute (
EFI_STATUS
GetMemoryRegionPage (
IN UINT32 *PageTable,
- IN OUT UINTN *BaseAddress,
- OUT UINTN *RegionLength,
- OUT UINTN *RegionAttributes
+ IN UINTN *BaseAddress,
+ IN UINTN *RegionAttributes,
+ OUT UINTN *RegionLength
)
{
- UINT32 PageAttributes;
- UINT32 TableIndex;
- UINT32 PageDescriptor;
+ UINT32 PageAttributes;
+ UINT32 TableIndex;
+ UINT32 PageDescriptor;
+ EFI_STATUS Status;
// Convert the section attributes into page attributes
PageAttributes = ConvertSectionAttributesToPageAttributes (*RegionAttributes);
+ Status = EFI_NOT_FOUND;
+ *RegionLength = 0;
// Calculate index into first level translation table for start of modification
TableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
@@ -449,23 +452,24 @@ GetMemoryRegionPage (
PageDescriptor = PageTable[TableIndex];
if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_FAULT) {
- // Case: End of the boundary of the region
- return EFI_SUCCESS;
+ Status = (*RegionLength > 0) ? EFI_SUCCESS : EFI_NO_MAPPING;
+ break;
} else if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_PAGE) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {
- if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) == PageAttributes) {
- *RegionLength = *RegionLength + TT_DESCRIPTOR_PAGE_SIZE;
- } else {
- // Case: End of the boundary of the region
- return EFI_SUCCESS;
+ if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) != PageAttributes) {
+ Status = EFI_SUCCESS;
+ break;
}
+
+ *RegionLength += TT_DESCRIPTOR_PAGE_SIZE;
} else {
- // We do not support Large Page yet. We return EFI_SUCCESS that means end of the region.
+ // Large pages are unsupported.
+ Status = EFI_UNSUPPORTED;
ASSERT (0);
- return EFI_SUCCESS;
+ break;
}
}
- return EFI_NOT_FOUND;
+ return Status;
}
EFI_STATUS
@@ -482,6 +486,7 @@ GetMemoryRegion (
UINT32 SectionDescriptor;
ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
UINT32 *PageTable;
+ UINTN Length;
// Initialize the arguments
*RegionLength = 0;
@@ -491,7 +496,11 @@ GetMemoryRegion (
// Calculate index into first level translation table for start of modification
TableIndex = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (*BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
- ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);
+
+ if (TableIndex >= TRANSLATION_TABLE_SECTION_COUNT) {
+ ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);
+ return EFI_INVALID_PARAMETER;
+ }
// Get the section at the given index
SectionDescriptor = FirstLevelTable[TableIndex];
@@ -524,6 +533,8 @@ GetMemoryRegion (
TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (PageAttributes);
}
+ Status = EFI_NOT_FOUND;
+
for ( ; TableIndex < TRANSLATION_TABLE_SECTION_COUNT; TableIndex++) {
// Get the section at the given index
SectionDescriptor = FirstLevelTable[TableIndex];
@@ -532,15 +543,18 @@ GetMemoryRegion (
if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (SectionDescriptor)) {
// Extract the page table location from the descriptor
PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
+ Length = 0;
// Scan the page table to find the end of the region.
- Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionLength, RegionAttributes);
- ASSERT (*RegionLength > 0);
+ Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionAttributes, &Length);
+ *RegionLength += Length;
- // If we have found the end of the region (Status == EFI_SUCCESS) then we exit the for-loop
- if (Status == EFI_SUCCESS) {
- break;
+ // Status == EFI_NOT_FOUND implies we have not reached the end of the region.
+ if ((Status == EFI_NOT_FOUND) && (Length > 0)) {
+ continue;
}
+
+ break;
} else if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||
((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))
{
@@ -556,5 +570,10 @@ GetMemoryRegion (
}
}
- return EFI_SUCCESS;
+ // Check if the region length was updated.
+ if (*RegionLength > 0) {
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
}