\r
return Status;\r
}\r
+\r
+UINT64\r
+EfiAttributeToArmAttribute (\r
+ IN UINT64 EfiAttributes\r
+ )\r
+{\r
+ UINT64 ArmAttributes;\r
+\r
+ switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {\r
+ case EFI_MEMORY_UC:\r
+ // Map to strongly ordered\r
+ ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WC:\r
+ // Map to normal non-cachable\r
+ ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WT:\r
+ // Write through with no-allocate\r
+ ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WB:\r
+ // Write back (with allocate)\r
+ ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
+ break;\r
+\r
+ case EFI_MEMORY_WP:\r
+ case EFI_MEMORY_XP:\r
+ case EFI_MEMORY_RP:\r
+ case EFI_MEMORY_UCE:\r
+ default:\r
+ // Cannot be implemented UEFI definition unclear for ARM\r
+ // Cause a page fault if these ranges are accessed.\r
+ ArmAttributes = TT_DESCRIPTOR_SECTION_TYPE_FAULT;\r
+ DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): Unsupported attribute %x will page fault on access\n", EfiAttributes));\r
+ break;\r
+ }\r
+\r
+ // Determine protection attributes\r
+ if (EfiAttributes & EFI_MEMORY_WP) {\r
+ ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RO_RO;\r
+ } else {\r
+ ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RW_RW;\r
+ }\r
+\r
+ // Determine eXecute Never attribute\r
+ if (EfiAttributes & EFI_MEMORY_XP) {\r
+ ArmAttributes |= TT_DESCRIPTOR_SECTION_XN_MASK;\r
+ }\r
+\r
+ return ArmAttributes;\r
+}\r
+\r
+EFI_STATUS\r
+GetMemoryRegionPage (\r
+ IN UINT32 *PageTable,\r
+ IN OUT UINTN *BaseAddress,\r
+ OUT UINTN *RegionLength,\r
+ OUT UINTN *RegionAttributes\r
+ )\r
+{\r
+ UINT32 PageAttributes;\r
+ UINT32 TableIndex;\r
+ UINT32 PageDescriptor;\r
+\r
+ // Convert the section attributes into page attributes\r
+ PageAttributes = ConvertSectionAttributesToPageAttributes (*RegionAttributes, 0);\r
+\r
+ // Calculate index into first level translation table for start of modification\r
+ TableIndex = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(*BaseAddress) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r
+ ASSERT (TableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r
+\r
+ // Go through the page table to find the end of the section\r
+ for (; TableIndex < TRANSLATION_TABLE_PAGE_COUNT; TableIndex++) {\r
+ // Get the section at the given index\r
+ PageDescriptor = PageTable[TableIndex];\r
+\r
+ if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_FAULT) {\r
+ // Case: End of the boundary of the region\r
+ return EFI_SUCCESS;\r
+ } else if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_PAGE) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {\r
+ if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) == PageAttributes) {\r
+ *RegionLength = *RegionLength + TT_DESCRIPTOR_PAGE_SIZE;\r
+ } else {\r
+ // Case: End of the boundary of the region\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ // We do not support Large Page yet. We return EFI_SUCCESS that means end of the region.\r
+ ASSERT(0);\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+GetMemoryRegion (\r
+ IN OUT UINTN *BaseAddress,\r
+ OUT UINTN *RegionLength,\r
+ OUT UINTN *RegionAttributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 TableIndex;\r
+ UINT32 PageAttributes;\r
+ UINT32 PageTableIndex;\r
+ UINT32 SectionDescriptor;\r
+ ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
+ UINT32 *PageTable;\r
+\r
+ // Initialize the arguments\r
+ *RegionLength = 0;\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
+ TableIndex = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (*BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
+ ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);\r
+\r
+ // Get the section at the given index\r
+ SectionDescriptor = FirstLevelTable[TableIndex];\r
+\r
+ // If 'BaseAddress' belongs to the section then round it to the section boundary\r
+ if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||\r
+ ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))\r
+ {\r
+ *BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK;\r
+ *RegionAttributes = SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK;\r
+ } else {\r
+ // Otherwise, we round it to the page boundary\r
+ *BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK;\r
+\r
+ // Get the attribute at the page table level (Level 2)\r
+ PageTable = (UINT32*)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);\r
+\r
+ // Calculate index into first level translation table for start of modification\r
+ PageTableIndex = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (*BaseAddress) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r
+ ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r
+\r
+ PageAttributes = PageTable[PageTableIndex] & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK;\r
+ *RegionAttributes = TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (PageAttributes, 0) |\r
+ TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (PageAttributes);\r
+ }\r
+\r
+ for (;TableIndex < TRANSLATION_TABLE_SECTION_COUNT; TableIndex++) {\r
+ // Get the section at the given index\r
+ SectionDescriptor = FirstLevelTable[TableIndex];\r
+\r
+ // If the entry is a level-2 page table then we scan it to find the end of the region\r
+ if ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE) {\r
+ // Extract the page table location from the descriptor\r
+ PageTable = (UINT32*)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);\r
+\r
+ // Scan the page table to find the end of the region.\r
+ Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionLength, RegionAttributes);\r
+\r
+ // If we have found the end of the region (Status == EFI_SUCCESS) then we exit the for-loop\r
+ if (Status == EFI_SUCCESS) {\r
+ break;\r
+ }\r
+ } else if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||\r
+ ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION)) {\r
+ if ((SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK) != *RegionAttributes) {\r
+ // If the attributes of the section differ from the one targeted then we exit the loop\r
+ break;\r
+ } else {\r
+ *RegionLength = *RegionLength + TT_DESCRIPTOR_SECTION_SIZE;\r
+ }\r
+ } else {\r
+ // If we are on an invalid section then it means it is the end of our section.\r
+ break;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r