22#define __EFI_MEMORY_RWX 0
24#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | \
33ConvertSectionToPages (
38 UINT32 SectionDescriptor;
39 UINT32 PageTableDescriptor;
40 UINT32 PageDescriptor;
43 volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
44 volatile ARM_PAGE_TABLE_ENTRY *PageTable;
46 DEBUG ((DEBUG_PAGE,
"Converting section at 0x%x to pages\n", (
UINTN)BaseAddress));
49 FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
52 FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
53 ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
56 SectionDescriptor = FirstLevelTable[FirstLevelIdx];
57 PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (SectionDescriptor);
60 PageTable = (
volatile ARM_PAGE_TABLE_ENTRY *)
AllocatePages (1);
61 if (PageTable ==
NULL) {
62 return EFI_OUT_OF_RESOURCES;
66 for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {
67 PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (BaseAddress + (Index << 12)) | PageDescriptor;
71 PageTableDescriptor = (((
UINTN)PageTable) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;
74 FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;
86 OUT BOOLEAN *FlushTlbs OPTIONAL
93 UINT32 NumPageEntries;
96 UINT32 PageTableIndex;
97 UINT32 PageTableEntry;
98 UINT32 CurrentPageTableEntry;
101 volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
102 volatile ARM_PAGE_TABLE_ENTRY *PageTable;
108 EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;
115 if ((Attributes & EFI_MEMORY_UC) != 0) {
117 EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
119 EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED;
120 }
else if ((Attributes & EFI_MEMORY_WC) != 0) {
122 EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
124 EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE;
125 }
else if ((Attributes & EFI_MEMORY_WT) != 0) {
127 EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
129 EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC;
130 }
else if ((Attributes & EFI_MEMORY_WB) != 0) {
132 EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
134 EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC;
135 }
else if ((Attributes & CACHE_ATTRIBUTE_MASK) != 0) {
138 return EFI_UNSUPPORTED;
141 if ((Attributes & EFI_MEMORY_RP) == 0) {
142 EntryValue |= TT_DESCRIPTOR_PAGE_AF;
145 if ((Attributes & EFI_MEMORY_RO) != 0) {
146 EntryValue |= TT_DESCRIPTOR_PAGE_AP_RO_RO;
148 EntryValue |= TT_DESCRIPTOR_PAGE_AP_RW_RW;
151 if ((Attributes & EFI_MEMORY_XP) != 0) {
152 EntryValue |= TT_DESCRIPTOR_PAGE_XN_MASK;
156 FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
159 NumPageEntries = (UINT32)(Length / TT_DESCRIPTOR_PAGE_SIZE);
163 for (p = 0; p < NumPageEntries; p++) {
166 FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
167 ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
170 Descriptor = FirstLevelTable[FirstLevelIdx];
173 if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (Descriptor)) {
179 if ((EntryValue & ~TT_DESCRIPTOR_PAGE_TYPE_MASK & EntryMask) ==
180 (ConvertSectionAttributesToPageAttributes (Descriptor) & EntryMask))
185 Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
186 if (EFI_ERROR (Status)) {
192 Descriptor = FirstLevelTable[FirstLevelIdx];
193 if (FlushTlbs !=
NULL) {
199 PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS (Descriptor);
202 PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
203 ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
206 CurrentPageTableEntry = PageTable[PageTableIndex];
209 PageTableEntry = CurrentPageTableEntry & ~EntryMask;
212 PageTableEntry |= EntryValue;
214 if (CurrentPageTableEntry != PageTableEntry) {
215 Mva = (VOID *)(
UINTN)((((
UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));
218 PageTable[PageTableIndex] = PageTableEntry;
219 ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);
223 Offset += TT_DESCRIPTOR_PAGE_SIZE;
231UpdateSectionEntries (
234 IN UINT64 Attributes,
240 UINT32 FirstLevelIdx;
243 UINT32 CurrentDescriptor;
246 volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
254 EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;
261 if ((Attributes & EFI_MEMORY_UC) != 0) {
263 EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
265 EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED;
266 }
else if ((Attributes & EFI_MEMORY_WC) != 0) {
268 EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
270 EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE;
271 }
else if ((Attributes & EFI_MEMORY_WT) != 0) {
273 EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
275 EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC;
276 }
else if ((Attributes & EFI_MEMORY_WB) != 0) {
278 EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
280 EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC;
281 }
else if ((Attributes & CACHE_ATTRIBUTE_MASK) != 0) {
284 return EFI_UNSUPPORTED;
287 if ((Attributes & EFI_MEMORY_RO) != 0) {
288 EntryValue |= TT_DESCRIPTOR_SECTION_AP_RO_RO;
290 EntryValue |= TT_DESCRIPTOR_SECTION_AP_RW_RW;
293 if ((Attributes & EFI_MEMORY_XP) != 0) {
294 EntryValue |= TT_DESCRIPTOR_SECTION_XN_MASK;
297 if ((Attributes & EFI_MEMORY_RP) == 0) {
298 EntryValue |= TT_DESCRIPTOR_SECTION_AF;
302 FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
305 FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
306 ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
309 NumSections = (UINT32)(Length / TT_DESCRIPTOR_SECTION_SIZE);
312 for (i = 0; i < NumSections; i++) {
313 CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];
316 if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (CurrentDescriptor)) {
318 Status = UpdatePageEntries (
319 (FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT,
320 TT_DESCRIPTOR_SECTION_SIZE,
322 ConvertSectionAttributesToPageAttributes (EntryMask),
328 if (CurrentDescriptor != 0) {
330 Descriptor = CurrentDescriptor & ~EntryMask;
332 Descriptor = ((
UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT;
336 Descriptor |= EntryValue;
338 if (CurrentDescriptor != Descriptor) {
339 Mva = (VOID *)(
UINTN)(((
UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
342 FirstLevelTable[FirstLevelIdx + i] = Descriptor;
343 ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);
371 IN UINT64 Attributes,
372 IN UINT32 SectionMask
382 "%a BaseAddress: 0x%llx is greater than MAX_ADDRESS: 0x%llx, fail to apply attributes!\n",
387 return EFI_UNSUPPORTED;
397 if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) &&
398 (Length >= TT_DESCRIPTOR_SECTION_SIZE))
400 ChunkLength = Length - Length % TT_DESCRIPTOR_SECTION_SIZE;
404 "SetMemoryAttributes(): MMU section 0x%lx length 0x%lx to %lx\n",
410 Status = UpdateSectionEntries (
423 ChunkLength = TT_DESCRIPTOR_SECTION_SIZE -
424 (BaseAddress % TT_DESCRIPTOR_SECTION_SIZE);
425 if (ChunkLength + TT_DESCRIPTOR_SECTION_SIZE > Length) {
426 ChunkLength = Length;
431 "SetMemoryAttributes(): MMU page 0x%lx length 0x%lx to %lx\n",
437 Status = UpdatePageEntries (
441 ConvertSectionAttributesToPageAttributes (SectionMask),
446 if (EFI_ERROR (Status)) {
449 "%a failed to update attributes with status %r for BaseAddress 0x%llx of length 0x%llx\n",
458 BaseAddress += ChunkLength;
459 Length -= ChunkLength;
506 IN UINT64 Attributes,
507 IN UINT64 AttributeMask
512 if (((BaseAddress | Length) & EFI_PAGE_MASK) != 0) {
513 return EFI_INVALID_PARAMETER;
516 if ((Attributes & EFI_MEMORY_CACHETYPE_MASK) == 0) {
521 if (AttributeMask != 0) {
522 if (((AttributeMask & ~(UINT64)(EFI_MEMORY_RP|EFI_MEMORY_RO|EFI_MEMORY_XP)) != 0) ||
523 ((Attributes & ~AttributeMask) != 0))
525 return EFI_INVALID_PARAMETER;
528 AttributeMask = EFI_MEMORY_RP | EFI_MEMORY_RO | EFI_MEMORY_XP;
532 if ((AttributeMask & EFI_MEMORY_RP) != 0) {
533 TtEntryMask |= TT_DESCRIPTOR_SECTION_AF;
536 if ((AttributeMask & EFI_MEMORY_RO) != 0) {
537 TtEntryMask |= TT_DESCRIPTOR_SECTION_AP_MASK;
540 if ((AttributeMask & EFI_MEMORY_XP) != 0) {
541 TtEntryMask |= TT_DESCRIPTOR_SECTION_XN_MASK;
544 ASSERT (AttributeMask == 0);
545 if (AttributeMask != 0) {
546 return EFI_INVALID_PARAMETER;
549 TtEntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK |
550 TT_DESCRIPTOR_SECTION_XN_MASK |
551 TT_DESCRIPTOR_SECTION_AP_MASK |
552 TT_DESCRIPTOR_SECTION_AF;
VOID EFIAPI ArmInvalidateTlb(VOID)
STATIC EFI_STATUS SetMemoryAttributes(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN UINT32 SectionMask)
EFI_STATUS ArmSetMemoryAttributes(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN UINT64 AttributeMask)
#define DEBUG(Expression)
VOID *EFIAPI AllocatePages(IN UINTN Pages)
UINT64 EFI_PHYSICAL_ADDRESS