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 Status = BlMmFreeHeap(MemoryDescriptor); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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