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