925c698244732d978adc6adde9a6f68687e42570
[reactos.git] / reactos / boot / environ / lib / mm / i386 / mmx86.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/mm/i386/mmx86.c
5 * PURPOSE: Boot Library Memory Manager x86-Specific Code
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12 #include "bcd.h"
13 #include "../../../../../ntoskrnl/include/internal/i386/mm.h"
14
15 /* DATA VARIABLES ************************************************************/
16
17 ULONG_PTR MmArchKsegBase;
18 ULONG_PTR MmArchKsegBias;
19 ULONG MmArchLargePageSize;
20 BL_ADDRESS_RANGE MmArchKsegAddressRange;
21 ULONG_PTR MmArchTopOfApplicationAddressSpace;
22 PHYSICAL_ADDRESS Mmx86SelfMapBase;
23 ULONG MmDeferredMappingCount;
24 PMMPTE MmPdpt;
25 PULONG MmArchReferencePage;
26 PVOID MmPteBase;
27 PVOID MmPdeBase;
28 ULONG MmArchReferencePageSize;
29
30 typedef VOID
31 (*PBL_MM_FLUSH_TLB) (
32 VOID
33 );
34
35 typedef VOID
36 (*PBL_MM_RELOCATE_SELF_MAP) (
37 VOID
38 );
39
40 typedef NTSTATUS
41 (*PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE) (
42 _In_ PVOID DestinationAddress,
43 _In_ PVOID SourceAddress,
44 _In_ ULONGLONG Size
45 );
46
47 typedef NTSTATUS
48 (*PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE) (
49 _In_ PVOID DestinationAddress,
50 _In_ ULONGLONG Size
51 );
52
53 typedef VOID
54 (*PBL_MM_DESTROY_SELF_MAP) (
55 VOID
56 );
57
58 typedef VOID
59 (*PBL_MM_FLUSH_TLB_ENTRY) (
60 _In_ PVOID VirtualAddress
61 );
62
63 typedef VOID
64 (*PBL_MM_FLUSH_TLB) (
65 VOID
66 );
67
68 typedef NTSTATUS
69 (*PBL_MM_UNMAP_VIRTUAL_ADDRESS) (
70 _In_ PVOID VirtualAddress,
71 _In_ ULONG Size
72 );
73
74 typedef NTSTATUS
75 (*PBL_MM_REMAP_VIRTUAL_ADDRESS) (
76 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
77 _Out_ PVOID VirtualAddress,
78 _In_ ULONG Size,
79 _In_ ULONG CacheAttributes
80 );
81
82 typedef NTSTATUS
83 (*PBL_MM_MAP_PHYSICAL_ADDRESS) (
84 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
85 _Out_ PVOID VirtualAddress,
86 _In_ ULONG Size,
87 _In_ ULONG CacheAttributes
88 );
89
90 typedef BOOLEAN
91 (*PBL_MM_TRANSLATE_VIRTUAL_ADDRESS) (
92 _In_ PVOID VirtualAddress,
93 _Out_ PPHYSICAL_ADDRESS PhysicalAddress,
94 _Out_opt_ PULONG CacheAttributes
95 );
96
97 PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress;
98 PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress;
99 PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress;
100 PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress;
101 PBL_MM_FLUSH_TLB Mmx86FlushTlb;
102 PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry;
103 PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap;
104
105 PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap;
106 PBL_MM_FLUSH_TLB BlMmFlushTlb;
107 PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange;
108 PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange;
109
110 PBL_MM_FLUSH_TLB Mmx86FlushTlb;
111
112 /* FUNCTIONS *****************************************************************/
113
114 VOID
115 MmArchNullFunction (
116 VOID
117 )
118 {
119 /* Nothing to do */
120 return;
121 }
122
123 VOID
124 MmDefRelocateSelfMap (
125 VOID
126 )
127 {
128 if (MmPteBase != (PVOID)PTE_BASE)
129 {
130 EfiPrintf(L"Supposed to relocate CR3\r\n");
131 }
132 }
133
134 NTSTATUS
135 MmDefMoveVirtualAddressRange (
136 _In_ PVOID DestinationAddress,
137 _In_ PVOID SourceAddress,
138 _In_ ULONGLONG Size
139 )
140 {
141 EfiPrintf(L"Supposed to move shit\r\n");
142 return STATUS_NOT_IMPLEMENTED;
143 }
144
145 NTSTATUS
146 MmDefZeroVirtualAddressRange (
147 _In_ PVOID DestinationAddress,
148 _In_ ULONGLONG Size
149 )
150 {
151 EfiPrintf(L"Supposed to zero shit\r\n");
152 return STATUS_NOT_IMPLEMENTED;
153 }
154
155 NTSTATUS
156 Mmx86pMapMemoryRegions (
157 _In_ ULONG Phase,
158 _In_ PBL_MEMORY_DATA MemoryData
159 )
160 {
161 BOOLEAN DoDeferred;
162
163 /* In phase 1 we don't initialize deferred mappings*/
164 if (Phase == 1)
165 {
166 DoDeferred = 0;
167 }
168 else
169 {
170 /* Don't do anything if there's nothing to initialize */
171 if (!MmDeferredMappingCount)
172 {
173 return STATUS_SUCCESS;
174 }
175
176 DoDeferred = 1;
177 }
178
179 if (DoDeferred)
180 {
181 EfiPrintf(L"Deferred todo\r\n");
182 }
183
184 EfiPrintf(L"Phase 1 TODO\r\n");
185 return STATUS_NOT_IMPLEMENTED;
186 }
187
188 BOOLEAN
189 MmArchTranslateVirtualAddress (
190 _In_ PVOID VirtualAddress,
191 _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress,
192 _Out_opt_ PULONG CachingFlags
193 )
194 {
195 PBL_MEMORY_DESCRIPTOR Descriptor;
196
197 /* Check if paging is on */
198 if ((CurrentExecutionContext) &&
199 (CurrentExecutionContext->ContextFlags & BL_CONTEXT_PAGING_ON))
200 {
201 /* Yes -- we have to translate this from virtual */
202 return Mmx86TranslateVirtualAddress(VirtualAddress,
203 PhysicalAddress,
204 CachingFlags);
205 }
206
207 /* Look in all descriptors except truncated and firmware ones */
208 Descriptor = MmMdFindDescriptor(BL_MM_INCLUDE_NO_FIRMWARE_MEMORY &
209 ~BL_MM_INCLUDE_TRUNCATED_MEMORY,
210 BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
211 (ULONG_PTR)VirtualAddress >> PAGE_SHIFT);
212
213 /* Return the virtual address as the physical address */
214 if (PhysicalAddress)
215 {
216 PhysicalAddress->HighPart = 0;
217 PhysicalAddress->LowPart = (ULONG_PTR)VirtualAddress;
218 }
219
220 /* There's no caching on physical memory */
221 if (CachingFlags)
222 {
223 *CachingFlags = 0;
224 }
225
226 /* Success is if we found a descriptor */
227 return Descriptor != NULL;
228 }
229
230 VOID
231 MmDefpDestroySelfMap (
232 VOID
233 )
234 {
235 EfiPrintf(L"No destroy\r\n");
236 }
237
238 VOID
239 MmDefpFlushTlbEntry (
240 _In_ PVOID VirtualAddress
241 )
242 {
243 /* Flush the TLB */
244 __invlpg(VirtualAddress);
245 }
246
247 VOID
248 MmDefpFlushTlb (
249 VOID
250 )
251 {
252 /* Flush the TLB */
253 __writecr3(__readcr3());
254 }
255
256 NTSTATUS
257 MmDefpUnmapVirtualAddress (
258 _In_ PVOID VirtualAddress,
259 _In_ ULONG Size
260 )
261 {
262 EfiPrintf(L"No unmap\r\n");
263 return STATUS_NOT_IMPLEMENTED;
264 }
265
266 NTSTATUS
267 MmDefpRemapVirtualAddress (
268 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
269 _Out_ PVOID VirtualAddress,
270 _In_ ULONG Size,
271 _In_ ULONG CacheAttributes
272 )
273 {
274 EfiPrintf(L"No remap\r\n");
275 return STATUS_NOT_IMPLEMENTED;
276 }
277
278 NTSTATUS
279 MmDefpMapPhysicalAddress (
280 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
281 _Out_ PVOID VirtualAddress,
282 _In_ ULONG Size,
283 _In_ ULONG CacheAttributes
284 )
285 {
286 EfiPrintf(L"No map\r\n");
287 return STATUS_NOT_IMPLEMENTED;
288 }
289
290 BOOLEAN
291 MmDefpTranslateVirtualAddress (
292 _In_ PVOID VirtualAddress,
293 _Out_ PPHYSICAL_ADDRESS PhysicalAddress,
294 _Out_opt_ PULONG CacheAttributes
295 )
296 {
297 EfiPrintf(L"No translate\r\n");
298 return FALSE;
299 }
300
301 NTSTATUS
302 Mmx86MapInitStructure (
303 _In_ PVOID VirtualAddress,
304 _In_ ULONGLONG Size,
305 _In_ PHYSICAL_ADDRESS PhysicalAddress
306 )
307 {
308 NTSTATUS Status;
309
310 /* Make a virtual mapping for this physical address */
311 Status = MmMapPhysicalAddress(&PhysicalAddress, &VirtualAddress, &Size, 0);
312 if (!NT_SUCCESS(Status))
313 {
314 return Status;
315 }
316
317 /* Nothing else to do if we're not in paging mode */
318 if (MmTranslationType == BlNone)
319 {
320 return STATUS_SUCCESS;
321 }
322
323 /* Otherwise, remove this region from the list of free virtual ranges */
324 Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
325 BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
326 (ULONG_PTR)VirtualAddress >> PAGE_SHIFT,
327 Size >> PAGE_SHIFT,
328 0);
329 if (!NT_SUCCESS(Status))
330 {
331 /* Unmap the address if that failed */
332 MmUnmapVirtualAddress(&VirtualAddress, &Size);
333 }
334
335 /* Return back to caller */
336 return Status;
337 }
338
339 NTSTATUS
340 Mmx86InitializeMemoryMap (
341 _In_ ULONG Phase,
342 _In_ PBL_MEMORY_DATA MemoryData
343 )
344 {
345 ULONG ImageSize;
346 PVOID ImageBase;
347 KDESCRIPTOR Gdt, Idt;
348 NTSTATUS Status;
349 PHYSICAL_ADDRESS PhysicalAddress;
350
351 /* If this is phase 2, map the memory regions */
352 if (Phase != 1)
353 {
354 return Mmx86pMapMemoryRegions(Phase, MemoryData);
355 }
356
357 /* Get the application image base/size */
358 Status = BlGetApplicationBaseAndSize(&ImageBase, &ImageSize);
359 if (!NT_SUCCESS(Status))
360 {
361 return Status;
362 }
363
364 /* Map the image back at the same place */
365 PhysicalAddress.QuadPart = (ULONG_PTR)ImageBase;
366 Status = Mmx86MapInitStructure(ImageBase, ImageSize, PhysicalAddress);
367 if (!NT_SUCCESS(Status))
368 {
369 return Status;
370 }
371
372 /* Map the first 4MB of memory */
373 PhysicalAddress.QuadPart = 0;
374 Status = Mmx86MapInitStructure(NULL, 4 * 1024 * 1024, PhysicalAddress);
375 if (!NT_SUCCESS(Status))
376 {
377 return Status;
378 }
379
380 /* Map the GDT */
381 _sgdt(&Gdt.Limit);
382 PhysicalAddress.QuadPart = Gdt.Base;
383 Status = Mmx86MapInitStructure((PVOID)Gdt.Base, Gdt.Limit + 1, PhysicalAddress);
384 if (!NT_SUCCESS(Status))
385 {
386 return Status;
387 }
388
389 /* Map the IDT */
390 __sidt(&Idt.Limit);
391 PhysicalAddress.QuadPart = Idt.Base;
392 Status = Mmx86MapInitStructure((PVOID)Idt.Base, Idt.Limit + 1, PhysicalAddress);
393 if (!NT_SUCCESS(Status))
394 {
395 return Status;
396 }
397
398 /* Map the reference page */
399 PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage;
400 Status = Mmx86MapInitStructure(MmArchReferencePage,
401 MmArchReferencePageSize,
402 PhysicalAddress);
403 if (!NT_SUCCESS(Status))
404 {
405 return Status;
406 }
407
408 /* More to do */
409 EfiPrintf(L"VM more work\r\n");
410 return STATUS_NOT_IMPLEMENTED;
411 }
412
413 NTSTATUS
414 MmDefInitializeTranslation (
415 _In_ PBL_MEMORY_DATA MemoryData,
416 _In_ BL_TRANSLATION_TYPE TranslationType
417 )
418 {
419 NTSTATUS Status;
420 PHYSICAL_ADDRESS PhysicalAddress;
421 ULONG PdeIndex;
422
423 /* Set the global function pointers for memory translation */
424 Mmx86TranslateVirtualAddress = MmDefpTranslateVirtualAddress;
425 Mmx86MapPhysicalAddress = MmDefpMapPhysicalAddress;
426 Mmx86UnmapVirtualAddress = MmDefpUnmapVirtualAddress;
427 Mmx86RemapVirtualAddress = MmDefpRemapVirtualAddress;
428 Mmx86FlushTlb = MmDefpFlushTlb;
429 Mmx86FlushTlbEntry = MmDefpFlushTlbEntry;
430 Mmx86DestroySelfMap = MmDefpDestroySelfMap;
431
432 /* Check what mode we're currently in */
433 if (TranslationType == BlVirtual)
434 {
435 EfiPrintf(L"Virtual->Virtual not yet supported\r\n");
436 return STATUS_NOT_IMPLEMENTED;
437 }
438 else if (TranslationType != BlNone)
439 {
440 /* Not even Windows supports PAE->Virtual downgrade */
441 return STATUS_NOT_IMPLEMENTED;
442 }
443
444 /* The None->Virtual case */
445 MmPdpt = NULL;
446 Mmx86SelfMapBase.QuadPart = 0;
447 MmArchReferencePage = NULL;
448
449 /* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */
450 EfiPrintf(L"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n");
451 //Status = MmPaTruncateMemory(0x100000);
452 Status = STATUS_SUCCESS;
453 if (!NT_SUCCESS(Status))
454 {
455 goto Quickie;
456 }
457
458 /* Allocate a page directory */
459 Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
460 BlLoaderPageDirectory,
461 1,
462 0,
463 0,
464 &MmMdlUnmappedAllocated,
465 0,
466 0);
467 if (!NT_SUCCESS(Status))
468 {
469 goto Quickie;
470 }
471
472 /* Zero out the page directory */
473 MmPdpt = (PVOID)PhysicalAddress.LowPart;
474 RtlZeroMemory(MmPdpt, PAGE_SIZE);
475
476 /* Set the page size */
477 MmArchReferencePageSize = PAGE_SIZE;
478
479 /* Allocate the self-map page */
480 Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
481 BlLoaderReferencePage,
482 1,
483 0,
484 0,
485 &MmMdlUnmappedAllocated,
486 0,
487 0);
488 if (!NT_SUCCESS(Status))
489 {
490 goto Quickie;
491 }
492
493 /* Set the reference page */
494 MmArchReferencePage = (PVOID)PhysicalAddress.LowPart;
495
496 /* Zero it out */
497 RtlZeroMemory(MmArchReferencePage, MmArchReferencePageSize);
498
499 /* Allocate 4MB worth of self-map pages */
500 Status = MmPaReserveSelfMapPages(&Mmx86SelfMapBase,
501 (4 * 1024 * 1024) >> PAGE_SHIFT,
502 (4 * 1024 * 1024) >> PAGE_SHIFT);
503 if (!NT_SUCCESS(Status))
504 {
505 goto Quickie;
506 }
507
508 /* Zero them out */
509 RtlZeroMemory((PVOID)Mmx86SelfMapBase.LowPart, 4 * 1024 * 1024);
510 EfiPrintf(L"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n",
511 MmPdpt, MmArchReferencePage, Mmx86SelfMapBase.LowPart);
512
513 /* Align PTE base to 4MB region */
514 MmPteBase = (PVOID)(Mmx86SelfMapBase.LowPart & ~0x3FFFFF);
515
516 /* The PDE is the PTE of the PTE base */
517 MmPdeBase = MiAddressToPte(MmPteBase);
518 PdeIndex = MiGetPdeOffset(MmPdeBase);
519 MmPdpt[PdeIndex].u.Hard.Valid = 1;
520 MmPdpt[PdeIndex].u.Hard.Write = 1;
521 MmPdpt[PdeIndex].u.Hard.PageFrameNumber = (ULONG_PTR)MmPdpt >> PAGE_SHIFT;
522 MmArchReferencePage[PdeIndex]++;
523
524 /* Remove PTE_BASE from free virtual memory */
525 Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
526 BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
527 PTE_BASE >> PAGE_SHIFT,
528 (4 * 1024 * 1024) >> PAGE_SHIFT,
529 0);
530 if (!NT_SUCCESS(Status))
531 {
532 goto Quickie;
533 }
534
535 /* Remove HAL_HEAP from free virtual memory */
536 Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
537 BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
538 MM_HAL_VA_START >> PAGE_SHIFT,
539 (4 * 1024 * 1024) >> PAGE_SHIFT,
540 0);
541 if (!NT_SUCCESS(Status))
542 {
543 goto Quickie;
544 }
545
546 /* Initialize the virtual->physical memory mappings */
547 Status = Mmx86InitializeMemoryMap(1, MemoryData);
548 if (!NT_SUCCESS(Status))
549 {
550 goto Quickie;
551 }
552
553 EfiPrintf(L"Ready to turn on motherfucking paging, brah!\r\n");
554 Status = STATUS_NOT_IMPLEMENTED;
555
556 Quickie:
557 /* Free reference page if we allocated it */
558 if (MmArchReferencePage)
559 {
560 PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage;
561 BlMmFreePhysicalPages(PhysicalAddress);
562 }
563
564 /* Free page directory if we allocated it */
565 if (MmPdpt)
566 {
567 PhysicalAddress.QuadPart = (ULONG_PTR)MmPdpt;
568 BlMmFreePhysicalPages(PhysicalAddress);
569 }
570
571 /* Free the self map if we allocated it */
572 if (Mmx86SelfMapBase.QuadPart)
573 {
574 MmPaReleaseSelfMapPages(Mmx86SelfMapBase);
575 }
576
577 /* All done */
578 return Status;
579 }
580
581 NTSTATUS
582 MmArchInitialize (
583 _In_ ULONG Phase,
584 _In_ PBL_MEMORY_DATA MemoryData,
585 _In_ BL_TRANSLATION_TYPE TranslationType,
586 _In_ BL_TRANSLATION_TYPE RequestedTranslationType
587 )
588 {
589 NTSTATUS Status;
590 ULONGLONG IncreaseUserVa, PerfCounter, CpuRandom;
591 INT CpuInfo[4];
592
593 /* For phase 2, just map deferred regions */
594 if (Phase != 1)
595 {
596 return Mmx86pMapMemoryRegions(2, MemoryData);
597 }
598
599 /* What translation type are we switching to? */
600 switch (RequestedTranslationType)
601 {
602 /* Physical memory */
603 case BlNone:
604
605 /* Initialize everything to default/null values */
606 MmArchLargePageSize = 1;
607 MmArchKsegBase = 0;
608 MmArchKsegBias = 0;
609 MmArchKsegAddressRange.Minimum = 0;
610 MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
611 MmArchTopOfApplicationAddressSpace = 0;
612 Mmx86SelfMapBase.QuadPart = 0;
613
614 /* Set stub functions */
615 BlMmRelocateSelfMap = MmArchNullFunction;
616 BlMmFlushTlb = MmArchNullFunction;
617
618 /* Set success */
619 Status = STATUS_SUCCESS;
620 break;
621
622 case BlVirtual:
623
624 /* Set the large page size to 1024 pages (4MB) */
625 MmArchLargePageSize = (4 * 1024 * 1024) / PAGE_SIZE;
626
627 /* Check if /USERVA option was used */
628 Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
629 BcdOSLoaderInteger_IncreaseUserVa,
630 &IncreaseUserVa);
631 if (NT_SUCCESS(Status) && (IncreaseUserVa))
632 {
633 /* Yes -- load the kernel at 0xE0000000 instead */
634 MmArchKsegBase = 0xE0000000;
635 }
636 else
637 {
638 /* Nope, load at the standard 2GB split */
639 MmArchKsegBase = 0x80000000;
640 }
641
642 /* Check if CPUID 01h is supported */
643 CpuRandom = 0;
644 if (BlArchIsCpuIdFunctionSupported(1))
645 {
646 /* Call it */
647 BlArchCpuId(1, 0, CpuInfo);
648
649 /* Check if RDRAND is supported */
650 if (CpuInfo[2] & 0x40000000)
651 {
652 EfiPrintf(L"Your CPU can do RDRAND! Good for you!\r\n");
653 CpuRandom = 0;
654 }
655 }
656
657 /* Read the TSC */
658 PerfCounter = BlArchGetPerformanceCounter();
659 PerfCounter >>= 4;
660 _rotl16(PerfCounter, 5);
661
662 /* Set the address range */
663 MmArchKsegAddressRange.Minimum = 0;
664 MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
665
666 /* Set the KASLR bias */
667 MmArchKsegBias = ((PerfCounter ^ CpuRandom) & 0xFFF) << 12;
668 MmArchKsegBias = 0;
669 MmArchKsegBase += MmArchKsegBias;
670
671 /* Set the kernel range */
672 MmArchKsegAddressRange.Minimum = MmArchKsegBase;
673 MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
674
675 /* Set the boot application top maximum */
676 MmArchTopOfApplicationAddressSpace = 0x70000000;
677
678 /* Initialize virtual address space translation */
679 Status = MmDefInitializeTranslation(MemoryData, TranslationType);
680 if (NT_SUCCESS(Status))
681 {
682 /* Set stub functions */
683 BlMmRelocateSelfMap = MmDefRelocateSelfMap;
684 BlMmFlushTlb = Mmx86FlushTlb;
685 BlMmMoveVirtualAddressRange = MmDefMoveVirtualAddressRange;
686 BlMmZeroVirtualAddressRange = MmDefZeroVirtualAddressRange;
687 }
688 break;
689
690 case BlPae:
691
692 Status = STATUS_NOT_SUPPORTED;
693 break;
694
695 default:
696 Status = STATUS_INVALID_PARAMETER;
697 break;
698 }
699
700 return Status;
701
702 }