ReactOS  0.4.14-dev-52-g6116262
mmx86.c
Go to the documentation of this file.
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 
14 #define PTE_BASE 0xC0000000
15 
16 //
17 // Specific PDE/PTE macros to be used inside the boot library environment
18 //
19 #define MiAddressToPte(x) ((PMMPTE)(((((ULONG)(x)) >> 12) << 2) + (ULONG_PTR)MmPteBase))
20 #define MiAddressToPde(x) ((PMMPDE)(((((ULONG)(x)) >> 22) << 2) + (ULONG_PTR)MmPdeBase))
21 #define MiAddressToPteOffset(x) ((((ULONG)(x)) << 10) >> 22)
22 #define MiAddressToPdeOffset(x) (((ULONG)(x)) / (1024 * PAGE_SIZE))
23 
24 /* DATA VARIABLES ************************************************************/
25 
38 
46 
51 
53 
54 /* FUNCTIONS *****************************************************************/
55 
56 BOOLEAN
58  VOID
59  )
60 {
61  /* Return if paging is on */
62  return ((CurrentExecutionContext) &&
64 }
65 
66 VOID
68  VOID
69  )
70 {
71  /* Nothing to do */
72  return;
73 }
74 
75 VOID
77  VOID
78  )
79 {
80  if (MmPteBase != (PVOID)PTE_BASE)
81  {
82  EfiPrintf(L"Supposed to relocate CR3\r\n");
83  }
84 }
85 
91  )
92 {
93  EfiPrintf(L"Supposed to move shit\r\n");
95 }
96 
101  )
102 {
103  EfiPrintf(L"Supposed to zero shit\r\n");
104  return STATUS_NOT_IMPLEMENTED;
105 }
106 
107 BOOLEAN
111  _Out_opt_ PULONG CachingFlags
112  )
113 {
115 
116  /* Check if paging is on */
117  if ((CurrentExecutionContext) &&
119  {
120  /* Yes -- we have to translate this from virtual */
123  CachingFlags);
124  }
125 
126  /* Look in all descriptors except truncated and firmware ones */
131 
132  /* Return the virtual address as the physical address */
133  if (PhysicalAddress)
134  {
137  }
138 
139  /* There's no caching on physical memory */
140  if (CachingFlags)
141  {
142  *CachingFlags = 0;
143  }
144 
145  /* Success is if we found a descriptor */
146  return Descriptor != NULL;
147 }
148 
149 VOID
151  VOID
152  )
153 {
154  EfiPrintf(L"No destroy\r\n");
155 }
156 
157 VOID
160  )
161 {
162  /* Flush the TLB */
164 }
165 
166 VOID
168  VOID
169  )
170 {
171  /* Flush the TLB */
173 }
174 
175 NTSTATUS
178  _In_ ULONG Size
179  )
180 {
181  EfiPrintf(L"No unmap\r\n");
182  return STATUS_NOT_IMPLEMENTED;
183 }
184 
185 NTSTATUS
189  _In_ ULONG Size,
190  _In_ ULONG CacheAttributes
191  )
192 {
193  EfiPrintf(L"No remap\r\n");
194  return STATUS_NOT_IMPLEMENTED;
195 }
196 
197 NTSTATUS
201  _In_ ULONG Size,
202  _In_ ULONG CacheAttributes
203  )
204 {
206  ULONG i, PageCount, PdeOffset;
207  ULONGLONG CurrentAddress;
208  PMMPDE Pde;
209  PMMPTE Pte;
211  PHYSICAL_ADDRESS PageTableAddress;
213 
214  /* Check if paging is on yet */
216 
217  /* Get the physical address aligned */
218  CurrentAddress = (PhysicalAddress.QuadPart >> PAGE_SHIFT) << PAGE_SHIFT;
219 
220  /* Get the number of pages and loop through each one */
221  PageCount = Size >> PAGE_SHIFT;
222  for (i = 0; i < PageCount; i++)
223  {
224  /* Check if translation already exists for this page */
226  {
227  /* Ignore it and move to the next one */
229  CurrentAddress += PAGE_SIZE;
230  continue;
231  }
232 
233  /* Get the PDE offset */
235 
236  /* Check if paging is actually turned on */
237  if (Enabled)
238  {
239  /* Get the PDE entry using the self-map */
241  }
242  else
243  {
244  /* Get it using our physical mappings */
245  Pde = &MmPdpt[PdeOffset];
247  }
248 
249  /* Check if we don't yet have a PDE */
250  if (!Pde->u.Hard.Valid)
251  {
252  /* Allocate a page table */
253  Status = MmPapAllocatePhysicalPagesInRange(&PageTableAddress,
255  1,
256  0,
257  0,
259  0,
260  0);
261  if (!NT_SUCCESS(Status))
262  {
263  EfiPrintf(L"PDE alloc failed!\r\n");
264  EfiStall(1000000);
265  return STATUS_NO_MEMORY;
266  }
267 
268  /* This is our page table */
269  PageTable = (PVOID)(ULONG_PTR)PageTableAddress.QuadPart;
270 
271  /* Build the PDE for it */
272  Pde->u.Hard.PageFrameNumber = PageTableAddress.QuadPart >> PAGE_SHIFT;
273  Pde->u.Hard.Write = 1;
274  Pde->u.Hard.CacheDisable = 1;
275  Pde->u.Hard.WriteThrough = 1;
276  Pde->u.Hard.Valid = 1;
277 
278  /* Check if paging is enabled */
279  if (Enabled)
280  {
281  /* Then actually, get the page table's virtual address */
283 
284  /* Flush the TLB */
285  Mmx86FlushTlb();
286  }
287 
288  /* Zero out the page table */
290 
291  /* Reset caching attributes now */
292  Pde->u.Hard.CacheDisable = 0;
293  Pde->u.Hard.WriteThrough = 0;
294 
295  /* Check for paging again */
296  if (Enabled)
297  {
298  /* Flush the TLB entry for the page table only */
300  }
301  }
302 
303  /* Add a reference to this page table */
304  MmArchReferencePage[PdeOffset]++;
305 
306  /* Check if a physical address was given */
307  if (PhysicalAddress.QuadPart != -1)
308  {
309  /* Check if paging is turned on */
310  if (Enabled)
311  {
312  /* Get the PTE using the self-map */
314  }
315  else
316  {
317  /* Get the PTE using physical addressing */
319  }
320 
321  /* Build a valid PTE for it */
322  Pte->u.Hard.PageFrameNumber = CurrentAddress >> PAGE_SHIFT;
323  Pte->u.Hard.Write = 1;
324  Pte->u.Hard.Valid = 1;
325 
326  /* Check if this is uncached */
327  if (CacheAttributes == BlMemoryUncached)
328  {
329  /* Set the flags */
330  Pte->u.Hard.CacheDisable = 1;
331  Pte->u.Hard.WriteThrough = 1;
332  }
333  else if (CacheAttributes == BlMemoryWriteThrough)
334  {
335  /* It's write-through, set the flag */
336  Pte->u.Hard.WriteThrough = 1;
337  }
338  }
339 
340  /* Move to the next physical/virtual address */
342  CurrentAddress += PAGE_SIZE;
343  }
344 
345  /* All done! */
346  return STATUS_SUCCESS;
347 }
348 
349 BOOLEAN
353  _Out_opt_ PULONG CacheAttributes
354  )
355 {
356  PMMPDE Pde;
357  PMMPTE Pte;
360 
361  /* Is there no page directory yet? */
362  if (!MmPdpt)
363  {
364  return FALSE;
365  }
366 
367  /* Is paging enabled? */
369 
370  /* Check if paging is actually turned on */
371  if (Enabled)
372  {
373  /* Get the PDE entry using the self-map */
375  }
376  else
377  {
378  /* Get it using our physical mappings */
380  }
381 
382  /* Is the PDE valid? */
383  if (!Pde->u.Hard.Valid)
384  {
385  return FALSE;
386  }
387 
388  /* Check if paging is turned on */
389  if (Enabled)
390  {
391  /* Get the PTE using the self-map */
393  }
394  else
395  {
396  /* Get the PTE using physical addressing */
399  }
400 
401  /* Is the PTE valid? */
402  if (!Pte->u.Hard.Valid)
403  {
404  return FALSE;
405  }
406 
407  /* Does caller want the physical address? */
408  if (PhysicalAddress)
409  {
410  /* Return it */
413  }
414 
415  /* Does caller want cache attributes? */
416  if (CacheAttributes)
417  {
418  /* Not yet -- lie and say it's cached */
419  EfiPrintf(L"Cache checking not yet enabled\r\n");
420  *CacheAttributes = BlMemoryWriteBack;
421  }
422 
423  /* It exists! */
424  return TRUE;
425 }
426 
427 NTSTATUS
429  _Inout_ PPHYSICAL_ADDRESS PhysicalAddressPtr,
430  _Inout_ PVOID* VirtualAddressPtr,
431  _Inout_ PULONGLONG SizePtr,
432  _In_ ULONG CacheAttributes
433  )
434 {
435  ULONGLONG Size;
439  ULONG_PTR CurrentAddress, VirtualAddressEnd;
441 
442  /* Fail if any parameters are missing */
443  if (!(PhysicalAddressPtr) || !(VirtualAddressPtr) || !(SizePtr))
444  {
446  }
447 
448  /* Fail if the size is over 32-bits */
449  Size = *SizePtr;
450  if (Size > 0xFFFFFFFF)
451  {
453  }
454 
455  /* Nothing to do if we're in physical mode */
456  if (MmTranslationType == BlNone)
457  {
458  return STATUS_SUCCESS;
459  }
460 
461  /* Can't use virtual memory in real mode */
463  {
464  return STATUS_UNSUCCESSFUL;
465  }
466 
467  /* Capture the current virtual and physical addresses */
468  VirtualAddress = *VirtualAddressPtr;
469  PhysicalAddress = PhysicalAddressPtr->QuadPart;
470 
471  /* Check if a physical address was requested */
472  if (PhysicalAddress != 0xFFFFFFFF)
473  {
474  /* Round down the base addresses */
477 
478  /* Round up the size */
479  Size = ROUND_TO_PAGES(PhysicalAddressPtr->QuadPart -
481  Size);
482 
483  /* Loop every virtual page */
484  CurrentAddress = (ULONG_PTR)VirtualAddress;
485  VirtualAddressEnd = CurrentAddress + Size - 1;
486  while (CurrentAddress < VirtualAddressEnd)
487  {
488  /* Get the physical page of this virtual page */
489  if (MmArchTranslateVirtualAddress((PVOID)CurrentAddress,
491  &CacheAttributes))
492  {
493  /* Make sure the physical page of the virtual page, matches our page */
495  (PhysicalAddress +
496  (CurrentAddress - (ULONG_PTR)VirtualAddress)))
497  {
498  /* There is an existing virtual mapping for a different address */
499  EfiPrintf(L"Existing mapping exists: %lx vs %lx\r\n",
501  PhysicalAddress + (CurrentAddress - (ULONG_PTR)VirtualAddress));
502  EfiStall(10000000);
504  }
505  }
506 
507  /* Try the next one */
508  CurrentAddress += PAGE_SIZE;
509  }
510  }
511 
512  /* Aactually do the mapping */
516  Size,
517  CacheAttributes);
518  if (!NT_SUCCESS(Status))
519  {
520  EfiPrintf(L"Failed to map!: %lx\r\n", Status);
521  EfiStall(1000000);
522  return Status;
523  }
524 
525  /* Return aligned/fixed up output parameters */
526  PhysicalAddressPtr->QuadPart = PhysicalAddress;
527  *VirtualAddressPtr = VirtualAddress;
528  *SizePtr = Size;
529 
530  /* Flush the TLB if paging is enabled */
532  {
533  Mmx86FlushTlb();
534  }
535 
536  /* All good! */
537  return STATUS_SUCCESS;
538 }
539 
540 NTSTATUS
545  )
546 {
548 
549  /* Make a virtual mapping for this physical address */
551  if (!NT_SUCCESS(Status))
552  {
553  return Status;
554  }
555 
556  /* Nothing else to do if we're not in paging mode */
557  if (MmTranslationType == BlNone)
558  {
559  return STATUS_SUCCESS;
560  }
561 
562  /* Otherwise, remove this region from the list of free virtual ranges */
566  Size >> PAGE_SHIFT,
567  0);
568  if (!NT_SUCCESS(Status))
569  {
570  /* Unmap the address if that failed */
572  }
573 
574  /* Return back to caller */
575  return Status;
576 }
577 
578 VOID
580  _In_ PBL_MEMORY_DESCRIPTOR_LIST DescriptorList,
581  _In_opt_ ULONG MaxCount
582  )
583 {
584  ULONGLONG EndPage, VirtualEndPage;
586  PLIST_ENTRY NextEntry;
587 
588  /* If no maximum was provided, use essentially infinite */
589  if (MaxCount == 0)
590  {
591  MaxCount = 0xFFFFFFFF;
592  }
593 
594  /* Loop the list as long as there's entries and max isn't reached */
595  NextEntry = DescriptorList->First->Flink;
596  while ((NextEntry != DescriptorList->First) && (MaxCount--))
597  {
598  /* Get the descriptor */
601  ListEntry);
602 
603  /* Get the descriptor end page, and see if it was virtually mapepd */
604  EndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
605  if (MemoryDescriptor->VirtualPage)
606  {
607  /* Get the virtual end page too, then */
608  VirtualEndPage = MemoryDescriptor->VirtualPage +
609  MemoryDescriptor->PageCount;
610  }
611  else
612  {
613  VirtualEndPage = 0;
614  }
615 
616  /* Print out the descriptor, physical range, virtual range, and type */
617  EfiPrintf(L"%p - [%08llx-%08llx @ %08llx-%08llx]:%x\r\n",
619  MemoryDescriptor->BasePage << PAGE_SHIFT,
620  (EndPage << PAGE_SHIFT) - 1,
621  MemoryDescriptor->VirtualPage << PAGE_SHIFT,
622  VirtualEndPage ? (VirtualEndPage << PAGE_SHIFT) - 1 : 0,
623  (ULONG)MemoryDescriptor->Type);
624 
625  /* Next entry */
626  NextEntry = NextEntry->Flink;
627  }
628 }
629 
630 NTSTATUS
632  _In_ ULONG Phase,
633  _In_ PBL_MEMORY_DATA MemoryData
634  )
635 {
636  BOOLEAN DoDeferred;
637  ULONG DescriptorCount;
639  ULONG FinalOffset;
641  ULONGLONG Size;
644  BL_MEMORY_DESCRIPTOR_LIST FirmwareMdl;
645  PLIST_ENTRY Head, NextEntry;
646 
647  /* Check which phase this is */
648  if (Phase == 1)
649  {
650  /* In phase 1 we don't initialize deferred mappings */
651  DoDeferred = FALSE;
652  }
653  else
654  {
655  /* Don't do anything if there's nothing to initialize */
657  {
658  return STATUS_SUCCESS;
659  }
660 
661  /* We'll do deferred descriptors in phase 2 */
662  DoDeferred = TRUE;
663  }
664 
665  /*
666  * Because BL supports cross x86-x64 application launches and a LIST_ENTRY
667  * is of variable size, care must be taken here to ensure that we see a
668  * consistent view of descriptors. BL uses some offset magic to figure out
669  * where the data actually starts, since everything is ULONGLONG past the
670  * LIST_ENTRY itself
671  */
672  FinalOffset = MemoryData->MdListOffset + MemoryData->DescriptorOffset;
673  Descriptor = (PBL_MEMORY_DESCRIPTOR)((ULONG_PTR)MemoryData + FinalOffset -
675 
676  /* Scan all of them */
677  DescriptorCount = MemoryData->DescriptorCount;
678  while (DescriptorCount != 0)
679  {
680  /* Ignore application data */
681  if (Descriptor->Type != BlApplicationData)
682  {
683  /* If this is a ramdisk, do it in phase 2 */
684  if ((Descriptor->Type == BlLoaderRamDisk) == DoDeferred)
685  {
686  /* Get the current physical address and size */
688  Size = Descriptor->PageCount << PAGE_SHIFT;
689 
690  /* Check if it was already mapped */
691  if (Descriptor->VirtualPage)
692  {
693  /* Use the existing address */
694  VirtualAddress = (PVOID)(ULONG_PTR)(Descriptor->VirtualPage << PAGE_SHIFT);
695  }
696  else
697  {
698  /* Use the physical address */
700  }
701 
702  /* Crete the mapping */
704  Size,
706  if (!NT_SUCCESS(Status))
707  {
708  return Status;
709  }
710  }
711 
712  /* Check if we're in phase 1 and deferring RAM disk */
713  if ((Phase == 1) && (Descriptor->Type == BlLoaderRamDisk))
714  {
716  }
717  }
718 
719  /* Move on to the next descriptor */
720  DescriptorCount--;
721  Descriptor = (PBL_MEMORY_DESCRIPTOR)((ULONG_PTR)Descriptor + MemoryData->DescriptorSize);
722  }
723 
724  /* In phase 1, also do UEFI mappings */
725  if (Phase != 2)
726  {
727  /* Get the memory map */
728  MmMdInitializeListHead(&FirmwareMdl);
730  if (!NT_SUCCESS(Status))
731  {
732  return Status;
733  }
734 
735  /* Iterate over it */
736  Head = FirmwareMdl.First;
737  NextEntry = Head->Flink;
738  while (NextEntry != Head)
739  {
740  /* Check if this is a UEFI-related descriptor, unless it's the self-map page */
741  Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
742  if (((Descriptor->Type == BlEfiBootMemory) ||
743  (Descriptor->Type == BlEfiRuntimeCodeMemory) ||
744  (Descriptor->Type == BlEfiRuntimeDataMemory) || // WINBUG?
745  (Descriptor->Type == BlLoaderMemory)) &&
746  ((Descriptor->BasePage << PAGE_SHIFT) != Mmx86SelfMapBase.QuadPart))
747  {
748  /* Identity-map it */
751  Descriptor->PageCount << PAGE_SHIFT,
753  if (!NT_SUCCESS(Status))
754  {
755  return Status;
756  }
757  }
758 
759  /* Move to the next descriptor */
760  NextEntry = NextEntry->Flink;
761  }
762 
763  /* Reset */
764  NextEntry = Head->Flink;
765  while (NextEntry != Head)
766  {
767  /* Get the descriptor */
768  Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
769 
770  /* Skip to the next entry before we free */
771  NextEntry = NextEntry->Flink;
772 
773  /* Remove and free it */
776  }
777  }
778 
779  /* All library mappings identity mapped now */
780  return STATUS_SUCCESS;
781 }
782 
783 NTSTATUS
785  _In_ ULONG Phase,
786  _In_ PBL_MEMORY_DATA MemoryData
787  )
788 {
789  ULONG ImageSize;
790  PVOID ImageBase;
791  KDESCRIPTOR Gdt, Idt;
794 
795  /* If this is phase 2, map the memory regions */
796  if (Phase != 1)
797  {
798  return Mmx86pMapMemoryRegions(Phase, MemoryData);
799  }
800 
801  /* Get the application image base/size */
802  Status = BlGetApplicationBaseAndSize(&ImageBase, &ImageSize);
803  if (!NT_SUCCESS(Status))
804  {
805  return Status;
806  }
807 
808  /* Map the image back at the same place */
809  PhysicalAddress.QuadPart = (ULONG_PTR)ImageBase;
810  Status = Mmx86MapInitStructure(ImageBase, ImageSize, PhysicalAddress);
811  if (!NT_SUCCESS(Status))
812  {
813  return Status;
814  }
815 
816  /* Map the first 4MB of memory */
818  Status = Mmx86MapInitStructure(NULL, 4 * 1024 * 1024, PhysicalAddress);
819  if (!NT_SUCCESS(Status))
820  {
821  return Status;
822  }
823 
824  /* Map the GDT */
825  _sgdt(&Gdt.Limit);
828  if (!NT_SUCCESS(Status))
829  {
830  return Status;
831  }
832 
833  /* Map the IDT */
834  __sidt(&Idt.Limit);
837  if (!NT_SUCCESS(Status))
838  {
839  return Status;
840  }
841 
842  /* Map the reference page */
847  if (!NT_SUCCESS(Status))
848  {
849  return Status;
850  }
851 
852  /* More to do */
853  return Mmx86pMapMemoryRegions(Phase, MemoryData);
854 }
855 
856 NTSTATUS
858  _In_ PBL_MEMORY_DATA MemoryData,
859  _In_ BL_TRANSLATION_TYPE TranslationType
860  )
861 {
864  ULONG PdeIndex;
865 
866  /* Set the global function pointers for memory translation */
874 
875  /* Check what mode we're currently in */
876  if (TranslationType == BlVirtual)
877  {
878  EfiPrintf(L"Virtual->Virtual not yet supported\r\n");
879  return STATUS_NOT_IMPLEMENTED;
880  }
881  else if (TranslationType != BlNone)
882  {
883  /* Not even Windows supports PAE->Virtual downgrade */
884  return STATUS_NOT_IMPLEMENTED;
885  }
886 
887  /* The None->Virtual case */
888  MmPdpt = NULL;
891 
892  /* Truncate all memory above 4GB so that we don't use it */
893  Status = MmPaTruncateMemory(0x100000);
894  if (!NT_SUCCESS(Status))
895  {
896  goto Failure;
897  }
898 
899  /* Allocate a page directory */
902  1,
903  0,
904  0,
906  0,
907  0);
908  if (!NT_SUCCESS(Status))
909  {
910  goto Failure;
911  }
912 
913  /* Zero out the page directory */
916 
917  /* Set the page size */
919 
920  /* Allocate the self-map page */
923  1,
924  0,
925  0,
927  0,
928  0);
929  if (!NT_SUCCESS(Status))
930  {
931  goto Failure;
932  }
933 
934  /* Set the reference page */
936 
937  /* Zero it out */
939 
940  /* Allocate 4MB worth of self-map pages */
942  (4 * 1024 * 1024) >> PAGE_SHIFT,
943  (4 * 1024 * 1024) >> PAGE_SHIFT);
944  if (!NT_SUCCESS(Status))
945  {
946  goto Failure;
947  }
948 
949  /* Zero them out */
950  RtlZeroMemory((PVOID)Mmx86SelfMapBase.LowPart, 4 * 1024 * 1024);
951  EfiPrintf(L"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n",
953 
954  /* Align PTE base to 4MB region */
955  MmPteBase = (PVOID)(Mmx86SelfMapBase.LowPart & ~0x3FFFFF);
956 
957  /* The PDE is the PTE of the PTE base */
959  PdeIndex = MiAddressToPdeOffset(MmPdeBase);
960  MmPdpt[PdeIndex].u.Hard.Valid = 1;
961  MmPdpt[PdeIndex].u.Hard.Write = 1;
963  MmArchReferencePage[PdeIndex]++;
964 
965  /* Remove PTE_BASE from free virtual memory */
968  PTE_BASE >> PAGE_SHIFT,
969  (4 * 1024 * 1024) >> PAGE_SHIFT,
970  0);
971  if (!NT_SUCCESS(Status))
972  {
973  goto Failure;
974  }
975 
976  /* Remove HAL_HEAP from free virtual memory */
980  (4 * 1024 * 1024) >> PAGE_SHIFT,
981  0);
982  if (!NT_SUCCESS(Status))
983  {
984  goto Failure;
985  }
986 
987  /* Initialize the virtual->physical memory mappings */
988  Status = Mmx86InitializeMemoryMap(1, MemoryData);
989  if (!NT_SUCCESS(Status))
990  {
991  goto Failure;
992  }
993 
994  /* Turn on paging with the new CR3 */
997  EfiPrintf(L"Paging... %d\r\n", BlMmIsTranslationEnabled());
998 
999  /* Return success */
1000  return Status;
1001 
1002 Failure:
1003  /* Free reference page if we allocated it */
1004  if (MmArchReferencePage)
1005  {
1008  }
1009 
1010  /* Free page directory if we allocated it */
1011  if (MmPdpt)
1012  {
1015  }
1016 
1017  /* Free the self map if we allocated it */
1019  {
1021  }
1022 
1023  /* All done */
1024  return Status;
1025 }
1026 
1027 NTSTATUS
1029  _In_ ULONG Phase,
1030  _In_ PBL_MEMORY_DATA MemoryData,
1031  _In_ BL_TRANSLATION_TYPE TranslationType,
1032  _In_ BL_TRANSLATION_TYPE RequestedTranslationType
1033  )
1034 {
1035  NTSTATUS Status;
1036  ULONGLONG IncreaseUserVa, PerfCounter, CpuRandom;
1037  CPU_INFO CpuInfo;
1038 
1039  /* For phase 2, just map deferred regions */
1040  if (Phase != 1)
1041  {
1042  return Mmx86pMapMemoryRegions(2, MemoryData);
1043  }
1044 
1045  /* What translation type are we switching to? */
1046  switch (RequestedTranslationType)
1047  {
1048  /* Physical memory */
1049  case BlNone:
1050 
1051  /* Initialize everything to default/null values */
1052  MmArchLargePageSize = 1;
1053  MmArchKsegBase = 0;
1054  MmArchKsegBias = 0;
1059 
1060  /* Set stub functions */
1063 
1064  /* Set success */
1066  break;
1067 
1068  case BlVirtual:
1069 
1070  /* Set the large page size to 1024 pages (4MB) */
1071  MmArchLargePageSize = (4 * 1024 * 1024) / PAGE_SIZE;
1072 
1073  /* Check if /USERVA option was used */
1076  &IncreaseUserVa);
1077  if (NT_SUCCESS(Status) && (IncreaseUserVa))
1078  {
1079  /* Yes -- load the kernel at 0xE0000000 instead */
1080  MmArchKsegBase = 0xE0000000;
1081  }
1082  else
1083  {
1084  /* Nope, load at the standard 2GB split */
1085  MmArchKsegBase = 0x80000000;
1086  }
1087 
1088  /* Check if CPUID 01h is supported */
1089  CpuRandom = 0;
1091  {
1092  /* Call it */
1093  BlArchCpuId(1, 0, &CpuInfo);
1094 
1095  /* Check if RDRAND is supported */
1096  if (CpuInfo.Ecx & 0x40000000)
1097  {
1098  EfiPrintf(L"Your CPU can do RDRAND! Good for you!\r\n");
1099  CpuRandom = 0;
1100  }
1101  }
1102 
1103  /* Read the TSC */
1104  PerfCounter = BlArchGetPerformanceCounter();
1105  PerfCounter >>= 4;
1106  _rotl16(PerfCounter, 5);
1107 
1108  /* Set the address range */
1111 
1112  /* Set the KASLR bias */
1113  MmArchKsegBias = ((PerfCounter ^ CpuRandom) & 0xFFF) << 12;
1114  MmArchKsegBias = 0;
1116 
1117  /* Set the kernel range */
1120 
1121  /* Set the boot application top maximum */
1122  MmArchTopOfApplicationAddressSpace = 0x70000000 - 1; // Windows bug
1123 
1124  /* Initialize virtual address space translation */
1125  Status = MmDefInitializeTranslation(MemoryData, TranslationType);
1126  if (NT_SUCCESS(Status))
1127  {
1128  /* Set stub functions */
1133  }
1134  break;
1135 
1136  case BlPae:
1137 
1138  /* We don't support PAE */
1140  break;
1141 
1142  default:
1143 
1144  /* Invalid architecture type*/
1146  break;
1147  }
1148 
1149  /* Back to caller */
1150  return Status;
1151 }
NTSTATUS MmDefZeroVirtualAddressRange(_In_ PVOID DestinationAddress, _In_ ULONGLONG Size)
Definition: mmx86.c:98
NTSTATUS BlGetApplicationBaseAndSize(_Out_ PVOID *ImageBase, _Out_ PULONG ImageSize)
Definition: bootlib.c:424
ULONG64 Write
Definition: mmtypes.h:170
NTSTATUS MmDefpRemapVirtualAddress(_In_ PPHYSICAL_ADDRESS PhysicalAddress, _Out_ PVOID VirtualAddress, _In_ ULONG Size, _In_ ULONG CacheAttributes)
Definition: mmx86.c:186
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
VOID BlpArchEnableTranslation(VOID)
Definition: arch.c:189
#define MM_HAL_VA_START
Definition: ketypes.h:256
#define TRUE
Definition: types.h:120
ULONG MmArchReferencePageSize
Definition: mmx86.c:37
NTSTATUS MmMapPhysicalAddress(_Inout_ PPHYSICAL_ADDRESS PhysicalAddressPtr, _Inout_ PVOID *VirtualAddressPtr, _Inout_ PULONGLONG SizePtr, _In_ ULONG CacheAttributes)
Definition: mmx86.c:428
_Out_ PNDIS_BUFFER _In_ NDIS_HANDLE _In_ PVOID MemoryDescriptor
Definition: ndis.h:3270
PVOID MmPdeBase
Definition: mmx86.c:36
#define MiAddressToPde(x)
Definition: mmx86.c:20
NTSTATUS EfiStall(_In_ ULONG StallTime)
Definition: firmware.c:1003
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
FORCEINLINE VOID MmMdInitializeListHead(_In_ PBL_MEMORY_DESCRIPTOR_LIST List)
Definition: bl.h:1377
static PMEM_HOOK PageTable[TOTAL_PAGES]
Definition: memory.c:40
PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress
Definition: mmx86.c:39
NTSTATUS(* PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE)(_In_ PVOID DestinationAddress, _In_ ULONGLONG Size)
Definition: bl.h:696
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
PVOID MmPteBase
Definition: mmx86.c:35
NTSTATUS(* PBL_MM_UNMAP_VIRTUAL_ADDRESS)(_In_ PVOID VirtualAddress, _In_ ULONG Size)
Definition: bl.h:717
NTSTATUS MmDefMoveVirtualAddressRange(_In_ PVOID DestinationAddress, _In_ PVOID SourceAddress, _In_ ULONGLONG Size)
Definition: mmx86.c:87
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS MmUnmapVirtualAddress(_Inout_ PVOID *VirtualAddress, _Inout_ PULONGLONG Size)
Definition: mm.c:453
VOID(* PBL_MM_RELOCATE_SELF_MAP)(VOID)
Definition: bl.h:684
VOID(* PBL_MM_FLUSH_TLB)(VOID)
Definition: bl.h:679
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
#define BL_CONTEXT_PAGING_ON
Definition: bl.h:84
PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress
Definition: mmx86.c:41
PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress
Definition: mmx86.c:42
VOID(* PBL_MM_FLUSH_TLB_ENTRY)(_In_ PVOID VirtualAddress)
Definition: bl.h:707
BOOLEAN(* PBL_MM_TRANSLATE_VIRTUAL_ADDRESS)(_In_ PVOID VirtualAddress, _Out_ PPHYSICAL_ADDRESS PhysicalAddress, _Out_opt_ PULONG CacheAttributes)
Definition: bl.h:739
__INTRIN_INLINE unsigned long __readcr3(void)
Definition: intrin_x86.h:1706
#define BL_MM_REMOVE_PHYSICAL_REGION_FLAG
Definition: bl.h:125
NTSTATUS BlMmFreePhysicalPages(_In_ PHYSICAL_ADDRESS Address)
Definition: pagealloc.c:1187
ULONG MmDeferredMappingCount
Definition: mmx86.c:32
#define BL_MM_REMOVE_VIRTUAL_REGION_FLAG
Definition: bl.h:126
NTSTATUS Mmx86pMapMemoryRegions(_In_ ULONG Phase, _In_ PBL_MEMORY_DATA MemoryData)
Definition: mmx86.c:631
VOID(* PBL_MM_DESTROY_SELF_MAP)(VOID)
Definition: bl.h:702
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG _Out_ PPHYSICAL_ADDRESS TranslatedAddress
Definition: iofuncs.h:2268
PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry
Definition: mmx86.c:44
ULONG_PTR MmArchKsegBias
Definition: mmx86.c:27
PVOID Base
Definition: ketypes.h:486
NTSTATUS(* PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE)(_In_ PVOID DestinationAddress, _In_ PVOID SourceAddress, _In_ ULONGLONG Size)
Definition: bl.h:689
int WINAPI EndPage(_In_ HDC)
enum _BL_TRANSLATION_TYPE BL_TRANSLATION_TYPE
#define _In_opt_
Definition: no_sal2.h:213
NTSTATUS MmMdRemoveRegionFromMdlEx(__in PBL_MEMORY_DESCRIPTOR_LIST MdList, __in ULONG Flags, __in ULONGLONG BasePage, __in ULONGLONG PageCount, __in PBL_MEMORY_DESCRIPTOR_LIST NewMdList)
ULONG_PTR MmArchTopOfApplicationAddressSpace
Definition: mmx86.c:30
NTSTATUS BlGetBootOptionInteger(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PULONGLONG Value)
Definition: bcdopt.c:467
PLIST_ENTRY First
Definition: bl.h:1008
USHORT Limit
Definition: ketypes.h:485
ULONG ContextFlags
Definition: bl.h:1002
BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry
Definition: bootlib.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:63
Definition: bl.h:232
PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress
Definition: mmx86.c:40
VOID MmArchNullFunction(VOID)
Definition: mmx86.c:67
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1675
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define MiAddressToPte(x)
Definition: mmx86.c:19
VOID MmMdRemoveDescriptorFromList(_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, _In_ PBL_MEMORY_DESCRIPTOR Entry)
Definition: descriptor.c:338
PHYSICAL_ADDRESS Mmx86SelfMapBase
Definition: mmx86.c:31
union _MMPTE::@2236 u
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:1920
struct _BL_MEMORY_DESCRIPTOR * PBL_MEMORY_DESCRIPTOR
PBL_BCD_OPTION BcdData
Definition: bl.h:868
PBL_MM_FLUSH_TLB Mmx86FlushTlb
Definition: mmx86.c:43
NTSTATUS MmPapAllocatePhysicalPagesInRange(_Inout_ PPHYSICAL_ADDRESS BaseAddress, _In_ BL_MEMORY_TYPE MemoryType, _In_ ULONGLONG Pages, _In_ ULONG Attributes, _In_ ULONG Alignment, _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList, _In_opt_ PBL_ADDRESS_RANGE Range, _In_ ULONG RangeType)
Definition: pagealloc.c:438
ULONG64 WriteThrough
Definition: mmtypes.h:161
BL_TRANSLATION_TYPE MmTranslationType
Definition: mm.c:17
VOID MmMdDbgDumpList(_In_ PBL_MEMORY_DESCRIPTOR_LIST DescriptorList, _In_opt_ ULONG MaxCount)
Definition: mmx86.c:579
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
struct _MMPTE * PMMPDE
Definition: bl.h:240
#define _Out_
Definition: no_sal2.h:323
void * PVOID
Definition: retypes.h:9
NTSTATUS(* PBL_MM_MAP_PHYSICAL_ADDRESS)(_In_ PHYSICAL_ADDRESS PhysicalAddress, _Out_ PVOID VirtualAddress, _In_ ULONG Size, _In_ ULONG CacheAttributes)
Definition: bl.h:731
PBL_ARCH_CONTEXT CurrentExecutionContext
Definition: arch.c:17
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
BOOLEAN BlArchIsCpuIdFunctionSupported(_In_ ULONG Function)
Definition: util.c:856
NTSTATUS MmDefpMapPhysicalAddress(_In_ PHYSICAL_ADDRESS PhysicalAddress, _In_ PVOID VirtualAddress, _In_ ULONG Size, _In_ ULONG CacheAttributes)
Definition: mmx86.c:198
ULONG_PTR MmArchKsegBase
Definition: mmx86.c:26
#define BL_MM_INCLUDE_NO_FIRMWARE_MEMORY
Definition: bl.h:108
#define _Out_opt_
Definition: no_sal2.h:339
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
NTSTATUS MmMdFreeDescriptor(_In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor)
Definition: descriptor.c:157
NTSTATUS MmArchInitialize(_In_ ULONG Phase, _In_ PBL_MEMORY_DATA MemoryData, _In_ BL_TRANSLATION_TYPE TranslationType, _In_ BL_TRANSLATION_TYPE RequestedTranslationType)
Definition: mmx86.c:1028
ULONGLONG Maximum
Definition: bl.h:1016
NTSTATUS MmFwGetMemoryMap(_Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap, _In_ ULONG Flags)
Definition: firmware.c:1845
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: bl.h:231
PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange
Definition: mmx86.c:49
uint64_t ULONGLONG
Definition: typedefs.h:65
ULONG64 Valid
Definition: mmtypes.h:150
struct _MMPTE * PMMPTE
ULONG Ecx
Definition: ketypes.h:298
NTSTATUS MmPaReleaseSelfMapPages(_In_ PHYSICAL_ADDRESS Address)
Definition: pagealloc.c:1505
VOID MmDefpFlushTlb(VOID)
Definition: mmx86.c:167
#define _Inout_
Definition: no_sal2.h:244
NTSTATUS MmPaReserveSelfMapPages(_Inout_ PPHYSICAL_ADDRESS PhysicalAddress, _In_ ULONG Alignment, _In_ ULONG PageCount)
Definition: pagealloc.c:1564
ULONG64 CacheDisable
Definition: mmtypes.h:162
NTSTATUS MmPaTruncateMemory(_In_ ULONGLONG BasePage)
Definition: pagealloc.c:51
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
static const WCHAR L[]
Definition: oid.c:1250
#define BL_MM_INCLUDE_TRUNCATED_MEMORY
Definition: bl.h:104
#define BL_MM_FLAG_REQUEST_COALESCING
Definition: bl.h:88
PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange
Definition: mmx86.c:50
PBL_MM_FLUSH_TLB BlMmFlushTlb
Definition: mmx86.c:48
ULONG LowPart
Definition: typedefs.h:104
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PTE_BASE
Definition: mmx86.c:14
Definition: typedefs.h:117
ULONG MmArchLargePageSize
Definition: mmx86.c:28
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
NTSTATUS MmDefpUnmapVirtualAddress(_In_ PVOID VirtualAddress, _In_ ULONG Size)
Definition: mmx86.c:176
PULONG MmArchReferencePage
Definition: mmx86.c:34
VOID MmDefRelocateSelfMap(VOID)
Definition: mmx86.c:76
VOID MmDefpFlushTlbEntry(_In_ PVOID VirtualAddress)
Definition: mmx86.c:158
ULONGLONG Minimum
Definition: bl.h:1015
__INTRIN_INLINE void _sgdt(void *Destination)
Definition: intrin_x86.h:1925
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
PBL_MEMORY_DESCRIPTOR MmMdFindDescriptor(_In_ ULONG WhichList, _In_ ULONG Flags, _In_ ULONGLONG Page)
Definition: descriptor.c:1049
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
BOOLEAN BlMmIsTranslationEnabled(VOID)
Definition: mmx86.c:57
BL_ADDRESS_RANGE MmArchKsegAddressRange
Definition: mmx86.c:29
#define ROUND_TO_PAGES(Size)
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
NTSTATUS(* PBL_MM_REMAP_VIRTUAL_ADDRESS)(_In_ PPHYSICAL_ADDRESS PhysicalAddress, _Out_ PVOID VirtualAddress, _In_ ULONG Size, _In_ ULONG CacheAttributes)
Definition: bl.h:723
unsigned int * PULONG
Definition: retypes.h:1
VOID EfiPrintf(_In_ PWCHAR Format,...)
Definition: firmware.c:126
ULONGLONG BlArchGetPerformanceCounter(VOID)
Definition: util.c:902
BOOLEAN MmDefpTranslateVirtualAddress(_In_ PVOID VirtualAddress, _Out_ PPHYSICAL_ADDRESS PhysicalAddress, _Out_opt_ PULONG CacheAttributes)
Definition: mmx86.c:350
PMMPTE MmPdpt
Definition: mmx86.c:33
NTSTATUS MmDefInitializeTranslation(_In_ PBL_MEMORY_DATA MemoryData, _In_ BL_TRANSLATION_TYPE TranslationType)
Definition: mmx86.c:857
__INTRIN_INLINE void __invlpg(void *Address)
Definition: intrin_x86.h:1865
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedAllocated
Definition: pagealloc.c:38
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
unsigned int ULONG
Definition: retypes.h:1
_Check_return_ unsigned short __cdecl _rotl16(_In_ unsigned short _Value, _In_ unsigned char _Shift)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
VOID BlArchCpuId(_In_ ULONG Function, _In_ ULONG SubFunction, _Out_ PCPU_INFO Result)
Definition: util.c:924
#define MiAddressToPdeOffset(x)
Definition: mmx86.c:22
#define MiAddressToPteOffset(x)
Definition: mmx86.c:21
BL_ARCH_MODE Mode
Definition: bl.h:1000
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Out_ PPHYSICAL_ADDRESS DestinationAddress
Definition: iotypes.h:1090
PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap
Definition: mmx86.c:45
NTSTATUS Mmx86MapInitStructure(_In_ PVOID VirtualAddress, _In_ ULONGLONG Size, _In_ PHYSICAL_ADDRESS PhysicalAddress)
Definition: mmx86.c:541
return STATUS_SUCCESS
Definition: btrfs.c:2966
PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap
Definition: mmx86.c:47
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1090
VOID MmDefpDestroySelfMap(VOID)
Definition: mmx86.c:150
BL_MEMORY_DESCRIPTOR_LIST MmMdlFreeVirtual
Definition: pagealloc.c:45
#define BYTE_OFFSET(Va)
Definition: bl.h:233
NTSTATUS Mmx86InitializeMemoryMap(_In_ ULONG Phase, _In_ PBL_MEMORY_DATA MemoryData)
Definition: mmx86.c:784
LONGLONG QuadPart
Definition: typedefs.h:112
BOOLEAN MmArchTranslateVirtualAddress(_In_ PVOID VirtualAddress, _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress, _Out_opt_ PULONG CachingFlags)
Definition: mmx86.c:108
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966