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