1 /** @file 2 The file contains the GCD related services in the EFI Boot Services Table. 3 The GCD services are used to manage the memory and I/O regions that 4 are accessible to the CPU that is executing the DXE core. 5 6 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 #include "DxeMain.h" 18 #include "Gcd.h" 19 20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000 21 22 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ 23 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ 24 EFI_RESOURCE_ATTRIBUTE_TESTED | \ 25 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \ 26 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \ 27 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \ 28 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \ 29 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \ 30 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \ 31 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \ 32 EFI_RESOURCE_ATTRIBUTE_PERSISTENT ) 33 34 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ 35 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ 36 EFI_RESOURCE_ATTRIBUTE_TESTED ) 37 38 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ 39 EFI_RESOURCE_ATTRIBUTE_INITIALIZED ) 40 41 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT) 42 43 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff 44 45 // 46 // Module Variables 47 // 48 EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); 49 EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); 50 LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap); 51 LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap); 52 53 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = { 54 EFI_GCD_MAP_SIGNATURE, 55 { 56 NULL, 57 NULL 58 }, 59 0, 60 0, 61 0, 62 0, 63 EfiGcdMemoryTypeNonExistent, 64 (EFI_GCD_IO_TYPE) 0, 65 NULL, 66 NULL 67 }; 68 69 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = { 70 EFI_GCD_MAP_SIGNATURE, 71 { 72 NULL, 73 NULL 74 }, 75 0, 76 0, 77 0, 78 0, 79 (EFI_GCD_MEMORY_TYPE) 0, 80 EfiGcdIoTypeNonExistent, 81 NULL, 82 NULL 83 }; 84 85 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = { 86 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE }, 87 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE }, 88 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE }, 89 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE }, 90 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE }, 91 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE, EFI_MEMORY_RP, TRUE }, 92 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE, EFI_MEMORY_WP, TRUE }, 93 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE, EFI_MEMORY_XP, TRUE }, 94 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE, EFI_MEMORY_RO, TRUE }, 95 { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE }, 96 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE }, 97 { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE }, 98 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE, EFI_MEMORY_NV, TRUE }, 99 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE, EFI_MEMORY_MORE_RELIABLE, TRUE }, 100 { 0, 0, FALSE } 101 }; 102 103 /// 104 /// Lookup table used to print GCD Memory Space Map 105 /// 106 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = { 107 "NonExist ", // EfiGcdMemoryTypeNonExistent 108 "Reserved ", // EfiGcdMemoryTypeReserved 109 "SystemMem", // EfiGcdMemoryTypeSystemMemory 110 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo 111 "PersisMem", // EfiGcdMemoryTypePersistentMemory 112 "MoreRelia", // EfiGcdMemoryTypeMoreReliable 113 "Unknown " // EfiGcdMemoryTypeMaximum 114 }; 115 116 /// 117 /// Lookup table used to print GCD I/O Space Map 118 /// 119 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdIoTypeNames[] = { 120 "NonExist", // EfiGcdIoTypeNonExistent 121 "Reserved", // EfiGcdIoTypeReserved 122 "I/O ", // EfiGcdIoTypeIo 123 "Unknown " // EfiGcdIoTypeMaximum 124 }; 125 126 /// 127 /// Lookup table used to print GCD Allocation Types 128 /// 129 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdAllocationTypeNames[] = { 130 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp 131 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp 132 "AtAddress ", // EfiGcdAllocateAddress 133 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown 134 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown 135 "Unknown " // EfiGcdMaxAllocateType 136 }; 137 138 /** 139 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when 140 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set. 141 142 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE. 143 144 **/ 145 VOID 146 EFIAPI 147 CoreDumpGcdMemorySpaceMap ( 148 BOOLEAN InitialMap 149 ) 150 { 151 DEBUG_CODE ( 152 EFI_STATUS Status; 153 UINTN NumberOfDescriptors; 154 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; 155 UINTN Index; 156 157 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); 158 ASSERT (Status == EFI_SUCCESS && MemorySpaceMap != NULL); 159 160 if (InitialMap) { 161 DEBUG ((DEBUG_GCD, "GCD:Initial GCD Memory Space Map\n")); 162 } 163 DEBUG ((DEBUG_GCD, "GCDMemType Range Capabilities Attributes \n")); 164 DEBUG ((DEBUG_GCD, "========== ================================= ================ ================\n")); 165 for (Index = 0; Index < NumberOfDescriptors; Index++) { 166 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx %016lx %016lx%c\n", 167 mGcdMemoryTypeNames[MIN (MemorySpaceMap[Index].GcdMemoryType, EfiGcdMemoryTypeMaximum)], 168 MemorySpaceMap[Index].BaseAddress, 169 MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1, 170 MemorySpaceMap[Index].Capabilities, 171 MemorySpaceMap[Index].Attributes, 172 MemorySpaceMap[Index].ImageHandle == NULL ? ' ' : '*' 173 )); 174 } 175 DEBUG ((DEBUG_GCD, "\n")); 176 FreePool (MemorySpaceMap); 177 ); 178 } 179 180 /** 181 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when 182 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set. 183 184 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE. 185 186 **/ 187 VOID 188 EFIAPI 189 CoreDumpGcdIoSpaceMap ( 190 BOOLEAN InitialMap 191 ) 192 { 193 DEBUG_CODE ( 194 EFI_STATUS Status; 195 UINTN NumberOfDescriptors; 196 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap; 197 UINTN Index; 198 199 Status = CoreGetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap); 200 ASSERT (Status == EFI_SUCCESS && IoSpaceMap != NULL); 201 202 if (InitialMap) { 203 DEBUG ((DEBUG_GCD, "GCD:Initial GCD I/O Space Map\n")); 204 } 205 206 DEBUG ((DEBUG_GCD, "GCDIoType Range \n")); 207 DEBUG ((DEBUG_GCD, "========== =================================\n")); 208 for (Index = 0; Index < NumberOfDescriptors; Index++) { 209 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx%c\n", 210 mGcdIoTypeNames[MIN (IoSpaceMap[Index].GcdIoType, EfiGcdIoTypeMaximum)], 211 IoSpaceMap[Index].BaseAddress, 212 IoSpaceMap[Index].BaseAddress + IoSpaceMap[Index].Length - 1, 213 IoSpaceMap[Index].ImageHandle == NULL ? ' ' : '*' 214 )); 215 } 216 DEBUG ((DEBUG_GCD, "\n")); 217 FreePool (IoSpaceMap); 218 ); 219 } 220 221 /** 222 Validate resource descriptor HOB's attributes. 223 224 If Attributes includes some memory resource's settings, it should include 225 the corresponding capabilites also. 226 227 @param Attributes Resource descriptor HOB attributes. 228 229 **/ 230 VOID 231 CoreValidateResourceDescriptorHobAttributes ( 232 IN UINT64 Attributes 233 ) 234 { 235 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED) == 0) || 236 ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE) != 0)); 237 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED) == 0) || 238 ((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE) != 0)); 239 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED) == 0) || 240 ((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE) != 0)); 241 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED) == 0) || 242 ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE) != 0)); 243 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == 0) || 244 ((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTABLE) != 0)); 245 } 246 247 /** 248 Acquire memory lock on mGcdMemorySpaceLock. 249 250 **/ 251 VOID 252 CoreAcquireGcdMemoryLock ( 253 VOID 254 ) 255 { 256 CoreAcquireLock (&mGcdMemorySpaceLock); 257 } 258 259 260 261 /** 262 Release memory lock on mGcdMemorySpaceLock. 263 264 **/ 265 VOID 266 CoreReleaseGcdMemoryLock ( 267 VOID 268 ) 269 { 270 CoreReleaseLock (&mGcdMemorySpaceLock); 271 } 272 273 274 275 /** 276 Acquire memory lock on mGcdIoSpaceLock. 277 278 **/ 279 VOID 280 CoreAcquireGcdIoLock ( 281 VOID 282 ) 283 { 284 CoreAcquireLock (&mGcdIoSpaceLock); 285 } 286 287 288 /** 289 Release memory lock on mGcdIoSpaceLock. 290 291 **/ 292 VOID 293 CoreReleaseGcdIoLock ( 294 VOID 295 ) 296 { 297 CoreReleaseLock (&mGcdIoSpaceLock); 298 } 299 300 301 302 // 303 // GCD Initialization Worker Functions 304 // 305 /** 306 Aligns a value to the specified boundary. 307 308 @param Value 64 bit value to align 309 @param Alignment Log base 2 of the boundary to align Value to 310 @param RoundUp TRUE if Value is to be rounded up to the nearest 311 aligned boundary. FALSE is Value is to be 312 rounded down to the nearest aligned boundary. 313 314 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. 315 316 **/ 317 UINT64 318 AlignValue ( 319 IN UINT64 Value, 320 IN UINTN Alignment, 321 IN BOOLEAN RoundUp 322 ) 323 { 324 UINT64 AlignmentMask; 325 326 AlignmentMask = LShiftU64 (1, Alignment) - 1; 327 if (RoundUp) { 328 Value += AlignmentMask; 329 } 330 return Value & (~AlignmentMask); 331 } 332 333 334 /** 335 Aligns address to the page boundary. 336 337 @param Value 64 bit address to align 338 339 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. 340 341 **/ 342 UINT64 343 PageAlignAddress ( 344 IN UINT64 Value 345 ) 346 { 347 return AlignValue (Value, EFI_PAGE_SHIFT, TRUE); 348 } 349 350 351 /** 352 Aligns length to the page boundary. 353 354 @param Value 64 bit length to align 355 356 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. 357 358 **/ 359 UINT64 360 PageAlignLength ( 361 IN UINT64 Value 362 ) 363 { 364 return AlignValue (Value, EFI_PAGE_SHIFT, FALSE); 365 } 366 367 // 368 // GCD Memory Space Worker Functions 369 // 370 371 /** 372 Allocate pool for two entries. 373 374 @param TopEntry An entry of GCD map 375 @param BottomEntry An entry of GCD map 376 377 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated. 378 @retval EFI_SUCCESS Both entries successfully allocated. 379 380 **/ 381 EFI_STATUS 382 CoreAllocateGcdMapEntry ( 383 IN OUT EFI_GCD_MAP_ENTRY **TopEntry, 384 IN OUT EFI_GCD_MAP_ENTRY **BottomEntry 385 ) 386 { 387 *TopEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY)); 388 if (*TopEntry == NULL) { 389 return EFI_OUT_OF_RESOURCES; 390 } 391 392 *BottomEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY)); 393 if (*BottomEntry == NULL) { 394 CoreFreePool (*TopEntry); 395 return EFI_OUT_OF_RESOURCES; 396 } 397 398 return EFI_SUCCESS; 399 } 400 401 402 /** 403 Internal function. Inserts a new descriptor into a sorted list 404 405 @param Link The linked list to insert the range BaseAddress 406 and Length into 407 @param Entry A pointer to the entry that is inserted 408 @param BaseAddress The base address of the new range 409 @param Length The length of the new range in bytes 410 @param TopEntry Top pad entry to insert if needed. 411 @param BottomEntry Bottom pad entry to insert if needed. 412 413 @retval EFI_SUCCESS The new range was inserted into the linked list 414 415 **/ 416 EFI_STATUS 417 CoreInsertGcdMapEntry ( 418 IN LIST_ENTRY *Link, 419 IN EFI_GCD_MAP_ENTRY *Entry, 420 IN EFI_PHYSICAL_ADDRESS BaseAddress, 421 IN UINT64 Length, 422 IN EFI_GCD_MAP_ENTRY *TopEntry, 423 IN EFI_GCD_MAP_ENTRY *BottomEntry 424 ) 425 { 426 ASSERT (Length != 0); 427 428 if (BaseAddress > Entry->BaseAddress) { 429 ASSERT (BottomEntry->Signature == 0); 430 431 CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY)); 432 Entry->BaseAddress = BaseAddress; 433 BottomEntry->EndAddress = BaseAddress - 1; 434 InsertTailList (Link, &BottomEntry->Link); 435 } 436 437 if ((BaseAddress + Length - 1) < Entry->EndAddress) { 438 ASSERT (TopEntry->Signature == 0); 439 440 CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY)); 441 TopEntry->BaseAddress = BaseAddress + Length; 442 Entry->EndAddress = BaseAddress + Length - 1; 443 InsertHeadList (Link, &TopEntry->Link); 444 } 445 446 return EFI_SUCCESS; 447 } 448 449 450 /** 451 Merge the Gcd region specified by Link and its adjacent entry. 452 453 @param Link Specify the entry to be merged (with its 454 adjacent entry). 455 @param Forward Direction (forward or backward). 456 @param Map Boundary. 457 458 @retval EFI_SUCCESS Successfully returned. 459 @retval EFI_UNSUPPORTED These adjacent regions could not merge. 460 461 **/ 462 EFI_STATUS 463 CoreMergeGcdMapEntry ( 464 IN LIST_ENTRY *Link, 465 IN BOOLEAN Forward, 466 IN LIST_ENTRY *Map 467 ) 468 { 469 LIST_ENTRY *AdjacentLink; 470 EFI_GCD_MAP_ENTRY *Entry; 471 EFI_GCD_MAP_ENTRY *AdjacentEntry; 472 473 // 474 // Get adjacent entry 475 // 476 if (Forward) { 477 AdjacentLink = Link->ForwardLink; 478 } else { 479 AdjacentLink = Link->BackLink; 480 } 481 482 // 483 // If AdjacentLink is the head of the list, then no merge can be performed 484 // 485 if (AdjacentLink == Map) { 486 return EFI_SUCCESS; 487 } 488 489 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 490 AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 491 492 if (Entry->Capabilities != AdjacentEntry->Capabilities) { 493 return EFI_UNSUPPORTED; 494 } 495 if (Entry->Attributes != AdjacentEntry->Attributes) { 496 return EFI_UNSUPPORTED; 497 } 498 if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) { 499 return EFI_UNSUPPORTED; 500 } 501 if (Entry->GcdIoType != AdjacentEntry->GcdIoType) { 502 return EFI_UNSUPPORTED; 503 } 504 if (Entry->ImageHandle != AdjacentEntry->ImageHandle) { 505 return EFI_UNSUPPORTED; 506 } 507 if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) { 508 return EFI_UNSUPPORTED; 509 } 510 511 if (Forward) { 512 Entry->EndAddress = AdjacentEntry->EndAddress; 513 } else { 514 Entry->BaseAddress = AdjacentEntry->BaseAddress; 515 } 516 RemoveEntryList (AdjacentLink); 517 CoreFreePool (AdjacentEntry); 518 519 return EFI_SUCCESS; 520 } 521 522 523 /** 524 Merge adjacent entries on total chain. 525 526 @param TopEntry Top entry of GCD map. 527 @param BottomEntry Bottom entry of GCD map. 528 @param StartLink Start link of the list for this loop. 529 @param EndLink End link of the list for this loop. 530 @param Map Boundary. 531 532 @retval EFI_SUCCESS GCD map successfully cleaned up. 533 534 **/ 535 EFI_STATUS 536 CoreCleanupGcdMapEntry ( 537 IN EFI_GCD_MAP_ENTRY *TopEntry, 538 IN EFI_GCD_MAP_ENTRY *BottomEntry, 539 IN LIST_ENTRY *StartLink, 540 IN LIST_ENTRY *EndLink, 541 IN LIST_ENTRY *Map 542 ) 543 { 544 LIST_ENTRY *Link; 545 546 if (TopEntry->Signature == 0) { 547 CoreFreePool (TopEntry); 548 } 549 if (BottomEntry->Signature == 0) { 550 CoreFreePool (BottomEntry); 551 } 552 553 Link = StartLink; 554 while (Link != EndLink->ForwardLink) { 555 CoreMergeGcdMapEntry (Link, FALSE, Map); 556 Link = Link->ForwardLink; 557 } 558 CoreMergeGcdMapEntry (EndLink, TRUE, Map); 559 560 return EFI_SUCCESS; 561 } 562 563 564 /** 565 Search a segment of memory space in GCD map. The result is a range of GCD entry list. 566 567 @param BaseAddress The start address of the segment. 568 @param Length The length of the segment. 569 @param StartLink The first GCD entry involves this segment of 570 memory space. 571 @param EndLink The first GCD entry involves this segment of 572 memory space. 573 @param Map Points to the start entry to search. 574 575 @retval EFI_SUCCESS Successfully found the entry. 576 @retval EFI_NOT_FOUND Not found. 577 578 **/ 579 EFI_STATUS 580 CoreSearchGcdMapEntry ( 581 IN EFI_PHYSICAL_ADDRESS BaseAddress, 582 IN UINT64 Length, 583 OUT LIST_ENTRY **StartLink, 584 OUT LIST_ENTRY **EndLink, 585 IN LIST_ENTRY *Map 586 ) 587 { 588 LIST_ENTRY *Link; 589 EFI_GCD_MAP_ENTRY *Entry; 590 591 ASSERT (Length != 0); 592 593 *StartLink = NULL; 594 *EndLink = NULL; 595 596 Link = Map->ForwardLink; 597 while (Link != Map) { 598 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 599 if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) { 600 *StartLink = Link; 601 } 602 if (*StartLink != NULL) { 603 if ((BaseAddress + Length - 1) >= Entry->BaseAddress && 604 (BaseAddress + Length - 1) <= Entry->EndAddress ) { 605 *EndLink = Link; 606 return EFI_SUCCESS; 607 } 608 } 609 Link = Link->ForwardLink; 610 } 611 612 return EFI_NOT_FOUND; 613 } 614 615 616 /** 617 Count the amount of GCD map entries. 618 619 @param Map Points to the start entry to do the count loop. 620 621 @return The count. 622 623 **/ 624 UINTN 625 CoreCountGcdMapEntry ( 626 IN LIST_ENTRY *Map 627 ) 628 { 629 UINTN Count; 630 LIST_ENTRY *Link; 631 632 Count = 0; 633 Link = Map->ForwardLink; 634 while (Link != Map) { 635 Count++; 636 Link = Link->ForwardLink; 637 } 638 639 return Count; 640 } 641 642 643 644 /** 645 Return the memory attribute specified by Attributes 646 647 @param Attributes A num with some attribute bits on. 648 649 @return The enum value of memory attribute. 650 651 **/ 652 UINT64 653 ConverToCpuArchAttributes ( 654 UINT64 Attributes 655 ) 656 { 657 if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) { 658 return EFI_MEMORY_UC; 659 } 660 661 if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) { 662 return EFI_MEMORY_WC; 663 } 664 665 if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) { 666 return EFI_MEMORY_WT; 667 } 668 669 if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) { 670 return EFI_MEMORY_WB; 671 } 672 673 if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) { 674 return EFI_MEMORY_WP; 675 } 676 677 return INVALID_CPU_ARCH_ATTRIBUTES; 678 679 } 680 681 682 /** 683 Do operation on a segment of memory space specified (add, free, remove, change attribute ...). 684 685 @param Operation The type of the operation 686 @param GcdMemoryType Additional information for the operation 687 @param GcdIoType Additional information for the operation 688 @param BaseAddress Start address of the segment 689 @param Length length of the segment 690 @param Capabilities The alterable attributes of a newly added entry 691 @param Attributes The attributes needs to be set 692 693 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when 694 setting attribute. 695 @retval EFI_SUCCESS Action successfully done. 696 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this 697 segment or set an upsupported attribute. 698 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an 699 image. 700 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist 701 space, and so on. 702 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated. 703 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol 704 is not available yet. 705 **/ 706 EFI_STATUS 707 CoreConvertSpace ( 708 IN UINTN Operation, 709 IN EFI_GCD_MEMORY_TYPE GcdMemoryType, 710 IN EFI_GCD_IO_TYPE GcdIoType, 711 IN EFI_PHYSICAL_ADDRESS BaseAddress, 712 IN UINT64 Length, 713 IN UINT64 Capabilities, 714 IN UINT64 Attributes 715 ) 716 { 717 EFI_STATUS Status; 718 LIST_ENTRY *Map; 719 LIST_ENTRY *Link; 720 EFI_GCD_MAP_ENTRY *Entry; 721 EFI_GCD_MAP_ENTRY *TopEntry; 722 EFI_GCD_MAP_ENTRY *BottomEntry; 723 LIST_ENTRY *StartLink; 724 LIST_ENTRY *EndLink; 725 UINT64 CpuArchAttributes; 726 727 if (Length == 0) { 728 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); 729 return EFI_INVALID_PARAMETER; 730 } 731 732 Map = NULL; 733 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { 734 CoreAcquireGcdMemoryLock (); 735 Map = &mGcdMemorySpaceMap; 736 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) { 737 CoreAcquireGcdIoLock (); 738 Map = &mGcdIoSpaceMap; 739 } else { 740 ASSERT (FALSE); 741 } 742 743 // 744 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length 745 // 746 Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map); 747 if (EFI_ERROR (Status)) { 748 Status = EFI_UNSUPPORTED; 749 750 goto Done; 751 } 752 ASSERT (StartLink != NULL && EndLink != NULL); 753 754 // 755 // Verify that the list of descriptors are unallocated non-existent memory. 756 // 757 Link = StartLink; 758 while (Link != EndLink->ForwardLink) { 759 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 760 switch (Operation) { 761 // 762 // Add operations 763 // 764 case GCD_ADD_MEMORY_OPERATION: 765 if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent || 766 Entry->ImageHandle != NULL ) { 767 Status = EFI_ACCESS_DENIED; 768 goto Done; 769 } 770 break; 771 case GCD_ADD_IO_OPERATION: 772 if (Entry->GcdIoType != EfiGcdIoTypeNonExistent || 773 Entry->ImageHandle != NULL ) { 774 Status = EFI_ACCESS_DENIED; 775 goto Done; 776 } 777 break; 778 // 779 // Free operations 780 // 781 case GCD_FREE_MEMORY_OPERATION: 782 case GCD_FREE_IO_OPERATION: 783 if (Entry->ImageHandle == NULL) { 784 Status = EFI_NOT_FOUND; 785 goto Done; 786 } 787 break; 788 // 789 // Remove operations 790 // 791 case GCD_REMOVE_MEMORY_OPERATION: 792 if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) { 793 Status = EFI_NOT_FOUND; 794 goto Done; 795 } 796 if (Entry->ImageHandle != NULL) { 797 Status = EFI_ACCESS_DENIED; 798 goto Done; 799 } 800 break; 801 case GCD_REMOVE_IO_OPERATION: 802 if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) { 803 Status = EFI_NOT_FOUND; 804 goto Done; 805 } 806 if (Entry->ImageHandle != NULL) { 807 Status = EFI_ACCESS_DENIED; 808 goto Done; 809 } 810 break; 811 // 812 // Set attributes operation 813 // 814 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION: 815 if ((Attributes & EFI_MEMORY_RUNTIME) != 0) { 816 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) { 817 Status = EFI_INVALID_PARAMETER; 818 goto Done; 819 } 820 } 821 if ((Entry->Capabilities & Attributes) != Attributes) { 822 Status = EFI_UNSUPPORTED; 823 goto Done; 824 } 825 break; 826 // 827 // Set capabilities operation 828 // 829 case GCD_SET_CAPABILITIES_MEMORY_OPERATION: 830 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) { 831 Status = EFI_INVALID_PARAMETER; 832 833 goto Done; 834 } 835 // 836 // Current attributes must still be supported with new capabilities 837 // 838 if ((Capabilities & Entry->Attributes) != Entry->Attributes) { 839 Status = EFI_UNSUPPORTED; 840 goto Done; 841 } 842 break; 843 } 844 Link = Link->ForwardLink; 845 } 846 847 // 848 // Allocate work space to perform this operation 849 // 850 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry); 851 if (EFI_ERROR (Status)) { 852 Status = EFI_OUT_OF_RESOURCES; 853 goto Done; 854 } 855 ASSERT (TopEntry != NULL && BottomEntry != NULL); 856 857 if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) { 858 // 859 // Call CPU Arch Protocol to attempt to set attributes on the range 860 // 861 CpuArchAttributes = ConverToCpuArchAttributes (Attributes); 862 if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) { 863 if (gCpu == NULL) { 864 Status = EFI_NOT_AVAILABLE_YET; 865 } else { 866 Status = gCpu->SetMemoryAttributes ( 867 gCpu, 868 BaseAddress, 869 Length, 870 CpuArchAttributes 871 ); 872 } 873 if (EFI_ERROR (Status)) { 874 CoreFreePool (TopEntry); 875 CoreFreePool (BottomEntry); 876 goto Done; 877 } 878 } 879 } 880 881 // 882 // Convert/Insert the list of descriptors from StartLink to EndLink 883 // 884 Link = StartLink; 885 while (Link != EndLink->ForwardLink) { 886 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 887 CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry); 888 switch (Operation) { 889 // 890 // Add operations 891 // 892 case GCD_ADD_MEMORY_OPERATION: 893 Entry->GcdMemoryType = GcdMemoryType; 894 if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { 895 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO; 896 } else { 897 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME; 898 } 899 break; 900 case GCD_ADD_IO_OPERATION: 901 Entry->GcdIoType = GcdIoType; 902 break; 903 // 904 // Free operations 905 // 906 case GCD_FREE_MEMORY_OPERATION: 907 case GCD_FREE_IO_OPERATION: 908 Entry->ImageHandle = NULL; 909 Entry->DeviceHandle = NULL; 910 break; 911 // 912 // Remove operations 913 // 914 case GCD_REMOVE_MEMORY_OPERATION: 915 Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent; 916 Entry->Capabilities = 0; 917 break; 918 case GCD_REMOVE_IO_OPERATION: 919 Entry->GcdIoType = EfiGcdIoTypeNonExistent; 920 break; 921 // 922 // Set attributes operation 923 // 924 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION: 925 Entry->Attributes = Attributes; 926 break; 927 // 928 // Set capabilities operation 929 // 930 case GCD_SET_CAPABILITIES_MEMORY_OPERATION: 931 Entry->Capabilities = Capabilities; 932 break; 933 } 934 Link = Link->ForwardLink; 935 } 936 937 // 938 // Cleanup 939 // 940 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map); 941 942 Done: 943 DEBUG ((DEBUG_GCD, " Status = %r\n", Status)); 944 945 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { 946 CoreReleaseGcdMemoryLock (); 947 CoreDumpGcdMemorySpaceMap (FALSE); 948 } 949 if ((Operation & GCD_IO_SPACE_OPERATION) != 0) { 950 CoreReleaseGcdIoLock (); 951 CoreDumpGcdIoSpaceMap (FALSE); 952 } 953 954 return Status; 955 } 956 957 958 /** 959 Check whether an entry could be used to allocate space. 960 961 @param Operation Allocate memory or IO 962 @param Entry The entry to be tested 963 @param GcdMemoryType The desired memory type 964 @param GcdIoType The desired IO type 965 966 @retval EFI_NOT_FOUND The memory type does not match or there's an 967 image handle on the entry. 968 @retval EFI_UNSUPPORTED The operation unsupported. 969 @retval EFI_SUCCESS It's ok for this entry to be used to allocate 970 space. 971 972 **/ 973 EFI_STATUS 974 CoreAllocateSpaceCheckEntry ( 975 IN UINTN Operation, 976 IN EFI_GCD_MAP_ENTRY *Entry, 977 IN EFI_GCD_MEMORY_TYPE GcdMemoryType, 978 IN EFI_GCD_IO_TYPE GcdIoType 979 ) 980 { 981 if (Entry->ImageHandle != NULL) { 982 return EFI_NOT_FOUND; 983 } 984 switch (Operation) { 985 case GCD_ALLOCATE_MEMORY_OPERATION: 986 if (Entry->GcdMemoryType != GcdMemoryType) { 987 return EFI_NOT_FOUND; 988 } 989 break; 990 case GCD_ALLOCATE_IO_OPERATION: 991 if (Entry->GcdIoType != GcdIoType) { 992 return EFI_NOT_FOUND; 993 } 994 break; 995 default: 996 return EFI_UNSUPPORTED; 997 } 998 return EFI_SUCCESS; 999 } 1000 1001 1002 /** 1003 Allocate space on specified address and length. 1004 1005 @param Operation The type of operation (memory or IO) 1006 @param GcdAllocateType The type of allocate operation 1007 @param GcdMemoryType The desired memory type 1008 @param GcdIoType The desired IO type 1009 @param Alignment Align with 2^Alignment 1010 @param Length Length to allocate 1011 @param BaseAddress Base address to allocate 1012 @param ImageHandle The image handle consume the allocated space. 1013 @param DeviceHandle The device handle consume the allocated space. 1014 1015 @retval EFI_INVALID_PARAMETER Invalid parameter. 1016 @retval EFI_NOT_FOUND No descriptor for the desired space exists. 1017 @retval EFI_SUCCESS Space successfully allocated. 1018 1019 **/ 1020 EFI_STATUS 1021 CoreAllocateSpace ( 1022 IN UINTN Operation, 1023 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, 1024 IN EFI_GCD_MEMORY_TYPE GcdMemoryType, 1025 IN EFI_GCD_IO_TYPE GcdIoType, 1026 IN UINTN Alignment, 1027 IN UINT64 Length, 1028 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, 1029 IN EFI_HANDLE ImageHandle, 1030 IN EFI_HANDLE DeviceHandle OPTIONAL 1031 ) 1032 { 1033 EFI_STATUS Status; 1034 EFI_PHYSICAL_ADDRESS AlignmentMask; 1035 EFI_PHYSICAL_ADDRESS MaxAddress; 1036 LIST_ENTRY *Map; 1037 LIST_ENTRY *Link; 1038 LIST_ENTRY *SubLink; 1039 EFI_GCD_MAP_ENTRY *Entry; 1040 EFI_GCD_MAP_ENTRY *TopEntry; 1041 EFI_GCD_MAP_ENTRY *BottomEntry; 1042 LIST_ENTRY *StartLink; 1043 LIST_ENTRY *EndLink; 1044 BOOLEAN Found; 1045 1046 // 1047 // Make sure parameters are valid 1048 // 1049 if ((UINT32)GcdAllocateType >= EfiGcdMaxAllocateType) { 1050 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); 1051 return EFI_INVALID_PARAMETER; 1052 } 1053 if ((UINT32)GcdMemoryType >= EfiGcdMemoryTypeMaximum) { 1054 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); 1055 return EFI_INVALID_PARAMETER; 1056 } 1057 if ((UINT32)GcdIoType >= EfiGcdIoTypeMaximum) { 1058 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); 1059 return EFI_INVALID_PARAMETER; 1060 } 1061 if (BaseAddress == NULL) { 1062 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); 1063 return EFI_INVALID_PARAMETER; 1064 } 1065 if (ImageHandle == NULL) { 1066 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); 1067 return EFI_INVALID_PARAMETER; 1068 } 1069 if (Alignment >= 64) { 1070 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_NOT_FOUND)); 1071 return EFI_NOT_FOUND; 1072 } 1073 if (Length == 0) { 1074 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); 1075 return EFI_INVALID_PARAMETER; 1076 } 1077 1078 Map = NULL; 1079 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { 1080 CoreAcquireGcdMemoryLock (); 1081 Map = &mGcdMemorySpaceMap; 1082 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) { 1083 CoreAcquireGcdIoLock (); 1084 Map = &mGcdIoSpaceMap; 1085 } else { 1086 ASSERT (FALSE); 1087 } 1088 1089 Found = FALSE; 1090 StartLink = NULL; 1091 EndLink = NULL; 1092 // 1093 // Compute alignment bit mask 1094 // 1095 AlignmentMask = LShiftU64 (1, Alignment) - 1; 1096 1097 if (GcdAllocateType == EfiGcdAllocateAddress) { 1098 // 1099 // Verify that the BaseAddress passed in is aligned correctly 1100 // 1101 if ((*BaseAddress & AlignmentMask) != 0) { 1102 Status = EFI_NOT_FOUND; 1103 goto Done; 1104 } 1105 1106 // 1107 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length 1108 // 1109 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map); 1110 if (EFI_ERROR (Status)) { 1111 Status = EFI_NOT_FOUND; 1112 goto Done; 1113 } 1114 ASSERT (StartLink != NULL && EndLink != NULL); 1115 1116 // 1117 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. 1118 // 1119 Link = StartLink; 1120 while (Link != EndLink->ForwardLink) { 1121 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1122 Link = Link->ForwardLink; 1123 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); 1124 if (EFI_ERROR (Status)) { 1125 goto Done; 1126 } 1127 } 1128 Found = TRUE; 1129 } else { 1130 1131 Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1132 1133 // 1134 // Compute the maximum address to use in the search algorithm 1135 // 1136 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp || 1137 GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) { 1138 MaxAddress = *BaseAddress; 1139 } else { 1140 MaxAddress = Entry->EndAddress; 1141 } 1142 1143 // 1144 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. 1145 // 1146 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || 1147 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) { 1148 Link = Map->BackLink; 1149 } else { 1150 Link = Map->ForwardLink; 1151 } 1152 while (Link != Map) { 1153 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1154 1155 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || 1156 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) { 1157 Link = Link->BackLink; 1158 } else { 1159 Link = Link->ForwardLink; 1160 } 1161 1162 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); 1163 if (EFI_ERROR (Status)) { 1164 continue; 1165 } 1166 1167 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || 1168 GcdAllocateType == EfiGcdAllocateAnySearchTopDown) { 1169 if ((Entry->BaseAddress + Length) > MaxAddress) { 1170 continue; 1171 } 1172 if (Length > (Entry->EndAddress + 1)) { 1173 Status = EFI_NOT_FOUND; 1174 goto Done; 1175 } 1176 if (Entry->EndAddress > MaxAddress) { 1177 *BaseAddress = MaxAddress; 1178 } else { 1179 *BaseAddress = Entry->EndAddress; 1180 } 1181 *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask); 1182 } else { 1183 *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask); 1184 if ((*BaseAddress + Length - 1) > MaxAddress) { 1185 Status = EFI_NOT_FOUND; 1186 goto Done; 1187 } 1188 } 1189 1190 // 1191 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length 1192 // 1193 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map); 1194 if (EFI_ERROR (Status)) { 1195 Status = EFI_NOT_FOUND; 1196 goto Done; 1197 } 1198 ASSERT (StartLink != NULL && EndLink != NULL); 1199 1200 Link = StartLink; 1201 // 1202 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. 1203 // 1204 Found = TRUE; 1205 SubLink = StartLink; 1206 while (SubLink != EndLink->ForwardLink) { 1207 Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1208 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); 1209 if (EFI_ERROR (Status)) { 1210 Link = SubLink; 1211 Found = FALSE; 1212 break; 1213 } 1214 SubLink = SubLink->ForwardLink; 1215 } 1216 if (Found) { 1217 break; 1218 } 1219 } 1220 } 1221 if (!Found) { 1222 Status = EFI_NOT_FOUND; 1223 goto Done; 1224 } 1225 1226 // 1227 // Allocate work space to perform this operation 1228 // 1229 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry); 1230 if (EFI_ERROR (Status)) { 1231 Status = EFI_OUT_OF_RESOURCES; 1232 goto Done; 1233 } 1234 ASSERT (TopEntry != NULL && BottomEntry != NULL); 1235 1236 // 1237 // Convert/Insert the list of descriptors from StartLink to EndLink 1238 // 1239 Link = StartLink; 1240 while (Link != EndLink->ForwardLink) { 1241 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1242 CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry); 1243 Entry->ImageHandle = ImageHandle; 1244 Entry->DeviceHandle = DeviceHandle; 1245 Link = Link->ForwardLink; 1246 } 1247 1248 // 1249 // Cleanup 1250 // 1251 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map); 1252 1253 Done: 1254 DEBUG ((DEBUG_GCD, " Status = %r", Status)); 1255 if (!EFI_ERROR (Status)) { 1256 DEBUG ((DEBUG_GCD, " (BaseAddress = %016lx)", *BaseAddress)); 1257 } 1258 DEBUG ((DEBUG_GCD, "\n")); 1259 1260 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { 1261 CoreReleaseGcdMemoryLock (); 1262 CoreDumpGcdMemorySpaceMap (FALSE); 1263 } 1264 if ((Operation & GCD_IO_SPACE_OPERATION) !=0) { 1265 CoreReleaseGcdIoLock (); 1266 CoreDumpGcdIoSpaceMap (FALSE); 1267 } 1268 1269 return Status; 1270 } 1271 1272 1273 /** 1274 Add a segment of memory to GCD map. 1275 1276 @param GcdMemoryType Memory type of the segment. 1277 @param BaseAddress Base address of the segment. 1278 @param Length Length of the segment. 1279 @param Capabilities alterable attributes of the segment. 1280 1281 @retval EFI_INVALID_PARAMETER Invalid parameters. 1282 @retval EFI_SUCCESS Successfully add a segment of memory space. 1283 1284 **/ 1285 EFI_STATUS 1286 CoreInternalAddMemorySpace ( 1287 IN EFI_GCD_MEMORY_TYPE GcdMemoryType, 1288 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1289 IN UINT64 Length, 1290 IN UINT64 Capabilities 1291 ) 1292 { 1293 DEBUG ((DEBUG_GCD, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1294 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)])); 1295 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities)); 1296 1297 // 1298 // Make sure parameters are valid 1299 // 1300 if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) { 1301 return EFI_INVALID_PARAMETER; 1302 } 1303 1304 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0); 1305 } 1306 1307 // 1308 // GCD Core Services 1309 // 1310 1311 /** 1312 Allocates nonexistent memory, reserved memory, system memory, or memorymapped 1313 I/O resources from the global coherency domain of the processor. 1314 1315 @param GcdAllocateType The type of allocate operation 1316 @param GcdMemoryType The desired memory type 1317 @param Alignment Align with 2^Alignment 1318 @param Length Length to allocate 1319 @param BaseAddress Base address to allocate 1320 @param ImageHandle The image handle consume the allocated space. 1321 @param DeviceHandle The device handle consume the allocated space. 1322 1323 @retval EFI_INVALID_PARAMETER Invalid parameter. 1324 @retval EFI_NOT_FOUND No descriptor contains the desired space. 1325 @retval EFI_SUCCESS Memory space successfully allocated. 1326 1327 **/ 1328 EFI_STATUS 1329 EFIAPI 1330 CoreAllocateMemorySpace ( 1331 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, 1332 IN EFI_GCD_MEMORY_TYPE GcdMemoryType, 1333 IN UINTN Alignment, 1334 IN UINT64 Length, 1335 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, 1336 IN EFI_HANDLE ImageHandle, 1337 IN EFI_HANDLE DeviceHandle OPTIONAL 1338 ) 1339 { 1340 DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length)); 1341 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)])); 1342 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)])); 1343 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment))); 1344 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle)); 1345 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle)); 1346 1347 return CoreAllocateSpace ( 1348 GCD_ALLOCATE_MEMORY_OPERATION, 1349 GcdAllocateType, 1350 GcdMemoryType, 1351 (EFI_GCD_IO_TYPE) 0, 1352 Alignment, 1353 Length, 1354 BaseAddress, 1355 ImageHandle, 1356 DeviceHandle 1357 ); 1358 } 1359 1360 1361 /** 1362 Adds reserved memory, system memory, or memory-mapped I/O resources to the 1363 global coherency domain of the processor. 1364 1365 @param GcdMemoryType Memory type of the memory space. 1366 @param BaseAddress Base address of the memory space. 1367 @param Length Length of the memory space. 1368 @param Capabilities alterable attributes of the memory space. 1369 1370 @retval EFI_SUCCESS Merged this memory space into GCD map. 1371 1372 **/ 1373 EFI_STATUS 1374 EFIAPI 1375 CoreAddMemorySpace ( 1376 IN EFI_GCD_MEMORY_TYPE GcdMemoryType, 1377 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1378 IN UINT64 Length, 1379 IN UINT64 Capabilities 1380 ) 1381 { 1382 EFI_STATUS Status; 1383 EFI_PHYSICAL_ADDRESS PageBaseAddress; 1384 UINT64 PageLength; 1385 1386 Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities); 1387 1388 if (!EFI_ERROR (Status) && ((GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || (GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) { 1389 1390 PageBaseAddress = PageAlignAddress (BaseAddress); 1391 PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress); 1392 1393 Status = CoreAllocateMemorySpace ( 1394 EfiGcdAllocateAddress, 1395 GcdMemoryType, 1396 EFI_PAGE_SHIFT, 1397 PageLength, 1398 &PageBaseAddress, 1399 gDxeCoreImageHandle, 1400 NULL 1401 ); 1402 1403 if (!EFI_ERROR (Status)) { 1404 CoreAddMemoryDescriptor ( 1405 EfiConventionalMemory, 1406 PageBaseAddress, 1407 RShiftU64 (PageLength, EFI_PAGE_SHIFT), 1408 Capabilities 1409 ); 1410 } else { 1411 for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) { 1412 Status = CoreAllocateMemorySpace ( 1413 EfiGcdAllocateAddress, 1414 GcdMemoryType, 1415 EFI_PAGE_SHIFT, 1416 EFI_PAGE_SIZE, 1417 &PageBaseAddress, 1418 gDxeCoreImageHandle, 1419 NULL 1420 ); 1421 1422 if (!EFI_ERROR (Status)) { 1423 CoreAddMemoryDescriptor ( 1424 EfiConventionalMemory, 1425 PageBaseAddress, 1426 1, 1427 Capabilities 1428 ); 1429 } 1430 } 1431 } 1432 } 1433 return Status; 1434 } 1435 1436 1437 /** 1438 Frees nonexistent memory, reserved memory, system memory, or memory-mapped 1439 I/O resources from the global coherency domain of the processor. 1440 1441 @param BaseAddress Base address of the memory space. 1442 @param Length Length of the memory space. 1443 1444 @retval EFI_SUCCESS Space successfully freed. 1445 1446 **/ 1447 EFI_STATUS 1448 EFIAPI 1449 CoreFreeMemorySpace ( 1450 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1451 IN UINT64 Length 1452 ) 1453 { 1454 DEBUG ((DEBUG_GCD, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1455 1456 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); 1457 } 1458 1459 1460 /** 1461 Removes reserved memory, system memory, or memory-mapped I/O resources from 1462 the global coherency domain of the processor. 1463 1464 @param BaseAddress Base address of the memory space. 1465 @param Length Length of the memory space. 1466 1467 @retval EFI_SUCCESS Successfully remove a segment of memory space. 1468 1469 **/ 1470 EFI_STATUS 1471 EFIAPI 1472 CoreRemoveMemorySpace ( 1473 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1474 IN UINT64 Length 1475 ) 1476 { 1477 DEBUG ((DEBUG_GCD, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1478 1479 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); 1480 } 1481 1482 1483 /** 1484 Build a memory descriptor according to an entry. 1485 1486 @param Descriptor The descriptor to be built 1487 @param Entry According to this entry 1488 1489 **/ 1490 VOID 1491 BuildMemoryDescriptor ( 1492 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor, 1493 IN EFI_GCD_MAP_ENTRY *Entry 1494 ) 1495 { 1496 Descriptor->BaseAddress = Entry->BaseAddress; 1497 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1; 1498 Descriptor->Capabilities = Entry->Capabilities; 1499 Descriptor->Attributes = Entry->Attributes; 1500 Descriptor->GcdMemoryType = Entry->GcdMemoryType; 1501 Descriptor->ImageHandle = Entry->ImageHandle; 1502 Descriptor->DeviceHandle = Entry->DeviceHandle; 1503 } 1504 1505 1506 /** 1507 Retrieves the descriptor for a memory region containing a specified address. 1508 1509 @param BaseAddress Specified start address 1510 @param Descriptor Specified length 1511 1512 @retval EFI_INVALID_PARAMETER Invalid parameter 1513 @retval EFI_SUCCESS Successfully get memory space descriptor. 1514 1515 **/ 1516 EFI_STATUS 1517 EFIAPI 1518 CoreGetMemorySpaceDescriptor ( 1519 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1520 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor 1521 ) 1522 { 1523 EFI_STATUS Status; 1524 LIST_ENTRY *StartLink; 1525 LIST_ENTRY *EndLink; 1526 EFI_GCD_MAP_ENTRY *Entry; 1527 1528 // 1529 // Make sure parameters are valid 1530 // 1531 if (Descriptor == NULL) { 1532 return EFI_INVALID_PARAMETER; 1533 } 1534 1535 CoreAcquireGcdMemoryLock (); 1536 1537 // 1538 // Search for the list of descriptors that contain BaseAddress 1539 // 1540 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap); 1541 if (EFI_ERROR (Status)) { 1542 Status = EFI_NOT_FOUND; 1543 } else { 1544 ASSERT (StartLink != NULL && EndLink != NULL); 1545 // 1546 // Copy the contents of the found descriptor into Descriptor 1547 // 1548 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1549 BuildMemoryDescriptor (Descriptor, Entry); 1550 } 1551 1552 CoreReleaseGcdMemoryLock (); 1553 1554 return Status; 1555 } 1556 1557 1558 /** 1559 Modifies the attributes for a memory region in the global coherency domain of the 1560 processor. 1561 1562 @param BaseAddress Specified start address 1563 @param Length Specified length 1564 @param Attributes Specified attributes 1565 1566 @retval EFI_SUCCESS The attributes were set for the memory region. 1567 @retval EFI_INVALID_PARAMETER Length is zero. 1568 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory 1569 resource range specified by BaseAddress and Length. 1570 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource 1571 range specified by BaseAddress and Length. 1572 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by 1573 BaseAddress and Length cannot be modified. 1574 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of 1575 the memory resource range. 1576 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is 1577 not available yet. 1578 1579 **/ 1580 EFI_STATUS 1581 EFIAPI 1582 CoreSetMemorySpaceAttributes ( 1583 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1584 IN UINT64 Length, 1585 IN UINT64 Attributes 1586 ) 1587 { 1588 DEBUG ((DEBUG_GCD, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1589 DEBUG ((DEBUG_GCD, " Attributes = %016lx\n", Attributes)); 1590 1591 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes); 1592 } 1593 1594 1595 /** 1596 Modifies the capabilities for a memory region in the global coherency domain of the 1597 processor. 1598 1599 @param BaseAddress The physical address that is the start address of a memory region. 1600 @param Length The size in bytes of the memory region. 1601 @param Capabilities The bit mask of capabilities that the memory region supports. 1602 1603 @retval EFI_SUCCESS The capabilities were set for the memory region. 1604 @retval EFI_INVALID_PARAMETER Length is zero. 1605 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the 1606 memory region attributes currently in use. 1607 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by 1608 BaseAddress and Length cannot be modified. 1609 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities 1610 of the memory resource range. 1611 **/ 1612 EFI_STATUS 1613 EFIAPI 1614 CoreSetMemorySpaceCapabilities ( 1615 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1616 IN UINT64 Length, 1617 IN UINT64 Capabilities 1618 ) 1619 { 1620 EFI_STATUS Status; 1621 1622 DEBUG ((DEBUG_GCD, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1623 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities)); 1624 1625 Status = CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0); 1626 if (!EFI_ERROR(Status)) { 1627 CoreUpdateMemoryAttributes(BaseAddress, RShiftU64(Length, EFI_PAGE_SHIFT), Capabilities); 1628 } 1629 1630 return Status; 1631 } 1632 1633 1634 /** 1635 Returns a map of the memory resources in the global coherency domain of the 1636 processor. 1637 1638 @param NumberOfDescriptors Number of descriptors. 1639 @param MemorySpaceMap Descriptor array 1640 1641 @retval EFI_INVALID_PARAMETER Invalid parameter 1642 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate 1643 @retval EFI_SUCCESS Successfully get memory space map. 1644 1645 **/ 1646 EFI_STATUS 1647 EFIAPI 1648 CoreGetMemorySpaceMap ( 1649 OUT UINTN *NumberOfDescriptors, 1650 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap 1651 ) 1652 { 1653 EFI_STATUS Status; 1654 LIST_ENTRY *Link; 1655 EFI_GCD_MAP_ENTRY *Entry; 1656 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor; 1657 1658 // 1659 // Make sure parameters are valid 1660 // 1661 if (NumberOfDescriptors == NULL) { 1662 return EFI_INVALID_PARAMETER; 1663 } 1664 if (MemorySpaceMap == NULL) { 1665 return EFI_INVALID_PARAMETER; 1666 } 1667 1668 CoreAcquireGcdMemoryLock (); 1669 1670 // 1671 // Count the number of descriptors 1672 // 1673 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap); 1674 1675 // 1676 // Allocate the MemorySpaceMap 1677 // 1678 *MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); 1679 if (*MemorySpaceMap == NULL) { 1680 Status = EFI_OUT_OF_RESOURCES; 1681 goto Done; 1682 } 1683 1684 // 1685 // Fill in the MemorySpaceMap 1686 // 1687 Descriptor = *MemorySpaceMap; 1688 Link = mGcdMemorySpaceMap.ForwardLink; 1689 while (Link != &mGcdMemorySpaceMap) { 1690 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1691 BuildMemoryDescriptor (Descriptor, Entry); 1692 Descriptor++; 1693 Link = Link->ForwardLink; 1694 } 1695 Status = EFI_SUCCESS; 1696 1697 Done: 1698 CoreReleaseGcdMemoryLock (); 1699 return Status; 1700 } 1701 1702 1703 /** 1704 Adds reserved I/O or I/O resources to the global coherency domain of the processor. 1705 1706 @param GcdIoType IO type of the segment. 1707 @param BaseAddress Base address of the segment. 1708 @param Length Length of the segment. 1709 1710 @retval EFI_SUCCESS Merged this segment into GCD map. 1711 @retval EFI_INVALID_PARAMETER Parameter not valid 1712 1713 **/ 1714 EFI_STATUS 1715 EFIAPI 1716 CoreAddIoSpace ( 1717 IN EFI_GCD_IO_TYPE GcdIoType, 1718 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1719 IN UINT64 Length 1720 ) 1721 { 1722 DEBUG ((DEBUG_GCD, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1723 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)])); 1724 1725 // 1726 // Make sure parameters are valid 1727 // 1728 if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) { 1729 return EFI_INVALID_PARAMETER; 1730 } 1731 return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0); 1732 } 1733 1734 1735 /** 1736 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency 1737 domain of the processor. 1738 1739 @param GcdAllocateType The type of allocate operation 1740 @param GcdIoType The desired IO type 1741 @param Alignment Align with 2^Alignment 1742 @param Length Length to allocate 1743 @param BaseAddress Base address to allocate 1744 @param ImageHandle The image handle consume the allocated space. 1745 @param DeviceHandle The device handle consume the allocated space. 1746 1747 @retval EFI_INVALID_PARAMETER Invalid parameter. 1748 @retval EFI_NOT_FOUND No descriptor contains the desired space. 1749 @retval EFI_SUCCESS IO space successfully allocated. 1750 1751 **/ 1752 EFI_STATUS 1753 EFIAPI 1754 CoreAllocateIoSpace ( 1755 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, 1756 IN EFI_GCD_IO_TYPE GcdIoType, 1757 IN UINTN Alignment, 1758 IN UINT64 Length, 1759 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, 1760 IN EFI_HANDLE ImageHandle, 1761 IN EFI_HANDLE DeviceHandle OPTIONAL 1762 ) 1763 { 1764 DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length)); 1765 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)])); 1766 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)])); 1767 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment))); 1768 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle)); 1769 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle)); 1770 1771 return CoreAllocateSpace ( 1772 GCD_ALLOCATE_IO_OPERATION, 1773 GcdAllocateType, 1774 (EFI_GCD_MEMORY_TYPE) 0, 1775 GcdIoType, 1776 Alignment, 1777 Length, 1778 BaseAddress, 1779 ImageHandle, 1780 DeviceHandle 1781 ); 1782 } 1783 1784 1785 /** 1786 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency 1787 domain of the processor. 1788 1789 @param BaseAddress Base address of the segment. 1790 @param Length Length of the segment. 1791 1792 @retval EFI_SUCCESS Space successfully freed. 1793 1794 **/ 1795 EFI_STATUS 1796 EFIAPI 1797 CoreFreeIoSpace ( 1798 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1799 IN UINT64 Length 1800 ) 1801 { 1802 DEBUG ((DEBUG_GCD, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1803 1804 return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); 1805 } 1806 1807 1808 /** 1809 Removes reserved I/O or I/O resources from the global coherency domain of the 1810 processor. 1811 1812 @param BaseAddress Base address of the segment. 1813 @param Length Length of the segment. 1814 1815 @retval EFI_SUCCESS Successfully removed a segment of IO space. 1816 1817 **/ 1818 EFI_STATUS 1819 EFIAPI 1820 CoreRemoveIoSpace ( 1821 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1822 IN UINT64 Length 1823 ) 1824 { 1825 DEBUG ((DEBUG_GCD, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); 1826 1827 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); 1828 } 1829 1830 1831 /** 1832 Build a IO descriptor according to an entry. 1833 1834 @param Descriptor The descriptor to be built 1835 @param Entry According to this entry 1836 1837 **/ 1838 VOID 1839 BuildIoDescriptor ( 1840 IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor, 1841 IN EFI_GCD_MAP_ENTRY *Entry 1842 ) 1843 { 1844 Descriptor->BaseAddress = Entry->BaseAddress; 1845 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1; 1846 Descriptor->GcdIoType = Entry->GcdIoType; 1847 Descriptor->ImageHandle = Entry->ImageHandle; 1848 Descriptor->DeviceHandle = Entry->DeviceHandle; 1849 } 1850 1851 1852 /** 1853 Retrieves the descriptor for an I/O region containing a specified address. 1854 1855 @param BaseAddress Specified start address 1856 @param Descriptor Specified length 1857 1858 @retval EFI_INVALID_PARAMETER Descriptor is NULL. 1859 @retval EFI_SUCCESS Successfully get the IO space descriptor. 1860 1861 **/ 1862 EFI_STATUS 1863 EFIAPI 1864 CoreGetIoSpaceDescriptor ( 1865 IN EFI_PHYSICAL_ADDRESS BaseAddress, 1866 OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor 1867 ) 1868 { 1869 EFI_STATUS Status; 1870 LIST_ENTRY *StartLink; 1871 LIST_ENTRY *EndLink; 1872 EFI_GCD_MAP_ENTRY *Entry; 1873 1874 // 1875 // Make sure parameters are valid 1876 // 1877 if (Descriptor == NULL) { 1878 return EFI_INVALID_PARAMETER; 1879 } 1880 1881 CoreAcquireGcdIoLock (); 1882 1883 // 1884 // Search for the list of descriptors that contain BaseAddress 1885 // 1886 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap); 1887 if (EFI_ERROR (Status)) { 1888 Status = EFI_NOT_FOUND; 1889 } else { 1890 ASSERT (StartLink != NULL && EndLink != NULL); 1891 // 1892 // Copy the contents of the found descriptor into Descriptor 1893 // 1894 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1895 BuildIoDescriptor (Descriptor, Entry); 1896 } 1897 1898 CoreReleaseGcdIoLock (); 1899 1900 return Status; 1901 } 1902 1903 1904 /** 1905 Returns a map of the I/O resources in the global coherency domain of the processor. 1906 1907 @param NumberOfDescriptors Number of descriptors. 1908 @param IoSpaceMap Descriptor array 1909 1910 @retval EFI_INVALID_PARAMETER Invalid parameter 1911 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate 1912 @retval EFI_SUCCESS Successfully get IO space map. 1913 1914 **/ 1915 EFI_STATUS 1916 EFIAPI 1917 CoreGetIoSpaceMap ( 1918 OUT UINTN *NumberOfDescriptors, 1919 OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap 1920 ) 1921 { 1922 EFI_STATUS Status; 1923 LIST_ENTRY *Link; 1924 EFI_GCD_MAP_ENTRY *Entry; 1925 EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor; 1926 1927 // 1928 // Make sure parameters are valid 1929 // 1930 if (NumberOfDescriptors == NULL) { 1931 return EFI_INVALID_PARAMETER; 1932 } 1933 if (IoSpaceMap == NULL) { 1934 return EFI_INVALID_PARAMETER; 1935 } 1936 1937 CoreAcquireGcdIoLock (); 1938 1939 // 1940 // Count the number of descriptors 1941 // 1942 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap); 1943 1944 // 1945 // Allocate the IoSpaceMap 1946 // 1947 *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR)); 1948 if (*IoSpaceMap == NULL) { 1949 Status = EFI_OUT_OF_RESOURCES; 1950 goto Done; 1951 } 1952 1953 // 1954 // Fill in the IoSpaceMap 1955 // 1956 Descriptor = *IoSpaceMap; 1957 Link = mGcdIoSpaceMap.ForwardLink; 1958 while (Link != &mGcdIoSpaceMap) { 1959 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); 1960 BuildIoDescriptor (Descriptor, Entry); 1961 Descriptor++; 1962 Link = Link->ForwardLink; 1963 } 1964 Status = EFI_SUCCESS; 1965 1966 Done: 1967 CoreReleaseGcdIoLock (); 1968 return Status; 1969 } 1970 1971 1972 /** 1973 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor 1974 capabilities mask 1975 1976 @param GcdMemoryType Type of resource in the GCD memory map. 1977 @param Attributes The attribute mask in the Resource Descriptor 1978 HOB. 1979 1980 @return The capabilities mask for an EFI Memory Descriptor. 1981 1982 **/ 1983 UINT64 1984 CoreConvertResourceDescriptorHobAttributesToCapabilities ( 1985 EFI_GCD_MEMORY_TYPE GcdMemoryType, 1986 UINT64 Attributes 1987 ) 1988 { 1989 UINT64 Capabilities; 1990 GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion; 1991 1992 // 1993 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask 1994 // 1995 for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) { 1996 if (Conversion->Memory || ((GcdMemoryType != EfiGcdMemoryTypeSystemMemory) && (GcdMemoryType != EfiGcdMemoryTypeMoreReliable))) { 1997 if (Attributes & Conversion->Attribute) { 1998 Capabilities |= Conversion->Capability; 1999 } 2000 } 2001 } 2002 2003 return Capabilities; 2004 } 2005 2006 /** 2007 Calculate total memory bin size neeeded. 2008 2009 @return The total memory bin size neeeded. 2010 2011 **/ 2012 UINT64 2013 CalculateTotalMemoryBinSizeNeeded ( 2014 VOID 2015 ) 2016 { 2017 UINTN Index; 2018 UINT64 TotalSize; 2019 2020 // 2021 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array 2022 // 2023 TotalSize = 0; 2024 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { 2025 TotalSize += LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT); 2026 } 2027 2028 return TotalSize; 2029 } 2030 2031 /** 2032 External function. Initializes memory services based on the memory 2033 descriptor HOBs. This function is responsible for priming the memory 2034 map, so memory allocations and resource allocations can be made. 2035 The first part of this function can not depend on any memory services 2036 until at least one memory descriptor is provided to the memory services. 2037 2038 @param HobStart The start address of the HOB. 2039 @param MemoryBaseAddress Start address of memory region found to init DXE 2040 core. 2041 @param MemoryLength Length of memory region found to init DXE core. 2042 2043 @retval EFI_SUCCESS Memory services successfully initialized. 2044 2045 **/ 2046 EFI_STATUS 2047 CoreInitializeMemoryServices ( 2048 IN VOID **HobStart, 2049 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress, 2050 OUT UINT64 *MemoryLength 2051 ) 2052 { 2053 EFI_PEI_HOB_POINTERS Hob; 2054 EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation; 2055 UINTN DataSize; 2056 BOOLEAN Found; 2057 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob; 2058 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; 2059 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob; 2060 EFI_PHYSICAL_ADDRESS BaseAddress; 2061 UINT64 Length; 2062 UINT64 Attributes; 2063 UINT64 Capabilities; 2064 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress; 2065 UINT64 TestedMemoryLength; 2066 EFI_PHYSICAL_ADDRESS HighAddress; 2067 EFI_HOB_GUID_TYPE *GuidHob; 2068 UINT32 ReservedCodePageNumber; 2069 UINT64 MinimalMemorySizeNeeded; 2070 2071 // 2072 // Point at the first HOB. This must be the PHIT HOB. 2073 // 2074 Hob.Raw = *HobStart; 2075 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF); 2076 2077 // 2078 // Initialize the spin locks and maps in the memory services. 2079 // Also fill in the memory services into the EFI Boot Services Table 2080 // 2081 CoreInitializePool (); 2082 2083 // 2084 // Initialize Local Variables 2085 // 2086 PhitResourceHob = NULL; 2087 ResourceHob = NULL; 2088 BaseAddress = 0; 2089 Length = 0; 2090 Attributes = 0; 2091 2092 // 2093 // Cache the PHIT HOB for later use 2094 // 2095 PhitHob = Hob.HandoffInformationTable; 2096 2097 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) { 2098 ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber); 2099 ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber); 2100 2101 // 2102 // cache the Top address for loading modules at Fixed Address 2103 // 2104 gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop 2105 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber); 2106 } 2107 // 2108 // See if a Memory Type Information HOB is available 2109 // 2110 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid); 2111 if (GuidHob != NULL) { 2112 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob); 2113 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob); 2114 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) { 2115 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize); 2116 } 2117 } 2118 2119 // 2120 // Include the total memory bin size needed to make sure memory bin could be allocated successfully. 2121 // 2122 MinimalMemorySizeNeeded = MINIMUM_INITIAL_MEMORY_SIZE + CalculateTotalMemoryBinSizeNeeded (); 2123 2124 // 2125 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop 2126 // 2127 Found = FALSE; 2128 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { 2129 // 2130 // Skip all HOBs except Resource Descriptor HOBs 2131 // 2132 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { 2133 continue; 2134 } 2135 2136 // 2137 // Skip Resource Descriptor HOBs that do not describe tested system memory 2138 // 2139 ResourceHob = Hob.ResourceDescriptor; 2140 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { 2141 continue; 2142 } 2143 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { 2144 continue; 2145 } 2146 2147 // 2148 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop 2149 // 2150 if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) { 2151 continue; 2152 } 2153 if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) { 2154 continue; 2155 } 2156 2157 // 2158 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB 2159 // 2160 PhitResourceHob = ResourceHob; 2161 Found = TRUE; 2162 2163 // 2164 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB 2165 // 2166 Attributes = PhitResourceHob->ResourceAttribute; 2167 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop); 2168 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress); 2169 if (Length < MinimalMemorySizeNeeded) { 2170 // 2171 // If that range is not large enough to intialize the DXE Core, then 2172 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop 2173 // 2174 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom); 2175 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress); 2176 if (Length < MinimalMemorySizeNeeded) { 2177 // 2178 // If that range is not large enough to intialize the DXE Core, then 2179 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List 2180 // 2181 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart); 2182 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress)); 2183 } 2184 } 2185 break; 2186 } 2187 2188 // 2189 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found 2190 // 2191 ASSERT (Found); 2192 2193 // 2194 // Take the range in the resource descriptor HOB for the memory region described 2195 // by the PHIT as higher priority if it is big enough. It can make the memory bin 2196 // allocated to be at the same memory region with PHIT that has more better compatibility 2197 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory. 2198 // 2199 if (Length < MinimalMemorySizeNeeded) { 2200 // 2201 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory 2202 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB. 2203 // The max address must be within the physically addressible range for the processor. 2204 // 2205 HighAddress = MAX_ADDRESS; 2206 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { 2207 // 2208 // Skip the Resource Descriptor HOB that contains the PHIT 2209 // 2210 if (Hob.ResourceDescriptor == PhitResourceHob) { 2211 continue; 2212 } 2213 // 2214 // Skip all HOBs except Resource Descriptor HOBs 2215 // 2216 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { 2217 continue; 2218 } 2219 2220 // 2221 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS 2222 // 2223 ResourceHob = Hob.ResourceDescriptor; 2224 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { 2225 continue; 2226 } 2227 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { 2228 continue; 2229 } 2230 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS) { 2231 continue; 2232 } 2233 2234 // 2235 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB 2236 // 2237 if (HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS && ResourceHob->PhysicalStart <= HighAddress) { 2238 continue; 2239 } 2240 2241 // 2242 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core 2243 // 2244 TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart); 2245 TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress); 2246 if (TestedMemoryLength < MinimalMemorySizeNeeded) { 2247 continue; 2248 } 2249 2250 // 2251 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core 2252 // 2253 BaseAddress = TestedMemoryBaseAddress; 2254 Length = TestedMemoryLength; 2255 Attributes = ResourceHob->ResourceAttribute; 2256 HighAddress = ResourceHob->PhysicalStart; 2257 } 2258 } 2259 2260 DEBUG ((EFI_D_INFO, "CoreInitializeMemoryServices:\n")); 2261 DEBUG ((EFI_D_INFO, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress, Length, MinimalMemorySizeNeeded)); 2262 2263 // 2264 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT(). 2265 // 2266 ASSERT (Length >= MinimalMemorySizeNeeded); 2267 2268 // 2269 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask 2270 // 2271 if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) { 2272 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes); 2273 } else { 2274 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes); 2275 } 2276 2277 // 2278 // Declare the very first memory region, so the EFI Memory Services are available. 2279 // 2280 CoreAddMemoryDescriptor ( 2281 EfiConventionalMemory, 2282 BaseAddress, 2283 RShiftU64 (Length, EFI_PAGE_SHIFT), 2284 Capabilities 2285 ); 2286 2287 *MemoryBaseAddress = BaseAddress; 2288 *MemoryLength = Length; 2289 2290 return EFI_SUCCESS; 2291 } 2292 2293 2294 /** 2295 External function. Initializes the GCD and memory services based on the memory 2296 descriptor HOBs. This function is responsible for priming the GCD map and the 2297 memory map, so memory allocations and resource allocations can be made. The 2298 HobStart will be relocated to a pool buffer. 2299 2300 @param HobStart The start address of the HOB 2301 @param MemoryBaseAddress Start address of memory region found to init DXE 2302 core. 2303 @param MemoryLength Length of memory region found to init DXE core. 2304 2305 @retval EFI_SUCCESS GCD services successfully initialized. 2306 2307 **/ 2308 EFI_STATUS 2309 CoreInitializeGcdServices ( 2310 IN OUT VOID **HobStart, 2311 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress, 2312 IN UINT64 MemoryLength 2313 ) 2314 { 2315 EFI_PEI_HOB_POINTERS Hob; 2316 VOID *NewHobList; 2317 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob; 2318 UINT8 SizeOfMemorySpace; 2319 UINT8 SizeOfIoSpace; 2320 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; 2321 EFI_PHYSICAL_ADDRESS BaseAddress; 2322 UINT64 Length; 2323 EFI_STATUS Status; 2324 EFI_GCD_MAP_ENTRY *Entry; 2325 EFI_GCD_MEMORY_TYPE GcdMemoryType; 2326 EFI_GCD_IO_TYPE GcdIoType; 2327 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; 2328 EFI_HOB_MEMORY_ALLOCATION *MemoryHob; 2329 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob; 2330 UINTN NumberOfDescriptors; 2331 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; 2332 UINTN Index; 2333 UINT64 Capabilities; 2334 EFI_HOB_CPU * CpuHob; 2335 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMapHobList; 2336 2337 // 2338 // Cache the PHIT HOB for later use 2339 // 2340 PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart); 2341 2342 // 2343 // Get the number of address lines in the I/O and Memory space for the CPU 2344 // 2345 CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU); 2346 ASSERT (CpuHob != NULL); 2347 SizeOfMemorySpace = CpuHob->SizeOfMemorySpace; 2348 SizeOfIoSpace = CpuHob->SizeOfIoSpace; 2349 2350 // 2351 // Initialize the GCD Memory Space Map 2352 // 2353 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate); 2354 ASSERT (Entry != NULL); 2355 2356 Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1; 2357 2358 InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link); 2359 2360 CoreDumpGcdMemorySpaceMap (TRUE); 2361 2362 // 2363 // Initialize the GCD I/O Space Map 2364 // 2365 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate); 2366 ASSERT (Entry != NULL); 2367 2368 Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1; 2369 2370 InsertHeadList (&mGcdIoSpaceMap, &Entry->Link); 2371 2372 CoreDumpGcdIoSpaceMap (TRUE); 2373 2374 // 2375 // Walk the HOB list and add all resource descriptors to the GCD 2376 // 2377 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { 2378 2379 GcdMemoryType = EfiGcdMemoryTypeNonExistent; 2380 GcdIoType = EfiGcdIoTypeNonExistent; 2381 2382 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { 2383 2384 ResourceHob = Hob.ResourceDescriptor; 2385 2386 switch (ResourceHob->ResourceType) { 2387 case EFI_RESOURCE_SYSTEM_MEMORY: 2388 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) { 2389 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) { 2390 GcdMemoryType = EfiGcdMemoryTypeMoreReliable; 2391 } else { 2392 GcdMemoryType = EfiGcdMemoryTypeSystemMemory; 2393 } 2394 } 2395 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) { 2396 GcdMemoryType = EfiGcdMemoryTypeReserved; 2397 } 2398 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) { 2399 GcdMemoryType = EfiGcdMemoryTypeReserved; 2400 } 2401 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT) { 2402 GcdMemoryType = EfiGcdMemoryTypePersistentMemory; 2403 } 2404 break; 2405 case EFI_RESOURCE_MEMORY_MAPPED_IO: 2406 case EFI_RESOURCE_FIRMWARE_DEVICE: 2407 GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo; 2408 break; 2409 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT: 2410 case EFI_RESOURCE_MEMORY_RESERVED: 2411 GcdMemoryType = EfiGcdMemoryTypeReserved; 2412 break; 2413 case EFI_RESOURCE_IO: 2414 GcdIoType = EfiGcdIoTypeIo; 2415 break; 2416 case EFI_RESOURCE_IO_RESERVED: 2417 GcdIoType = EfiGcdIoTypeReserved; 2418 break; 2419 } 2420 2421 if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) { 2422 // 2423 // Validate the Resource HOB Attributes 2424 // 2425 CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute); 2426 2427 // 2428 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask 2429 // 2430 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities ( 2431 GcdMemoryType, 2432 ResourceHob->ResourceAttribute 2433 ); 2434 2435 Status = CoreInternalAddMemorySpace ( 2436 GcdMemoryType, 2437 ResourceHob->PhysicalStart, 2438 ResourceHob->ResourceLength, 2439 Capabilities 2440 ); 2441 } 2442 2443 if (GcdIoType != EfiGcdIoTypeNonExistent) { 2444 Status = CoreAddIoSpace ( 2445 GcdIoType, 2446 ResourceHob->PhysicalStart, 2447 ResourceHob->ResourceLength 2448 ); 2449 } 2450 } 2451 } 2452 2453 // 2454 // Allocate first memory region from the GCD by the DXE core 2455 // 2456 Status = CoreGetMemorySpaceDescriptor (MemoryBaseAddress, &Descriptor); 2457 if (!EFI_ERROR (Status)) { 2458 ASSERT ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || 2459 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable)); 2460 Status = CoreAllocateMemorySpace ( 2461 EfiGcdAllocateAddress, 2462 Descriptor.GcdMemoryType, 2463 0, 2464 MemoryLength, 2465 &MemoryBaseAddress, 2466 gDxeCoreImageHandle, 2467 NULL 2468 ); 2469 } 2470 2471 // 2472 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs, 2473 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs. 2474 // 2475 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { 2476 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { 2477 MemoryHob = Hob.MemoryAllocation; 2478 BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress; 2479 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor); 2480 if (!EFI_ERROR (Status)) { 2481 Status = CoreAllocateMemorySpace ( 2482 EfiGcdAllocateAddress, 2483 Descriptor.GcdMemoryType, 2484 0, 2485 MemoryHob->AllocDescriptor.MemoryLength, 2486 &BaseAddress, 2487 gDxeCoreImageHandle, 2488 NULL 2489 ); 2490 if (!EFI_ERROR (Status) && 2491 ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || 2492 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) { 2493 CoreAddMemoryDescriptor ( 2494 MemoryHob->AllocDescriptor.MemoryType, 2495 MemoryHob->AllocDescriptor.MemoryBaseAddress, 2496 RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT), 2497 Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME) 2498 ); 2499 } 2500 } 2501 } 2502 2503 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) { 2504 FirmwareVolumeHob = Hob.FirmwareVolume; 2505 BaseAddress = FirmwareVolumeHob->BaseAddress; 2506 Status = CoreAllocateMemorySpace ( 2507 EfiGcdAllocateAddress, 2508 EfiGcdMemoryTypeMemoryMappedIo, 2509 0, 2510 FirmwareVolumeHob->Length, 2511 &BaseAddress, 2512 gDxeCoreImageHandle, 2513 NULL 2514 ); 2515 } 2516 } 2517 2518 // 2519 // Add and allocate the remaining unallocated system memory to the memory services. 2520 // 2521 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); 2522 ASSERT (Status == EFI_SUCCESS); 2523 2524 MemorySpaceMapHobList = NULL; 2525 for (Index = 0; Index < NumberOfDescriptors; Index++) { 2526 if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || 2527 (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable)) { 2528 if (MemorySpaceMap[Index].ImageHandle == NULL) { 2529 BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress); 2530 Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress); 2531 if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) { 2532 continue; 2533 } 2534 if (((UINTN) MemorySpaceMap[Index].BaseAddress <= (UINTN) (*HobStart)) && 2535 ((UINTN) (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) >= (UINTN) PhitHob->EfiFreeMemoryBottom)) { 2536 // 2537 // Skip the memory space that covers HOB List, it should be processed 2538 // after HOB List relocation to avoid the resources allocated by others 2539 // to corrupt HOB List before its relocation. 2540 // 2541 MemorySpaceMapHobList = &MemorySpaceMap[Index]; 2542 continue; 2543 } 2544 CoreAddMemoryDescriptor ( 2545 EfiConventionalMemory, 2546 BaseAddress, 2547 RShiftU64 (Length, EFI_PAGE_SHIFT), 2548 MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME) 2549 ); 2550 Status = CoreAllocateMemorySpace ( 2551 EfiGcdAllocateAddress, 2552 MemorySpaceMap[Index].GcdMemoryType, 2553 0, 2554 Length, 2555 &BaseAddress, 2556 gDxeCoreImageHandle, 2557 NULL 2558 ); 2559 } 2560 } 2561 } 2562 2563 // 2564 // Relocate HOB List to an allocated pool buffer. 2565 // The relocation should be at after all the tested memory resources added 2566 // (except the memory space that covers HOB List) to the memory services, 2567 // because the memory resource found in CoreInitializeMemoryServices() 2568 // may have not enough remaining resource for HOB List. 2569 // 2570 NewHobList = AllocateCopyPool ( 2571 (UINTN) PhitHob->EfiFreeMemoryBottom - (UINTN) (*HobStart), 2572 *HobStart 2573 ); 2574 ASSERT (NewHobList != NULL); 2575 2576 *HobStart = NewHobList; 2577 gHobList = NewHobList; 2578 2579 if (MemorySpaceMapHobList != NULL) { 2580 // 2581 // Add and allocate the memory space that covers HOB List to the memory services 2582 // after HOB List relocation. 2583 // 2584 BaseAddress = PageAlignAddress (MemorySpaceMapHobList->BaseAddress); 2585 Length = PageAlignLength (MemorySpaceMapHobList->BaseAddress + MemorySpaceMapHobList->Length - BaseAddress); 2586 CoreAddMemoryDescriptor ( 2587 EfiConventionalMemory, 2588 BaseAddress, 2589 RShiftU64 (Length, EFI_PAGE_SHIFT), 2590 MemorySpaceMapHobList->Capabilities & (~EFI_MEMORY_RUNTIME) 2591 ); 2592 Status = CoreAllocateMemorySpace ( 2593 EfiGcdAllocateAddress, 2594 MemorySpaceMapHobList->GcdMemoryType, 2595 0, 2596 Length, 2597 &BaseAddress, 2598 gDxeCoreImageHandle, 2599 NULL 2600 ); 2601 } 2602 2603 CoreFreePool (MemorySpaceMap); 2604 2605 return EFI_SUCCESS; 2606 } 2607