16#define INVALID_ENTRY ((UINT64)~0)
19#define BITS_PER_LEVEL 9
31GetRootTranslationTableInfo (
37 *RootTableLevel = (T0SZ - MIN_T0SZ) / BITS_PER_LEVEL;
38 *RootTableEntryCount = TT_ENTRY_COUNT >> (T0SZ - MIN_T0SZ) % BITS_PER_LEVEL;
50PageAttributeToGcdAttribute (
51 IN UINT64 PageAttributes
56 switch (PageAttributes & TT_ATTR_INDX_MASK) {
57 case TT_ATTR_INDX_DEVICE_MEMORY:
58 GcdAttributes = EFI_MEMORY_UC;
60 case TT_ATTR_INDX_MEMORY_NON_CACHEABLE:
61 GcdAttributes = EFI_MEMORY_WC;
63 case TT_ATTR_INDX_MEMORY_WRITE_THROUGH:
64 GcdAttributes = EFI_MEMORY_WT;
66 case TT_ATTR_INDX_MEMORY_WRITE_BACK:
67 GcdAttributes = EFI_MEMORY_WB;
72 "PageAttributeToGcdAttribute: PageAttributes:0x%lX not supported.\n",
82 if ((PageAttributes & TT_AF) == 0) {
83 GcdAttributes |= EFI_MEMORY_RP;
86 if (((PageAttributes & TT_AP_MASK) == TT_AP_NO_RO) ||
87 ((PageAttributes & TT_AP_MASK) == TT_AP_RO_RO))
90 GcdAttributes |= EFI_MEMORY_RO;
94 if ((PageAttributes & (TT_PXN_MASK | TT_UXN_MASK)) != 0) {
95 GcdAttributes |= EFI_MEMORY_XP;
111RegionAttributeToGcdAttribute (
115 return PageAttributeToGcdAttribute (PageAttributes);
128GetFirstPageAttribute (
129 IN UINT64 *FirstLevelTableAddress,
136 FirstEntry = *FirstLevelTableAddress;
138 if ((TableLevel != 3) && ((FirstEntry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY)) {
142 return GetFirstPageAttribute ((UINT64 *)(FirstEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE), TableLevel + 1);
143 }
else if (((FirstEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) ||
144 ((TableLevel == 3) && ((FirstEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY_LEVEL3)))
146 return FirstEntry & TT_ATTRIBUTES_MASK;
148 return INVALID_ENTRY;
167GetNextEntryAttribute (
168 IN UINT64 *TableAddress,
171 IN UINT64 BaseAddress,
172 IN OUT UINT64 *PrevEntryAttribute,
173 IN OUT UINT64 *StartGcdRegion
178 UINT64 EntryAttribute;
181 UINTN NumberOfDescriptors;
185 MemorySpaceMap =
NULL;
186 Status =
gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
188 if (EFI_ERROR (Status) || (TableLevel > 3)) {
190 ASSERT (TableLevel <= 3);
196 for (Index = 0; Index < EntryCount; Index++) {
197 Entry = TableAddress[Index];
198 EntryType = Entry & TT_TYPE_MASK;
199 EntryAttribute = Entry & TT_ATTRIBUTES_MASK;
202 if ((EntryType == TT_TYPE_BLOCK_ENTRY) ||
203 ((TableLevel == 3) && (EntryType == TT_TYPE_BLOCK_ENTRY_LEVEL3)))
205 if ((*PrevEntryAttribute == INVALID_ENTRY) || (EntryAttribute != *PrevEntryAttribute)) {
206 if (*PrevEntryAttribute != INVALID_ENTRY) {
212 (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))) - *StartGcdRegion,
213 PageAttributeToGcdAttribute (*PrevEntryAttribute)
218 *StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel));
219 *PrevEntryAttribute = EntryAttribute;
223 }
else if (EntryType == TT_TYPE_TABLE_ENTRY) {
225 ASSERT (TableLevel < 3);
228 GetNextEntryAttribute (
229 (UINT64 *)(Entry & TT_ADDRESS_MASK_DESCRIPTION_TABLE),
232 (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))),
237 if (*PrevEntryAttribute != INVALID_ENTRY) {
243 (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))) - *StartGcdRegion,
244 PageAttributeToGcdAttribute (*PrevEntryAttribute)
248 *StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel));
249 *PrevEntryAttribute = INVALID_ENTRY;
256 return BaseAddress + (EntryCount * TT_ADDRESS_AT_LEVEL (TableLevel));
274 UINT64 PageAttribute;
275 UINT64 *FirstLevelTableAddress;
278 UINTN NumberOfDescriptors;
282 UINT64 BaseAddressGcdRegion;
283 UINT64 EndAddressGcdRegion;
286 ASSERT (ArmMmuEnabled ());
291 MemorySpaceMap =
NULL;
292 Status =
gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
294 if (EFI_ERROR (Status)) {
306 FirstLevelTableAddress = (UINT64 *)(ArmGetTTBR0BaseAddress ());
311 T0SZ = Tcr & TCR_T0SZ_MASK;
314 GetRootTranslationTableInfo (T0SZ, &TableLevel, &TableCount);
317 PageAttribute = GetFirstPageAttribute (FirstLevelTableAddress, TableLevel);
320 BaseAddressGcdRegion = 0x0;
321 EndAddressGcdRegion = GetNextEntryAttribute (
322 FirstLevelTableAddress,
325 BaseAddressGcdRegion,
327 &BaseAddressGcdRegion
331 if ((PageAttribute != INVALID_ENTRY) && (EndAddressGcdRegion > BaseAddressGcdRegion)) {
335 BaseAddressGcdRegion,
336 EndAddressGcdRegion - BaseAddressGcdRegion,
337 PageAttributeToGcdAttribute (PageAttribute)
354EfiAttributeToArmAttribute (
355 IN UINT64 EfiAttributes
358 UINT64 ArmAttributes;
360 switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
362 if (ArmReadCurrentEL () == AARCH64_EL2) {
363 ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_XN_MASK;
365 ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_UXN_MASK | TT_PXN_MASK;
370 ArmAttributes = TT_ATTR_INDX_MEMORY_NON_CACHEABLE;
373 ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_THROUGH | TT_SH_INNER_SHAREABLE;
376 ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_BACK | TT_SH_INNER_SHAREABLE;
379 ArmAttributes = TT_ATTR_INDX_MASK;
383 if ((EfiAttributes & EFI_MEMORY_RP) == 0) {
384 ArmAttributes |= TT_AF;
388 if ((EfiAttributes & EFI_MEMORY_RO) != 0) {
389 ArmAttributes |= TT_AP_NO_RO;
393 if ((EfiAttributes & EFI_MEMORY_XP) != 0) {
394 ArmAttributes |= TT_PXN_MASK;
397 return ArmAttributes;
421 IN UINT64 *TranslationTable,
423 IN UINT64 *LastBlockEntry,
430 UINT64 *NextTranslationTable;
432 UINT64 BlockEntryType;
435 if (TableLevel != 3) {
436 BlockEntryType = TT_TYPE_BLOCK_ENTRY;
438 BlockEntryType = TT_TYPE_BLOCK_ENTRY_LEVEL3;
442 BlockEntry = (UINT64 *)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, TableLevel, *BaseAddress);
443 EntryType = *BlockEntry & TT_TYPE_MASK;
445 if ((TableLevel < 3) && (EntryType == TT_TYPE_TABLE_ENTRY)) {
446 NextTranslationTable = (UINT64 *)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE);
449 Status = GetMemoryRegionRec (
450 NextTranslationTable,
452 (
UINTN *)TT_LAST_BLOCK_ADDRESS (NextTranslationTable, TT_ENTRY_COUNT),
460 if (Status != EFI_NOT_FOUND) {
466 }
else if (EntryType == BlockEntryType) {
469 *BaseAddress = *BaseAddress & ~(TT_ADDRESS_AT_LEVEL (TableLevel) - 1);
471 *RegionAttributes = *BlockEntry & TT_ATTRIBUTES_MASK;
473 return EFI_NO_MAPPING;
476 while (BlockEntry <= LastBlockEntry) {
477 if (((*BlockEntry & TT_TYPE_MASK) == BlockEntryType) &&
478 ((*BlockEntry & TT_ATTRIBUTES_MASK) == *RegionAttributes))
480 *RegionLength = *RegionLength + TT_BLOCK_ENTRY_SIZE_AT_LEVEL (TableLevel);
492 return EFI_NOT_FOUND;
522 UINT64 *TranslationTable;
527 if ((BaseAddress ==
NULL) || (RegionLength ==
NULL) || (RegionAttributes ==
NULL)) {
528 ASSERT ((BaseAddress !=
NULL) && (RegionLength !=
NULL) && (RegionAttributes !=
NULL));
529 return EFI_INVALID_PARAMETER;
532 TranslationTable = ArmGetTTBR0BaseAddress ();
537 *RegionAttributes = 0;
539 T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
541 GetRootTranslationTableInfo (T0SZ, &TableLevel, &EntryCount);
543 Status = GetMemoryRegionRec (
546 (
UINTN *)TT_LAST_BLOCK_ADDRESS (TranslationTable, EntryCount),
554 if ((Status == EFI_NOT_FOUND) && (*RegionLength > 0)) {
EFI_STATUS SetGcdMemorySpaceAttributes(IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, IN UINTN NumberOfDescriptors, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)