]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c
ArmPkg/ArmMmuLib: Explicitly cast UINT32 data conversions
[mirror_edk2.git] / ArmPkg / Library / ArmMmuLib / Arm / ArmMmuLibCore.c
index edb4de341f851b72eb8e983645ca6318558fc871..b4fffed9ae49027fdaec52dd5f3f69cfbbddb373 100644 (file)
 #define ID_MMFR0_SHR_IMP_HW_COHERENT   1\r
 #define ID_MMFR0_SHR_IGNORED         0xf\r
 \r
-#define __EFI_MEMORY_RWX               0    // no restrictions\r
-\r
-#define CACHE_ATTRIBUTE_MASK   (EFI_MEMORY_UC | \\r
-                                EFI_MEMORY_WC | \\r
-                                EFI_MEMORY_WT | \\r
-                                EFI_MEMORY_WB | \\r
-                                EFI_MEMORY_UCE | \\r
-                                EFI_MEMORY_WP)\r
-\r
 UINTN\r
 EFIAPI\r
 ArmReadIdMmfr0 (\r
@@ -52,24 +43,6 @@ ArmHasMpExtensions (
   VOID\r
   );\r
 \r
-UINT32\r
-ConvertSectionAttributesToPageAttributes (\r
-  IN UINT32   SectionAttributes,\r
-  IN BOOLEAN  IsLargePage\r
-  )\r
-{\r
-  UINT32 PageAttributes;\r
-\r
-  PageAttributes = 0;\r
-  PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (SectionAttributes, IsLargePage);\r
-  PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (SectionAttributes);\r
-  PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN (SectionAttributes, IsLargePage);\r
-  PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG (SectionAttributes);\r
-  PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S (SectionAttributes);\r
-\r
-  return PageAttributes;\r
-}\r
-\r
 STATIC\r
 BOOLEAN\r
 PreferNonshareableMemory (\r
@@ -165,14 +138,22 @@ PopulateLevel2PageTable (
       // Case where a virtual memory map descriptor overlapped a section entry\r
 \r
       // Allocate a Level2 Page Table for this Section\r
-      TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT));\r
-      TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK;\r
+      TranslationTable = (UINTN)AllocateAlignedPages (\r
+                                  EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_PAGE_SIZE),\r
+                                  TRANSLATION_TABLE_PAGE_ALIGNMENT);\r
 \r
       // Translate the Section Descriptor into Page Descriptor\r
       SectionDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (*SectionEntry, FALSE);\r
 \r
       BaseSectionAddress = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(*SectionEntry);\r
 \r
+      //\r
+      // Make sure we are not inadvertently hitting in the caches\r
+      // when populating the page tables\r
+      //\r
+      InvalidateDataCacheRange ((VOID *)TranslationTable,\r
+        TRANSLATION_TABLE_PAGE_SIZE);\r
+\r
       // Populate the new Level2 Page Table for the section\r
       PageEntry = (UINT32*)TranslationTable;\r
       for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {\r
@@ -189,9 +170,15 @@ PopulateLevel2PageTable (
       return;\r
     }\r
   } else {\r
-    TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT));\r
-    TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK;\r
-\r
+    TranslationTable = (UINTN)AllocateAlignedPages (\r
+                                EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_PAGE_SIZE),\r
+                                TRANSLATION_TABLE_PAGE_ALIGNMENT);\r
+    //\r
+    // Make sure we are not inadvertently hitting in the caches\r
+    // when populating the page tables\r
+    //\r
+    InvalidateDataCacheRange ((VOID *)TranslationTable,\r
+      TRANSLATION_TABLE_PAGE_SIZE);\r
     ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_PAGE_SIZE);\r
 \r
     *SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) |\r
@@ -210,6 +197,13 @@ PopulateLevel2PageTable (
     PhysicalBase += TT_DESCRIPTOR_PAGE_SIZE;\r
   }\r
 \r
+  //\r
+  // Invalidate again to ensure that any line fetches that may have occurred\r
+  // [speculatively] since the previous invalidate are evicted again.\r
+  //\r
+  ArmDataMemoryBarrier ();\r
+  InvalidateDataCacheRange ((UINT32 *)TranslationTable + FirstPageOffset,\r
+    RemainLength / TT_DESCRIPTOR_PAGE_SIZE * sizeof (*PageEntry));\r
 }\r
 \r
 STATIC\r
@@ -231,7 +225,7 @@ FillTranslationTable (
     return;\r
   }\r
 \r
-  PhysicalBase = MemoryRegion->PhysicalBase;\r
+  PhysicalBase = (UINT32)MemoryRegion->PhysicalBase;\r
   RemainLength = MIN(MemoryRegion->Length, SIZE_4GB - PhysicalBase);\r
 \r
   switch (MemoryRegion->Attributes) {\r
@@ -284,19 +278,36 @@ FillTranslationTable (
         RemainLength >= TT_DESCRIPTOR_SECTION_SIZE) {\r
       // Case: Physical address aligned on the Section Size (1MB) && the length\r
       // is greater than the Section Size\r
-      *SectionEntry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;\r
+      *SectionEntry = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;\r
+\r
+      //\r
+      // Issue a DMB to ensure that the page table entry update made it to\r
+      // memory before we issue the invalidate, otherwise, a subsequent\r
+      // speculative fetch could observe the old value.\r
+      //\r
+      ArmDataMemoryBarrier ();\r
+      ArmInvalidateDataCacheEntryByMVA ((UINTN)SectionEntry++);\r
+\r
       PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;\r
       RemainLength -= TT_DESCRIPTOR_SECTION_SIZE;\r
     } else {\r
-      PageMapLength = MIN (RemainLength, TT_DESCRIPTOR_SECTION_SIZE -\r
+      PageMapLength = MIN ((UINT32)RemainLength, TT_DESCRIPTOR_SECTION_SIZE -\r
                                          (PhysicalBase % TT_DESCRIPTOR_SECTION_SIZE));\r
 \r
       // Case: Physical address aligned on the Section Size (1MB) && the length\r
       //       does not fill a section\r
       // Case: Physical address NOT aligned on the Section Size (1MB)\r
-      PopulateLevel2PageTable (SectionEntry++, PhysicalBase, PageMapLength,\r
+      PopulateLevel2PageTable (SectionEntry, PhysicalBase, PageMapLength,\r
         MemoryRegion->Attributes);\r
 \r
+      //\r
+      // Issue a DMB to ensure that the page table entry update made it to\r
+      // memory before we issue the invalidate, otherwise, a subsequent\r
+      // speculative fetch could observe the old value.\r
+      //\r
+      ArmDataMemoryBarrier ();\r
+      ArmInvalidateDataCacheEntryByMVA ((UINTN)SectionEntry++);\r
+\r
       // If it is the last entry\r
       if (RemainLength < TT_DESCRIPTOR_SECTION_SIZE) {\r
         break;\r
@@ -316,16 +327,15 @@ ArmConfigureMmu (
   OUT UINTN                         *TranslationTableSize OPTIONAL\r
   )\r
 {\r
-  VOID*                         TranslationTable;\r
-  ARM_MEMORY_REGION_ATTRIBUTES  TranslationTableAttribute;\r
+  VOID                          *TranslationTable;\r
   UINT32                        TTBRAttributes;\r
 \r
-  // Allocate pages for translation table.\r
-  TranslationTable = AllocatePages (EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_SECTION_SIZE + TRANSLATION_TABLE_SECTION_ALIGNMENT));\r
+  TranslationTable = AllocateAlignedPages (\r
+                       EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_SECTION_SIZE),\r
+                       TRANSLATION_TABLE_SECTION_ALIGNMENT);\r
   if (TranslationTable == NULL) {\r
     return RETURN_OUT_OF_RESOURCES;\r
   }\r
-  TranslationTable = (VOID*)(((UINTN)TranslationTable + TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK);\r
 \r
   if (TranslationTableBase != NULL) {\r
     *TranslationTableBase = TranslationTable;\r
@@ -335,30 +345,20 @@ ArmConfigureMmu (
     *TranslationTableSize = TRANSLATION_TABLE_SECTION_SIZE;\r
   }\r
 \r
+  //\r
+  // Make sure we are not inadvertently hitting in the caches\r
+  // when populating the page tables\r
+  //\r
+  InvalidateDataCacheRange (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);\r
   ZeroMem (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);\r
 \r
-  // By default, mark the translation table as belonging to a uncached region\r
-  TranslationTableAttribute = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;\r
   while (MemoryTable->Length != 0) {\r
-    // Find the memory attribute for the Translation Table\r
-    if (((UINTN)TranslationTable >= MemoryTable->PhysicalBase) && ((UINTN)TranslationTable <= MemoryTable->PhysicalBase - 1 + MemoryTable->Length)) {\r
-      TranslationTableAttribute = MemoryTable->Attributes;\r
-    }\r
-\r
     FillTranslationTable (TranslationTable, MemoryTable);\r
     MemoryTable++;\r
   }\r
 \r
-  // Translate the Memory Attributes into Translation Table Register Attributes\r
-  if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) ||\r
-      (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK)) {\r
-    TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_BACK_ALLOC : TTBR_WRITE_BACK_ALLOC;\r
-  } else {\r
-    // Page tables must reside in memory mapped as write-back cacheable\r
-    ASSERT (0);\r
-    return RETURN_UNSUPPORTED;\r
-  }\r
-\r
+  TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_BACK_ALLOC\r
+                                         : TTBR_WRITE_BACK_ALLOC;\r
   if (TTBRAttributes & TTBR_SHAREABLE) {\r
     if (PreferNonshareableMemory ()) {\r
       TTBRAttributes ^= TTBR_SHAREABLE;\r
@@ -376,19 +376,7 @@ ArmConfigureMmu (
     }\r
   }\r
 \r
-  ArmCleanInvalidateDataCache ();\r
-  ArmInvalidateInstructionCache ();\r
-\r
-  ArmDisableDataCache ();\r
-  ArmDisableInstructionCache();\r
-  // TLBs are also invalidated when calling ArmDisableMmu()\r
-  ArmDisableMmu ();\r
-\r
-  // Make sure nothing sneaked into the cache\r
-  ArmCleanInvalidateDataCache ();\r
-  ArmInvalidateInstructionCache ();\r
-\r
-  ArmSetTTBR0 ((VOID *)(UINTN)(((UINTN)TranslationTable & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) | (TTBRAttributes & 0x7F)));\r
+  ArmSetTTBR0 ((VOID *)((UINTN)TranslationTable | TTBRAttributes));\r
 \r
   //\r
   // The TTBCR register value is undefined at reset in the Non-Secure world.\r
@@ -423,419 +411,3 @@ ArmConfigureMmu (
   ArmEnableMmu();\r
   return RETURN_SUCCESS;\r
 }\r
-\r
-STATIC\r
-EFI_STATUS\r
-ConvertSectionToPages (\r
-  IN EFI_PHYSICAL_ADDRESS  BaseAddress\r
-  )\r
-{\r
-  UINT32                  FirstLevelIdx;\r
-  UINT32                  SectionDescriptor;\r
-  UINT32                  PageTableDescriptor;\r
-  UINT32                  PageDescriptor;\r
-  UINT32                  Index;\r
-\r
-  volatile ARM_FIRST_LEVEL_DESCRIPTOR   *FirstLevelTable;\r
-  volatile ARM_PAGE_TABLE_ENTRY         *PageTable;\r
-\r
-  DEBUG ((EFI_D_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));\r
-\r
-  // Obtain page table base\r
-  FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
-\r
-  // Calculate index into first level translation table for start of modification\r
-  FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
-  ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
-\r
-  // Get section attributes and convert to page attributes\r
-  SectionDescriptor = FirstLevelTable[FirstLevelIdx];\r
-  PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (SectionDescriptor, FALSE);\r
-\r
-  // Allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)\r
-  PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)AllocatePages (1);\r
-  if (PageTable == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  // Write the page table entries out\r
-  for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {\r
-    PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (Index << 12)) | PageDescriptor;\r
-  }\r
-\r
-  // Formulate page table entry, Domain=0, NS=0\r
-  PageTableDescriptor = (((UINTN)PageTable) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;\r
-\r
-  // Write the page table entry out, replacing section entry\r
-  FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-UpdatePageEntries (\r
-  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN  UINT64                    Length,\r
-  IN  UINT64                    Attributes,\r
-  OUT BOOLEAN                   *FlushTlbs OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-  UINT32        EntryValue;\r
-  UINT32        EntryMask;\r
-  UINT32        FirstLevelIdx;\r
-  UINT32        Offset;\r
-  UINT32        NumPageEntries;\r
-  UINT32        Descriptor;\r
-  UINT32        p;\r
-  UINT32        PageTableIndex;\r
-  UINT32        PageTableEntry;\r
-  UINT32        CurrentPageTableEntry;\r
-  VOID          *Mva;\r
-\r
-  volatile ARM_FIRST_LEVEL_DESCRIPTOR   *FirstLevelTable;\r
-  volatile ARM_PAGE_TABLE_ENTRY         *PageTable;\r
-\r
-  Status = EFI_SUCCESS;\r
-\r
-  // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r
-  // EntryValue: values at bit positions specified by EntryMask\r
-  EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK | TT_DESCRIPTOR_PAGE_AP_MASK;\r
-  if (Attributes & EFI_MEMORY_XP) {\r
-    EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN;\r
-  } else {\r
-    EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;\r
-  }\r
-\r
-  // Although the PI spec is unclear on this, the GCD guarantees that only\r
-  // one Attribute bit is set at a time, so the order of the conditionals below\r
-  // is irrelevant. If no memory attribute is specified, we preserve whatever\r
-  // memory type is set in the page tables, and update the permission attributes\r
-  // only.\r
-  if (Attributes & EFI_MEMORY_UC) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
-    // map to strongly ordered\r
-    EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
-  } else if (Attributes & EFI_MEMORY_WC) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
-    // map to normal non-cachable\r
-    EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
-  } else if (Attributes & EFI_MEMORY_WT) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
-    // write through with no-allocate\r
-    EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
-  } else if (Attributes & EFI_MEMORY_WB) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
-    // write back (with allocate)\r
-    EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
-  } else if (Attributes & CACHE_ATTRIBUTE_MASK) {\r
-    // catch unsupported memory type attributes\r
-    ASSERT (FALSE);\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  if (Attributes & EFI_MEMORY_RO) {\r
-    EntryValue |= TT_DESCRIPTOR_PAGE_AP_RO_RO;\r
-  } else {\r
-    EntryValue |= TT_DESCRIPTOR_PAGE_AP_RW_RW;\r
-  }\r
-\r
-  // Obtain page table base\r
-  FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
-\r
-  // Calculate number of 4KB page table entries to change\r
-  NumPageEntries = Length / TT_DESCRIPTOR_PAGE_SIZE;\r
-\r
-  // Iterate for the number of 4KB pages to change\r
-  Offset = 0;\r
-  for(p = 0; p < NumPageEntries; p++) {\r
-    // Calculate index into first level translation table for page table value\r
-\r
-    FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
-    ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
-\r
-    // Read the descriptor from the first level page table\r
-    Descriptor = FirstLevelTable[FirstLevelIdx];\r
-\r
-    // Does this descriptor need to be converted from section entry to 4K pages?\r
-    if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) {\r
-      Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
-      if (EFI_ERROR(Status)) {\r
-        // Exit for loop\r
-        break;\r
-      }\r
-\r
-      // Re-read descriptor\r
-      Descriptor = FirstLevelTable[FirstLevelIdx];\r
-      if (FlushTlbs != NULL) {\r
-        *FlushTlbs = TRUE;\r
-      }\r
-    }\r
-\r
-    // Obtain page table base address\r
-    PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(Descriptor);\r
-\r
-    // Calculate index into the page table\r
-    PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r
-    ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r
-\r
-    // Get the entry\r
-    CurrentPageTableEntry = PageTable[PageTableIndex];\r
-\r
-    // Mask off appropriate fields\r
-    PageTableEntry = CurrentPageTableEntry & ~EntryMask;\r
-\r
-    // Mask in new attributes and/or permissions\r
-    PageTableEntry |= EntryValue;\r
-\r
-    if (CurrentPageTableEntry  != PageTableEntry) {\r
-      Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));\r
-\r
-      // Only need to update if we are changing the entry\r
-      PageTable[PageTableIndex] = PageTableEntry;\r
-      ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);\r
-    }\r
-\r
-    Status = EFI_SUCCESS;\r
-    Offset += TT_DESCRIPTOR_PAGE_SIZE;\r
-\r
-  } // End first level translation table loop\r
-\r
-  return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-UpdateSectionEntries (\r
-  IN EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN UINT64                    Length,\r
-  IN UINT64                    Attributes\r
-  )\r
-{\r
-  EFI_STATUS    Status = EFI_SUCCESS;\r
-  UINT32        EntryMask;\r
-  UINT32        EntryValue;\r
-  UINT32        FirstLevelIdx;\r
-  UINT32        NumSections;\r
-  UINT32        i;\r
-  UINT32        CurrentDescriptor;\r
-  UINT32        Descriptor;\r
-  VOID          *Mva;\r
-  volatile ARM_FIRST_LEVEL_DESCRIPTOR   *FirstLevelTable;\r
-\r
-  // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r
-  // EntryValue: values at bit positions specified by EntryMask\r
-\r
-  // Make sure we handle a section range that is unmapped\r
-  EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK | TT_DESCRIPTOR_SECTION_XN_MASK |\r
-              TT_DESCRIPTOR_SECTION_AP_MASK;\r
-  EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;\r
-\r
-  // Although the PI spec is unclear on this, the GCD guarantees that only\r
-  // one Attribute bit is set at a time, so the order of the conditionals below\r
-  // is irrelevant. If no memory attribute is specified, we preserve whatever\r
-  // memory type is set in the page tables, and update the permission attributes\r
-  // only.\r
-  if (Attributes & EFI_MEMORY_UC) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
-    // map to strongly ordered\r
-    EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
-  } else if (Attributes & EFI_MEMORY_WC) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
-    // map to normal non-cachable\r
-    EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
-  } else if (Attributes & EFI_MEMORY_WT) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
-    // write through with no-allocate\r
-    EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
-  } else if (Attributes & EFI_MEMORY_WB) {\r
-    // modify cacheability attributes\r
-    EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
-    // write back (with allocate)\r
-    EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
-  } else if (Attributes & CACHE_ATTRIBUTE_MASK) {\r
-    // catch unsupported memory type attributes\r
-    ASSERT (FALSE);\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  if (Attributes & EFI_MEMORY_RO) {\r
-    EntryValue |= TT_DESCRIPTOR_SECTION_AP_RO_RO;\r
-  } else {\r
-    EntryValue |= TT_DESCRIPTOR_SECTION_AP_RW_RW;\r
-  }\r
-\r
-  if (Attributes & EFI_MEMORY_XP) {\r
-    EntryValue |= TT_DESCRIPTOR_SECTION_XN_MASK;\r
-  }\r
-\r
-  // obtain page table base\r
-  FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
-\r
-  // calculate index into first level translation table for start of modification\r
-  FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
-  ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
-\r
-  // calculate number of 1MB first level entries this applies to\r
-  NumSections = Length / TT_DESCRIPTOR_SECTION_SIZE;\r
-\r
-  // iterate through each descriptor\r
-  for(i=0; i<NumSections; i++) {\r
-    CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];\r
-\r
-    // has this descriptor already been coverted to pages?\r
-    if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {\r
-      // forward this 1MB range to page table function instead\r
-      Status = UpdatePageEntries (\r
-                 (FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT,\r
-                 TT_DESCRIPTOR_SECTION_SIZE,\r
-                 Attributes,\r
-                 NULL);\r
-    } else {\r
-      // still a section entry\r
-\r
-      if (CurrentDescriptor != 0) {\r
-        // mask off appropriate fields\r
-        Descriptor = CurrentDescriptor & ~EntryMask;\r
-      } else {\r
-        Descriptor = ((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
-      }\r
-\r
-      // mask in new attributes and/or permissions\r
-      Descriptor |= EntryValue;\r
-\r
-      if (CurrentDescriptor  != Descriptor) {\r
-        Mva = (VOID *)(UINTN)(((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
-\r
-        // Only need to update if we are changing the descriptor\r
-        FirstLevelTable[FirstLevelIdx + i] = Descriptor;\r
-        ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);\r
-      }\r
-\r
-      Status = EFI_SUCCESS;\r
-    }\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-EFI_STATUS\r
-ArmSetMemoryAttributes (\r
-  IN EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN UINT64                    Length,\r
-  IN UINT64                    Attributes\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-  UINT64        ChunkLength;\r
-  BOOLEAN       FlushTlbs;\r
-\r
-  if (BaseAddress > (UINT64)MAX_ADDRESS) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Length = MIN (Length, (UINT64)MAX_ADDRESS - BaseAddress + 1);\r
-  if (Length == 0) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  FlushTlbs = FALSE;\r
-  while (Length > 0) {\r
-    if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) &&\r
-        Length >= TT_DESCRIPTOR_SECTION_SIZE) {\r
-\r
-      ChunkLength = Length - Length % TT_DESCRIPTOR_SECTION_SIZE;\r
-\r
-      DEBUG ((DEBUG_PAGE,\r
-        "SetMemoryAttributes(): MMU section 0x%lx length 0x%lx to %lx\n",\r
-        BaseAddress, ChunkLength, Attributes));\r
-\r
-      Status = UpdateSectionEntries (BaseAddress, ChunkLength, Attributes);\r
-\r
-      FlushTlbs = TRUE;\r
-    } else {\r
-\r
-      //\r
-      // Process page by page until the next section boundary, but only if\r
-      // we have more than a section's worth of area to deal with after that.\r
-      //\r
-      ChunkLength = TT_DESCRIPTOR_SECTION_SIZE -\r
-                    (BaseAddress % TT_DESCRIPTOR_SECTION_SIZE);\r
-      if (ChunkLength + TT_DESCRIPTOR_SECTION_SIZE > Length) {\r
-        ChunkLength = Length;\r
-      }\r
-\r
-      DEBUG ((DEBUG_PAGE,\r
-        "SetMemoryAttributes(): MMU page 0x%lx length 0x%lx to %lx\n",\r
-        BaseAddress, ChunkLength, Attributes));\r
-\r
-      Status = UpdatePageEntries (BaseAddress, ChunkLength, Attributes,\r
-                 &FlushTlbs);\r
-    }\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      break;\r
-    }\r
-\r
-    BaseAddress += ChunkLength;\r
-    Length -= ChunkLength;\r
-  }\r
-\r
-  if (FlushTlbs) {\r
-    ArmInvalidateTlb ();\r
-  }\r
-  return Status;\r
-}\r
-\r
-EFI_STATUS\r
-ArmSetMemoryRegionNoExec (\r
-  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN  UINT64                    Length\r
-  )\r
-{\r
-  return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP);\r
-}\r
-\r
-EFI_STATUS\r
-ArmClearMemoryRegionNoExec (\r
-  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN  UINT64                    Length\r
-  )\r
-{\r
-  return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);\r
-}\r
-\r
-EFI_STATUS\r
-ArmSetMemoryRegionReadOnly (\r
-  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN  UINT64                    Length\r
-  )\r
-{\r
-  return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO);\r
-}\r
-\r
-EFI_STATUS\r
-ArmClearMemoryRegionReadOnly (\r
-  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN  UINT64                    Length\r
-  )\r
-{\r
-  return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);\r
-}\r
-\r
-RETURN_STATUS\r
-EFIAPI\r
-ArmMmuBaseLibConstructor (\r
-  VOID\r
-  )\r
-{\r
-  return RETURN_SUCCESS;\r
-}\r