]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c
ArmVirtPkg: enable PE/COFF image and memory protection for ARM platforms
[mirror_edk2.git] / ArmPkg / Library / ArmMmuLib / Arm / ArmMmuLibCore.c
CommitLineData
d7f03464
AB
1/** @file\r
2* File managing the MMU for ARMv7 architecture\r
3*\r
4* Copyright (c) 2011-2016, ARM Limited. All rights reserved.\r
5*\r
6* This program and the accompanying materials\r
7* are licensed and made available under the terms and conditions of the BSD License\r
8* which accompanies this distribution. The full text of the license may be found at\r
9* http://opensource.org/licenses/bsd-license.php\r
10*\r
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13*\r
14**/\r
15\r
16#include <Uefi.h>\r
17#include <Chipset/ArmV7.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include <Library/ArmLib.h>\r
21#include <Library/BaseLib.h>\r
22#include <Library/DebugLib.h>\r
23#include <Library/PcdLib.h>\r
24\r
25#define ID_MMFR0_SHARELVL_SHIFT 12\r
26#define ID_MMFR0_SHARELVL_MASK 0xf\r
27#define ID_MMFR0_SHARELVL_ONE 0\r
28#define ID_MMFR0_SHARELVL_TWO 1\r
29\r
30#define ID_MMFR0_INNERSHR_SHIFT 28\r
31#define ID_MMFR0_INNERSHR_MASK 0xf\r
32#define ID_MMFR0_OUTERSHR_SHIFT 8\r
33#define ID_MMFR0_OUTERSHR_MASK 0xf\r
34\r
35#define ID_MMFR0_SHR_IMP_UNCACHED 0\r
36#define ID_MMFR0_SHR_IMP_HW_COHERENT 1\r
37#define ID_MMFR0_SHR_IGNORED 0xf\r
38\r
39UINTN\r
40EFIAPI\r
41ArmReadIdMmfr0 (\r
42 VOID\r
43 );\r
44\r
45BOOLEAN\r
46EFIAPI\r
47ArmHasMpExtensions (\r
48 VOID\r
49 );\r
50\r
51UINT32\r
52ConvertSectionAttributesToPageAttributes (\r
53 IN UINT32 SectionAttributes,\r
54 IN BOOLEAN IsLargePage\r
55 )\r
56{\r
57 UINT32 PageAttributes;\r
58\r
59 PageAttributes = 0;\r
60 PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (SectionAttributes, IsLargePage);\r
61 PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (SectionAttributes);\r
62 PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN (SectionAttributes, IsLargePage);\r
63 PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG (SectionAttributes);\r
64 PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S (SectionAttributes);\r
65\r
66 return PageAttributes;\r
67}\r
68\r
69STATIC\r
70BOOLEAN\r
71PreferNonshareableMemory (\r
72 VOID\r
73 )\r
74{\r
75 UINTN Mmfr;\r
76 UINTN Val;\r
77\r
78 if (FeaturePcdGet (PcdNormalMemoryNonshareableOverride)) {\r
79 return TRUE;\r
80 }\r
81\r
82 //\r
83 // Check whether the innermost level of shareability (the level we will use\r
84 // by default to map normal memory) is implemented with hardware coherency\r
85 // support. Otherwise, revert to mapping as non-shareable.\r
86 //\r
87 Mmfr = ArmReadIdMmfr0 ();\r
88 switch ((Mmfr >> ID_MMFR0_SHARELVL_SHIFT) & ID_MMFR0_SHARELVL_MASK) {\r
89 case ID_MMFR0_SHARELVL_ONE:\r
90 // one level of shareability\r
91 Val = (Mmfr >> ID_MMFR0_OUTERSHR_SHIFT) & ID_MMFR0_OUTERSHR_MASK;\r
92 break;\r
93 case ID_MMFR0_SHARELVL_TWO:\r
94 // two levels of shareability\r
95 Val = (Mmfr >> ID_MMFR0_INNERSHR_SHIFT) & ID_MMFR0_INNERSHR_MASK;\r
96 break;\r
97 default:\r
98 // unexpected value -> shareable is the safe option\r
99 ASSERT (FALSE);\r
100 return FALSE;\r
101 }\r
102 return Val != ID_MMFR0_SHR_IMP_HW_COHERENT;\r
103}\r
104\r
105STATIC\r
106VOID\r
107PopulateLevel2PageTable (\r
108 IN UINT32 *SectionEntry,\r
109 IN UINT32 PhysicalBase,\r
110 IN UINT32 RemainLength,\r
111 IN ARM_MEMORY_REGION_ATTRIBUTES Attributes\r
112 )\r
113{\r
114 UINT32* PageEntry;\r
115 UINT32 Pages;\r
116 UINT32 Index;\r
117 UINT32 PageAttributes;\r
118 UINT32 SectionDescriptor;\r
119 UINT32 TranslationTable;\r
120 UINT32 BaseSectionAddress;\r
121\r
122 switch (Attributes) {\r
123 case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK:\r
124 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK:\r
125 PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_BACK;\r
126 break;\r
127 case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH:\r
128 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH:\r
129 PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_THROUGH;\r
130 break;\r
131 case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE:\r
132 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE:\r
133 PageAttributes = TT_DESCRIPTOR_PAGE_DEVICE;\r
134 break;\r
135 case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:\r
136 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED:\r
137 PageAttributes = TT_DESCRIPTOR_PAGE_UNCACHED;\r
138 break;\r
139 default:\r
140 PageAttributes = TT_DESCRIPTOR_PAGE_UNCACHED;\r
141 break;\r
142 }\r
143\r
144 if (PreferNonshareableMemory ()) {\r
145 PageAttributes &= ~TT_DESCRIPTOR_PAGE_S_SHARED;\r
146 }\r
147\r
148 // Check if the Section Entry has already been populated. Otherwise attach a\r
149 // Level 2 Translation Table to it\r
150 if (*SectionEntry != 0) {\r
151 // The entry must be a page table. Otherwise it exists an overlapping in the memory map\r
152 if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(*SectionEntry)) {\r
153 TranslationTable = *SectionEntry & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK;\r
154 } else if ((*SectionEntry & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) {\r
155 // Case where a virtual memory map descriptor overlapped a section entry\r
156\r
157 // Allocate a Level2 Page Table for this Section\r
158 TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT));\r
159 TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK;\r
160\r
161 // Translate the Section Descriptor into Page Descriptor\r
162 SectionDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (*SectionEntry, FALSE);\r
163\r
164 BaseSectionAddress = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(*SectionEntry);\r
165\r
166 // Populate the new Level2 Page Table for the section\r
167 PageEntry = (UINT32*)TranslationTable;\r
168 for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {\r
169 PageEntry[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseSectionAddress + (Index << 12)) | SectionDescriptor;\r
170 }\r
171\r
172 // Overwrite the section entry to point to the new Level2 Translation Table\r
173 *SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) |\r
174 (IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE(Attributes) ? (1 << 3) : 0) |\r
175 TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;\r
176 } else {\r
177 // We do not support the other section type (16MB Section)\r
178 ASSERT(0);\r
179 return;\r
180 }\r
181 } else {\r
182 TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT));\r
183 TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK;\r
184\r
185 ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_PAGE_SIZE);\r
186\r
187 *SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) |\r
188 (IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE(Attributes) ? (1 << 3) : 0) |\r
189 TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;\r
190 }\r
191\r
192 PageEntry = ((UINT32 *)(TranslationTable) + ((PhysicalBase & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT));\r
193 Pages = RemainLength / TT_DESCRIPTOR_PAGE_SIZE;\r
194\r
195 for (Index = 0; Index < Pages; Index++) {\r
196 *PageEntry++ = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(PhysicalBase) | PageAttributes;\r
197 PhysicalBase += TT_DESCRIPTOR_PAGE_SIZE;\r
198 }\r
199\r
200}\r
201\r
202STATIC\r
203VOID\r
204FillTranslationTable (\r
205 IN UINT32 *TranslationTable,\r
206 IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion\r
207 )\r
208{\r
209 UINT32 *SectionEntry;\r
210 UINT32 Attributes;\r
211 UINT32 PhysicalBase;\r
212 UINT64 RemainLength;\r
213\r
214 ASSERT(MemoryRegion->Length > 0);\r
215\r
216 if (MemoryRegion->PhysicalBase >= SIZE_4GB) {\r
217 return;\r
218 }\r
219\r
220 PhysicalBase = MemoryRegion->PhysicalBase;\r
221 RemainLength = MIN(MemoryRegion->Length, SIZE_4GB - PhysicalBase);\r
222\r
223 switch (MemoryRegion->Attributes) {\r
224 case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK:\r
225 Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(0);\r
226 break;\r
227 case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH:\r
228 Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0);\r
229 break;\r
230 case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE:\r
231 Attributes = TT_DESCRIPTOR_SECTION_DEVICE(0);\r
232 break;\r
233 case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:\r
234 Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);\r
235 break;\r
236 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK:\r
237 Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(1);\r
238 break;\r
239 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH:\r
240 Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH(1);\r
241 break;\r
242 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE:\r
243 Attributes = TT_DESCRIPTOR_SECTION_DEVICE(1);\r
244 break;\r
245 case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED:\r
246 Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(1);\r
247 break;\r
248 default:\r
249 Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);\r
250 break;\r
251 }\r
252\r
253 if (PreferNonshareableMemory ()) {\r
254 Attributes &= ~TT_DESCRIPTOR_SECTION_S_SHARED;\r
255 }\r
256\r
257 // Get the first section entry for this mapping\r
258 SectionEntry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase);\r
259\r
260 while (RemainLength != 0) {\r
261 if (PhysicalBase % TT_DESCRIPTOR_SECTION_SIZE == 0) {\r
262 if (RemainLength >= TT_DESCRIPTOR_SECTION_SIZE) {\r
263 // Case: Physical address aligned on the Section Size (1MB) && the length is greater than the Section Size\r
264 *SectionEntry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;\r
265 PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;\r
266 } else {\r
267 // Case: Physical address aligned on the Section Size (1MB) && the length does not fill a section\r
268 PopulateLevel2PageTable (SectionEntry++, PhysicalBase, RemainLength, MemoryRegion->Attributes);\r
269\r
270 // It must be the last entry\r
271 break;\r
272 }\r
273 } else {\r
274 // Case: Physical address NOT aligned on the Section Size (1MB)\r
275 PopulateLevel2PageTable (SectionEntry++, PhysicalBase, RemainLength, MemoryRegion->Attributes);\r
276 // Aligned the address\r
277 PhysicalBase = (PhysicalBase + TT_DESCRIPTOR_SECTION_SIZE) & ~(TT_DESCRIPTOR_SECTION_SIZE-1);\r
278\r
279 // If it is the last entry\r
280 if (RemainLength < TT_DESCRIPTOR_SECTION_SIZE) {\r
281 break;\r
282 }\r
283 }\r
284 RemainLength -= TT_DESCRIPTOR_SECTION_SIZE;\r
285 }\r
286}\r
287\r
288RETURN_STATUS\r
289EFIAPI\r
290ArmConfigureMmu (\r
291 IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable,\r
292 OUT VOID **TranslationTableBase OPTIONAL,\r
293 OUT UINTN *TranslationTableSize OPTIONAL\r
294 )\r
295{\r
296 VOID* TranslationTable;\r
297 ARM_MEMORY_REGION_ATTRIBUTES TranslationTableAttribute;\r
298 UINT32 TTBRAttributes;\r
299\r
300 // Allocate pages for translation table.\r
301 TranslationTable = AllocatePages (EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_SECTION_SIZE + TRANSLATION_TABLE_SECTION_ALIGNMENT));\r
302 if (TranslationTable == NULL) {\r
303 return RETURN_OUT_OF_RESOURCES;\r
304 }\r
305 TranslationTable = (VOID*)(((UINTN)TranslationTable + TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK);\r
306\r
307 if (TranslationTableBase != NULL) {\r
308 *TranslationTableBase = TranslationTable;\r
309 }\r
310\r
311 if (TranslationTableSize != NULL) {\r
312 *TranslationTableSize = TRANSLATION_TABLE_SECTION_SIZE;\r
313 }\r
314\r
315 ZeroMem (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);\r
316\r
317 // By default, mark the translation table as belonging to a uncached region\r
318 TranslationTableAttribute = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;\r
319 while (MemoryTable->Length != 0) {\r
320 // Find the memory attribute for the Translation Table\r
321 if (((UINTN)TranslationTable >= MemoryTable->PhysicalBase) && ((UINTN)TranslationTable <= MemoryTable->PhysicalBase - 1 + MemoryTable->Length)) {\r
322 TranslationTableAttribute = MemoryTable->Attributes;\r
323 }\r
324\r
325 FillTranslationTable (TranslationTable, MemoryTable);\r
326 MemoryTable++;\r
327 }\r
328\r
329 // Translate the Memory Attributes into Translation Table Register Attributes\r
330 if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED) ||\r
331 (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED)) {\r
332 TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_NON_CACHEABLE : TTBR_NON_CACHEABLE;\r
333 } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) ||\r
334 (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK)) {\r
335 TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_BACK_ALLOC : TTBR_WRITE_BACK_ALLOC;\r
336 } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH) ||\r
337 (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH)) {\r
338 TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_THROUGH : TTBR_WRITE_THROUGH;\r
339 } else {\r
340 ASSERT (0); // No support has been found for the attributes of the memory region that the translation table belongs to.\r
341 return RETURN_UNSUPPORTED;\r
342 }\r
343\r
344 if (TTBRAttributes & TTBR_SHAREABLE) {\r
345 if (PreferNonshareableMemory ()) {\r
346 TTBRAttributes ^= TTBR_SHAREABLE;\r
347 } else {\r
348 //\r
349 // Unlike the S bit in the short descriptors, which implies inner shareable\r
350 // on an implementation that supports two levels, the meaning of the S bit\r
351 // in the TTBR depends on the NOS bit, which defaults to Outer Shareable.\r
352 // However, we should only set this bit after we have confirmed that the\r
353 // implementation supports multiple levels, or else the NOS bit is UNK/SBZP\r
354 //\r
355 if (((ArmReadIdMmfr0 () >> 12) & 0xf) != 0) {\r
356 TTBRAttributes |= TTBR_NOT_OUTER_SHAREABLE;\r
357 }\r
358 }\r
359 }\r
360\r
361 ArmCleanInvalidateDataCache ();\r
362 ArmInvalidateInstructionCache ();\r
363\r
364 ArmDisableDataCache ();\r
365 ArmDisableInstructionCache();\r
366 // TLBs are also invalidated when calling ArmDisableMmu()\r
367 ArmDisableMmu ();\r
368\r
369 // Make sure nothing sneaked into the cache\r
370 ArmCleanInvalidateDataCache ();\r
371 ArmInvalidateInstructionCache ();\r
372\r
373 ArmSetTTBR0 ((VOID *)(UINTN)(((UINTN)TranslationTable & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) | (TTBRAttributes & 0x7F)));\r
374\r
375 //\r
376 // The TTBCR register value is undefined at reset in the Non-Secure world.\r
377 // Writing 0 has the effect of:\r
378 // Clearing EAE: Use short descriptors, as mandated by specification.\r
379 // Clearing PD0 and PD1: Translation Table Walk Disable is off.\r
380 // Clearing N: Perform all translation table walks through TTBR0.\r
381 // (0 is the default reset value in systems not implementing\r
382 // the Security Extensions.)\r
383 //\r
384 ArmSetTTBCR (0);\r
385\r
386 ArmSetDomainAccessControl (DOMAIN_ACCESS_CONTROL_NONE(15) |\r
387 DOMAIN_ACCESS_CONTROL_NONE(14) |\r
388 DOMAIN_ACCESS_CONTROL_NONE(13) |\r
389 DOMAIN_ACCESS_CONTROL_NONE(12) |\r
390 DOMAIN_ACCESS_CONTROL_NONE(11) |\r
391 DOMAIN_ACCESS_CONTROL_NONE(10) |\r
392 DOMAIN_ACCESS_CONTROL_NONE( 9) |\r
393 DOMAIN_ACCESS_CONTROL_NONE( 8) |\r
394 DOMAIN_ACCESS_CONTROL_NONE( 7) |\r
395 DOMAIN_ACCESS_CONTROL_NONE( 6) |\r
396 DOMAIN_ACCESS_CONTROL_NONE( 5) |\r
397 DOMAIN_ACCESS_CONTROL_NONE( 4) |\r
398 DOMAIN_ACCESS_CONTROL_NONE( 3) |\r
399 DOMAIN_ACCESS_CONTROL_NONE( 2) |\r
400 DOMAIN_ACCESS_CONTROL_NONE( 1) |\r
401 DOMAIN_ACCESS_CONTROL_CLIENT(0));\r
402\r
403 ArmEnableInstructionCache();\r
404 ArmEnableDataCache();\r
405 ArmEnableMmu();\r
406 return RETURN_SUCCESS;\r
407}\r
408\r
409RETURN_STATUS\r
410ArmSetMemoryRegionNoExec (\r
411 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
412 IN UINT64 Length\r
413 )\r
414{\r
415 return RETURN_UNSUPPORTED;\r
416}\r
417\r
418RETURN_STATUS\r
419ArmClearMemoryRegionNoExec (\r
420 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
421 IN UINT64 Length\r
422 )\r
423{\r
424 return RETURN_UNSUPPORTED;\r
425}\r
426\r
427RETURN_STATUS\r
428ArmSetMemoryRegionReadOnly (\r
429 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
430 IN UINT64 Length\r
431 )\r
432{\r
433 return RETURN_UNSUPPORTED;\r
434}\r
435\r
436RETURN_STATUS\r
437ArmClearMemoryRegionReadOnly (\r
438 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
439 IN UINT64 Length\r
440 )\r
441{\r
442 return RETURN_UNSUPPORTED;\r
443}\r
444\r
445RETURN_STATUS\r
446EFIAPI\r
447ArmMmuBaseLibConstructor (\r
448 VOID\r
449 )\r
450{\r
451 return RETURN_SUCCESS;\r
452}\r