d11c36f14639cab6f8bf6fe04fa9a2983a559479
[reactos.git] / reactos / boot / environ / lib / mm / descriptor.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/mm/descriptor.c
5 * PURPOSE: Boot Library Memory Manager Descriptor Manager
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12
13 /* DATA VARIABLES ************************************************************/
14
15 BL_MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[512];
16 ULONG MmGlobalMemoryDescriptorCount;
17 PBL_MEMORY_DESCRIPTOR MmGlobalMemoryDescriptors;
18 ULONG MmGlobalMemoryDescriptorsUsed;
19 PBL_MEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
20 ULONG MmDynamicMemoryDescriptorCount;
21
22 BL_MEMORY_TYPE MmPlatformMemoryTypePrecedence[] =
23 {
24 BlReservedMemory,
25 BlUnusableMemory,
26 BlDeviceIoMemory,
27 BlDevicePortMemory,
28 BlPalMemory,
29 BlEfiRuntimeCodeMemory,
30 BlEfiRuntimeDataMemory,
31 BlAcpiNvsMemory,
32 BlAcpiReclaimMemory,
33 BlEfiBootMemory,
34 BlConventionalMemory,
35 BlConventionalZeroedMemory
36 };
37
38 /* FUNCTIONS *****************************************************************/
39
40 LONG
41 MmMdpLookupTypePrecedenceIndex (
42 _In_ BL_MEMORY_TYPE Type
43 )
44 {
45 ULONG i;
46
47 /* Check the precedence array */
48 for (i = 0; i < RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence); i++)
49 {
50 /* Check for a match */
51 if (MmPlatformMemoryTypePrecedence[i] == Type)
52 {
53 /* Return the index */
54 return i;
55 }
56 }
57
58 /* Invalid index type */
59 return -1;
60 }
61
62 /* The order is Conventional > Other > System > Loader > Application */
63 BOOLEAN
64 MmMdpHasPrecedence (
65 _In_ BL_MEMORY_TYPE Type1,
66 _In_ BL_MEMORY_TYPE Type2
67 )
68 {
69 BL_MEMORY_CLASS Class1, Class2;
70 ULONG i, j;
71
72 /* It isn't free RAM, but the comparator is -- it succeeds it */
73 if (Type2 == BlConventionalMemory)
74 {
75 return TRUE;
76 }
77
78 /* Descriptor is free RAM -- it precedes */
79 if (Type1 == BlConventionalMemory)
80 {
81 return FALSE;
82 }
83
84 /* Descriptor is not system, application, or loader class -- it precedes */
85 Class1 = Type1 >> BL_MEMORY_CLASS_SHIFT;
86 if ((Class1 != BlSystemClass) &&
87 (Class1 != BlApplicationClass) &&
88 (Class1 != BlLoaderClass))
89 {
90 return TRUE;
91 }
92
93 /* It isn't one of those classes, but the comparator it -- it succeeds it */
94 Class2 = Type2 >> BL_MEMORY_CLASS_SHIFT;
95 if ((Class2 != BlSystemClass) &&
96 (Class2 != BlApplicationClass) &&
97 (Class2 != BlLoaderClass))
98 {
99 return FALSE;
100 }
101
102 /* Descriptor is system class */
103 if (Class1 == BlSystemClass)
104 {
105 /* If the other guy isn't, system wins */
106 if (Class2 != BlSystemClass)
107 {
108 return TRUE;
109 }
110
111 /* Scan for the descriptor's system precedence index */
112 i = MmMdpLookupTypePrecedenceIndex(Type1);
113 j = MmMdpLookupTypePrecedenceIndex(Type2);
114
115 /* Does the current have a valid index? */
116 if (i == 0xFFFFFFFF)
117 {
118 return TRUE;
119 }
120
121 /* Yes, what about the comparator? */
122 if (j == 0xFFFFFFFF)
123 {
124 return FALSE;
125 }
126
127 /* Let the indexes fight! */
128 return i <= j;
129 }
130
131 /* Descriptor is not system class, but comparator is -- it succeeds it */
132 if (Class2 == BlSystemClass)
133 {
134 return FALSE;
135 }
136
137 /* Descriptor is loader class -- it preceedes */
138 if (Class1 == BlLoaderClass)
139 {
140 return TRUE;
141 }
142
143 /* It isn't loader class -- if the other guy is, succeed it */
144 return Class2 != BlLoaderClass;
145 }
146
147 VOID
148 MmMdpSwitchToDynamicDescriptors (
149 _In_ ULONG Count
150 )
151 {
152 EfiPrintf(L"Dynamic switch NOT SUPPORTED!!!\r\n");
153 EfiStall(10000000);
154 }
155
156 NTSTATUS
157 MmMdFreeDescriptor (
158 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
159 )
160 {
161 NTSTATUS Status;
162
163 /* Check if this is a valid static descriptor */
164 if (((MmDynamicMemoryDescriptors) &&
165 (MemoryDescriptor >= MmDynamicMemoryDescriptors) &&
166 (MemoryDescriptor < &MmDynamicMemoryDescriptors[MmDynamicMemoryDescriptorCount])) ||
167 ((MemoryDescriptor >= MmStaticMemoryDescriptors) &&
168 (MemoryDescriptor < &MmStaticMemoryDescriptors[RTL_NUMBER_OF(MmStaticMemoryDescriptors)])))
169 {
170 /* It's a global/static descriptor, so just zero it */
171 RtlZeroMemory(MemoryDescriptor, sizeof(BL_MEMORY_DESCRIPTOR));
172 Status = STATUS_SUCCESS;
173 }
174 else
175 {
176 /* It's a dynamic descriptor, so free it */
177 EfiPrintf(L"Freeing dynamic descriptors not yet supported\r\n");
178 EfiStall(10000000);
179 Status = STATUS_NOT_IMPLEMENTED;
180 }
181
182 /* Done */
183 return Status;
184 }
185
186 VOID
187 MmMdpSaveCurrentListPointer (
188 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
189 _In_ PLIST_ENTRY Current
190 )
191 {
192 PBL_MEMORY_DESCRIPTOR FirstEntry, LastEntry;
193
194 /* Make sure that this is not a global descriptor and not the first one */
195 FirstEntry = &MmGlobalMemoryDescriptors[0];
196 LastEntry = &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorCount];
197 if ((((ULONG_PTR)Current < (ULONG_PTR)FirstEntry) ||
198 ((ULONG_PTR)Current >= (ULONG_PTR)LastEntry)) &&
199 (Current != MdList->First))
200 {
201 /* Save this as the current pointer */
202 MdList->This = Current;
203 }
204 }
205
206 ULONG
207 MmMdCountList (
208 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
209 )
210 {
211 PLIST_ENTRY First, NextEntry;
212 ULONG Count;
213
214 /* Iterate the list */
215 for (Count = 0, First = MdList->First, NextEntry = First->Flink;
216 NextEntry != First;
217 NextEntry = NextEntry->Flink, Count++);
218
219 /* Return the count */
220 return Count;
221 }
222
223 VOID
224 MmMdInitializeList (
225 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
226 _In_ ULONG Type,
227 _In_ PLIST_ENTRY ListHead
228 )
229 {
230 /* Check if a list was specified */
231 if (ListHead)
232 {
233 /* Use it */
234 MdList->First = ListHead;
235 }
236 else
237 {
238 /* Otherwise, use the internal, built-in list */
239 InitializeListHead(&MdList->ListHead);
240 MdList->First = &MdList->ListHead;
241 }
242
243 /* Set the type */
244 MdList->Type = Type;
245
246 /* Initialize current iterator to nothing */
247 MdList->This = NULL;
248 }
249
250 NTSTATUS
251 MmMdCopyList (
252 _In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList,
253 _In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList,
254 _In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor,
255 _Out_ PULONG ActualCount,
256 _In_ ULONG Count,
257 _In_ ULONG Flags
258 )
259 {
260 NTSTATUS Status;
261 PULONG Used;
262 PLIST_ENTRY First, NextEntry;
263 PBL_MEMORY_DESCRIPTOR Descriptor;
264
265 /* Both parameters must be present */
266 if (!(DestinationList) || !(SourceList))
267 {
268 return STATUS_INVALID_PARAMETER;
269 }
270
271 /* Assume success */
272 Status = STATUS_SUCCESS;
273
274 /* Check if a descriptor is being used to store the list */
275 if (ListDescriptor)
276 {
277 /* See how big it is */
278 Flags |= BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG;
279 Used = ActualCount;
280 }
281 else
282 {
283 /* We are using our internal descriptors instead */
284 Used = &MmGlobalMemoryDescriptorsUsed;
285 ++MmDescriptorCallTreeCount;
286
287 /* Use as many as are available */
288 Count = MmGlobalMemoryDescriptorCount;
289 ListDescriptor = MmGlobalMemoryDescriptors;
290 }
291
292 /* Never truncate descriptors during a list copy */
293 Flags |= BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG;
294
295 /* Iterate through the list */
296 First = SourceList->First;
297 NextEntry = First->Flink;
298 while ((NextEntry != First) && (NT_SUCCESS(Status)))
299 {
300 /* Make sure there's still space */
301 if (Count <= *Used)
302 {
303 Status = STATUS_NO_MEMORY;
304 break;
305 }
306
307 /* Get the current descriptor */
308 Descriptor = CONTAINING_RECORD(NextEntry,
309 BL_MEMORY_DESCRIPTOR,
310 ListEntry);
311
312 /* Copy it into one of the descriptors we have */
313 RtlCopyMemory(&ListDescriptor[*Used],
314 Descriptor,
315 sizeof(*Descriptor));
316
317 /* Add it to the list we have */
318 Status = MmMdAddDescriptorToList(DestinationList,
319 &ListDescriptor[*Used],
320 Flags);
321 ++*Used;
322
323 /* Move to the next entry */
324 NextEntry = NextEntry->Flink;
325 }
326
327 /* Check if the global descriptors were used */
328 if (ListDescriptor == MmGlobalMemoryDescriptors)
329 {
330 /* Unwind our usage */
331 MmMdFreeGlobalDescriptors();
332 --MmDescriptorCallTreeCount;
333 }
334
335 /* Return back to caller */
336 return Status;
337 }
338
339 VOID
340 MmMdRemoveDescriptorFromList (
341 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
342 _In_ PBL_MEMORY_DESCRIPTOR Entry
343 )
344 {
345 /* Remove the entry */
346 RemoveEntryList(&Entry->ListEntry);
347
348 /* Check if this was the current link */
349 if (MdList->This == &Entry->ListEntry)
350 {
351 /* Remove the current link and set the next one */
352 MdList->This = NULL;
353 MmMdpSaveCurrentListPointer(MdList, Entry->ListEntry.Blink);
354 }
355 }
356
357 VOID
358 MmMdFreeList(
359 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
360 )
361 {
362 PLIST_ENTRY FirstEntry, NextEntry;
363 PBL_MEMORY_DESCRIPTOR Entry;
364
365 /* Go over every descriptor from the top */
366 FirstEntry = MdList->First;
367 NextEntry = FirstEntry->Flink;
368 while (NextEntry != FirstEntry)
369 {
370 /* Remove and free each one */
371 Entry = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
372 NextEntry = NextEntry->Flink;
373 MmMdRemoveDescriptorFromList(MdList, Entry);
374 MmMdFreeDescriptor(Entry);
375 }
376 }
377
378 PBL_MEMORY_DESCRIPTOR
379 MmMdInitByteGranularDescriptor (
380 _In_ ULONG Flags,
381 _In_ BL_MEMORY_TYPE Type,
382 _In_ ULONGLONG BasePage,
383 _In_ ULONGLONG VirtualPage,
384 _In_ ULONGLONG PageCount
385 )
386 {
387 PBL_MEMORY_DESCRIPTOR MemoryDescriptor;
388
389 /* If we're out of descriptors, bail out */
390 if (MmGlobalMemoryDescriptorsUsed >= MmGlobalMemoryDescriptorCount)
391 {
392 EfiPrintf(L"Out of descriptors!\r\n");
393 EfiStall(1000000);
394 return NULL;
395 }
396
397 /* Take one of the available descriptors and fill it out */
398 MemoryDescriptor = &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorsUsed];
399 MemoryDescriptor->BasePage = BasePage;
400 MemoryDescriptor->VirtualPage = VirtualPage;
401 MemoryDescriptor->PageCount = PageCount;
402 MemoryDescriptor->Flags = Flags;
403 MemoryDescriptor->Type = Type;
404 InitializeListHead(&MemoryDescriptor->ListEntry);
405
406 /* Increment the count and return the descriptor */
407 MmGlobalMemoryDescriptorsUsed++;
408 return MemoryDescriptor;
409 }
410
411 NTSTATUS
412 MmMdTruncateDescriptors (
413 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
414 _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList,
415 _In_ ULONGLONG BasePage
416 )
417 {
418 PLIST_ENTRY ListHead, NextEntry;
419 PBL_MEMORY_DESCRIPTOR Descriptor, NewDescriptor;
420 ULONGLONG FoundEndPage;
421
422 /* Search the descriptor list */
423 ListHead = MdList->First;
424 NextEntry = ListHead->Flink;
425 while (NextEntry != ListHead)
426 {
427 /* Get the current descriptor */
428 Descriptor = CONTAINING_RECORD(NextEntry,
429 BL_MEMORY_DESCRIPTOR,
430 ListEntry);
431
432 /* Go to the next entry in case we have to remove */
433 NextEntry = NextEntry->Flink;
434
435 /* Don't touch anything else but free RAM */
436 if (((Descriptor->Type >> BL_MEMORY_CLASS_SHIFT) == BlSystemClass) &&
437 (Descriptor->Type != BlConventionalMemory))
438 {
439 continue;
440 }
441
442 /* Check if this page is within the descriptor's region */
443 FoundEndPage = Descriptor->BasePage + Descriptor->PageCount;
444 if (BasePage > Descriptor->BasePage)
445 {
446 /* Check if it doesn't go beyond the descriptor */
447 if (BasePage < FoundEndPage)
448 {
449 /* Create a new descriptor to describe this region */
450 EfiPrintf(L"Truncating descriptor type %lx base: %llx end: %llx\r\n",
451 Descriptor->Type, Descriptor->BasePage, FoundEndPage);
452 NewDescriptor = MmMdInitByteGranularDescriptor(Descriptor->Flags,
453 Descriptor->Type,
454 BasePage,
455 0,
456 FoundEndPage - BasePage);
457 if (!NewDescriptor)
458 {
459 return STATUS_NO_MEMORY;
460 }
461
462 /* Cut off this descriptor to make it shorter */
463 Descriptor->PageCount = BasePage - Descriptor->BasePage;
464
465 /* Add the region to the new list */
466 MmMdAddDescriptorToList(NewList,
467 NewDescriptor,
468 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
469 }
470 }
471 else
472 {
473 /* This whole descriptor covers the truncated area */
474 EfiPrintf(L"Truncating descriptor type %lx base: %llx end: %llx\r\n",
475 Descriptor->Type, Descriptor->BasePage, FoundEndPage);
476 MmMdRemoveDescriptorFromList(MdList, Descriptor);
477 MmMdAddDescriptorToList(NewList,
478 Descriptor,
479 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
480 }
481 }
482
483 /* All good if we got here */
484 return STATUS_SUCCESS;
485 }
486
487 BOOLEAN
488 MmMdpTruncateDescriptor (
489 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
490 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
491 _In_ ULONG Flags
492 )
493 {
494 PBL_MEMORY_DESCRIPTOR NextDescriptor, PreviousDescriptor;
495 PLIST_ENTRY NextEntry, PreviousEntry;
496 ULONGLONG EndPage, PreviousEndPage;// , NextEndPage;
497
498 /* Get the next descriptor */
499 NextEntry = MemoryDescriptor->ListEntry.Flink;
500 NextDescriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
501
502 /* Get the previous descriptor */
503 PreviousEntry = MemoryDescriptor->ListEntry.Blink;
504 PreviousDescriptor = CONTAINING_RECORD(PreviousEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
505
506 /* Calculate end pages */
507 EndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
508 //NextEndPage = NextDescriptor->BasePage + NextDescriptor->PageCount;
509 PreviousEndPage = PreviousDescriptor->BasePage + PreviousDescriptor->PageCount;
510
511 /* Check for backward overlap */
512 if ((PreviousEntry != MdList->First) && (MemoryDescriptor->BasePage < PreviousEndPage))
513 {
514 EfiPrintf(L"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
515 EfiStall(1000000);
516 }
517
518 /* Check for forward overlap */
519 if ((NextEntry != MdList->First) && (NextDescriptor->BasePage < EndPage))
520 {
521 EfiPrintf(L"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
522 EfiStall(1000000);
523 }
524
525 /* Nothing to do */
526 return FALSE;
527 }
528
529 BOOLEAN
530 MmMdpCoalesceDescriptor (
531 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
532 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
533 _In_ ULONG Flags
534 )
535 {
536 PBL_MEMORY_DESCRIPTOR NextDescriptor, PreviousDescriptor;
537 PLIST_ENTRY NextEntry, PreviousEntry;
538 ULONGLONG EndPage, PreviousEndPage, PreviousMappedEndPage, MappedEndPage;
539
540 /* Get the next descriptor */
541 NextEntry = MemoryDescriptor->ListEntry.Flink;
542 NextDescriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
543
544 /* Get the previous descriptor */
545 PreviousEntry = MemoryDescriptor->ListEntry.Blink;
546 PreviousDescriptor = CONTAINING_RECORD(PreviousEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
547
548 /* Calculate end pages */
549 EndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
550 MappedEndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
551 PreviousMappedEndPage = PreviousDescriptor->VirtualPage + PreviousDescriptor->PageCount;
552 PreviousEndPage = PreviousDescriptor->BasePage + PreviousDescriptor->PageCount;
553 PreviousMappedEndPage = PreviousDescriptor->VirtualPage + PreviousDescriptor->PageCount;
554
555 /* Check if the previous entry touches the current entry, and is compatible */
556 if ((PreviousEntry != MdList->First) &&
557 (PreviousDescriptor->Type == MemoryDescriptor->Type) &&
558 ((PreviousDescriptor->Flags ^ MemoryDescriptor->Flags) & 0x1B19FFFF) &&
559 (PreviousEndPage == MemoryDescriptor->BasePage) &&
560 ((!(MemoryDescriptor->VirtualPage) && !(PreviousDescriptor->VirtualPage)) ||
561 ((MemoryDescriptor->VirtualPage) && (PreviousDescriptor->VirtualPage) &&
562 (PreviousMappedEndPage == MemoryDescriptor->VirtualPage))))
563 {
564 EfiPrintf(L"Previous descriptor coalescable!\r\n");
565 }
566
567 /* CHeck if the current entry touches the next entry, and is compatible */
568 if ((NextEntry != MdList->First) &&
569 (NextDescriptor->Type == MemoryDescriptor->Type) &&
570 ((NextDescriptor->Flags ^ MemoryDescriptor->Flags) & 0x1B19FFFF) &&
571 (EndPage == NextDescriptor->BasePage) &&
572 ((!(MemoryDescriptor->VirtualPage) && !(NextDescriptor->VirtualPage)) ||
573 ((MemoryDescriptor->VirtualPage) && (NextDescriptor->VirtualPage) &&
574 (MappedEndPage == NextDescriptor->VirtualPage))))
575 {
576 EfiPrintf(L"Next descriptor coalescable!\r\n");
577 }
578
579 /* Nothing to do */
580 return FALSE;
581 }
582
583 NTSTATUS
584 MmMdAddDescriptorToList (
585 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
586 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
587 _In_ ULONG Flags
588 )
589 {
590 PLIST_ENTRY ThisEntry, FirstEntry;
591 PBL_MEMORY_DESCRIPTOR ThisDescriptor;
592
593 /* Arguments must be present */
594 if (!(MdList) || !(MemoryDescriptor))
595 {
596 return STATUS_INVALID_PARAMETER;
597 }
598
599 /* Check if coalescing is forcefully disabled */
600 if (Flags & BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG)
601 {
602 /* Then we won't be coalescing */
603 Flags &= ~BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG;
604 }
605 else if (MemoryDescriptor->Flags & BlMemoryCoalesced)
606 {
607 /* Coalesce if the descriptor requires it */
608 Flags |= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG;
609 }
610
611 /* Check if truncation is forcefully disabled */
612 if (Flags & BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG)
613 {
614 Flags &= ~BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG;
615 }
616
617 /* Update the current list pointer if the descriptor requires it */
618 if (MemoryDescriptor->Flags & BlMemoryUpdate)
619 {
620 Flags |= BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG;
621 }
622
623 /* Get the current descriptor */
624 ThisEntry = MdList->This;
625 ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
626
627 /* Also get the first descriptor */
628 FirstEntry = MdList->First;
629
630 /* Check if there's no current pointer, or if it's higher than the new one */
631 if (!(ThisEntry) ||
632 (MemoryDescriptor->BasePage <= ThisDescriptor->BasePage))
633 {
634 /* Start at the first descriptor instead, since current is past us */
635 ThisEntry = FirstEntry->Flink;
636 }
637
638 /* Loop until we find the right location to insert */
639 while (ThisEntry != FirstEntry)
640 {
641 /* Get the descriptor part of this entry */
642 ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
643
644 /* Is the address smaller, or equal but more important? */
645 if ((MemoryDescriptor->BasePage < ThisDescriptor->BasePage) ||
646 ((MemoryDescriptor->BasePage == ThisDescriptor->BasePage) &&
647 (MmMdpHasPrecedence(MemoryDescriptor->Type, ThisDescriptor->Type))))
648 {
649 /* Then insert right here */
650 InsertTailList(ThisEntry, &MemoryDescriptor->ListEntry);
651 goto Quickie;
652 }
653
654 /* Try the next entry */
655 ThisEntry = ThisEntry->Flink;
656 }
657
658 /* Then we didn't find a good match, so insert it right here */
659 InsertTailList(FirstEntry, &MemoryDescriptor->ListEntry);
660
661 Quickie:
662 /* Do we have to truncate? */
663 if (Flags & BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG)
664 {
665 /* Do it and then exit */
666 if (MmMdpTruncateDescriptor(MdList, MemoryDescriptor, Flags))
667 {
668 return STATUS_SUCCESS;
669 }
670 }
671
672 /* Do we have to coalesce? */
673 if (Flags & BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG)
674 {
675 /* Do it and then exit */
676 if (MmMdpCoalesceDescriptor(MdList, MemoryDescriptor, Flags))
677 {
678 return STATUS_SUCCESS;
679 }
680 }
681
682 /* Do we have to update the current pointer? */
683 if (Flags & BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG)
684 {
685 /* Do it */
686 MmMdpSaveCurrentListPointer(MdList, &MemoryDescriptor->ListEntry);
687 }
688
689 /* We're done */
690 return STATUS_SUCCESS;
691 }
692
693 NTSTATUS
694 MmMdRemoveRegionFromMdlEx (
695 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
696 _In_ ULONG Flags,
697 _In_ ULONGLONG BasePage,
698 _In_ ULONGLONG PageCount,
699 _Out_opt_ PBL_MEMORY_DESCRIPTOR_LIST NewMdList
700 )
701 {
702 BOOLEAN HaveNewList, UseVirtualPage;
703 NTSTATUS Status;
704 PLIST_ENTRY ListHead, NextEntry;
705 PBL_MEMORY_DESCRIPTOR Descriptor, NewDescriptor, ListDescriptor;
706 BL_MEMORY_DESCRIPTOR OldDescriptor;
707 ULONGLONG RegionSize;
708 ULONGLONG FoundBasePage, FoundEndPage, FoundPageCount, EndPage, VirtualPage;
709
710 /* Set initial status */
711 Status = STATUS_SUCCESS;
712 ListDescriptor = NULL;
713 NewDescriptor = NULL;
714 HaveNewList = FALSE;
715
716 /* Check if removed descriptors should go into a new list */
717 if (NewMdList != NULL)
718 {
719 /* Initialize it */
720 MmMdInitializeList(NewMdList, MdList->Type, NULL);
721
722 /* Remember for later */
723 HaveNewList = TRUE;
724 }
725
726 /* Is the region being removed physical? */
727 UseVirtualPage = FALSE;
728 if (!(Flags & BL_MM_REMOVE_VIRTUAL_REGION_FLAG))
729 {
730 /* Is this a list of virtual descriptors? */
731 if (MdList->Type == BlMdVirtual)
732 {
733 /* Request is nonsensical, fail */
734 Status = STATUS_INVALID_PARAMETER;
735 goto Quickie;
736 }
737 }
738 else
739 {
740 /* Is this a list of physical descriptors? */
741 if (MdList->Type == BlMdPhysical)
742 {
743 /* We'll have to use the virtual page instead */
744 UseVirtualPage = TRUE;
745 }
746 }
747
748 /* Loop the list*/
749 ListHead = MdList->First;
750 NextEntry = ListHead->Flink;
751 while (NextEntry != ListHead)
752 {
753 /* Get the descriptor */
754 Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
755
756 /* Extract range details */
757 FoundBasePage = UseVirtualPage ? Descriptor->VirtualPage : Descriptor->BasePage;
758 FoundPageCount = Descriptor->PageCount;
759 FoundEndPage = FoundBasePage + FoundPageCount;
760 EndPage = PageCount + BasePage;
761
762 /* Make a copy of the original descriptor */
763 OldDescriptor = *Descriptor;
764
765 /* Check if the region to be removed starts after the found region starts */
766 if ((BasePage > FoundBasePage) || (FoundBasePage >= EndPage))
767 {
768 /* Check if the region ends after the found region */
769 if ((BasePage >= FoundEndPage) || (FoundEndPage > EndPage))
770 {
771 /* Check if the found region starts after the region or ends before the region */
772 if ((FoundBasePage >= BasePage) || (EndPage >= FoundEndPage))
773 {
774 /* This is a fully-mapped descriptor -- change nothing */
775 OldDescriptor.PageCount = 0;
776 }
777 else
778 {
779 /* This descriptor fully covers the entire allocation */
780 FoundBasePage = Descriptor->BasePage;
781 VirtualPage = Descriptor->VirtualPage;
782 FoundPageCount = BasePage - FoundBasePage;
783
784 /* This is how many pages we will eat away from the descriptor */
785 RegionSize = FoundPageCount + PageCount;
786
787 /* Update the descriptor to account for the consumed pages */
788 Descriptor->BasePage += RegionSize;
789 Descriptor->PageCount -= RegionSize;
790 if (VirtualPage)
791 {
792 Descriptor->VirtualPage += RegionSize;
793 }
794
795 /* Initialize a descriptor for the start of the region */
796 NewDescriptor = MmMdInitByteGranularDescriptor(Descriptor->Flags,
797 Descriptor->Type,
798 FoundBasePage,
799 VirtualPage,
800 FoundPageCount);
801 if (!NewDescriptor)
802 {
803 Status = STATUS_NO_MEMORY;
804 goto Quickie;
805 }
806
807 /* Add it into the list */
808 Status = MmMdAddDescriptorToList(MdList, NewDescriptor, Flags);
809 if (!NT_SUCCESS(Status))
810 {
811 Status = STATUS_NO_MEMORY;
812 goto Quickie;
813 }
814
815 /* Don't free it on exit path */
816 NewDescriptor = NULL;
817
818 /* Adjust the leftover descriptor */
819 OldDescriptor.BasePage += FoundPageCount;
820 OldDescriptor.PageCount = PageCount;
821 if (OldDescriptor.VirtualPage)
822 {
823 OldDescriptor.VirtualPage += FoundPageCount;
824 }
825 }
826 }
827 else
828 {
829 /* This descriptor contains the entire allocation */
830 RegionSize = FoundEndPage - BasePage;
831 Descriptor->PageCount -= RegionSize;
832
833 /* Adjust the leftover descriptor */
834 OldDescriptor.BasePage += Descriptor->PageCount;
835 OldDescriptor.PageCount = RegionSize;
836 if (OldDescriptor.VirtualPage)
837 {
838 OldDescriptor.VirtualPage += FoundPageCount;
839 }
840 }
841
842 /* Go to the next entry */
843 NextEntry = NextEntry->Flink;
844 }
845 else
846 {
847 /*
848 * This descriptor contains the end of the allocation. It may:
849 *
850 * - Contain the full allocation (i.e.: the start is aligned)
851 * - Contain parts of the end of the allocation (i.e.: the end is beyond)
852 * - Contain the entire tail end of the allocation (i..e:the end is within)
853 *
854 * So first, figure out if we cover the entire end or not
855 */
856 if (EndPage < FoundEndPage)
857 {
858 /* The allocation goes past the end of this descriptor */
859 FoundEndPage = EndPage;
860 }
861
862 /* This is how many pages we will eat away from the descriptor */
863 FoundPageCount = FoundEndPage - FoundBasePage;
864
865 /* Update the descriptor to account for the consumed pages */
866 Descriptor->BasePage += FoundPageCount;
867 Descriptor->PageCount -= FoundPageCount;
868 if (Descriptor->VirtualPage)
869 {
870 Descriptor->VirtualPage += FoundPageCount;
871 }
872
873 /* Go to the next entry */
874 NextEntry = NextEntry->Flink;
875
876 /* Check if the descriptor is now empty */
877 if (!Descriptor->PageCount)
878 {
879 /* Remove it */
880 MmMdRemoveDescriptorFromList(MdList, Descriptor);
881
882 /* Check if we're supposed to insert it into a new list */
883 if (HaveNewList)
884 {
885 /* This is the one to add */
886 ListDescriptor = Descriptor;
887 }
888 else
889 {
890 /* Nope -- just get rid of it */
891 MmMdFreeDescriptor(Descriptor);
892 }
893 }
894 }
895
896 /* Is there a remainder descriptor, and do we have a list for it */
897 if ((OldDescriptor.PageCount) && (HaveNewList))
898 {
899 /* Did we already chop off the descriptor? */
900 if (ListDescriptor)
901 {
902 /* Use what we previously chopped */
903 *ListDescriptor = OldDescriptor;
904 }
905 else
906 {
907 /* First time, so build a descriptor to describe the leftover */
908 ListDescriptor = MmMdInitByteGranularDescriptor(OldDescriptor.Flags,
909 OldDescriptor.Type,
910 OldDescriptor.BasePage,
911 OldDescriptor.VirtualPage,
912 OldDescriptor.PageCount);
913 if (!ListDescriptor)
914 {
915 Status = STATUS_NO_MEMORY;
916 goto Quickie;
917 }
918
919 /* Add it into the list */
920 Status = MmMdAddDescriptorToList(NewMdList, ListDescriptor, 0);
921 if (!NT_SUCCESS(Status))
922 {
923 goto Quickie;
924 }
925
926 /* Don't free on exit path */
927 ListDescriptor = NULL;
928 }
929 }
930 }
931
932 Quickie:
933 /* Check for failure cleanup */
934 if (!NT_SUCCESS(Status))
935 {
936 /* Did we have to build a new list? */
937 if (HaveNewList)
938 {
939 /* Free and re-initialize it */
940 MmMdFreeList(NewMdList);
941 MmMdInitializeList(NewMdList, MdList->Type, NULL);
942 }
943
944 /* Check if we had a list descriptor, and free it */
945 if (ListDescriptor)
946 {
947 MmMdFreeDescriptor(ListDescriptor);
948 }
949
950 /* Check if we had a new descriptor, and free it */
951 if (NewDescriptor)
952 {
953 MmMdFreeDescriptor(NewDescriptor);
954 }
955 }
956
957 /* All done */
958 return Status;
959 }
960
961 PBL_MEMORY_DESCRIPTOR
962 MmMdFindDescriptorFromMdl (
963 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
964 _In_ ULONG Flags,
965 _In_ ULONGLONG Page
966 )
967 {
968 BOOLEAN IsVirtual;
969 PLIST_ENTRY NextEntry, ListHead;
970 PBL_MEMORY_DESCRIPTOR Current;
971 ULONGLONG BasePage;
972
973 /* Assume physical */
974 IsVirtual = FALSE;
975
976 /* Check if the caller wants physical memory */
977 if (!(Flags & BL_MM_REMOVE_VIRTUAL_REGION_FLAG))
978 {
979 /* Check if this is a virtual memory list */
980 if (MdList->Type == BlMdVirtual)
981 {
982 /* We won't find anything */
983 return NULL;
984 }
985 }
986 else if (MdList->Type == BlMdPhysical)
987 {
988 /* Otherwise, caller wants virtual, but this is a physical list */
989 IsVirtual = TRUE;
990 NextEntry = MdList->First->Flink;
991 }
992
993 /* Check if this is a physical search */
994 if (!IsVirtual)
995 {
996 /* Check if we can use the current pointer */
997 NextEntry = MdList->This;
998 if (!NextEntry)
999 {
1000 /* We can't -- start at the beginning */
1001 NextEntry = MdList->First->Flink;
1002 }
1003 else
1004 {
1005 /* If the page is below the current pointer, restart */
1006 Current = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
1007 if (Page < Current->BasePage)
1008 {
1009 NextEntry = MdList->First->Flink;
1010 }
1011 }
1012 }
1013
1014 /* Loop the list of descriptors */
1015 ListHead = MdList->First;
1016 while (NextEntry != ListHead)
1017 {
1018 /* Get the current one */
1019 Current = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
1020
1021 /* Check if we are looking for virtual memory */
1022 if (IsVirtual)
1023 {
1024 /* Use the base address */
1025 BasePage = Current->VirtualPage;
1026 }
1027 else
1028 {
1029 /* Use the page */
1030 BasePage = Current->BasePage;
1031 }
1032
1033 /* If this is a virtual descriptor, make sure it has a base address */
1034 if ((!(IsVirtual) || (BasePage)) &&
1035 (BasePage <= Page) &&
1036 (Page < (BasePage + Current->PageCount)))
1037 {
1038 /* The descriptor fits the page being requested */
1039 return Current;
1040 }
1041
1042 /* Try the next one */
1043 NextEntry = NextEntry->Flink;
1044 }
1045
1046 /* Nothing found if we're here */
1047 return NULL;
1048 }
1049
1050 PBL_MEMORY_DESCRIPTOR
1051 MmMdFindDescriptor (
1052 _In_ ULONG WhichList,
1053 _In_ ULONG Flags,
1054 _In_ ULONGLONG Page
1055 )
1056 {
1057 PBL_MEMORY_DESCRIPTOR FoundDescriptor;
1058
1059 /* Check if the caller is looking for mapped, allocated memory */
1060 if (WhichList & BL_MM_INCLUDE_MAPPED_ALLOCATED)
1061 {
1062 /* Find a descriptor in that list */
1063 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlMappedAllocated, Flags, Page);
1064 if (FoundDescriptor)
1065 {
1066 /* Got it */
1067 return FoundDescriptor;
1068 }
1069 }
1070
1071 /* Check if the caller is looking for mapped, unallocated memory */
1072 if (WhichList & BL_MM_INCLUDE_MAPPED_UNALLOCATED)
1073 {
1074 /* Find a descriptor in that list */
1075 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlMappedUnallocated, Flags, Page);
1076 if (FoundDescriptor)
1077 {
1078 /* Got it */
1079 return FoundDescriptor;
1080 }
1081 }
1082
1083 /* Check if the caller is looking for unmapped, allocated memory */
1084 if (WhichList & BL_MM_INCLUDE_UNMAPPED_ALLOCATED)
1085 {
1086 /* Find a descriptor in that list */
1087 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlUnmappedAllocated, Flags, Page);
1088 if (FoundDescriptor)
1089 {
1090 /* Got it */
1091 return FoundDescriptor;
1092 }
1093 }
1094
1095 /* Check if the caller is looking for unmapped, unallocated memory */
1096 if (WhichList & BL_MM_INCLUDE_UNMAPPED_UNALLOCATED)
1097 {
1098 /* Find a descriptor in that list */
1099 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlUnmappedUnallocated, Flags, Page);
1100 if (FoundDescriptor)
1101 {
1102 /* Got it */
1103 return FoundDescriptor;
1104 }
1105 }
1106
1107 /* Check if the caller is looking for reserved, allocated memory */
1108 if (WhichList & BL_MM_INCLUDE_RESERVED_ALLOCATED)
1109 {
1110 /* Find a descriptor in that list */
1111 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlReservedAllocated, Flags, Page);
1112 if (FoundDescriptor)
1113 {
1114 /* Got it */
1115 return FoundDescriptor;
1116 }
1117 }
1118
1119 /* Check if the caller is looking for bad memory */
1120 if (WhichList & BL_MM_INCLUDE_BAD_MEMORY)
1121 {
1122 /* Find a descriptor in that list */
1123 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlBadMemory, Flags, Page);
1124 if (FoundDescriptor)
1125 {
1126 /* Got it */
1127 return FoundDescriptor;
1128 }
1129 }
1130
1131 /* Check if the caller is looking for truncated memory */
1132 if (WhichList & BL_MM_INCLUDE_TRUNCATED_MEMORY)
1133 {
1134 /* Find a descriptor in that list */
1135 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlTruncatedMemory, Flags, Page);
1136 if (FoundDescriptor)
1137 {
1138 /* Got it */
1139 return FoundDescriptor;
1140 }
1141 }
1142
1143 /* Check if the caller is looking for persistent memory */
1144 if (WhichList & BL_MM_INCLUDE_PERSISTENT_MEMORY)
1145 {
1146 /* Find a descriptor in that list */
1147 FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlPersistentMemory, Flags, Page);
1148 if (FoundDescriptor)
1149 {
1150 /* Got it */
1151 return FoundDescriptor;
1152 }
1153 }
1154
1155 /* Nothing if we got here */
1156 return NULL;
1157 }
1158
1159 BOOLEAN
1160 MmMdFindSatisfyingRegion (
1161 _In_ PBL_MEMORY_DESCRIPTOR Descriptor,
1162 _Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor,
1163 _In_ ULONGLONG Pages,
1164 _In_ PBL_ADDRESS_RANGE BaseRange,
1165 _In_ PBL_ADDRESS_RANGE VirtualRange,
1166 _In_ BOOLEAN TopDown,
1167 _In_ BL_MEMORY_TYPE MemoryType,
1168 _In_ ULONG Flags,
1169 _In_ ULONG Alignment
1170 )
1171 {
1172 ULONGLONG BaseMin, BaseMax, AlignedMin;
1173 ULONGLONG VirtualPage, BasePage;
1174 ULONGLONG BaseDelta, AlignedBase;
1175 ULONGLONG VirtualMin, VirtualMax;
1176
1177 /* Extract the minimum and maximum range */
1178 BaseMin = BaseRange->Minimum;
1179 BaseMax = BaseRange->Maximum;
1180
1181 /* Don't go below where the descriptor starts */
1182 if (BaseMin < Descriptor->BasePage)
1183 {
1184 BaseMin = Descriptor->BasePage;
1185 }
1186
1187 /* Don't go beyond where the descriptor ends */
1188 if (BaseMax > (Descriptor->BasePage + Descriptor->PageCount - 1))
1189 {
1190 BaseMax = (Descriptor->BasePage + Descriptor->PageCount - 1);
1191 }
1192
1193 /* Check for start overflow */
1194 if (BaseMin > BaseMax)
1195 {
1196 return FALSE;
1197 }
1198
1199 /* Align the base as required */
1200 if (Alignment != 1)
1201 {
1202 AlignedMin = ALIGN_UP_BY(BaseMin, Alignment);
1203 }
1204 else
1205 {
1206 AlignedMin = BaseMin;
1207 }
1208
1209 /* Check for range overflow */
1210 if (((AlignedMin + Pages - 1) < AlignedMin) || ((AlignedMin + Pages - 1) > BaseMax))
1211 {
1212 return FALSE;
1213 }
1214
1215 /* Check if this was a top-down request */
1216 if (TopDown)
1217 {
1218 /* Then get the highest page possible */
1219 BasePage = BaseMax - Pages + 1;
1220 if (Alignment != 1)
1221 {
1222 /* Align it as needed */
1223 AlignedBase = ALIGN_DOWN_BY(BasePage, Alignment);
1224 }
1225 else
1226 {
1227 AlignedBase = BasePage;
1228 }
1229
1230 /* Calculate the delta between max address and our aligned base */
1231 BaseDelta = BasePage - AlignedBase;
1232 BasePage -= BaseDelta;
1233 }
1234 else
1235 {
1236 /* Otherwise, get the lowest page possible */
1237 BasePage = AlignedMin;
1238 BaseDelta = 0;
1239 }
1240
1241 /* If a virtual address range was passed in, this must be a virtual descriptor */
1242 if (((VirtualRange->Minimum) || (VirtualRange->Maximum)) &&
1243 !(Descriptor->VirtualPage))
1244 {
1245 return FALSE;
1246 }
1247
1248 /* Any mapped page already? */
1249 if (Descriptor->VirtualPage)
1250 {
1251 /* Get virtual min/max */
1252 VirtualMin = VirtualRange->Minimum;
1253 VirtualMax = VirtualRange->Maximum;
1254
1255 /* Don't go below where the descriptor maps */
1256 if (VirtualMin <= Descriptor->VirtualPage)
1257 {
1258 VirtualMin = Descriptor->VirtualPage;
1259 }
1260
1261 /* Don't go above where the descriptor maps */
1262 if (VirtualMax >= (Descriptor->VirtualPage + Descriptor->PageCount - 1))
1263 {
1264 VirtualMax = Descriptor->VirtualPage + Descriptor->PageCount - 1;
1265 }
1266
1267 /* Don't let the base overflow */
1268 if (VirtualMin > VirtualMax)
1269 {
1270 return 0;
1271 }
1272
1273 /* Adjust the base by the alignment delta */
1274 VirtualMin += AlignedMin - BaseMin;
1275
1276 /* Check that the bounds don't overflow or underflow */
1277 if (((VirtualMin + Pages - 1) < VirtualMin) ||
1278 ((VirtualMin + Pages - 1) > VirtualMax))
1279 {
1280 return 0;
1281 }
1282
1283 /* Finally, pick the correct address based on direction */
1284 if (TopDown)
1285 {
1286 /* Highest possible base address, aligned */
1287 VirtualPage = VirtualMax - Pages + 1 - BaseDelta;
1288 }
1289 else
1290 {
1291 /* Lowest possible base address, aligned */
1292 VirtualPage = VirtualMin;
1293 }
1294 }
1295 else
1296 {
1297 /* Nothing to worry about */
1298 VirtualPage = 0;
1299 }
1300
1301 /* Bail out if the memory type attributes don't match */
1302 if ((((Flags & 0xFF) & (Descriptor->Flags & 0xFF)) != (Flags & 0xFF)) ||
1303 (((Flags & 0xFF00) & (Descriptor->Flags & 0xFF00)) != (Flags & 0xFF00)))
1304 {
1305 EfiPrintf(L"Incorrect memory attributes\r\n");
1306 return FALSE;
1307 }
1308
1309 /* Bail out if the allocation flags don't match */
1310 if (((Flags ^ Descriptor->Flags) & (BlMemoryRuntime | BlMemoryBelow1MB | BlMemoryLargePages)))
1311 {
1312 //EfiPrintf(L"Incorrect memory allocation flags\r\n");
1313 return FALSE;
1314 }
1315
1316 /* Bail out if the type doesn't match */
1317 if (Descriptor->Type != MemoryType)
1318 {
1319 //EfiPrintf(L"Incorrect descriptor type: %lx %lx\r\n", Descriptor->Type, MemoryType);
1320 return FALSE;
1321 }
1322
1323 /* We have a matching region, fill out the descriptor for it */
1324 NewDescriptor->BasePage = BasePage;
1325 NewDescriptor->PageCount = Pages;
1326 NewDescriptor->Type = Descriptor->Type;
1327 NewDescriptor->VirtualPage = VirtualPage;
1328 NewDescriptor->Flags = Descriptor->Flags;
1329 //EfiPrintf(L"Found a matching descriptor: %08I64X with %08I64X pages\r\n", BasePage, Pages);
1330 return TRUE;
1331 }
1332
1333 VOID
1334 MmMdFreeGlobalDescriptors (
1335 VOID
1336 )
1337 {
1338 PBL_MEMORY_DESCRIPTOR Descriptor, OldDescriptor;
1339 ULONG Index = 0;
1340 PLIST_ENTRY OldFlink, OldBlink;
1341
1342 /* Make sure we're not int middle of a call using a descriptor */
1343 if (MmDescriptorCallTreeCount != 1)
1344 {
1345 return;
1346 }
1347
1348 /* Loop every current global descriptor */
1349 while (Index < MmGlobalMemoryDescriptorsUsed)
1350 {
1351 /* Does it have any valid pages? */
1352 OldDescriptor = &MmGlobalMemoryDescriptors[Index];
1353 if (OldDescriptor->PageCount)
1354 {
1355 /* Allocate a copy of it */
1356 Descriptor = BlMmAllocateHeap(sizeof(*Descriptor));
1357 if (!Descriptor)
1358 {
1359 return;
1360 }
1361
1362 /* Save the links */
1363 OldBlink = OldDescriptor->ListEntry.Blink;
1364 OldFlink = OldDescriptor->ListEntry.Flink;
1365
1366 /* Make the copy */
1367 *Descriptor = *OldDescriptor;
1368
1369 /* Fix the links */
1370 OldBlink->Flink = &Descriptor->ListEntry;
1371 OldFlink->Blink = &Descriptor->ListEntry;
1372
1373 /* Zero the descriptor */
1374 RtlZeroMemory(OldDescriptor, sizeof(*OldDescriptor));
1375 }
1376
1377 /* Keep going */
1378 Index++;
1379 }
1380
1381 /* All global descriptors freed */
1382 MmGlobalMemoryDescriptorsUsed = 0;
1383 }
1384
1385 VOID
1386 MmMdInitialize (
1387 _In_ ULONG Phase,
1388 _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
1389 )
1390 {
1391 /* Are we in phase 1? */
1392 if (Phase != 0)
1393 {
1394 /* Switch to dynamic descriptors if we have too many */
1395 if (LibraryParameters->DescriptorCount > RTL_NUMBER_OF(MmStaticMemoryDescriptors))
1396 {
1397 MmMdpSwitchToDynamicDescriptors(LibraryParameters->DescriptorCount);
1398 }
1399 }
1400 else
1401 {
1402 /* In phase 0, start with a pool of 512 static descriptors */
1403 MmGlobalMemoryDescriptorCount = RTL_NUMBER_OF(MmStaticMemoryDescriptors);
1404 MmGlobalMemoryDescriptors = MmStaticMemoryDescriptors;
1405 RtlZeroMemory(MmStaticMemoryDescriptors, sizeof(MmStaticMemoryDescriptors));
1406 MmGlobalMemoryDescriptorsUsed = 0;
1407 }
1408 }