ReactOS  0.4.13-dev-247-g0f29b3f
pagealloc.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/pagealloc.c
5  * PURPOSE: Boot Library Memory Manager Page Allocator
6  * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include "bl.h"
12 #include "bcd.h"
13 
14 typedef struct _BL_PA_REQUEST
15 {
24 
25 /* DATA VARIABLES ************************************************************/
26 
28 
30 
32 
34 
47 
48 /* FUNCTIONS *****************************************************************/
49 
52  _In_ ULONGLONG BasePage
53  )
54 {
56 
57  /* Increase nesting depth */
59 
60  /* Set the maximum page to the truncated request */
61  if (BasePage < PapMaximumPhysicalPage)
62  {
63  PapMaximumPhysicalPage = BasePage;
64  }
65 
66  /* Truncate mapped and allocated memory */
69  BasePage);
70  if (NT_SUCCESS(Status))
71  {
72  /* Truncate unmapped and allocated memory */
75  BasePage);
76  if (NT_SUCCESS(Status))
77  {
78  /* Truncate mapped and unallocated memory */
81  BasePage);
82  if (NT_SUCCESS(Status))
83  {
84  /* Truncate unmapped and unallocated memory */
87  BasePage);
88  if (NT_SUCCESS(Status))
89  {
90  /* Truncate reserved memory */
93  BasePage);
94  }
95  }
96  }
97  }
98 
99  /* Restore the nesting depth */
102  return Status;
103 }
104 
105 NTSTATUS
107  VOID
108  )
109 {
110  NTSTATUS Status, ReturnStatus;
111  ULONGLONG LowestAddressValid, HighestAddressValid;
112  ULONGLONG LowestPage, HighestPage;
113 
114  /* Assume success */
115  ReturnStatus = STATUS_SUCCESS;
116 
117  /* Check for LOWMEM */
120  &LowestAddressValid);
121  if (NT_SUCCESS(Status))
122  {
123  /* Align the address */
124  LowestAddressValid = (ULONG_PTR)PAGE_ALIGN(LowestAddressValid);
125  LowestPage = LowestAddressValid >> PAGE_SHIFT;
126 
127  /* Make sure it's below 4GB */
128  if (LowestPage <= 0x100000)
129  {
130  PapMinimumPhysicalPage = LowestPage;
131  }
132  }
133 
134  /* Check for MAXMEM */
137  &HighestAddressValid);
138  if (NT_SUCCESS(Status))
139  {
140  /* Get the page */
141  HighestPage = HighestAddressValid >> PAGE_SHIFT;
142 
143  /* Truncate memory above this page */
144  ReturnStatus = MmPaTruncateMemory(HighestPage);
145  }
146 
147  /* Return back to the caller */
148  return ReturnStatus;
149 }
150 
151 PWCHAR
153 {
154  if (MdList == &MmMdlUnmappedAllocated)
155  {
156  return L"UnmapAlloc";
157  }
158  else if (MdList == &MmMdlUnmappedUnallocated)
159  {
160  return L"UnmapUnalloc";
161  }
162  else if (MdList == &MmMdlMappedAllocated)
163  {
164  return L"MapAlloc";
165  }
166  else if (MdList == &MmMdlMappedUnallocated)
167  {
168  return L"MapUnalloc";
169  }
170  else
171  {
172  return L"Other";
173  }
174 }
175 
176 NTSTATUS
180  _In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList,
183  )
184 {
186  BL_MEMORY_DESCRIPTOR LocalDescriptor = {{0}};
187  PBL_MEMORY_DESCRIPTOR FoundDescriptor, TempDescriptor;
188  PLIST_ENTRY ListHead, NextEntry;
189  BOOLEAN TopDown, GotFwPages;
190  EFI_PHYSICAL_ADDRESS EfiAddress;
191  ULONGLONG LocalEndPage, FoundEndPage, LocalVirtualEndPage;
192 
193  /* Check if any parameters were not passed in correctly */
194  if (!(CurrentList) || !(Request) || (!(NewList) && !(Descriptor)))
195  {
197  }
198 
199  /* Set failure by default */
201 
202  /* Take the head and next entry in the list, as appropriate */
203  ListHead = CurrentList->First;
205  {
206  NextEntry = ListHead->Blink;
207  TopDown = TRUE;
208  }
209  else
210  {
211  NextEntry = ListHead->Flink;
212  TopDown = FALSE;
213  }
214 
215  /* Loop through the list */
216  GotFwPages = FALSE;
217  while (NextEntry != ListHead)
218  {
219  /* Grab a descriptor */
220  FoundDescriptor = CONTAINING_RECORD(NextEntry,
222  ListEntry);
223 
224  /* See if it matches the request */
225  if (MmMdFindSatisfyingRegion(FoundDescriptor,
226  &LocalDescriptor,
227  Request->Pages,
228  &Request->BaseRange,
229  &Request->VirtualRange,
230  TopDown,
231  Request->MemoryType,
232  Request->Flags,
233  Request->Alignment))
234  {
235  break;
236  }
237 
238  /* It doesn't, move to the next appropriate entry */
239  if (TopDown)
240  {
241  NextEntry = NextEntry->Blink;
242  }
243  else
244  {
245  NextEntry = NextEntry->Flink;
246  }
247  }
248 
249  /* Check if we exhausted the list */
250  if (NextEntry == ListHead)
251  {
252  return Status;
253  }
254 
255  /* Copy all the flags that are not request flag */
256  LocalDescriptor.Flags = (Request->Flags & 0xFFFF0000) |
257  (LocalDescriptor.Flags & 0x0000FFFF);
258 
259  /* Are we using the physical memory list, and are we OK with using firmware? */
260  if ((CurrentList == &MmMdlUnmappedUnallocated) &&
261  !((Request->Flags & BlMemoryNonFirmware) ||
262  (LocalDescriptor.Flags & BlMemoryNonFirmware)))
263  {
264  /* Allocate the requested address from EFI */
265  EfiAddress = LocalDescriptor.BasePage << PAGE_SHIFT;
267  (ULONG)LocalDescriptor.PageCount,
268  &EfiAddress);
269  if (!NT_SUCCESS(Status))
270  {
271  EfiPrintf(L"EFI memory allocation failure\r\n");
272  EfiStall(10000000);
273  return Status;
274  }
275 
276  /* Remember we got memory from EFI */
277  GotFwPages = TRUE;
278  }
279 
280  /* Remove the descriptor from the original list it was on */
281  MmMdRemoveDescriptorFromList(CurrentList, FoundDescriptor);
282 
283  /* Get the end pages */
284  LocalEndPage = LocalDescriptor.PageCount + LocalDescriptor.BasePage;
285  FoundEndPage = FoundDescriptor->PageCount + FoundDescriptor->BasePage;
286 
287  /* Are we allocating from the virtual memory list? */
288  if (CurrentList == &MmMdlMappedUnallocated)
289  {
290  /* Check if the region matches perfectly */
291  if ((LocalDescriptor.BasePage == FoundDescriptor->BasePage) &&
292  (LocalEndPage == FoundEndPage))
293  {
294  /* Check if the original descriptor had the flag set */
295  if ((FoundDescriptor->Flags & 0x40000000) && (Descriptor))
296  {
297  /* Make our local one have it too, even if not needed */
298  LocalDescriptor.Flags |= 0x40000000;
299  }
300  }
301  else
302  {
303  /* Write the 'incomplete mapping' flag */
304  FoundDescriptor->Flags |= 0x40000000;
305  if (Descriptor)
306  {
307  /* Including on the local one if there's one passed in */
308  LocalDescriptor.Flags |= 0x40000000;
309  }
310  }
311  }
312 
313  /* Does the memory we received not exactly fall onto the beginning of its descriptor? */
314  if (LocalDescriptor.BasePage != FoundDescriptor->BasePage)
315  {
316  TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
317  FoundDescriptor->Type,
318  FoundDescriptor->BasePage,
319  FoundDescriptor->VirtualPage,
320  LocalDescriptor.BasePage -
321  FoundDescriptor->BasePage);
322  Status = MmMdAddDescriptorToList(CurrentList, TempDescriptor, 0);
323  if (!NT_SUCCESS(Status))
324  {
325  return Status;
326  }
327  }
328 
329  /* Does the memory we received not exactly fall onto the end of its descriptor? */
330  LocalVirtualEndPage = LocalDescriptor.VirtualPage ?
331  LocalDescriptor.VirtualPage + LocalDescriptor.PageCount : 0;
332  if (LocalEndPage != FoundEndPage)
333  {
334  TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
335  FoundDescriptor->Type,
336  LocalEndPage,
337  LocalVirtualEndPage,
338  FoundEndPage - LocalEndPage);
339  Status = MmMdAddDescriptorToList(CurrentList, TempDescriptor, 0);
340  if (!NT_SUCCESS(Status))
341  {
342  return Status;
343  }
344  }
345 
346  /* We got the memory we needed */
348 
349  /* Are we supposed to insert it into a new list? */
350  if (NewList)
351  {
352  /* Copy the allocated region descriptor into the one we found */
353  FoundDescriptor->BaseAddress = LocalDescriptor.BaseAddress;
354  FoundDescriptor->VirtualPage = LocalDescriptor.VirtualPage;
355  FoundDescriptor->PageCount = LocalDescriptor.PageCount;
356  FoundDescriptor->Type = Type;
357  FoundDescriptor->Flags = LocalDescriptor.Flags;
358 
359  /* Remember if it came from EFI */
360  if (GotFwPages)
361  {
362  FoundDescriptor->Flags |= BlMemoryFirmware;
363  }
364 
365  /* Add the descriptor to the requested list */
366  Status = MmMdAddDescriptorToList(NewList, FoundDescriptor, 0);
367  }
368  else
369  {
370  /* Free the descriptor, nobody wants to know about it anymore */
371  MmMdFreeDescriptor(FoundDescriptor);
372  }
373 
374  /* Return the allocation region back */
375  RtlCopyMemory(Descriptor, &LocalDescriptor, sizeof(LocalDescriptor));
376  return Status;
377 }
378 
379 NTSTATUS
383  _In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList,
385  _In_ BL_MEMORY_TYPE MemoryType
386  )
387 {
389 
390  /* Heap and page directory/table pages have a special flag */
391  if ((MemoryType >= BlLoaderHeap) && (MemoryType <= BlLoaderReferencePage))
392  {
393  Request->Flags |= BlMemorySpecial;
394  }
395 
396  /* Try to find a free region of RAM matching this range and request */
397  Request->MemoryType = BlConventionalMemory;
399  Descriptor,
400  CurrentList,
401  Request,
402  MemoryType);
403  if (Status == STATUS_NOT_FOUND)
404  {
405  /* Need to re-synchronize the memory map and check other lists */
406  EfiPrintf(L"No RAM found -- backup plan not yet implemented\r\n");
407  }
408 
409  /* Did we get the region we wanted? */
410  if (NT_SUCCESS(Status))
411  {
412  /* All good, return back */
413  return Status;
414  }
415 
416  /* Are we failing due to some attributes? */
418  {
419  if (Request->Flags & BlMemoryLargePages)
420  {
421  EfiPrintf(L"large alloc fail not yet implemented %lx\r\n", Status);
422  EfiStall(1000000);
423  return STATUS_NOT_IMPLEMENTED;
424  }
425  if (Request->Flags & BlMemoryFixed)
426  {
427  EfiPrintf(L"fixed alloc fail not yet implemented %lx\r\n", Status);
428  EfiStall(1000000);
429  return STATUS_NOT_IMPLEMENTED;
430  }
431  }
432 
433  /* Nope, just fail the entire call */
434  return Status;
435 }
436 
437 NTSTATUS
440  _In_ BL_MEMORY_TYPE MemoryType,
441  _In_ ULONGLONG Pages,
446  _In_ ULONG RangeType
447  )
448 {
452 
453  /* Increase nesting depth */
455 
456  /* Bail out if no address was specified */
457  if (!BaseAddress)
458  {
460  goto Quickie;
461  }
462 
463  /* Bail out if no page count was passed in, or a bad list was specified */
464  if (!(Pages) ||
465  ((NewList != &MmMdlUnmappedAllocated) &&
466  (NewList != &MmMdlPersistentMemory)))
467  {
469  goto Quickie;
470  }
471 
472  /* Bail out if the passed in range is invalid */
473  if ((Range) && (Range->Minimum >= Range->Maximum))
474  {
476  goto Quickie;
477  }
478 
479  /* Adjust alignment as needed */
480  if (!Alignment)
481  {
482  Alignment = 1;
483  }
484 
485  /* Clear the virtual range */
486  Request.VirtualRange.Minimum = 0;
487  Request.VirtualRange.Maximum = 0;
488 
489  /* Check if a fixed allocation was requested*/
491  {
492  /* Force the only available range to be the passed in address */
493  Request.BaseRange.Minimum = BaseAddress->QuadPart >> PAGE_SHIFT;
494  Request.BaseRange.Maximum = Request.BaseRange.Minimum + Pages - 1;
495  }
496  else if (Range)
497  {
498  /* Otherwise, a manual range was specified, use it */
499  Request.BaseRange.Minimum = Range->Minimum >> PAGE_SHIFT;
500  Request.BaseRange.Maximum = Request.BaseRange.Minimum +
501  (Range->Maximum >> PAGE_SHIFT) - 1;
502  }
503  else
504  {
505  /* Otherwise, use any possible range of pages */
506  Request.BaseRange.Minimum = PapMinimumPhysicalPage;
507  Request.BaseRange.Maximum = MAXULONG >> PAGE_SHIFT;
508  }
509 
510  /* Check if no type was specified, or if it was invalid */
511  if (!(RangeType) ||
513  {
514  /* Use default type */
516  }
517  else
518  {
519  /* Use the requested type */
520  Request.Type = RangeType;
521  }
522 
523  /* Capture the other request parameters */
524  Request.Alignment = Alignment;
525  Request.Pages = Pages;
526  Request.Flags = Attributes;
527  Status = MmPaAllocatePages(NewList,
528  &Descriptor,
530  &Request,
531  MemoryType);
532  if (NT_SUCCESS(Status))
533  {
534  /* We got a descriptor back, return its address */
535  BaseAddress->QuadPart = Descriptor.BasePage << PAGE_SHIFT;
536  }
537 
538 Quickie:
539  /* Restore the nesting depth */
542  return Status;
543 }
544 
545 NTSTATUS
549  _In_ ULONGLONG PageCount,
550  _In_ ULONGLONG VirtualPage,
553  )
554 {
556  ULONGLONG PageRange;
558  ULONG AllocationFlags, CacheAttributes, AddFlags;
564 
565  /* Is the caller requesting less pages than allowed? */
566  if (!(Attributes & BlMemoryFixed) &&
567  !(Range) &&
568  (PageCount < PapMinimumAllocationCount))
569  {
570  /* Unless this is a fixed request, then adjust the original requirements */
571  PageCount = PapMinimumAllocationCount;
573  }
574 
575  /* Extract only the allocation attributes */
577 
578  /* Check if the caller wants large pages */
579  if ((AllocationFlags & BlMemoryLargePages) && (MmArchLargePageSize != 1))
580  {
581  EfiPrintf(L"Large pages not supported!\r\n");
582  EfiStall(10000000);
583  return STATUS_NOT_IMPLEMENTED;
584  }
585 
586  /* Set an emty virtual range */
587  Request.VirtualRange.Minimum = 0;
588  Request.VirtualRange.Maximum = 0;
589 
590  /* Check if the caller requested a range */
591  if (Range)
592  {
593  /* Calculate it size in pages, minus a page as this is a 0-based range */
594  PageRange = ((Range->Maximum - Range->Minimum) >> PAGE_SHIFT) - 1;
595 
596  /* Set the minimum and maximum, in pages */
597  Request.BaseRange.Minimum = Range->Minimum >> PAGE_SHIFT;
598  Request.BaseRange.Maximum = Request.BaseRange.Minimum + PageRange;
599  }
600  else
601  {
602  /* Initialize a range from the smallest page to the biggest */
603  Request.BaseRange.Minimum = PapMinimumPhysicalPage;
604  Request.BaseRange.Maximum = 0xFFFFFFFF / PAGE_SIZE;
605  }
606 
607  /* Get the cache attributes */
608  CacheAttributes = Attributes & BlMemoryValidCacheAttributeMask;
609 
610  /* Check if the caller requested a valid allocation type */
611  if ((Type) && !(Type & ~(BL_MM_REQUEST_DEFAULT_TYPE |
613  {
614  /* Use what the caller wanted */
615  Request.Type = Type;
616  }
617  else
618  {
619  /* Use the default bottom-up type */
621  }
622 
623  /* Use the original protection and type, but ignore other attributes */
626  Request.Alignment = Alignment;
627  Request.Pages = PageCount;
628 
629  /* Allocate some free pages */
631  &NewDescriptor,
633  &Request,
635  if (!NT_SUCCESS(Status))
636  {
637  EfiPrintf(L"Failed to get unmapped, unallocated memory!\r\n");
638  EfiStall(10000000);
639  return Status;
640  }
641 
642  /* Initialize a descriptor for these pages, adding in the allocation flags */
643  Descriptor = MmMdInitByteGranularDescriptor(AllocationFlags |
644  NewDescriptor.Flags,
646  NewDescriptor.BasePage,
647  NewDescriptor.VirtualPage,
648  NewDescriptor.PageCount);
649 
650  /* Now map a virtual address for these physical pages */
651  VirtualAddress = (PVOID)((ULONG_PTR)VirtualPage << PAGE_SHIFT);
654  AllocationFlags | CacheAttributes,
655  NewDescriptor.PageCount << PAGE_SHIFT,
657  if (Status == STATUS_SUCCESS)
658  {
659  /* Add the cache attributes now that the mapping worked */
660  Descriptor->Flags |= CacheAttributes;
661 
662  /* Update the virtual page now that we mapped it */
663  Descriptor->VirtualPage = (ULONG_PTR)VirtualAddress >> PAGE_SHIFT;
664 
665  /* Add this as a mapped region */
667  Descriptor,
669 
670  /* Make new descriptor that we'll add in firmware allocation tracker */
671  MdList = &MmMdlFwAllocationTracker;
674  NewDescriptor.BasePage,
675  0,
676  NewDescriptor.PageCount);
677 
678  /* Do not coalesce */
679  AddFlags = 0;
680  }
681  else
682  {
683  /* We failed, free the physical pages */
684  Status = MmFwFreePages(NewDescriptor.BasePage, NewDescriptor.PageCount);
685  if (!NT_SUCCESS(Status))
686  {
687  /* We failed to free the pages, so this is still around */
688  MdList = &MmMdlUnmappedAllocated;
689  }
690  else
691  {
692  /* This is now back to unmapped/unallocated memory */
693  Descriptor->Flags = 0;
694  MdList = &MmMdlUnmappedUnallocated;
695  }
696 
697  /* Coalesce the free descriptor */
699  }
700 
701  /* Either add to firmware list, or to unmapped list, then return result */
702  MmMdAddDescriptorToList(MdList, Descriptor, AddFlags);
703  return Status;
704 }
705 
706 NTSTATUS
709  _In_ BL_MEMORY_TYPE MemoryType,
710  _In_ ULONGLONG Pages,
714  _In_ ULONG Type
715  )
716 {
722 
723  /* Increment nesting depth */
725 
726  /* Default list */
728 
729  /* Check for missing parameters or invalid range */
730  if (!(PhysicalAddress) ||
731  !(Pages) ||
732  ((Range) && (Range->Minimum >= Range->Maximum)))
733  {
735  goto Exit;
736  }
737 
738  /* What translation mode are we using? */
739  if (MmTranslationType != BlNone)
740  {
741  /* Use 1 page alignment if none was requested */
742  if (!Alignment)
743  {
744  Alignment = 1;
745  }
746 
747  /* Check if we got a range */
748  if (Range)
749  {
750  /* We don't support virtual memory yet @TODO */
751  EfiPrintf(L"virt range not yet implemented in %S\r\n", __FUNCTION__);
752  EfiStall(1000000);
754  goto Exit;
755  }
756  else
757  {
758  /* Use the entire range that's possible */
759  Request.BaseRange.Minimum = PapMinimumPhysicalPage;
760  Request.BaseRange.Maximum = 0xFFFFFFFF >> PAGE_SHIFT;
761  }
762 
763  /* Check if a fixed allocation was requested */
765  {
766  /* We don't support virtual memory yet @TODO */
767  EfiPrintf(L"fixed not yet implemented in %S\r\n", __FUNCTION__);
768  EfiStall(1000000);
770  goto Exit;
771  }
772  else
773  {
774  /* Check if kernel range was specifically requested */
776  {
777  /* Use the kernel range */
778  Request.VirtualRange.Minimum = MmArchKsegAddressRange.Minimum >> PAGE_SHIFT;
779  Request.VirtualRange.Maximum = MmArchKsegAddressRange.Maximum >> PAGE_SHIFT;
780  }
781  else
782  {
783  /* Set the virtual address range */
784  Request.VirtualRange.Minimum = 0;
785  Request.VirtualRange.Maximum = 0xFFFFFFFF >> PAGE_SHIFT;
786  }
787  }
788 
789  /* Check what type of allocation was requested */
790  if ((Type) && !(Type & ~(BL_MM_REQUEST_DEFAULT_TYPE |
792  {
793  /* Save it if it was valid */
794  Request.Type = Type;
795  }
796  else
797  {
798  /* Set the default */
800  }
801 
802  /* Fill out the request of the request */
803  Request.Flags = Attributes;
804  Request.Alignment = Alignment;
805  Request.Pages = Pages;
806 
807  /* Try to allocate the pages */
809  &Descriptor,
811  &Request,
812  MemoryType);
813  if (!NT_SUCCESS(Status))
814  {
815  /* Extend the physical allocator */
817  Alignment,
818  Pages,
820  PAGE_SHIFT,
821  Range,
822  Type);
823  if (!NT_SUCCESS(Status))
824  {
825  /* Fail since we're out of memory */
826  EfiPrintf(L"EXTEND OUT OF MEMORY: %lx\r\n", Status);
828  goto Exit;
829  }
830 
831  /* Try the allocation again now */
833  &Descriptor,
835  &Request,
836  MemoryType);
837  if (!NT_SUCCESS(Status))
838  {
839  /* Fail since we're out of memory */
840  EfiPrintf(L"PALLOC OUT OF MEMORY: %lx\r\n", Status);
841  goto Exit;
842  }
843  }
844 
845  /* Return the allocated address */
846  *PhysicalAddress = (PVOID)((ULONG_PTR)Descriptor.VirtualPage << PAGE_SHIFT);
847  }
848  else
849  {
850  /* Check if this is a fixed allocation */
851  BaseAddress.QuadPart = (Attributes & BlMemoryFixed) ?
853 
854  /* Allocate the pages */
856  MemoryType,
857  Pages,
858  Attributes,
859  Alignment,
864  Range,
865  Type);
866 
867  /* Return the allocated address */
869  }
870 
871 Exit:
872  /* Restore the nesting depth */
875  return Status;
876 }
877 
878 NTSTATUS
880  __in PBL_MEMORY_DATA BootMemoryData,
881  __in ULONG MinimumAllocationCount
882  )
883 {
885  ULONG ExistingDescriptors, FinalOffset;
887 
888  /* Initialize physical allocator variables */
889  PapMaximumPhysicalPage = 0xFFFFFFFFFFFFF;
890  PapMinimumAllocationCount = MinimumAllocationCount;
892 
893  /* Initialize all the lists */
904 
905  /* Get the BIOS memory map */
909  if (NT_SUCCESS(Status))
910  {
911 #if 0
912  PLIST_ENTRY listHead, nextEntry;
913 
914  /* Loop the NT firmware memory list */
915  EfiPrintf(L"NT MEMORY MAP\n\r\n");
917  nextEntry = listHead->Flink;
918  while (listHead != nextEntry)
919  {
920  Descriptor = CONTAINING_RECORD(nextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
921 
922  EfiPrintf(L"Type: %08lX Flags: %08lX Base: 0x%016I64X End: 0x%016I64X\r\n",
923  Descriptor->Type,
924  Descriptor->Flags,
925  Descriptor->BasePage << PAGE_SHIFT,
926  (Descriptor->BasePage + Descriptor->PageCount) << PAGE_SHIFT);
927 
928  nextEntry = nextEntry->Flink;
929  }
930 #endif
931 
932  /*
933  * Because BL supports cross x86-x64 application launches and a LIST_ENTRY
934  * is of variable size, care must be taken here to ensure that we see a
935  * consistent view of descriptors. BL uses some offset magic to figure out
936  * where the data actually starts, since everything is ULONGLONG past the
937  * LIST_ENTRY itself
938  */
939  FinalOffset = BootMemoryData->MdListOffset + BootMemoryData->DescriptorOffset;
940  Descriptor = (PBL_MEMORY_DESCRIPTOR)((ULONG_PTR)BootMemoryData + FinalOffset -
942 
943  /* Scan all of them */
944  ExistingDescriptors = BootMemoryData->DescriptorCount;
945  while (ExistingDescriptors != 0)
946  {
947  /* Remove this region from our free memory MDL */
948  //EfiPrintf(L"Handling existing descriptor: %llx %llx\r\n", Descriptor->BasePage, Descriptor->PageCount);
951  Descriptor->BasePage,
952  Descriptor->PageCount,
953  NULL);
954  if (!NT_SUCCESS(Status))
955  {
957  }
958 
959  /* Build a descriptor for it */
961  Descriptor->Type,
962  Descriptor->BasePage,
963  Descriptor->VirtualPage,
964  Descriptor->PageCount);
965  if (!NewDescriptor)
966  {
967  return STATUS_NO_MEMORY;
968  }
969 
970  /* And add this region to the reserved & allocated MDL */
972  if (!NT_SUCCESS(Status))
973  {
974  return Status;
975  }
976 
977  /* Move on to the next descriptor */
978  ExistingDescriptors--;
979  Descriptor = (PBL_MEMORY_DESCRIPTOR)((ULONG_PTR)Descriptor + BootMemoryData->DescriptorSize);
980  }
981 
982  /* We are done, so check for any RAM constraints which will make us truncate memory */
984  if (NT_SUCCESS(Status))
985  {
986  /* The Page Allocator has initialized */
989  }
990  }
991 
992  /* Return status */
993  return Status;
994 }
995 
996 NTSTATUS
999  _In_ BL_MEMORY_TYPE MemoryType,
1000  _In_ ULONGLONG PageCount,
1003  )
1004 {
1005  /* Call the physical allocator */
1007  MemoryType,
1008  PageCount,
1009  Attributes,
1010  Alignment,
1012  NULL,
1013  0);
1014 }
1015 
1016 NTSTATUS
1018  _In_ ULONG WhichList,
1019  _In_ ULONGLONG PageCount,
1021  )
1022 {
1024  ULONGLONG Page;
1025  ULONG DescriptorFlags, Flags;
1026  BOOLEAN DontFree, HasPageData;
1027  BL_LIBRARY_PARAMETERS LibraryParameters;
1028  NTSTATUS Status;
1029 
1030  /* Set some defaults */
1032  DontFree = FALSE;
1033  HasPageData = FALSE;
1034 
1035  /* Only page-aligned addresses are accepted */
1036  if (Address.QuadPart & (PAGE_SIZE - 1))
1037  {
1038  EfiPrintf(L"free mem fail 1\r\n");
1039  return STATUS_INVALID_PARAMETER;
1040  }
1041 
1042  /* Try to find the descriptor containing this address */
1043  Page = Address.QuadPart >> PAGE_SHIFT;
1044  Descriptor = MmMdFindDescriptor(WhichList,
1046  Page);
1047  if (!Descriptor)
1048  {
1049  EfiPrintf(L"free mem fail 2\r\n");
1050  return STATUS_INVALID_PARAMETER;
1051  }
1052 
1053  /* If a page count was given, it must match, unless it's coalesced */
1054  DescriptorFlags = Descriptor->Flags;
1055  if (!(DescriptorFlags & BlMemoryCoalesced) &&
1056  (PageCount) && (PageCount != Descriptor->PageCount))
1057  {
1058  EfiPrintf(L"free mem fail 3\r\n");
1059  return STATUS_INVALID_PARAMETER;
1060  }
1061 
1062  /* Check if this is persistent memory in teardown status */
1063  if ((PapInitializationStatus == 2) &&
1064  (DescriptorFlags & BlMemoryPersistent))
1065  {
1066  /* Then we should keep it */
1067  DontFree = TRUE;
1068  }
1069  else
1070  {
1071  /* Mark it as non-persistent, since we're freeing it */
1072  Descriptor->Flags &= ~BlMemoryPersistent;
1073  }
1074 
1075  /* Check if this memory contains paging data */
1076  if ((Descriptor->Type == BlLoaderPageDirectory) ||
1077  (Descriptor->Type == BlLoaderReferencePage))
1078  {
1079  HasPageData = TRUE;
1080  }
1081 
1082  /* Check if a page count was given */
1083  if (PageCount)
1084  {
1085  /* The pages must fit within the descriptor */
1086  if ((PageCount + Page - Descriptor->BasePage) > Descriptor->PageCount)
1087  {
1088  EfiPrintf(L"free mem fail 4\r\n");
1089  return STATUS_INVALID_PARAMETER;
1090  }
1091  }
1092  else
1093  {
1094  /* No page count given, so the address must be at the beginning then */
1095  if (Descriptor->BasePage != Page)
1096  {
1097  EfiPrintf(L"free mem fail 5\r\n");
1098  return STATUS_INVALID_PARAMETER;
1099  }
1100 
1101  /* And we'll use the page count in the descriptor */
1102  PageCount = Descriptor->PageCount;
1103  }
1104 
1105  /* Copy library parameters since we will read them */
1106  RtlCopyMemory(&LibraryParameters,
1108  sizeof(LibraryParameters));
1109 
1110  /* Check if this is teardown */
1111  if (PapInitializationStatus == 2)
1112  {
1113  EfiPrintf(L"Case 2 not yet handled!\r\n");
1114  return STATUS_NOT_SUPPORTED;
1115  }
1116  else if (!DontFree)
1117  {
1118  /* Caller wants memory to be freed -- should we zero it? */
1119  if (!(HasPageData) &&
1120  (LibraryParameters.LibraryFlags &
1122  {
1123  EfiPrintf(L"Freeing zero data not yet handled!\r\n");
1124  return STATUS_NOT_SUPPORTED;
1125  }
1126  }
1127 
1128  /* Now call into firmware to actually free the physical pages */
1129  Status = MmFwFreePages(Page, PageCount);
1130  if (!NT_SUCCESS(Status))
1131  {
1132  EfiPrintf(L"free mem fail 6\r\n");
1133  return Status;
1134  }
1135 
1136  /* Remove the firmware flags */
1137  Descriptor->Flags &= ~(BlMemoryNonFirmware |
1140 
1141  /* If we're not actually freeing, don't coalesce with anyone nearby */
1142  if (DontFree)
1143  {
1145  }
1146 
1147  /* Check if the entire allocation is being freed */
1148  if (PageCount == Descriptor->PageCount)
1149  {
1150  /* Remove the descriptor from the allocated list */
1152 
1153  /* Mark the entire descriptor as free */
1155  }
1156  else
1157  {
1158  /* Init a descriptor for what we're actually freeing */
1161  Page,
1162  0,
1163  PageCount);
1164  if (!Descriptor)
1165  {
1166  return STATUS_NO_MEMORY;
1167  }
1168 
1169  /* Remove the region from the existing descriptor */
1172  Page,
1173  PageCount,
1174  NULL);
1175  if (!NT_SUCCESS(Status))
1176  {
1177  return Status;
1178  }
1179  }
1180 
1181  /* Add the new descriptor into in the list (or the old, repurposed one) */
1182  Descriptor->Flags &= ~BlMemoryCoalesced;
1184 }
1185 
1186 NTSTATUS
1189  )
1190 {
1191  /* Call the physical allocator */
1193 }
1194 
1195 NTSTATUS
1197  _In_ PVOID Address,
1198  _In_ ULONG WhichList
1199  )
1200 {
1202 
1203  /* Handle virtual memory scenario */
1204  if (MmTranslationType != BlNone)
1205  {
1206  EfiPrintf(L"Unimplemented free virtual path: %p %lx\r\n", Address, WhichList);
1207  return STATUS_SUCCESS;
1208  }
1209 
1210  /* Physical memory should be in the unmapped allocated list */
1211  if (WhichList != BL_MM_INCLUDE_PERSISTENT_MEMORY)
1212  {
1214  }
1215 
1216  /* Free it from there */
1218  return MmPapFreePhysicalPages(WhichList, 0, PhysicalAddress);
1219 }
1220 
1221 NTSTATUS
1224  _In_ PBL_BUFFER_DESCRIPTOR MemoryParameters,
1225  _In_ ULONG WhichTypes,
1226  _In_ ULONG Flags
1227  )
1228 {
1229  BL_MEMORY_DESCRIPTOR_LIST FirmwareMdList, FullMdList;
1230  BOOLEAN DoFirmware, DoPersistent, DoTruncated, DoBad;
1231  BOOLEAN DoReserved, DoUnmapUnalloc, DoUnmapAlloc;
1232  BOOLEAN DoMapAlloc, DoMapUnalloc, DoFirmware2;
1233  ULONG LoopCount, MdListCount, MdListSize, Used;
1234  NTSTATUS Status;
1235 
1236  /* Initialize the firmware list if we use it */
1237  MmMdInitializeListHead(&FirmwareMdList);
1238 
1239  /* Make sure we got our input parameters */
1240  if (!(MemoryMap) || !(MemoryParameters))
1241  {
1242  return STATUS_INVALID_PARAMETER;
1243  }
1244 
1245  /* Either ask for firmware memory, or don't. Not neither */
1246  if ((WhichTypes & ~BL_MM_INCLUDE_NO_FIRMWARE_MEMORY) &&
1247  (WhichTypes & ~BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY))
1248  {
1249  return STATUS_INVALID_PARAMETER;
1250  }
1251 
1252  /* Either ask for firmware memory, or don't. Not both */
1253  if ((WhichTypes & BL_MM_INCLUDE_NO_FIRMWARE_MEMORY) &&
1254  (WhichTypes & BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY))
1255  {
1256  return STATUS_INVALID_PARAMETER;
1257  }
1258 
1259  /* Initialize the memory map list */
1261 
1262  /* Check which types of memory to dump */
1263  DoFirmware = WhichTypes & BL_MM_INCLUDE_FIRMWARE_MEMORY;
1264  DoPersistent = WhichTypes & BL_MM_INCLUDE_PERSISTENT_MEMORY;
1265  DoTruncated = WhichTypes & BL_MM_INCLUDE_TRUNCATED_MEMORY;
1266  DoBad = WhichTypes & BL_MM_INCLUDE_BAD_MEMORY;
1267  DoReserved = WhichTypes & BL_MM_INCLUDE_RESERVED_ALLOCATED;
1268  DoUnmapUnalloc = WhichTypes & BL_MM_INCLUDE_UNMAPPED_UNALLOCATED;
1269  DoUnmapAlloc = WhichTypes & BL_MM_INCLUDE_UNMAPPED_ALLOCATED;
1270  DoMapAlloc = WhichTypes & BL_MM_INCLUDE_MAPPED_ALLOCATED;
1271  DoMapUnalloc = WhichTypes & BL_MM_INCLUDE_MAPPED_UNALLOCATED;
1272  DoFirmware2 = WhichTypes & BL_MM_INCLUDE_FIRMWARE_MEMORY_2;
1273 
1274  /* Begin the attempt loop */
1275  LoopCount = 0;
1276  while (TRUE)
1277  {
1278  /* Count how many entries we will need */
1279  MdListCount = 0;
1280  if (DoMapAlloc) MdListCount = MmMdCountList(&MmMdlMappedAllocated);
1281  if (DoMapUnalloc) MdListCount += MmMdCountList(&MmMdlMappedUnallocated);
1282  if (DoUnmapAlloc) MdListCount += MmMdCountList(&MmMdlUnmappedAllocated);
1283  if (DoUnmapUnalloc) MdListCount += MmMdCountList(&MmMdlUnmappedUnallocated);
1284  if (DoReserved) MdListCount += MmMdCountList(&MmMdlReservedAllocated);
1285  if (DoBad) MdListCount += MmMdCountList(&MmMdlBadMemory);
1286  if (DoTruncated) MdListCount += MmMdCountList(&MmMdlTruncatedMemory);
1287  if (DoPersistent) MdListCount += MmMdCountList(&MmMdlPersistentMemory);
1288 
1289  /* Plus firmware entries */
1290  if (DoFirmware)
1291  {
1292  /* Free the previous entries, if any */
1293  MmMdFreeList(&FirmwareMdList);
1294 
1295  /* Get the firmware map, coalesced */
1296  Status = MmFwGetMemoryMap(&FirmwareMdList,
1298  if (!NT_SUCCESS(Status))
1299  {
1300  goto Quickie;
1301  }
1302 
1303  /* We overwrite, since this type is exclusive */
1304  MdListCount = MmMdCountList(&FirmwareMdList);
1305  }
1306 
1307  /* Plus firmware entries-2 */
1308  if (DoFirmware2)
1309  {
1310  /* Free the previous entries, if any */
1311  MmMdFreeList(&FirmwareMdList);
1312 
1313  /* Get the firmware map, uncoalesced */
1314  Status = MmFwGetMemoryMap(&FirmwareMdList, 0);
1315  if (!NT_SUCCESS(Status))
1316  {
1317  goto Quickie;
1318  }
1319 
1320  /* We overwrite, since this type is exclusive */
1321  MdListCount = MmMdCountList(&FirmwareMdList);
1322  }
1323 
1324  /* If there's no descriptors, we're done */
1325  if (!MdListCount)
1326  {
1328  goto Quickie;
1329  }
1330 
1331  /* Check if the buffer we have is big enough */
1332  if (MemoryParameters->BufferSize >=
1333  (sizeof(BL_MEMORY_DESCRIPTOR) * MdListCount))
1334  {
1335  break;
1336  }
1337 
1338  /* It's not, allocate it, with a slack of 4 extra descriptors */
1339  MdListSize = sizeof(BL_MEMORY_DESCRIPTOR) * (MdListCount + 4);
1340 
1341  /* Except if we weren't asked to */
1343  {
1344  MemoryParameters->BufferSize = MdListSize;
1346  goto Quickie;
1347  }
1348 
1349  /* Has it been less than 4 times we've tried this? */
1350  if (++LoopCount <= 4)
1351  {
1352  /* Free the previous attempt, if any */
1353  if (MemoryParameters->BufferSize)
1354  {
1355  BlMmFreeHeap(MemoryParameters->Buffer);
1356  }
1357 
1358  /* Allocate a new buffer */
1359  MemoryParameters->BufferSize = MdListSize;
1360  MemoryParameters->Buffer = BlMmAllocateHeap(MdListSize);
1361  if (MemoryParameters->Buffer)
1362  {
1363  /* Try again */
1364  continue;
1365  }
1366  }
1367 
1368  /* If we got here, we're out of memory after 4 attempts */
1370  goto Quickie;
1371  }
1372 
1373  /* We should have a buffer by now... */
1374  if (MemoryParameters->Buffer)
1375  {
1376  /* Zero it out */
1377  RtlZeroMemory(MemoryParameters->Buffer,
1378  MdListCount * sizeof(BL_MEMORY_DESCRIPTOR));
1379  }
1380 
1381  /* Initialize our list of descriptors */
1382  MmMdInitializeList(&FullMdList, 0, MemoryMap);
1383  Used = 0;
1384 
1385  /* Handle mapped, allocated */
1386  if (DoMapAlloc)
1387  {
1388  Status = MmMdCopyList(&FullMdList,
1390  MemoryParameters->Buffer,
1391  &Used,
1392  MdListCount,
1393  Flags);
1394  }
1395 
1396  /* Handle mapped, unallocated */
1397  if (DoMapUnalloc)
1398  {
1399  Status = MmMdCopyList(&FullMdList,
1401  MemoryParameters->Buffer,
1402  &Used,
1403  MdListCount,
1404  Flags);
1405  }
1406 
1407  /* Handle unmapped, allocated */
1408  if (DoUnmapAlloc)
1409  {
1410  Status = MmMdCopyList(&FullMdList,
1412  MemoryParameters->Buffer,
1413  &Used,
1414  MdListCount,
1415  Flags);
1416  }
1417 
1418  /* Handle unmapped, unallocated */
1419  if (DoUnmapUnalloc)
1420  {
1421  Status = MmMdCopyList(&FullMdList,
1423  MemoryParameters->Buffer,
1424  &Used,
1425  MdListCount,
1426  Flags);
1427  }
1428 
1429  /* Handle reserved, allocated */
1430  if (DoReserved)
1431  {
1432  Status = MmMdCopyList(&FullMdList,
1434  MemoryParameters->Buffer,
1435  &Used,
1436  MdListCount,
1437  Flags);
1438  }
1439 
1440  /* Handle bad */
1441  if (DoBad)
1442  {
1443  Status = MmMdCopyList(&FullMdList,
1444  &MmMdlBadMemory,
1445  MemoryParameters->Buffer,
1446  &Used,
1447  MdListCount,
1448  Flags);
1449  }
1450 
1451  /* Handle truncated */
1452  if (DoTruncated)
1453  {
1454  Status = MmMdCopyList(&FullMdList,
1456  MemoryParameters->Buffer,
1457  &Used,
1458  MdListCount,
1459  Flags);
1460  }
1461 
1462  /* Handle persistent */
1463  if (DoPersistent)
1464  {
1465  Status = MmMdCopyList(&FullMdList,
1467  MemoryParameters->Buffer,
1468  &Used,
1469  MdListCount,
1470  Flags);
1471  }
1472 
1473  /* Handle firmware */
1474  if (DoFirmware)
1475  {
1476  Status = MmMdCopyList(&FullMdList,
1477  &FirmwareMdList,
1478  MemoryParameters->Buffer,
1479  &Used,
1480  MdListCount,
1481  Flags);
1482  }
1483 
1484  /* Handle firmware2 */
1485  if (DoFirmware2)
1486  {
1487  Status = MmMdCopyList(&FullMdList,
1488  &FirmwareMdList,
1489  MemoryParameters->Buffer,
1490  &Used,
1491  MdListCount,
1492  Flags);
1493  }
1494 
1495  /* Add up the final size */
1496  Status = RtlULongLongToULong(Used * sizeof(BL_MEMORY_DESCRIPTOR),
1497  &MemoryParameters->ActualSize);
1498 
1499 Quickie:
1500  MmMdFreeList(&FirmwareMdList);
1501  return Status;
1502 }
1503 
1504 NTSTATUS
1507  )
1508 {
1510  ULONGLONG BasePage;
1511  NTSTATUS Status;
1512 
1513  /* Only page-aligned addresses are accepted */
1514  if (Address.QuadPart & (PAGE_SIZE - 1))
1515  {
1516  EfiPrintf(L"free mem fail 1\r\n");
1517  return STATUS_INVALID_PARAMETER;
1518  }
1519 
1520  /* Get the base page, and find a descriptor that matches */
1521  BasePage = Address.QuadPart >> PAGE_SHIFT;
1524  BasePage);
1525  if (!(Descriptor) || (Descriptor->BasePage != BasePage))
1526  {
1527  return STATUS_INVALID_PARAMETER;
1528  }
1529 
1530  /* Free the physical pages */
1531  Status = MmFwFreePages(BasePage, Descriptor->PageCount);
1532  if (!NT_SUCCESS(Status))
1533  {
1534  return Status;
1535  }
1536 
1537  /* Remove the firmware flags */
1538  Descriptor->Flags &= ~(BlMemoryNonFirmware |
1541 
1542  /* Set it as free memory */
1544 
1545  /* Create a new descriptor that's free memory, covering the old range */
1548  BasePage,
1549  0,
1550  Descriptor->PageCount);
1551  if (!Descriptor)
1552  {
1553  return STATUS_NO_MEMORY;
1554  }
1555 
1556  /* Insert it into the virtual free list */
1558  Descriptor,
1561 }
1562 
1563 NTSTATUS
1566  _In_ ULONG Alignment,
1567  _In_ ULONG PageCount
1568  )
1569 {
1570  NTSTATUS Status;
1573 
1574  /* Increment descriptor usage count */
1576 
1577  /* Bail if we don't have an address */
1578  if (!PhysicalAddress)
1579  {
1581  goto Quickie;
1582  }
1583 
1584  /* Make a request for the required number of self-map pages */
1585  Request.BaseRange.Minimum = PapMinimumPhysicalPage;
1586  Request.BaseRange.Maximum = 0xFFFFFFFF >> PAGE_SHIFT;
1587  Request.VirtualRange.Minimum = 0;
1588  Request.VirtualRange.Maximum = 0;
1589  Request.Pages = PageCount;
1590  Request.Alignment = Alignment;
1592  Request.Flags = 0;;
1594  &Descriptor,
1596  &Request,
1597  BlLoaderSelfMap);
1598  if (!NT_SUCCESS(Status))
1599  {
1600  goto Quickie;
1601  }
1602 
1603  /* Remove this region from free virtual memory */
1606  Descriptor.BasePage,
1607  Descriptor.PageCount,
1608  0);
1609  if (!NT_SUCCESS(Status))
1610  {
1611  goto Quickie;
1612  }
1613 
1614  /* Return the physical address */
1616 
1617 Quickie:
1618  /* Free global descriptors and reduce the count by one */
1621  return Status;
1622 }
1623 
1624 NTSTATUS
1626  _Out_ PVOID* MappingAddress,
1627  _In_ PVOID PreferredAddress,
1630  _In_ ULONG Flags,
1632  )
1633 {
1635  NTSTATUS Status;
1637 
1638  /* Are we in physical mode? */
1639  if (MmTranslationType == BlNone)
1640  {
1641  /* Just return the physical address as the mapping address */
1642  PreferredAddress = PhysicalAddressToPtr(PhysicalAddress);
1643  goto Success;
1644  }
1645 
1646  /* If no physical address, or caller wants a fixed address... */
1647  if ((PhysicalAddress.QuadPart == -1) || (Flags & BlMemoryFixed))
1648  {
1649  /* Then just return the preferred address */
1650  goto Success;
1651  }
1652 
1653  /* Check which range of virtual memory should be used */
1655  {
1656  /* Use kernel range */
1657  Request.BaseRange.Minimum = MmArchKsegAddressRange.Minimum >> PAGE_SHIFT;
1658  Request.BaseRange.Maximum = MmArchKsegAddressRange.Maximum >> PAGE_SHIFT;
1660  }
1661  else
1662  {
1663  /* User user/application range */
1664  Request.BaseRange.Minimum = 0 >> PAGE_SHIFT;
1665  Request.BaseRange.Maximum = MmArchTopOfApplicationAddressSpace >> PAGE_SHIFT;
1667  }
1668 
1669  /* Build a request */
1670  Request.VirtualRange.Minimum = 0;
1671  Request.VirtualRange.Maximum = 0;
1673  Request.Alignment = 1;
1675 
1676  /* Allocate the physical pages */
1678  &NewDescriptor,
1680  &Request,
1682  if (!NT_SUCCESS(Status))
1683  {
1684  return Status;
1685  }
1686 
1687  /* Return the address we got back */
1688  PreferredAddress = (PVOID)((ULONG_PTR)NewDescriptor.BasePage << PAGE_SHIFT);
1689 
1690  /* Check if the existing physical address was not aligned */
1691  if (PhysicalAddress.QuadPart != -1)
1692  {
1693  /* Add the offset to the returned virtual address */
1694  PreferredAddress = (PVOID)((ULONG_PTR)PreferredAddress +
1696  }
1697 
1698 Success:
1699  /* Return the mapping address and success */
1700  *MappingAddress = PreferredAddress;
1701  return STATUS_SUCCESS;
1702 }
#define BL_MM_REQUEST_TOP_DOWN_TYPE
Definition: bl.h:123
BL_MEMORY_DESCRIPTOR_LIST MmMdlCompleteBadMemory
Definition: pagealloc.c:44
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
BL_LIBRARY_PARAMETERS BlpLibraryParameters
Definition: bootlib.c:15
PWCHAR MmMdListPointerToName(_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList)
Definition: pagealloc.c:152
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define BL_MM_INCLUDE_PERSISTENT_MEMORY
Definition: bl.h:105
VOID MmMdFreeList(_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList)
Definition: descriptor.c:356
NTSTATUS BlMmMapPhysicalAddressEx(_In_ PVOID *VirtualAddress, _In_ ULONG Attributes, _In_ ULONGLONG Size, _In_ PHYSICAL_ADDRESS PhysicalAddress)
Definition: mm.c:192
Type
Definition: Type.h:6
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG AllocationAttributes
Definition: mmfuncs.h:360
NTSTATUS EfiStall(_In_ ULONG StallTime)
Definition: firmware.c:1003
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
NTSTATUS BlMmAllocatePhysicalPages(_In_ PPHYSICAL_ADDRESS Address, _In_ BL_MEMORY_TYPE MemoryType, _In_ ULONGLONG PageCount, _In_ ULONG Attributes, _In_ ULONG Alignment)
Definition: pagealloc.c:997
FORCEINLINE VOID MmMdInitializeListHead(_In_ PBL_MEMORY_DESCRIPTOR_LIST List)
Definition: bl.h:1377
ULONGLONG PapMinimumPhysicalPage
Definition: pagealloc.c:29
BOOLEAN PapInitializationStatus
Definition: pagealloc.c:33
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
ULONG MmMdCountList(_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList)
Definition: descriptor.c:205
LONG NTSTATUS
Definition: precomp.h:26
struct _BL_MEMORY_DESCRIPTOR BL_MEMORY_DESCRIPTOR
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedAllocated
Definition: pagealloc.c:35
NTSTATUS MmMdAddDescriptorToList(_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor, _In_ ULONG Flags)
Definition: descriptor.c:582
#define BL_MM_ADD_DESCRIPTOR_ALLOCATE_FLAG
Definition: bl.h:94
ULONG_PTR MmArchTopOfApplicationAddressSpace
Definition: mmx86.c:30
#define BL_MM_REMOVE_PHYSICAL_REGION_FLAG
Definition: bl.h:125
NTSTATUS MmPaInitialize(__in PBL_MEMORY_DATA BootMemoryData, __in ULONG MinimumAllocationCount)
Definition: pagealloc.c:879
NTSTATUS BlMmFreePhysicalPages(_In_ PHYSICAL_ADDRESS Address)
Definition: pagealloc.c:1187
uint16_t * PWCHAR
Definition: typedefs.h:54
#define BL_MM_REMOVE_VIRTUAL_REGION_FLAG
Definition: bl.h:126
#define BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
Definition: bl.h:90
_In_opt_ PSECURITY_DESCRIPTOR _Out_ PSECURITY_DESCRIPTOR * NewDescriptor
Definition: sefuncs.h:29
NTSTATUS BlMmFreeHeap(_In_ PVOID Buffer)
Definition: heapalloc.c:663
NTSTATUS EfiAllocatePages(_In_ ULONG Type, _In_ ULONG Pages, _Inout_ EFI_PHYSICAL_ADDRESS *Memory)
Definition: firmware.c:1568
NTSTATUS MmFwFreePages(_In_ ULONG BasePage, _In_ ULONG PageCount)
Definition: fwutil.c:28
NTSTATUS MmMdCopyList(_In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList, _In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList, _In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor, _Out_ PULONG ActualCount, _In_ ULONG Count, _In_ ULONG Flags)
Definition: descriptor.c:249
#define BL_MM_INCLUDE_RESERVED_ALLOCATED
Definition: bl.h:101
#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)
NTSTATUS BlGetBootOptionInteger(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PULONGLONG Value)
Definition: bcdopt.c:467
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:52
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry
Definition: bootlib.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:63
NTSTATUS MmSelectMappingAddress(_Out_ PVOID *MappingAddress, _In_ PVOID PreferredAddress, _In_ ULONGLONG Size, _In_ ULONG AllocationAttributes, _In_ ULONG Flags, _In_ PHYSICAL_ADDRESS PhysicalAddress)
Definition: pagealloc.c:1625
_In_ NDIS_HANDLE _In_ PNDIS_REQUEST Request
Definition: ndis.h:5173
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedUnallocated
Definition: pagealloc.c:36
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
NTSTATUS MmPaReserveSelfMapPages(_Inout_ PPHYSICAL_ADDRESS PhysicalAddress, _In_ ULONG Alignment, _In_ ULONG PageCount)
Definition: pagealloc.c:1564
BL_MEMORY_TYPE Type
Definition: bl.h:842
VOID MmMdRemoveDescriptorFromList(_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, _In_ PBL_MEMORY_DESCRIPTOR Entry)
Definition: descriptor.c:338
struct _BL_MEMORY_DESCRIPTOR * PBL_MEMORY_DESCRIPTOR
PBL_BCD_OPTION BcdData
Definition: bl.h:868
ULONG LibraryFlags
Definition: bl.h:758
BL_TRANSLATION_TYPE MmTranslationType
Definition: mm.c:17
union Alignment_ Alignment
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
PVOID BlMmAllocateHeap(_In_ SIZE_T Size)
Definition: heapalloc.c:569
BL_MEMORY_DESCRIPTOR_LIST MmMdlFwAllocationTracker
Definition: pagealloc.c:37
#define _Out_
Definition: no_sal2.h:323
ULONGLONG PageCount
Definition: bl.h:840
void * PVOID
Definition: retypes.h:9
NTSTATUS MmPaAllocatePages(_In_ PBL_MEMORY_DESCRIPTOR_LIST NewList, _In_ PBL_MEMORY_DESCRIPTOR Descriptor, _In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList, _In_ PBL_PA_REQUEST Request, _In_ BL_MEMORY_TYPE MemoryType)
Definition: pagealloc.c:380
PBL_MEMORY_DESCRIPTOR MmMdInitByteGranularDescriptor(_In_ ULONG Flags, _In_ BL_MEMORY_TYPE Type, _In_ ULONGLONG BasePage, _In_ ULONGLONG VirtualPage, _In_ ULONGLONG PageCount)
Definition: descriptor.c:377
BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedAllocated
Definition: pagealloc.c:38
ULONGLONG PapMaximumPhysicalPage
Definition: pagealloc.c:29
BL_MEMORY_DESCRIPTOR_LIST MmMdlPersistentMemory
Definition: pagealloc.c:43
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
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define BL_MM_INCLUDE_MAPPED_ALLOCATED
Definition: bl.h:97
#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
#define STATUS_NOT_FOUND
Definition: shellext.h:67
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
LIST_ENTRY ListHead
Definition: bl.h:1007
ULONGLONG Maximum
Definition: bl.h:1016
NTSTATUS MmFwGetMemoryMap(_Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap, _In_ ULONG Flags)
Definition: firmware.c:1845
LIST_ENTRY List
Definition: psmgr.c:57
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG PapMinimumAllocationCount
Definition: pagealloc.c:31
Definition: bl.h:231
uint64_t ULONGLONG
Definition: typedefs.h:65
static void Exit(void)
Definition: sock.c:1331
ULONGLONG Pages
Definition: pagealloc.c:19
BL_MEMORY_DESCRIPTOR_LIST MmMdlTruncatedMemory
Definition: pagealloc.c:42
#define PAGE_ALIGN(Va)
#define BL_MM_INCLUDE_FIRMWARE_MEMORY
Definition: bl.h:103
#define _Inout_
Definition: no_sal2.h:244
struct _BL_PA_REQUEST BL_PA_REQUEST
#define BL_LIBRARY_FLAG_ZERO_HEAP_ALLOCATIONS_ON_FREE
Definition: bl.h:131
NTSTATUS MmPapFreePhysicalPages(_In_ ULONG WhichList, _In_ ULONGLONG PageCount, _In_ PHYSICAL_ADDRESS Address)
Definition: pagealloc.c:1017
struct _BL_PA_REQUEST * PBL_PA_REQUEST
enum _BL_MEMORY_TYPE BL_MEMORY_TYPE
NTSTATUS MmPapAllocatePagesInRange(_Inout_ PVOID *PhysicalAddress, _In_ BL_MEMORY_TYPE MemoryType, _In_ ULONGLONG Pages, _In_ ULONG Attributes, _In_ ULONG Alignment, _In_opt_ PBL_ADDRESS_RANGE Range, _In_ ULONG Type)
Definition: pagealloc.c:707
VOID MmMdFreeGlobalDescriptors(VOID)
Definition: descriptor.c:1332
ULONG Alignment
Definition: pagealloc.c:21
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1060
BL_MEMORY_DESCRIPTOR_LIST MmMdlBadMemory
Definition: pagealloc.c:41
#define BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG
Definition: bl.h:92
ULONG MmArchLargePageSize
Definition: mmx86.c:28
static const WCHAR L[]
Definition: oid.c:1250
#define BL_MM_INCLUDE_TRUNCATED_MEMORY
Definition: bl.h:104
ULONGLONG BaseAddress
Definition: bl.h:836
#define BL_MM_FLAG_REQUEST_COALESCING
Definition: bl.h:88
NTSTATUS MmPapAllocateRegionFromMdl(_In_ PBL_MEMORY_DESCRIPTOR_LIST NewList, _Out_opt_ PBL_MEMORY_DESCRIPTOR Descriptor, _In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList, _In_ PBL_PA_REQUEST Request, _In_ BL_MEMORY_TYPE Type)
Definition: pagealloc.c:177
NTSTATUS BlMmGetMemoryMap(_In_ PLIST_ENTRY MemoryMap, _In_ PBL_BUFFER_DESCRIPTOR MemoryParameters, _In_ ULONG WhichTypes, _In_ ULONG Flags)
Definition: pagealloc.c:1222
#define BL_MM_INCLUDE_UNMAPPED_ALLOCATED
Definition: bl.h:99
#define BL_MM_INCLUDE_UNMAPPED_UNALLOCATED
Definition: bl.h:100
#define BL_MM_INCLUDE_MAPPED_UNALLOCATED
Definition: bl.h:98
ULONG LowPart
Definition: typedefs.h:104
NTSTATUS MmPapPageAllocatorExtend(_In_ ULONG Attributes, _In_ ULONG Alignment, _In_ ULONGLONG PageCount, _In_ ULONGLONG VirtualPage, _In_opt_ PBL_ADDRESS_RANGE Range, _In_opt_ ULONG Type)
Definition: pagealloc.c:546
#define BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY
Definition: bl.h:118
BL_ADDRESS_RANGE VirtualRange
Definition: pagealloc.c:17
ULONG MemoryType
Definition: pagealloc.c:20
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS
Definition: bl.h:87
Definition: typedefs.h:117
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
Definition: range.c:43
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
Definition: bl.h:91
ULONGLONG Minimum
Definition: bl.h:1015
Status
Definition: gdiplustypes.h:24
#define MAXULONG
Definition: typedefs.h:250
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
#define _In_
Definition: no_sal2.h:204
PBL_MEMORY_DESCRIPTOR MmMdFindDescriptor(_In_ ULONG WhichList, _In_ ULONG Flags, _In_ ULONGLONG Page)
Definition: descriptor.c:1049
ULONGLONG BasePage
Definition: bl.h:831
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
BL_ADDRESS_RANGE BaseRange
Definition: pagealloc.c:16
NTSTATUS MmPapFreePages(_In_ PVOID Address, _In_ ULONG WhichList)
Definition: pagealloc.c:1196
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
FORCEINLINE PVOID PhysicalAddressToPtr(_In_ PHYSICAL_ADDRESS PhysicalAddress)
Definition: bl.h:1390
VOID EfiPrintf(_In_ PWCHAR Format,...)
Definition: firmware.c:126
#define BL_MM_REQUEST_DEFAULT_TYPE
Definition: bl.h:122
NTSTATUS BlpMmInitializeConstraints(VOID)
Definition: pagealloc.c:106
BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedUnallocated
Definition: pagealloc.c:39
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define BL_MM_INCLUDE_BAD_MEMORY
Definition: bl.h:102
#define BL_MM_INCLUDE_FIRMWARE_MEMORY_2
Definition: bl.h:106
BL_MEMORY_DESCRIPTOR_LIST MmMdlFreeVirtual
Definition: pagealloc.c:45
NTSTATUS MmPaReleaseSelfMapPages(_In_ PHYSICAL_ADDRESS Address)
Definition: pagealloc.c:1505
NTSTATUS MmMdTruncateDescriptors(_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList, _In_ ULONGLONG BasePage)
Definition: descriptor.c:410
ULONGLONG VirtualPage
Definition: bl.h:832
BL_ADDRESS_RANGE MmArchKsegAddressRange
Definition: mmx86.c:29
return STATUS_SUCCESS
Definition: btrfs.c:2745
#define __in
Definition: dbghelp.h:35
#define __FUNCTION__
Definition: types.h:112
BOOLEAN MmMdFindSatisfyingRegion(_In_ PBL_MEMORY_DESCRIPTOR Descriptor, _Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor, _In_ ULONGLONG Pages, _In_ PBL_ADDRESS_RANGE BaseRange, _In_ PBL_ADDRESS_RANGE VirtualRange, _In_ BOOLEAN TopDown, _In_ BL_MEMORY_TYPE MemoryType, _In_ ULONG Flags, _In_ ULONG Alignment)
Definition: descriptor.c:1158
VOID MmMdInitializeList(_In_ PBL_MEMORY_DESCRIPTOR_LIST DescriptorList, _In_ ULONG Type, _In_ PLIST_ENTRY ListHead)
Definition: descriptor.c:222
#define BYTE_OFFSET(Va)
ULONG MmDescriptorCallTreeCount
Definition: mm.c:19
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappingTrackers
Definition: pagealloc.c:46
NTSTATUS MmPaTruncateMemory(_In_ ULONGLONG BasePage)
Definition: pagealloc.c:51
LONGLONG QuadPart
Definition: typedefs.h:112
BL_MEMORY_DESCRIPTOR_LIST MmMdlReservedAllocated
Definition: pagealloc.c:40
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966