[STORAHCI] Merge Storport Miniport driver by Aman Priyadarshi in GSoC.
[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 BOOLEAN 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 BlEfiRuntimeMemory,
30 BlAcpiNvsMemory,
31 BlAcpiReclaimMemory,
32 BlEfiBootMemory
33 };
34
35 /* FUNCTIONS *****************************************************************/
36
37 /* The order is Conventional > Other > System > Loader > Application */
38 BOOLEAN
39 MmMdpHasPrecedence (
40 _In_ BL_MEMORY_TYPE Type1,
41 _In_ BL_MEMORY_TYPE Type2
42 )
43 {
44 BL_MEMORY_CLASS Class1, Class2;
45 ULONG i, j;
46
47 /* Descriptor is free RAM -- it precedes */
48 if (Type1 == BlConventionalMemory)
49 {
50 return TRUE;
51 }
52
53 /* It isn't free RAM, but the comparator is -- it succeeds it */
54 if (Type2 == BlConventionalMemory)
55 {
56 return FALSE;
57 }
58
59 /* Descriptor is not system, application, or loader class -- it precedes */
60 Class1 = Type1 >> BL_MEMORY_CLASS_SHIFT;
61 if ((Class1 != BlSystemClass) &&
62 (Class1 != BlApplicationClass) &&
63 (Class1 != BlLoaderClass))
64 {
65 return TRUE;
66 }
67
68 /* It isn't one of those classes, but the comparator it -- it succeeds it */
69 Class2 = Type2 >> BL_MEMORY_CLASS_SHIFT;
70 if ((Class2 != BlSystemClass) &&
71 (Class2 != BlApplicationClass) &&
72 (Class2 != BlLoaderClass))
73 {
74 return FALSE;
75 }
76
77 /* Descriptor is system class */
78 if (Class1 == BlSystemClass)
79 {
80 /* And so is the other guy... */
81 if (Class2 == BlSystemClass)
82 {
83 i = 0;
84 j = 0;
85
86 /* Scan for the descriptor's system precedence index */
87 do
88 {
89 if (MmPlatformMemoryTypePrecedence[j] == Type1)
90 {
91 break;
92 }
93 } while (++j < RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence));
94
95 /* Use an invalid index if one wasn't found */
96 if (j == RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence))
97 {
98 j = 0xFFFFFFFF;
99 }
100
101 /* Now scan for the comparator's system precedence index */
102 while (MmPlatformMemoryTypePrecedence[i] != Type2)
103 {
104 /* Use an invalid index if one wasn't found */
105 if (++i >= RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence))
106 {
107 i = 0xFFFFFFFF;
108 break;
109 }
110 }
111
112 /* Does the current have a valid index? */
113 if (j != 0xFFFFFFFF)
114 {
115 /* Yes, what about the comparator? */
116 if (i != 0xFFFFFFFF)
117 {
118 /* Let the indexes fight! */
119 return i >= j;
120 }
121
122 /* Succeed the comparator, its index is unknown */
123 return FALSE;
124 }
125 }
126
127 /* The comparator isn't system, so it precedes it */
128 return TRUE;
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 precedes */
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 while (1);
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) && (MemoryDescriptor < &MmStaticMemoryDescriptors[511])))
168 {
169 /* It's a global/static descriptor, so just zero it */
170 RtlZeroMemory(MemoryDescriptor, sizeof(BL_MEMORY_DESCRIPTOR));
171 Status = STATUS_SUCCESS;
172 }
173 else
174 {
175 /* It's a dynamic descriptor, so free it */
176 EfiPrintf(L"Dynamic descriptors not yet supported\r\n");
177 Status = STATUS_NOT_IMPLEMENTED;
178 }
179
180 /* Done */
181 return Status;
182 }
183
184 VOID
185 MmMdpSaveCurrentListPointer (
186 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
187 _In_ PLIST_ENTRY Current
188 )
189 {
190 /* Make sure that this is not a global descriptor and not the first one */
191 if (((Current < &MmGlobalMemoryDescriptors->ListEntry) ||
192 (Current >= &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorCount].ListEntry)) &&
193 (Current != MdList->First))
194 {
195 /* Save this as the current pointer */
196 MdList->This = Current;
197 }
198 }
199
200 VOID
201 MmMdRemoveDescriptorFromList (
202 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
203 _In_ PBL_MEMORY_DESCRIPTOR Entry
204 )
205 {
206 /* Remove the entry */
207 RemoveEntryList(&Entry->ListEntry);
208
209 /* Check if this was the current link */
210 if (MdList->This == &Entry->ListEntry)
211 {
212 /* Remove the current link and set the next one */
213 MdList->This = NULL;
214 MmMdpSaveCurrentListPointer(MdList, Entry->ListEntry.Blink);
215 }
216 }
217
218 VOID
219 MmMdFreeList(
220 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
221 )
222 {
223 PLIST_ENTRY FirstEntry, NextEntry;
224 PBL_MEMORY_DESCRIPTOR Entry;
225
226 /* Go over every descriptor from the top */
227 FirstEntry = MdList->First;
228 NextEntry = FirstEntry->Flink;
229 while (NextEntry != FirstEntry)
230 {
231 /* Remove and free each one */
232 Entry = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
233 NextEntry = NextEntry->Flink;
234 MmMdRemoveDescriptorFromList(MdList, Entry);
235 MmMdFreeDescriptor(Entry);
236 }
237 }
238
239 PBL_MEMORY_DESCRIPTOR
240 MmMdInitByteGranularDescriptor (
241 _In_ ULONG Flags,
242 _In_ BL_MEMORY_TYPE Type,
243 _In_ ULONGLONG BasePage,
244 _In_ ULONGLONG VirtualPage,
245 _In_ ULONGLONG PageCount
246 )
247 {
248 PBL_MEMORY_DESCRIPTOR MemoryDescriptor;
249
250 /* If we're out of descriptors, bail out */
251 if (MmGlobalMemoryDescriptorsUsed >= MmGlobalMemoryDescriptorCount)
252 {
253 EfiPrintf(L"Out of descriptors!\r\n");
254 return NULL;
255 }
256
257 /* Take one of the available descriptors and fill it out */
258 MemoryDescriptor = &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorsUsed];
259 MemoryDescriptor->BaseAddress = BasePage;
260 MemoryDescriptor->VirtualPage = VirtualPage;
261 MemoryDescriptor->PageCount = PageCount;
262 MemoryDescriptor->Flags = Flags;
263 MemoryDescriptor->Type = Type;
264 InitializeListHead(&MemoryDescriptor->ListEntry);
265
266 /* Increment the count and return the descriptor */
267 MmGlobalMemoryDescriptorsUsed++;
268 return MemoryDescriptor;
269 }
270
271 BOOLEAN
272 MmMdpTruncateDescriptor (
273 __in PBL_MEMORY_DESCRIPTOR_LIST MdList,
274 __in PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
275 __in ULONG Flags
276 )
277 {
278 PBL_MEMORY_DESCRIPTOR NextDescriptor, PreviousDescriptor;
279 PLIST_ENTRY NextEntry, PreviousEntry;
280 ULONGLONG EndPage, PreviousEndPage;// , NextEndPage;
281
282 /* Get the next descriptor */
283 NextEntry = MemoryDescriptor->ListEntry.Flink;
284 NextDescriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
285
286 /* Get the previous descriptor */
287 PreviousEntry = MemoryDescriptor->ListEntry.Blink;
288 PreviousDescriptor = CONTAINING_RECORD(PreviousEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
289
290 /* Calculate end pages */
291 EndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
292 //NextEndPage = NextDescriptor->BasePage + NextDescriptor->PageCount;
293 PreviousEndPage = PreviousDescriptor->BasePage + PreviousDescriptor->PageCount;
294
295 /* Check for backward overlap */
296 if ((PreviousEntry != MdList->First) && (MemoryDescriptor->BasePage < PreviousEndPage))
297 {
298 EfiPrintf(L"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
299 }
300
301 /* Check for forward overlap */
302 if ((NextEntry != MdList->First) && (NextDescriptor->BasePage < EndPage))
303 {
304 EfiPrintf(L"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
305 }
306
307 /* Nothing to do */
308 return FALSE;
309 }
310
311 BOOLEAN
312 MmMdpCoalesceDescriptor (
313 __in PBL_MEMORY_DESCRIPTOR_LIST MdList,
314 __in PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
315 __in ULONG Flags
316 )
317 {
318 PBL_MEMORY_DESCRIPTOR NextDescriptor, PreviousDescriptor;
319 PLIST_ENTRY NextEntry, PreviousEntry;
320 ULONGLONG EndPage, PreviousEndPage, PreviousMappedEndPage, MappedEndPage;
321
322 /* Get the next descriptor */
323 NextEntry = MemoryDescriptor->ListEntry.Flink;
324 NextDescriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
325
326 /* Get the previous descriptor */
327 PreviousEntry = MemoryDescriptor->ListEntry.Blink;
328 PreviousDescriptor = CONTAINING_RECORD(PreviousEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
329
330 /* Calculate end pages */
331 EndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
332 MappedEndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
333 PreviousMappedEndPage = PreviousDescriptor->VirtualPage + PreviousDescriptor->PageCount;
334 PreviousEndPage = PreviousDescriptor->BasePage + PreviousDescriptor->PageCount;
335 PreviousMappedEndPage = PreviousDescriptor->VirtualPage + PreviousDescriptor->PageCount;
336
337 /* Check if the previous entry touches the current entry, and is compatible */
338 if ((PreviousEntry != MdList->First) &&
339 (PreviousDescriptor->Type == MemoryDescriptor->Type) &&
340 ((PreviousDescriptor->Flags ^ MemoryDescriptor->Flags) & 0x1B19FFFF) &&
341 (PreviousEndPage == MemoryDescriptor->BasePage) &&
342 ((!(MemoryDescriptor->VirtualPage) && !(PreviousDescriptor->VirtualPage)) ||
343 ((MemoryDescriptor->VirtualPage) && (PreviousDescriptor->VirtualPage) &&
344 (PreviousMappedEndPage == MemoryDescriptor->VirtualPage))))
345 {
346 EfiPrintf(L"Previous descriptor coalescable!\r\n");
347 }
348
349 /* CHeck if the current entry touches the next entry, and is compatible */
350 if ((NextEntry != MdList->First) &&
351 (NextDescriptor->Type == MemoryDescriptor->Type) &&
352 ((NextDescriptor->Flags ^ MemoryDescriptor->Flags) & 0x1B19FFFF) &&
353 (EndPage == NextDescriptor->BasePage) &&
354 ((!(MemoryDescriptor->VirtualPage) && !(PreviousDescriptor->VirtualPage)) ||
355 ((MemoryDescriptor->VirtualPage) && (PreviousDescriptor->VirtualPage) &&
356 (MappedEndPage == NextDescriptor->VirtualPage))))
357 {
358 EfiPrintf(L"Next descriptor coalescable!\r\n");
359 }
360
361 /* Nothing to do */
362 return FALSE;
363 }
364
365 NTSTATUS
366 MmMdAddDescriptorToList (
367 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
368 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
369 _In_ ULONG Flags
370 )
371 {
372 PLIST_ENTRY ThisEntry, FirstEntry;
373 PBL_MEMORY_DESCRIPTOR ThisDescriptor;
374
375 /* Arguments must be present */
376 if (!(MdList) || !(MemoryDescriptor))
377 {
378 return STATUS_INVALID_PARAMETER;
379 }
380
381 /* Check if coalescing is forcefully disabled */
382 if (Flags & BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG)
383 {
384 /* Then we won't be coalescing */
385 Flags &= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG;
386 }
387 else
388 {
389 /* Coalesce if the descriptor requires it */
390 if (MemoryDescriptor->Flags & BlMemoryCoalesced)
391 {
392 Flags |= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG;
393 }
394 }
395
396 /* Check if truncation is forcefully disabled */
397 if (Flags & BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG)
398 {
399 Flags &= ~BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG;
400 }
401
402 /* Update the current list pointer if the descriptor requires it */
403 if (MemoryDescriptor->Flags & BlMemoryUpdate)
404 {
405 Flags |= BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG;
406 }
407
408 /* Get the current descriptor */
409 ThisEntry = MdList->This;
410 ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
411
412 /* Also get the first descriptor */
413 FirstEntry = MdList->First;
414
415 /* Check if there's no current pointer, or if it's higher than the new one */
416 if (!(ThisEntry) ||
417 (MemoryDescriptor->BaseAddress <= ThisDescriptor->BaseAddress))
418 {
419 /* Start at the first descriptor instead, since current is past us */
420 ThisEntry = FirstEntry->Flink;
421 ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
422 }
423
424 /* Loop until we find the right location to insert */
425 while (1)
426 {
427 /* Have we gotten back to the first entry? */
428 if (ThisEntry == FirstEntry)
429 {
430 /* Then we didn't find a good match, so insert it right here */
431 InsertTailList(FirstEntry, &MemoryDescriptor->ListEntry);
432
433 /* Do we have to truncate? */
434 if (Flags & BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG)
435 {
436 /* Do it and then exit */
437 if (MmMdpTruncateDescriptor(MdList, MemoryDescriptor, Flags))
438 {
439 return STATUS_SUCCESS;
440 }
441 }
442
443 /* Do we have to coalesce? */
444 if (Flags & BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG)
445 {
446 /* Do it and then exit */
447 if (MmMdpCoalesceDescriptor(MdList, MemoryDescriptor, Flags))
448 {
449 return STATUS_SUCCESS;
450 }
451 }
452
453 /* Do we have to update the current pointer? */
454 if (Flags & BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG)
455 {
456 /* Do it */
457 MmMdpSaveCurrentListPointer(MdList, &MemoryDescriptor->ListEntry);
458 }
459
460 /* We're done */
461 return STATUS_SUCCESS;
462 }
463
464 /* Is the new descriptor below this address, and has precedence over it? */
465 if ((MemoryDescriptor->BaseAddress < ThisDescriptor->BaseAddress) &&
466 (MmMdpHasPrecedence(MemoryDescriptor->Type, ThisDescriptor->Type)))
467 {
468 /* Then insert right here */
469 InsertTailList(ThisEntry, &MemoryDescriptor->ListEntry);
470 return STATUS_SUCCESS;
471 }
472
473 /* Try the next descriptor */
474 ThisEntry = ThisEntry->Flink;
475 ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
476 }
477 }
478
479 NTSTATUS
480 MmMdRemoveRegionFromMdlEx (
481 __in PBL_MEMORY_DESCRIPTOR_LIST MdList,
482 __in ULONG Flags,
483 __in ULONGLONG BasePage,
484 __in ULONGLONG PageCount,
485 __in PBL_MEMORY_DESCRIPTOR_LIST NewMdList
486 )
487 {
488 BOOLEAN HaveNewList, UseVirtualPage;
489 NTSTATUS Status;
490 PLIST_ENTRY ListHead, NextEntry;
491 PBL_MEMORY_DESCRIPTOR Descriptor;
492 BL_MEMORY_DESCRIPTOR NewDescriptor;
493 ULONGLONG RegionSize;
494 ULONGLONG FoundBasePage, FoundEndPage, FoundPageCount, EndPage;
495
496 /* Set initial status */
497 Status = STATUS_SUCCESS;
498
499 /* Check if removed descriptors should go into a new list */
500 if (NewMdList != NULL)
501 {
502 /* Initialize it */
503 MmMdInitializeListHead(NewMdList);
504 NewMdList->Type = MdList->Type;
505
506 /* Remember for later */
507 HaveNewList = TRUE;
508 }
509 else
510 {
511 /* For later */
512 HaveNewList = FALSE;
513 }
514
515 /* Is the region being removed physical? */
516 UseVirtualPage = FALSE;
517 if (!(Flags & BL_MM_REMOVE_VIRTUAL_REGION_FLAG))
518 {
519 /* Is this a list of virtual descriptors? */
520 if (MdList->Type == BlMdVirtual)
521 {
522 /* Request is nonsensical, fail */
523 Status = STATUS_INVALID_PARAMETER;
524 goto Quickie;
525 }
526 }
527 else
528 {
529 /* Is this a list of physical descriptors? */
530 if (MdList->Type == BlMdPhysical)
531 {
532 /* We'll have to use the virtual page instead */
533 UseVirtualPage = TRUE;
534 }
535 }
536
537 /* Loop the list*/
538 ListHead = MdList->First;
539 NextEntry = ListHead->Flink;
540 while (NextEntry != ListHead)
541 {
542 /* Get the descriptor */
543 Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
544
545 /* Extract range details */
546 FoundBasePage = UseVirtualPage ? Descriptor->VirtualPage : Descriptor->BasePage;
547 FoundPageCount = Descriptor->PageCount;
548 FoundEndPage = FoundBasePage + FoundPageCount;
549 EndPage = PageCount + BasePage;
550 //EarlyPrint(L"Looking for Region 0x%08I64X-0x%08I64X in 0x%08I64X-0x%08I64X\r\n", BasePage, EndPage, FoundBasePage, FoundEndPage);
551
552 /* Make a copy of the original descriptor */
553 RtlCopyMemory(&NewDescriptor, NextEntry, sizeof(NewDescriptor));
554
555 /* Check if the region to be removed starts after the found region starts */
556 if ((BasePage > FoundBasePage) || (FoundBasePage >= EndPage))
557 {
558 /* Check if the region ends after the found region */
559 if ((BasePage >= FoundEndPage) || (FoundEndPage > EndPage))
560 {
561 /* Check if the found region starts after the region or ends before the region */
562 if ((FoundBasePage >= BasePage) || (EndPage >= FoundEndPage))
563 {
564 /* This descriptor doesn't cover any part of the range */
565 //EarlyPrint(L"No part of this descriptor contains the region\r\n");
566 }
567 else
568 {
569 /* This descriptor covers the head of the allocation */
570 //EarlyPrint(L"Descriptor covers the head of the region\r\n");
571 }
572 }
573 else
574 {
575 /* This descriptor contains the entire allocation */
576 //EarlyPrint(L"Descriptor contains the entire region\r\n");
577 }
578
579 /* Keep going */
580 NextEntry = NextEntry->Flink;
581 }
582 else
583 {
584 /*
585 * This descriptor contains the end of the allocation. It may:
586 *
587 * - Contain the full allocation (i.e.: the start is aligned)
588 * - Contain parts of the end of the allocation (i.e.: the end is beyond)
589 * - Contain the entire tail end of the allocation (i..e:the end is within)
590 *
591 * So first, figure out if we cover the entire end or not
592 */
593 if (EndPage > FoundEndPage)
594 {
595 /* The allocation goes past the end of this descriptor */
596 EndPage = FoundEndPage;
597 }
598
599 /* This is how many pages we will eat away from the descriptor */
600 RegionSize = EndPage - FoundBasePage;
601
602 /* Update the descriptor to account for the consumed pages */
603 Descriptor->BasePage += RegionSize;
604 Descriptor->PageCount -= RegionSize;
605 if (Descriptor->VirtualPage)
606 {
607 Descriptor->VirtualPage += RegionSize;
608 }
609
610 /* Go to the next entry */
611 NextEntry = NextEntry->Flink;
612
613 /* Check if the descriptor is now empty */
614 if (!Descriptor->PageCount)
615 {
616 /* Remove it */
617 //EarlyPrint(L"Entire descriptor consumed\r\n");
618 MmMdRemoveDescriptorFromList(MdList, Descriptor);
619 MmMdFreeDescriptor(Descriptor);
620
621 /* Check if we're supposed to insert it into a new list */
622 if (HaveNewList)
623 {
624 EfiPrintf(L"Not yet implemented\r\n");
625 Status = STATUS_NOT_IMPLEMENTED;
626 goto Quickie;
627 }
628 }
629 }
630 }
631
632 Quickie:
633 /* Check for failure cleanup */
634 if (!NT_SUCCESS(Status))
635 {
636 /* Did we have to build a new list? */
637 if (HaveNewList)
638 {
639 /* Free and re-initialize it */
640 MmMdFreeList(NewMdList);
641 MmMdInitializeListHead(NewMdList);
642 NewMdList->Type = MdList->Type;
643 }
644 }
645
646 return Status;
647 }
648
649 BOOLEAN
650 MmMdFindSatisfyingRegion (
651 _In_ PBL_MEMORY_DESCRIPTOR Descriptor,
652 _Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor,
653 _In_ ULONGLONG Pages,
654 _In_ PBL_ADDRESS_RANGE BaseRange,
655 _In_ PBL_ADDRESS_RANGE VirtualRange,
656 _In_ BOOLEAN TopDown,
657 _In_ BL_MEMORY_TYPE MemoryType,
658 _In_ ULONG Flags,
659 _In_ ULONG Alignment
660 )
661 {
662 ULONGLONG BaseMin, BaseMax;
663 ULONGLONG VirtualPage, BasePage;
664
665 /* Extract the minimum and maximum range */
666 BaseMin = BaseRange->Minimum;
667 BaseMax = BaseRange->Maximum;
668
669 /* Don't go below where the descriptor starts */
670 if (BaseMin < Descriptor->BasePage)
671 {
672 BaseMin = Descriptor->BasePage;
673 }
674
675 /* Don't go beyond where the descriptor ends */
676 if (BaseMax > (Descriptor->BasePage + Descriptor->PageCount - 1))
677 {
678 BaseMax = (Descriptor->BasePage + Descriptor->PageCount - 1);
679 }
680
681 /* Check for start overflow */
682 if (BaseMin > BaseMax)
683 {
684 EfiPrintf(L"Descriptor overflow\r\n");
685 return FALSE;
686 }
687
688 /* Align the base as required */
689 if (Alignment != 1)
690 {
691 BaseMin = ALIGN_UP_BY(BaseMin, Alignment);
692 }
693
694 /* Check for range overflow */
695 if (((BaseMin + Pages - 1) < BaseMin) || ((BaseMin + Pages - 1) > BaseMax))
696 {
697 return FALSE;
698 }
699
700 /* Check if this was a top-down request */
701 if (TopDown)
702 {
703 /* Then get the highest page possible */
704 BasePage = BaseMax - Pages + 1;
705 if (Alignment != 1)
706 {
707 /* Align it as needed */
708 BasePage = ALIGN_DOWN_BY(BasePage, Alignment);
709 }
710 }
711 else
712 {
713 /* Otherwise, get the lowest page possible */
714 BasePage = BaseMin;
715 }
716
717 /* If a virtual address range was passed in, this must be a virtual descriptor */
718 if (((VirtualRange->Minimum) || (VirtualRange->Maximum)) &&
719 !(Descriptor->VirtualPage))
720 {
721 return FALSE;
722 }
723
724 /* Any mapped page already? */
725 if (Descriptor->VirtualPage)
726 {
727 EfiPrintf(L"Virtual memory not yet supported\r\n");
728 return FALSE;
729 }
730 else
731 {
732 /* Nothing to worry about */
733 VirtualPage = 0;
734 }
735
736 /* Bail out if the memory type attributes don't match */
737 if ((((Flags & 0xFF) & (Descriptor->Flags & 0xFF)) != (Flags & 0xFF)) ||
738 (((Flags & 0xFF00) & (Descriptor->Flags & 0xFF00)) != (Flags & 0xFF00)))
739 {
740 EfiPrintf(L"Incorrect memory attributes\r\n");
741 return FALSE;
742 }
743
744 /* Bail out if the allocation flags don't match */
745 if (((Flags ^ Descriptor->Flags) & (BlMemoryRuntime | BlMemoryReserved | BlMemoryUnknown)))
746 {
747 //EfiPrintf(L"Incorrect memory allocation flags\r\n");
748 return FALSE;
749 }
750
751 /* Bail out if the type doesn't match */
752 if (Descriptor->Type != MemoryType)
753 {
754 //EfiPrintf(L"Incorrect descriptor type: %lx %lx\r\n", Descriptor->Type, MemoryType);
755 return FALSE;
756 }
757
758 /* We have a matching region, fill out the descriptor for it */
759 NewDescriptor->BasePage = BasePage;
760 NewDescriptor->PageCount = Pages;
761 NewDescriptor->Type = Descriptor->Type;
762 NewDescriptor->VirtualPage = VirtualPage;
763 NewDescriptor->Flags = Descriptor->Flags;
764 //EfiPrintf(L"Found a matching descriptor: %08I64X with %08I64X pages\r\n", BasePage, Pages);
765 return TRUE;
766 }
767
768 VOID
769 MmMdFreeGlobalDescriptors (
770 VOID
771 )
772 {
773 PBL_MEMORY_DESCRIPTOR Descriptor, OldDescriptor;
774 ULONG Index = 0;
775 PLIST_ENTRY OldFlink, OldBlink;
776
777 /* Make sure we're not int middle of a call using a descriptor */
778 if (MmDescriptorCallTreeCount != 1)
779 {
780 return;
781 }
782
783 /* Loop every current global descriptor */
784 while (Index < MmGlobalMemoryDescriptorsUsed)
785 {
786 /* Does it have any valid pageS? */
787 OldDescriptor = &MmGlobalMemoryDescriptors[Index];
788 if (OldDescriptor->PageCount)
789 {
790 /* Allocate a copy of it */
791 Descriptor = BlMmAllocateHeap(sizeof(*Descriptor));
792 if (!Descriptor)
793 {
794 return;
795 }
796
797 /* Save the links */
798 OldBlink = OldDescriptor->ListEntry.Blink;
799 OldFlink = OldDescriptor->ListEntry.Flink;
800
801 /* Make the copy */
802 *Descriptor = *OldDescriptor;
803
804 /* Fix the links */
805 OldBlink->Flink = &Descriptor->ListEntry;
806 OldFlink->Blink = &Descriptor->ListEntry;
807
808 /* Zero the descriptor */
809 RtlZeroMemory(OldDescriptor, sizeof(*OldDescriptor));
810 }
811
812 /* Keep going */
813 Index++;
814 }
815
816 /* All global descriptors freed */
817 MmGlobalMemoryDescriptorsUsed = 0;
818 }
819
820 VOID
821 MmMdInitialize (
822 _In_ ULONG Phase,
823 _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
824 )
825 {
826 /* Are we in phase 1? */
827 if (Phase != 0)
828 {
829 /* Switch to dynamic descriptors if we have too many */
830 if (LibraryParameters->DescriptorCount > RTL_NUMBER_OF(MmStaticMemoryDescriptors))
831 {
832 MmMdpSwitchToDynamicDescriptors(LibraryParameters->DescriptorCount);
833 }
834 }
835 else
836 {
837 /* In phase 0, start with a pool of 512 static descriptors */
838 MmGlobalMemoryDescriptorCount = RTL_NUMBER_OF(MmStaticMemoryDescriptors);
839 MmGlobalMemoryDescriptors = MmStaticMemoryDescriptors;
840 RtlZeroMemory(MmStaticMemoryDescriptors, sizeof(MmStaticMemoryDescriptors));
841 MmGlobalMemoryDescriptorsUsed = FALSE;
842 }
843 }