]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
ArmPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmPkg / Drivers / CpuDxe / Arm / Mmu.c
CommitLineData
aeb61534
A
1/*++\r
2\r
d6ebcab7
HT
3Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>\r
4Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>\r
a387f2ee 5Portions copyright (c) 2013-2021, Arm Limited. All rights reserved.<BR>\r
b7a09b71 6Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
aeb61534 7\r
4059386c 8SPDX-License-Identifier: BSD-2-Clause-Patent\r
aeb61534
A
9\r
10\r
11--*/\r
12\r
5b53eaff 13#include <Library/MemoryAllocationLib.h>\r
aeb61534 14#include "CpuDxe.h"\r
aeb61534 15\r
3402aac7 16EFI_STATUS\r
aeb61534
A
17SectionToGcdAttributes (\r
18 IN UINT32 SectionAttributes,\r
19 OUT UINT64 *GcdAttributes\r
20 )\r
21{\r
22 *GcdAttributes = 0;\r
23\r
24 // determine cacheability attributes\r
429309e0 25 switch (SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {\r
1bfda055 26 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:\r
aeb61534
A
27 *GcdAttributes |= EFI_MEMORY_UC;\r
28 break;\r
1bfda055 29 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:\r
aeb61534
A
30 *GcdAttributes |= EFI_MEMORY_UC;\r
31 break;\r
1bfda055 32 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:\r
aeb61534
A
33 *GcdAttributes |= EFI_MEMORY_WT;\r
34 break;\r
1bfda055 35 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:\r
aeb61534
A
36 *GcdAttributes |= EFI_MEMORY_WB;\r
37 break;\r
1bfda055 38 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:\r
aeb61534
A
39 *GcdAttributes |= EFI_MEMORY_WC;\r
40 break;\r
1bfda055 41 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:\r
aeb61534
A
42 *GcdAttributes |= EFI_MEMORY_WB;\r
43 break;\r
1bfda055 44 case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:\r
aeb61534
A
45 *GcdAttributes |= EFI_MEMORY_UC;\r
46 break;\r
47 default:\r
48 return EFI_UNSUPPORTED;\r
aeb61534 49 }\r
1bfda055 50\r
aeb61534 51 // determine protection attributes\r
429309e0 52 switch (SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {\r
1bfda055 53 case TT_DESCRIPTOR_SECTION_AP_NO_NO: // no read, no write\r
429309e0 54 // *GcdAttributes |= EFI_MEMORY_RO | EFI_MEMORY_RP;\r
aeb61534
A
55 break;\r
56\r
1bfda055 57 case TT_DESCRIPTOR_SECTION_AP_RW_NO:\r
58 case TT_DESCRIPTOR_SECTION_AP_RW_RW:\r
aeb61534
A
59 // normal read/write access, do not add additional attributes\r
60 break;\r
61\r
62 // read only cases map to write-protect\r
1bfda055 63 case TT_DESCRIPTOR_SECTION_AP_RO_NO:\r
64 case TT_DESCRIPTOR_SECTION_AP_RO_RO:\r
b7a09b71 65 *GcdAttributes |= EFI_MEMORY_RO;\r
aeb61534
A
66 break;\r
67\r
68 default:\r
69 return EFI_UNSUPPORTED;\r
aeb61534
A
70 }\r
71\r
72 // now process eXectue Never attribute\r
1bfda055 73 if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0 ) {\r
aeb61534
A
74 *GcdAttributes |= EFI_MEMORY_XP;\r
75 }\r
76\r
77 return EFI_SUCCESS;\r
78}\r
79\r
2cf4b608 80EFI_STATUS\r
81PageToGcdAttributes (\r
82 IN UINT32 PageAttributes,\r
83 OUT UINT64 *GcdAttributes\r
84 )\r
85{\r
86 *GcdAttributes = 0;\r
87\r
88 // determine cacheability attributes\r
429309e0 89 switch (PageAttributes & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) {\r
2cf4b608 90 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED:\r
91 *GcdAttributes |= EFI_MEMORY_UC;\r
92 break;\r
93 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE:\r
94 *GcdAttributes |= EFI_MEMORY_UC;\r
95 break;\r
96 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:\r
97 *GcdAttributes |= EFI_MEMORY_WT;\r
98 break;\r
99 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC:\r
100 *GcdAttributes |= EFI_MEMORY_WB;\r
101 break;\r
102 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE:\r
103 *GcdAttributes |= EFI_MEMORY_WC;\r
104 break;\r
105 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC:\r
106 *GcdAttributes |= EFI_MEMORY_WB;\r
107 break;\r
108 case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE:\r
109 *GcdAttributes |= EFI_MEMORY_UC;\r
110 break;\r
111 default:\r
112 return EFI_UNSUPPORTED;\r
113 }\r
114\r
115 // determine protection attributes\r
429309e0 116 switch (PageAttributes & TT_DESCRIPTOR_PAGE_AP_MASK) {\r
2cf4b608 117 case TT_DESCRIPTOR_PAGE_AP_NO_NO: // no read, no write\r
429309e0 118 // *GcdAttributes |= EFI_MEMORY_RO | EFI_MEMORY_RP;\r
2cf4b608 119 break;\r
120\r
121 case TT_DESCRIPTOR_PAGE_AP_RW_NO:\r
122 case TT_DESCRIPTOR_PAGE_AP_RW_RW:\r
123 // normal read/write access, do not add additional attributes\r
124 break;\r
125\r
126 // read only cases map to write-protect\r
127 case TT_DESCRIPTOR_PAGE_AP_RO_NO:\r
128 case TT_DESCRIPTOR_PAGE_AP_RO_RO:\r
b7a09b71 129 *GcdAttributes |= EFI_MEMORY_RO;\r
2cf4b608 130 break;\r
131\r
132 default:\r
133 return EFI_UNSUPPORTED;\r
134 }\r
135\r
136 // now process eXectue Never attribute\r
137 if ((PageAttributes & TT_DESCRIPTOR_PAGE_XN_MASK) != 0 ) {\r
138 *GcdAttributes |= EFI_MEMORY_XP;\r
139 }\r
140\r
141 return EFI_SUCCESS;\r
142}\r
143\r
2cf4b608 144EFI_STATUS\r
145SyncCacheConfigPage (\r
429309e0
MK
146 IN UINT32 SectionIndex,\r
147 IN UINT32 FirstLevelDescriptor,\r
148 IN UINTN NumberOfDescriptors,\r
149 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
150 IN OUT EFI_PHYSICAL_ADDRESS *NextRegionBase,\r
151 IN OUT UINT64 *NextRegionLength,\r
152 IN OUT UINT32 *NextSectionAttributes\r
2cf4b608 153 )\r
154{\r
429309e0
MK
155 EFI_STATUS Status;\r
156 UINT32 i;\r
157 volatile ARM_PAGE_TABLE_ENTRY *SecondLevelTable;\r
158 UINT32 NextPageAttributes;\r
159 UINT32 PageAttributes;\r
160 UINT32 BaseAddress;\r
161 UINT64 GcdAttributes;\r
2cf4b608 162\r
163 // Get the Base Address from FirstLevelDescriptor;\r
429309e0 164 BaseAddress = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (SectionIndex << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
2cf4b608 165\r
166 // Convert SectionAttributes into PageAttributes\r
167 NextPageAttributes =\r
429309e0
MK
168 TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (*NextSectionAttributes, 0) |\r
169 TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (*NextSectionAttributes);\r
2cf4b608 170\r
171 // obtain page table base\r
172 SecondLevelTable = (ARM_PAGE_TABLE_ENTRY *)(FirstLevelDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);\r
173\r
429309e0 174 for (i = 0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {\r
2cf4b608 175 if ((SecondLevelTable[i] & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {\r
176 // extract attributes (cacheability and permissions)\r
177 PageAttributes = SecondLevelTable[i] & (TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK | TT_DESCRIPTOR_PAGE_AP_MASK);\r
178\r
179 if (NextPageAttributes == 0) {\r
180 // start on a new region\r
429309e0
MK
181 *NextRegionLength = 0;\r
182 *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
2cf4b608 183 NextPageAttributes = PageAttributes;\r
184 } else if (PageAttributes != NextPageAttributes) {\r
185 // Convert Section Attributes into GCD Attributes\r
186 Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);\r
187 ASSERT_EFI_ERROR (Status);\r
188\r
189 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
190 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);\r
191\r
192 // start on a new region\r
429309e0
MK
193 *NextRegionLength = 0;\r
194 *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
2cf4b608 195 NextPageAttributes = PageAttributes;\r
196 }\r
197 } else if (NextPageAttributes != 0) {\r
198 // Convert Page Attributes into GCD Attributes\r
199 Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);\r
200 ASSERT_EFI_ERROR (Status);\r
201\r
202 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
203 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);\r
204\r
429309e0
MK
205 *NextRegionLength = 0;\r
206 *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
2cf4b608 207 NextPageAttributes = 0;\r
208 }\r
429309e0 209\r
2cf4b608 210 *NextRegionLength += TT_DESCRIPTOR_PAGE_SIZE;\r
211 }\r
212\r
213 // Convert back PageAttributes into SectionAttributes\r
214 *NextSectionAttributes =\r
429309e0
MK
215 TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (NextPageAttributes, 0) |\r
216 TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (NextPageAttributes);\r
2cf4b608 217\r
218 return EFI_SUCCESS;\r
219}\r
aeb61534
A
220\r
221EFI_STATUS\r
222SyncCacheConfig (\r
429309e0 223 IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol\r
aeb61534
A
224 )\r
225{\r
429309e0
MK
226 EFI_STATUS Status;\r
227 UINT32 i;\r
228 EFI_PHYSICAL_ADDRESS NextRegionBase;\r
229 UINT64 NextRegionLength;\r
230 UINT32 NextSectionAttributes;\r
231 UINT32 SectionAttributes;\r
232 UINT64 GcdAttributes;\r
233 volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
234 UINTN NumberOfDescriptors;\r
235 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
aeb61534 236\r
ff5fef14 237 DEBUG ((DEBUG_PAGE, "SyncCacheConfig()\n"));\r
f659880b 238\r
aeb61534
A
239 // This code assumes MMU is enabled and filed with section translations\r
240 ASSERT (ArmMmuEnabled ());\r
241\r
f659880b
A
242 //\r
243 // Get the memory space map from GCD\r
244 //\r
245 MemorySpaceMap = NULL;\r
429309e0 246 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
f659880b
A
247 ASSERT_EFI_ERROR (Status);\r
248\r
aeb61534
A
249 // The GCD implementation maintains its own copy of the state of memory space attributes. GCD needs\r
250 // to know what the initial memory space attributes are. The CPU Arch. Protocol does not provide a\r
251 // GetMemoryAttributes function for GCD to get this so we must resort to calling GCD (as if we were\r
252 // a client) to update its copy of the attributes. This is bad architecture and should be replaced\r
253 // with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.\r
254\r
255 // obtain page table base\r
1bfda055 256 FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());\r
aeb61534 257\r
2cf4b608 258 // Get the first region\r
259 NextSectionAttributes = FirstLevelTable[0] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);\r
aeb61534
A
260\r
261 // iterate through each 1MB descriptor\r
262 NextRegionBase = NextRegionLength = 0;\r
429309e0 263 for (i = 0; i < TRANSLATION_TABLE_SECTION_COUNT; i++) {\r
2cf4b608 264 if ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) {\r
265 // extract attributes (cacheability and permissions)\r
266 SectionAttributes = FirstLevelTable[i] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);\r
267\r
268 if (NextSectionAttributes == 0) {\r
269 // start on a new region\r
429309e0
MK
270 NextRegionLength = 0;\r
271 NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
2cf4b608 272 NextSectionAttributes = SectionAttributes;\r
273 } else if (SectionAttributes != NextSectionAttributes) {\r
274 // Convert Section Attributes into GCD Attributes\r
275 Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
f659880b 276 ASSERT_EFI_ERROR (Status);\r
aeb61534
A
277\r
278 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
f659880b
A
279 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
280\r
aeb61534 281 // start on a new region\r
429309e0
MK
282 NextRegionLength = 0;\r
283 NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
2cf4b608 284 NextSectionAttributes = SectionAttributes;\r
aeb61534 285 }\r
429309e0 286\r
2cf4b608 287 NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;\r
429309e0 288 } else if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (FirstLevelTable[i])) {\r
f6be48e9
KK
289 // In this case any bits set in the 'NextSectionAttributes' are garbage and were set from\r
290 // bits that are actually part of the pagetable address. We clear it out to zero so that\r
291 // the SyncCacheConfigPage will use the page attributes instead of trying to convert the\r
292 // section attributes into page attributes\r
293 NextSectionAttributes = 0;\r
429309e0
MK
294 Status = SyncCacheConfigPage (\r
295 i,\r
296 FirstLevelTable[i],\r
297 NumberOfDescriptors,\r
298 MemorySpaceMap,\r
299 &NextRegionBase,\r
300 &NextRegionLength,\r
301 &NextSectionAttributes\r
302 );\r
2cf4b608 303 ASSERT_EFI_ERROR (Status);\r
304 } else {\r
305 // We do not support yet 16MB sections\r
306 ASSERT ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) != TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION);\r
aeb61534 307\r
2cf4b608 308 // start on a new region\r
309 if (NextSectionAttributes != 0) {\r
310 // Convert Section Attributes into GCD Attributes\r
311 Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
312 ASSERT_EFI_ERROR (Status);\r
aeb61534 313\r
2cf4b608 314 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
315 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
aeb61534 316\r
429309e0
MK
317 NextRegionLength = 0;\r
318 NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
2cf4b608 319 NextSectionAttributes = 0;\r
320 }\r
429309e0 321\r
2cf4b608 322 NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;\r
323 }\r
aeb61534
A
324 } // section entry loop\r
325\r
2cf4b608 326 if (NextSectionAttributes != 0) {\r
327 // Convert Section Attributes into GCD Attributes\r
328 Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
329 ASSERT_EFI_ERROR (Status);\r
330\r
331 // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
332 SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
333 }\r
334\r
5b53eaff
OM
335 FreePool (MemorySpaceMap);\r
336\r
aeb61534
A
337 return EFI_SUCCESS;\r
338}\r
339\r
2e969d2e
OM
340UINT64\r
341EfiAttributeToArmAttribute (\r
429309e0 342 IN UINT64 EfiAttributes\r
2e969d2e
OM
343 )\r
344{\r
429309e0 345 UINT64 ArmAttributes;\r
2e969d2e
OM
346\r
347 switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {\r
348 case EFI_MEMORY_UC:\r
349 // Map to strongly ordered\r
350 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
351 break;\r
352\r
353 case EFI_MEMORY_WC:\r
b8de64be 354 // Map to normal non-cacheable\r
2e969d2e
OM
355 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
356 break;\r
357\r
358 case EFI_MEMORY_WT:\r
359 // Write through with no-allocate\r
360 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
361 break;\r
362\r
363 case EFI_MEMORY_WB:\r
364 // Write back (with allocate)\r
365 ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
366 break;\r
367\r
2e969d2e
OM
368 case EFI_MEMORY_UCE:\r
369 default:\r
2e969d2e 370 ArmAttributes = TT_DESCRIPTOR_SECTION_TYPE_FAULT;\r
2e969d2e
OM
371 break;\r
372 }\r
373\r
374 // Determine protection attributes\r
a387f2ee 375 if ((EfiAttributes & EFI_MEMORY_RO) != 0) {\r
2e969d2e
OM
376 ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RO_RO;\r
377 } else {\r
378 ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RW_RW;\r
379 }\r
380\r
381 // Determine eXecute Never attribute\r
a387f2ee 382 if ((EfiAttributes & EFI_MEMORY_XP) != 0) {\r
2e969d2e
OM
383 ArmAttributes |= TT_DESCRIPTOR_SECTION_XN_MASK;\r
384 }\r
385\r
386 return ArmAttributes;\r
387}\r
388\r
389EFI_STATUS\r
390GetMemoryRegionPage (\r
429309e0
MK
391 IN UINT32 *PageTable,\r
392 IN OUT UINTN *BaseAddress,\r
393 OUT UINTN *RegionLength,\r
394 OUT UINTN *RegionAttributes\r
2e969d2e
OM
395 )\r
396{\r
429309e0
MK
397 UINT32 PageAttributes;\r
398 UINT32 TableIndex;\r
399 UINT32 PageDescriptor;\r
2e969d2e
OM
400\r
401 // Convert the section attributes into page attributes\r
402 PageAttributes = ConvertSectionAttributesToPageAttributes (*RegionAttributes, 0);\r
403\r
404 // Calculate index into first level translation table for start of modification\r
b75d7605 405 TableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r
2e969d2e
OM
406 ASSERT (TableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r
407\r
408 // Go through the page table to find the end of the section\r
429309e0 409 for ( ; TableIndex < TRANSLATION_TABLE_PAGE_COUNT; TableIndex++) {\r
2e969d2e
OM
410 // Get the section at the given index\r
411 PageDescriptor = PageTable[TableIndex];\r
412\r
413 if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_FAULT) {\r
414 // Case: End of the boundary of the region\r
415 return EFI_SUCCESS;\r
416 } else if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_PAGE) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {\r
417 if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) == PageAttributes) {\r
418 *RegionLength = *RegionLength + TT_DESCRIPTOR_PAGE_SIZE;\r
419 } else {\r
420 // Case: End of the boundary of the region\r
421 return EFI_SUCCESS;\r
422 }\r
423 } else {\r
424 // We do not support Large Page yet. We return EFI_SUCCESS that means end of the region.\r
429309e0 425 ASSERT (0);\r
2e969d2e
OM
426 return EFI_SUCCESS;\r
427 }\r
428 }\r
429\r
430 return EFI_NOT_FOUND;\r
431}\r
432\r
433EFI_STATUS\r
434GetMemoryRegion (\r
429309e0
MK
435 IN OUT UINTN *BaseAddress,\r
436 OUT UINTN *RegionLength,\r
437 OUT UINTN *RegionAttributes\r
2e969d2e
OM
438 )\r
439{\r
440 EFI_STATUS Status;\r
441 UINT32 TableIndex;\r
442 UINT32 PageAttributes;\r
443 UINT32 PageTableIndex;\r
444 UINT32 SectionDescriptor;\r
429309e0
MK
445 ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
446 UINT32 *PageTable;\r
2e969d2e
OM
447\r
448 // Initialize the arguments\r
449 *RegionLength = 0;\r
450\r
451 // Obtain page table base\r
452 FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
453\r
454 // Calculate index into first level translation table for start of modification\r
455 TableIndex = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (*BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
456 ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);\r
457\r
458 // Get the section at the given index\r
459 SectionDescriptor = FirstLevelTable[TableIndex];\r
36a87fec
AB
460 if (!SectionDescriptor) {\r
461 return EFI_NOT_FOUND;\r
462 }\r
2e969d2e
OM
463\r
464 // If 'BaseAddress' belongs to the section then round it to the section boundary\r
465 if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||\r
466 ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))\r
467 {\r
429309e0 468 *BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK;\r
2e969d2e
OM
469 *RegionAttributes = SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK;\r
470 } else {\r
471 // Otherwise, we round it to the page boundary\r
472 *BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK;\r
473\r
474 // Get the attribute at the page table level (Level 2)\r
429309e0 475 PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);\r
2e969d2e
OM
476\r
477 // Calculate index into first level translation table for start of modification\r
b75d7605 478 PageTableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r
2e969d2e
OM
479 ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r
480\r
429309e0 481 PageAttributes = PageTable[PageTableIndex] & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK;\r
2e969d2e
OM
482 *RegionAttributes = TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (PageAttributes, 0) |\r
483 TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (PageAttributes);\r
484 }\r
485\r
429309e0 486 for ( ; TableIndex < TRANSLATION_TABLE_SECTION_COUNT; TableIndex++) {\r
2e969d2e
OM
487 // Get the section at the given index\r
488 SectionDescriptor = FirstLevelTable[TableIndex];\r
489\r
490 // If the entry is a level-2 page table then we scan it to find the end of the region\r
5ad9b48f 491 if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (SectionDescriptor)) {\r
2e969d2e 492 // Extract the page table location from the descriptor\r
429309e0 493 PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);\r
2e969d2e
OM
494\r
495 // Scan the page table to find the end of the region.\r
496 Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionLength, RegionAttributes);\r
497\r
498 // If we have found the end of the region (Status == EFI_SUCCESS) then we exit the for-loop\r
499 if (Status == EFI_SUCCESS) {\r
500 break;\r
501 }\r
502 } else if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||\r
429309e0
MK
503 ((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))\r
504 {\r
2e969d2e
OM
505 if ((SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK) != *RegionAttributes) {\r
506 // If the attributes of the section differ from the one targeted then we exit the loop\r
507 break;\r
508 } else {\r
509 *RegionLength = *RegionLength + TT_DESCRIPTOR_SECTION_SIZE;\r
510 }\r
511 } else {\r
512 // If we are on an invalid section then it means it is the end of our section.\r
513 break;\r
514 }\r
515 }\r
516\r
517 return EFI_SUCCESS;\r
518}\r