mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 16:44:10 +02:00
ArmPkg/CpuDxe: Added support to not set a memory region with the same attribute
Changing the attribute implies some cache management (clean & invalidate). Preventing the cache management should improve the performance. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14568 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
6adbd5b4d2
commit
2e969d2e9e
@ -194,3 +194,149 @@ SyncCacheConfig (
|
|||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
EfiAttributeToArmAttribute (
|
||||||
|
IN UINT64 EfiAttributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT64 ArmAttributes;
|
||||||
|
|
||||||
|
switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
|
||||||
|
case EFI_MEMORY_UC:
|
||||||
|
ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY;
|
||||||
|
break;
|
||||||
|
case EFI_MEMORY_WC:
|
||||||
|
ArmAttributes = TT_ATTR_INDX_MEMORY_NON_CACHEABLE;
|
||||||
|
break;
|
||||||
|
case EFI_MEMORY_WT:
|
||||||
|
ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_THROUGH;
|
||||||
|
break;
|
||||||
|
case EFI_MEMORY_WB:
|
||||||
|
ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_BACK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG ((EFI_D_ERROR, "EfiAttributeToArmAttribute: 0x%lX attributes is not supported.\n", EfiAttributes));
|
||||||
|
ASSERT (0);
|
||||||
|
ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the access flag to match the block attributes
|
||||||
|
ArmAttributes |= TT_AF;
|
||||||
|
|
||||||
|
// Determine protection attributes
|
||||||
|
if (EfiAttributes & EFI_MEMORY_WP) {
|
||||||
|
ArmAttributes |= TT_AP_RO_RO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process eXecute Never attribute
|
||||||
|
if (EfiAttributes & EFI_MEMORY_XP) {
|
||||||
|
ArmAttributes |= TT_PXN_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArmAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will recursively go down the page table to find the first block address linked to 'BaseAddress'.
|
||||||
|
// And then the function will identify the size of the region that has the same page table attribute.
|
||||||
|
EFI_STATUS
|
||||||
|
GetMemoryRegionRec (
|
||||||
|
IN UINT64 *TranslationTable,
|
||||||
|
IN UINTN TableLevel,
|
||||||
|
IN UINT64 *LastBlockEntry,
|
||||||
|
IN OUT UINTN *BaseAddress,
|
||||||
|
OUT UINTN *RegionLength,
|
||||||
|
OUT UINTN *RegionAttributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT64 *NextTranslationTable;
|
||||||
|
UINT64 *BlockEntry;
|
||||||
|
UINT64 BlockEntryType;
|
||||||
|
UINT64 EntryType;
|
||||||
|
|
||||||
|
if (TableLevel != 3) {
|
||||||
|
BlockEntryType = TT_TYPE_BLOCK_ENTRY;
|
||||||
|
} else {
|
||||||
|
BlockEntryType = TT_TYPE_BLOCK_ENTRY_LEVEL3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the block entry linked to the Base Address
|
||||||
|
BlockEntry = (UINT64*)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, TableLevel, *BaseAddress);
|
||||||
|
EntryType = *BlockEntry & TT_TYPE_MASK;
|
||||||
|
|
||||||
|
if (EntryType == TT_TYPE_TABLE_ENTRY) {
|
||||||
|
NextTranslationTable = (UINT64*)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE);
|
||||||
|
|
||||||
|
// The entry is a page table, so we go to the next level
|
||||||
|
Status = GetMemoryRegionRec (
|
||||||
|
NextTranslationTable, // Address of the next level page table
|
||||||
|
TableLevel + 1, // Next Page Table level
|
||||||
|
(UINTN*)TT_LAST_BLOCK_ADDRESS(NextTranslationTable, TT_ENTRY_COUNT),
|
||||||
|
BaseAddress, RegionLength, RegionAttributes);
|
||||||
|
|
||||||
|
// In case of 'Success', it means the end of the block region has been found into the upper
|
||||||
|
// level translation table
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
} else if (EntryType == BlockEntryType) {
|
||||||
|
// We have found the BlockEntry attached to the address. We save its start address (the start
|
||||||
|
// address might be before the 'BaseAdress') and attributes
|
||||||
|
*BaseAddress = *BaseAddress & ~(TT_ADDRESS_AT_LEVEL(TableLevel) - 1);
|
||||||
|
*RegionLength = 0;
|
||||||
|
*RegionAttributes = *BlockEntry & TT_ATTRIBUTES_MASK;
|
||||||
|
} else {
|
||||||
|
// We have an 'Invalid' entry
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (BlockEntry <= LastBlockEntry) {
|
||||||
|
if ((*BlockEntry & TT_ATTRIBUTES_MASK) == *RegionAttributes) {
|
||||||
|
*RegionLength = *RegionLength + TT_BLOCK_ENTRY_SIZE_AT_LEVEL(TableLevel);
|
||||||
|
} else {
|
||||||
|
// In case we have found the end of the region we return success
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
BlockEntry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have reached the end of the TranslationTable and we have not found the end of the region then
|
||||||
|
// we return EFI_NOT_FOUND.
|
||||||
|
// The caller will continue to look for the memory region at its level
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
GetMemoryRegion (
|
||||||
|
IN OUT UINTN *BaseAddress,
|
||||||
|
OUT UINTN *RegionLength,
|
||||||
|
OUT UINTN *RegionAttributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT64 *TranslationTable;
|
||||||
|
UINTN TableLevel;
|
||||||
|
UINTN EntryCount;
|
||||||
|
UINTN T0SZ;
|
||||||
|
|
||||||
|
ASSERT ((BaseAddress != NULL) && (RegionLength != NULL) && (RegionAttributes != NULL));
|
||||||
|
|
||||||
|
TranslationTable = ArmGetTTBR0BaseAddress ();
|
||||||
|
|
||||||
|
T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
|
||||||
|
// Get the Table info from T0SZ
|
||||||
|
GetRootTranslationTableInfo (T0SZ, &TableLevel, &EntryCount);
|
||||||
|
|
||||||
|
Status = GetMemoryRegionRec (TranslationTable, TableLevel,
|
||||||
|
(UINTN*)TT_LAST_BLOCK_ADDRESS(TranslationTable, EntryCount),
|
||||||
|
BaseAddress, RegionLength, RegionAttributes);
|
||||||
|
|
||||||
|
// If the region continues up to the end of the root table then GetMemoryRegionRec()
|
||||||
|
// will return EFI_NOT_FOUND
|
||||||
|
if (Status == EFI_NOT_FOUND) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -696,3 +696,185 @@ SetMemoryAttributes (
|
|||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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-cachable
|
||||||
|
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_WP:
|
||||||
|
case EFI_MEMORY_XP:
|
||||||
|
case EFI_MEMORY_RP:
|
||||||
|
case EFI_MEMORY_UCE:
|
||||||
|
default:
|
||||||
|
// Cannot be implemented UEFI definition unclear for ARM
|
||||||
|
// Cause a page fault if these ranges are accessed.
|
||||||
|
ArmAttributes = TT_DESCRIPTOR_SECTION_TYPE_FAULT;
|
||||||
|
DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): Unsupported attribute %x will page fault on access\n", EfiAttributes));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine protection attributes
|
||||||
|
if (EfiAttributes & EFI_MEMORY_WP) {
|
||||||
|
ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RO_RO;
|
||||||
|
} else {
|
||||||
|
ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RW_RW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine eXecute Never attribute
|
||||||
|
if (EfiAttributes & EFI_MEMORY_XP) {
|
||||||
|
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 = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(*BaseAddress) >> 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 '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 = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (*BaseAddress) >> 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 ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE) {
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
@ -148,6 +148,19 @@ SetMemoryAttributes (
|
|||||||
IN EFI_PHYSICAL_ADDRESS VirtualMask
|
IN EFI_PHYSICAL_ADDRESS VirtualMask
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// The ARM Attributes might be defined on 64-bit (case of the long format description table)
|
||||||
|
UINT64
|
||||||
|
EfiAttributeToArmAttribute (
|
||||||
|
IN UINT64 EfiAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
GetMemoryRegion (
|
||||||
|
IN OUT UINTN *BaseAddress,
|
||||||
|
OUT UINTN *RegionLength,
|
||||||
|
OUT UINTN *RegionAttributes
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
GetRootTranslationTableInfo (
|
GetRootTranslationTableInfo (
|
||||||
IN UINTN T0SZ,
|
IN UINTN T0SZ,
|
||||||
|
@ -178,18 +178,37 @@ CpuSetMemoryAttributes (
|
|||||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||||
IN UINT64 Length,
|
IN UINT64 Length,
|
||||||
IN UINT64 Attributes
|
IN UINT64 EfiAttributes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DEBUG ((EFI_D_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress, Length, Attributes));
|
EFI_STATUS Status;
|
||||||
|
UINTN ArmAttributes;
|
||||||
|
UINTN RegionBaseAddress;
|
||||||
|
UINTN RegionLength;
|
||||||
|
UINTN RegionArmAttributes;
|
||||||
|
|
||||||
if ((BaseAddress & (SIZE_4KB - 1)) != 0) {
|
if ((BaseAddress & (SIZE_4KB - 1)) != 0) {
|
||||||
// Minimum granularity is SIZE_4KB (4KB on ARM)
|
// Minimum granularity is SIZE_4KB (4KB on ARM)
|
||||||
DEBUG ((EFI_D_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum ganularity is SIZE_4KB\n", BaseAddress, Length, Attributes));
|
DEBUG ((EFI_D_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum ganularity is SIZE_4KB\n", BaseAddress, Length, EfiAttributes));
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SetMemoryAttributes (BaseAddress, Length, Attributes, 0);
|
// Convert the 'Attribute' into ARM Attribute
|
||||||
|
ArmAttributes = EfiAttributeToArmAttribute (EfiAttributes);
|
||||||
|
|
||||||
|
// Get the region starting from 'BaseAddress' and its 'Attribute'
|
||||||
|
RegionBaseAddress = BaseAddress;
|
||||||
|
Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes);
|
||||||
|
|
||||||
|
// Data & Instruction Caches are flushed when we set new memory attributes.
|
||||||
|
// So, we only set the attributes if the new region is different.
|
||||||
|
if (EFI_ERROR (Status) || (RegionArmAttributes != ArmAttributes) ||
|
||||||
|
((BaseAddress + Length) > (RegionBaseAddress + RegionLength)))
|
||||||
|
{
|
||||||
|
return SetMemoryAttributes (BaseAddress, Length, EfiAttributes, 0);
|
||||||
|
} else {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
Loading…
x
Reference in New Issue
Block a user