REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the ArmPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Andrew Fish <afish@apple.com>
		
			
				
	
	
		
			519 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			519 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
 | |
| Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
 | |
| Portions copyright (c) 2013-2021, Arm Limited. All rights reserved.<BR>
 | |
| Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include "CpuDxe.h"
 | |
| 
 | |
| EFI_STATUS
 | |
| SectionToGcdAttributes (
 | |
|   IN  UINT32  SectionAttributes,
 | |
|   OUT UINT64  *GcdAttributes
 | |
|   )
 | |
| {
 | |
|   *GcdAttributes = 0;
 | |
| 
 | |
|   // determine cacheability attributes
 | |
|   switch (SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {
 | |
|     case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:
 | |
|       *GcdAttributes |= EFI_MEMORY_UC;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:
 | |
|       *GcdAttributes |= EFI_MEMORY_UC;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
 | |
|       *GcdAttributes |= EFI_MEMORY_WT;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
 | |
|       *GcdAttributes |= EFI_MEMORY_WB;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:
 | |
|       *GcdAttributes |= EFI_MEMORY_WC;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:
 | |
|       *GcdAttributes |= EFI_MEMORY_WB;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:
 | |
|       *GcdAttributes |= EFI_MEMORY_UC;
 | |
|       break;
 | |
|     default:
 | |
|       return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   // determine protection attributes
 | |
|   switch (SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {
 | |
|     case TT_DESCRIPTOR_SECTION_AP_NO_NO: // no read, no write
 | |
|       // *GcdAttributes |= EFI_MEMORY_RO | EFI_MEMORY_RP;
 | |
|       break;
 | |
| 
 | |
|     case TT_DESCRIPTOR_SECTION_AP_RW_NO:
 | |
|     case TT_DESCRIPTOR_SECTION_AP_RW_RW:
 | |
|       // normal read/write access, do not add additional attributes
 | |
|       break;
 | |
| 
 | |
|     // read only cases map to write-protect
 | |
|     case TT_DESCRIPTOR_SECTION_AP_RO_NO:
 | |
|     case TT_DESCRIPTOR_SECTION_AP_RO_RO:
 | |
|       *GcdAttributes |= EFI_MEMORY_RO;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   // now process eXectue Never attribute
 | |
|   if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0 ) {
 | |
|     *GcdAttributes |= EFI_MEMORY_XP;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| PageToGcdAttributes (
 | |
|   IN  UINT32  PageAttributes,
 | |
|   OUT UINT64  *GcdAttributes
 | |
|   )
 | |
| {
 | |
|   *GcdAttributes = 0;
 | |
| 
 | |
|   // determine cacheability attributes
 | |
|   switch (PageAttributes & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) {
 | |
|     case TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED:
 | |
|       *GcdAttributes |= EFI_MEMORY_UC;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE:
 | |
|       *GcdAttributes |= EFI_MEMORY_UC;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
 | |
|       *GcdAttributes |= EFI_MEMORY_WT;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
 | |
|       *GcdAttributes |= EFI_MEMORY_WB;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE:
 | |
|       *GcdAttributes |= EFI_MEMORY_WC;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC:
 | |
|       *GcdAttributes |= EFI_MEMORY_WB;
 | |
|       break;
 | |
|     case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE:
 | |
|       *GcdAttributes |= EFI_MEMORY_UC;
 | |
|       break;
 | |
|     default:
 | |
|       return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   // determine protection attributes
 | |
|   switch (PageAttributes & TT_DESCRIPTOR_PAGE_AP_MASK) {
 | |
|     case TT_DESCRIPTOR_PAGE_AP_NO_NO: // no read, no write
 | |
|       // *GcdAttributes |= EFI_MEMORY_RO | EFI_MEMORY_RP;
 | |
|       break;
 | |
| 
 | |
|     case TT_DESCRIPTOR_PAGE_AP_RW_NO:
 | |
|     case TT_DESCRIPTOR_PAGE_AP_RW_RW:
 | |
|       // normal read/write access, do not add additional attributes
 | |
|       break;
 | |
| 
 | |
|     // read only cases map to write-protect
 | |
|     case TT_DESCRIPTOR_PAGE_AP_RO_NO:
 | |
|     case TT_DESCRIPTOR_PAGE_AP_RO_RO:
 | |
|       *GcdAttributes |= EFI_MEMORY_RO;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   // now process eXectue Never attribute
 | |
|   if ((PageAttributes & TT_DESCRIPTOR_PAGE_XN_MASK) != 0 ) {
 | |
|     *GcdAttributes |= EFI_MEMORY_XP;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SyncCacheConfigPage (
 | |
|   IN     UINT32                           SectionIndex,
 | |
|   IN     UINT32                           FirstLevelDescriptor,
 | |
|   IN     UINTN                            NumberOfDescriptors,
 | |
|   IN     EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap,
 | |
|   IN OUT EFI_PHYSICAL_ADDRESS             *NextRegionBase,
 | |
|   IN OUT UINT64                           *NextRegionLength,
 | |
|   IN OUT UINT32                           *NextSectionAttributes
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   UINT32                         i;
 | |
|   volatile ARM_PAGE_TABLE_ENTRY  *SecondLevelTable;
 | |
|   UINT32                         NextPageAttributes;
 | |
|   UINT32                         PageAttributes;
 | |
|   UINT32                         BaseAddress;
 | |
|   UINT64                         GcdAttributes;
 | |
| 
 | |
|   // Get the Base Address from FirstLevelDescriptor;
 | |
|   BaseAddress = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (SectionIndex << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
 | |
| 
 | |
|   // Convert SectionAttributes into PageAttributes
 | |
|   NextPageAttributes =
 | |
|     TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (*NextSectionAttributes, 0) |
 | |
|     TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (*NextSectionAttributes);
 | |
| 
 | |
|   // obtain page table base
 | |
|   SecondLevelTable = (ARM_PAGE_TABLE_ENTRY *)(FirstLevelDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
 | |
| 
 | |
|   for (i = 0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {
 | |
|     if ((SecondLevelTable[i] & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {
 | |
|       // extract attributes (cacheability and permissions)
 | |
|       PageAttributes = SecondLevelTable[i] & (TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK | TT_DESCRIPTOR_PAGE_AP_MASK);
 | |
| 
 | |
|       if (NextPageAttributes == 0) {
 | |
|         // start on a new region
 | |
|         *NextRegionLength  = 0;
 | |
|         *NextRegionBase    = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
 | |
|         NextPageAttributes = PageAttributes;
 | |
|       } else if (PageAttributes != NextPageAttributes) {
 | |
|         // Convert Section Attributes into GCD Attributes
 | |
|         Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);
 | |
|         ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|         // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
 | |
|         SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);
 | |
| 
 | |
|         // start on a new region
 | |
|         *NextRegionLength  = 0;
 | |
|         *NextRegionBase    = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
 | |
|         NextPageAttributes = PageAttributes;
 | |
|       }
 | |
|     } else if (NextPageAttributes != 0) {
 | |
|       // Convert Page Attributes into GCD Attributes
 | |
|       Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|       // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
 | |
|       SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);
 | |
| 
 | |
|       *NextRegionLength  = 0;
 | |
|       *NextRegionBase    = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
 | |
|       NextPageAttributes = 0;
 | |
|     }
 | |
| 
 | |
|     *NextRegionLength += TT_DESCRIPTOR_PAGE_SIZE;
 | |
|   }
 | |
| 
 | |
|   // Convert back PageAttributes into SectionAttributes
 | |
|   *NextSectionAttributes =
 | |
|     TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (NextPageAttributes, 0) |
 | |
|     TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (NextPageAttributes);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SyncCacheConfig (
 | |
|   IN  EFI_CPU_ARCH_PROTOCOL  *CpuProtocol
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                           Status;
 | |
|   UINT32                               i;
 | |
|   EFI_PHYSICAL_ADDRESS                 NextRegionBase;
 | |
|   UINT64                               NextRegionLength;
 | |
|   UINT32                               NextSectionAttributes;
 | |
|   UINT32                               SectionAttributes;
 | |
|   UINT64                               GcdAttributes;
 | |
|   volatile ARM_FIRST_LEVEL_DESCRIPTOR  *FirstLevelTable;
 | |
|   UINTN                                NumberOfDescriptors;
 | |
|   EFI_GCD_MEMORY_SPACE_DESCRIPTOR      *MemorySpaceMap;
 | |
| 
 | |
|   DEBUG ((DEBUG_PAGE, "SyncCacheConfig()\n"));
 | |
| 
 | |
|   // This code assumes MMU is enabled and filed with section translations
 | |
|   ASSERT (ArmMmuEnabled ());
 | |
| 
 | |
|   //
 | |
|   // Get the memory space map from GCD
 | |
|   //
 | |
|   MemorySpaceMap = NULL;
 | |
|   Status         = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   // The GCD implementation maintains its own copy of the state of memory space attributes.  GCD needs
 | |
|   // to know what the initial memory space attributes are.  The CPU Arch. Protocol does not provide a
 | |
|   // GetMemoryAttributes function for GCD to get this so we must resort to calling GCD (as if we were
 | |
|   // a client) to update its copy of the attributes.  This is bad architecture and should be replaced
 | |
|   // with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.
 | |
| 
 | |
|   // obtain page table base
 | |
|   FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());
 | |
| 
 | |
|   // Get the first region
 | |
|   NextSectionAttributes = FirstLevelTable[0] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);
 | |
| 
 | |
|   // iterate through each 1MB descriptor
 | |
|   NextRegionBase = NextRegionLength = 0;
 | |
|   for (i = 0; i < TRANSLATION_TABLE_SECTION_COUNT; i++) {
 | |
|     if ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) {
 | |
|       // extract attributes (cacheability and permissions)
 | |
|       SectionAttributes = FirstLevelTable[i] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);
 | |
| 
 | |
|       if (NextSectionAttributes == 0) {
 | |
|         // start on a new region
 | |
|         NextRegionLength      = 0;
 | |
|         NextRegionBase        = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
 | |
|         NextSectionAttributes = SectionAttributes;
 | |
|       } else if (SectionAttributes != NextSectionAttributes) {
 | |
|         // Convert Section Attributes into GCD Attributes
 | |
|         Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
 | |
|         ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|         // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
 | |
|         SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
 | |
| 
 | |
|         // start on a new region
 | |
|         NextRegionLength      = 0;
 | |
|         NextRegionBase        = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
 | |
|         NextSectionAttributes = SectionAttributes;
 | |
|       }
 | |
| 
 | |
|       NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
 | |
|     } else if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (FirstLevelTable[i])) {
 | |
|       // In this case any bits set in the 'NextSectionAttributes' are garbage and were set from
 | |
|       // bits that are actually part of the pagetable address.  We clear it out to zero so that
 | |
|       // the SyncCacheConfigPage will use the page attributes instead of trying to convert the
 | |
|       // section attributes into page attributes
 | |
|       NextSectionAttributes = 0;
 | |
|       Status                = SyncCacheConfigPage (
 | |
|                                 i,
 | |
|                                 FirstLevelTable[i],
 | |
|                                 NumberOfDescriptors,
 | |
|                                 MemorySpaceMap,
 | |
|                                 &NextRegionBase,
 | |
|                                 &NextRegionLength,
 | |
|                                 &NextSectionAttributes
 | |
|                                 );
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
|     } else {
 | |
|       // We do not support yet 16MB sections
 | |
|       ASSERT ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) != TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION);
 | |
| 
 | |
|       // start on a new region
 | |
|       if (NextSectionAttributes != 0) {
 | |
|         // Convert Section Attributes into GCD Attributes
 | |
|         Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
 | |
|         ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|         // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
 | |
|         SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
 | |
| 
 | |
|         NextRegionLength      = 0;
 | |
|         NextRegionBase        = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
 | |
|         NextSectionAttributes = 0;
 | |
|       }
 | |
| 
 | |
|       NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
 | |
|     }
 | |
|   } // section entry loop
 | |
| 
 | |
|   if (NextSectionAttributes != 0) {
 | |
|     // Convert Section Attributes into GCD Attributes
 | |
|     Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
 | |
|     SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
 | |
|   }
 | |
| 
 | |
|   FreePool (MemorySpaceMap);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| UINT64
 | |
| EfiAttributeToArmAttribute (
 | |
|   IN UINT64  EfiAttributes
 | |
|   )
 | |
| {
 | |
|   UINT64  ArmAttributes;
 | |
| 
 | |
|   switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
 | |
|     case EFI_MEMORY_UC:
 | |
|       // Map to strongly ordered
 | |
|       ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
 | |
|       break;
 | |
| 
 | |
|     case EFI_MEMORY_WC:
 | |
|       // Map to normal non-cacheable
 | |
|       ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
 | |
|       break;
 | |
| 
 | |
|     case EFI_MEMORY_WT:
 | |
|       // Write through with no-allocate
 | |
|       ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
 | |
|       break;
 | |
| 
 | |
|     case EFI_MEMORY_WB:
 | |
|       // Write back (with allocate)
 | |
|       ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
 | |
|       break;
 | |
| 
 | |
|     case EFI_MEMORY_UCE:
 | |
|     default:
 | |
|       ArmAttributes = TT_DESCRIPTOR_SECTION_TYPE_FAULT;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   // Determine protection attributes
 | |
|   if ((EfiAttributes & EFI_MEMORY_RO) != 0) {
 | |
|     ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RO_RO;
 | |
|   } else {
 | |
|     ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RW_RW;
 | |
|   }
 | |
| 
 | |
|   // Determine eXecute Never attribute
 | |
|   if ((EfiAttributes & EFI_MEMORY_XP) != 0) {
 | |
|     ArmAttributes |= TT_DESCRIPTOR_SECTION_XN_MASK;
 | |
|   }
 | |
| 
 | |
|   return ArmAttributes;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| GetMemoryRegionPage (
 | |
|   IN     UINT32  *PageTable,
 | |
|   IN OUT UINTN   *BaseAddress,
 | |
|   OUT    UINTN   *RegionLength,
 | |
|   OUT    UINTN   *RegionAttributes
 | |
|   )
 | |
| {
 | |
|   UINT32  PageAttributes;
 | |
|   UINT32  TableIndex;
 | |
|   UINT32  PageDescriptor;
 | |
| 
 | |
|   // Convert the section attributes into page attributes
 | |
|   PageAttributes = ConvertSectionAttributesToPageAttributes (*RegionAttributes, 0);
 | |
| 
 | |
|   // Calculate index into first level translation table for start of modification
 | |
|   TableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK)  >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
 | |
|   ASSERT (TableIndex < TRANSLATION_TABLE_PAGE_COUNT);
 | |
| 
 | |
|   // Go through the page table to find the end of the section
 | |
|   for ( ; TableIndex < TRANSLATION_TABLE_PAGE_COUNT; TableIndex++) {
 | |
|     // Get the section at the given index
 | |
|     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;
 | |
|     } 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;
 | |
|       }
 | |
|     } else {
 | |
|       // We do not support Large Page yet. We return EFI_SUCCESS that means end of the region.
 | |
|       ASSERT (0);
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| GetMemoryRegion (
 | |
|   IN OUT UINTN  *BaseAddress,
 | |
|   OUT    UINTN  *RegionLength,
 | |
|   OUT    UINTN  *RegionAttributes
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINT32                      TableIndex;
 | |
|   UINT32                      PageAttributes;
 | |
|   UINT32                      PageTableIndex;
 | |
|   UINT32                      SectionDescriptor;
 | |
|   ARM_FIRST_LEVEL_DESCRIPTOR  *FirstLevelTable;
 | |
|   UINT32                      *PageTable;
 | |
| 
 | |
|   // Initialize the arguments
 | |
|   *RegionLength = 0;
 | |
| 
 | |
|   // Obtain page table base
 | |
|   FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
 | |
| 
 | |
|   // 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);
 | |
| 
 | |
|   // Get the section at the given index
 | |
|   SectionDescriptor = FirstLevelTable[TableIndex];
 | |
|   if (!SectionDescriptor) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   // If 'BaseAddress' belongs to the section then round it to the section boundary
 | |
|   if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||
 | |
|       ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))
 | |
|   {
 | |
|     *BaseAddress      = (*BaseAddress) & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK;
 | |
|     *RegionAttributes = SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK;
 | |
|   } else {
 | |
|     // Otherwise, we round it to the page boundary
 | |
|     *BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK;
 | |
| 
 | |
|     // Get the attribute at the page table level (Level 2)
 | |
|     PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
 | |
| 
 | |
|     // Calculate index into first level translation table for start of modification
 | |
|     PageTableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK)  >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
 | |
|     ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
 | |
| 
 | |
|     PageAttributes    = PageTable[PageTableIndex] & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK;
 | |
|     *RegionAttributes = TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (PageAttributes, 0) |
 | |
|                         TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (PageAttributes);
 | |
|   }
 | |
| 
 | |
|   for ( ; TableIndex < TRANSLATION_TABLE_SECTION_COUNT; TableIndex++) {
 | |
|     // Get the section at the given index
 | |
|     SectionDescriptor = FirstLevelTable[TableIndex];
 | |
| 
 | |
|     // If the entry is a level-2 page table then we scan it to find the end of the region
 | |
|     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);
 | |
| 
 | |
|       // Scan the page table to find the end of the region.
 | |
|       Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionLength, RegionAttributes);
 | |
| 
 | |
|       // If we have found the end of the region (Status == EFI_SUCCESS) then we exit the for-loop
 | |
|       if (Status == EFI_SUCCESS) {
 | |
|         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))
 | |
|     {
 | |
|       if ((SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK) != *RegionAttributes) {
 | |
|         // If the attributes of the section differ from the one targeted then we exit the loop
 | |
|         break;
 | |
|       } else {
 | |
|         *RegionLength = *RegionLength + TT_DESCRIPTOR_SECTION_SIZE;
 | |
|       }
 | |
|     } else {
 | |
|       // If we are on an invalid section then it means it is the end of our section.
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |