1 /** @file 2 Pci Host Bridge driver for a simple IIO. There is only one PCI Root Bridge in the system. 3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation. 4 5 Copyright (c) 2013-2015 Intel Corporation. 6 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 18 #include "PciHostBridge.h" 19 #include <IntelQNCRegs.h> 20 21 // 22 // We can hardcode the following for a Simple IIO - 23 // Root Bridge Count within the host bridge 24 // Root Bridge's device path 25 // Root Bridge's resource appeture 26 // 27 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[ROOT_BRIDGE_COUNT] = { 28 { 29 { 30 { 31 ACPI_DEVICE_PATH, 32 ACPI_DP, 33 { 34 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), 35 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) 36 } 37 }, 38 EISA_PNP_ID (0x0A03), 39 0 40 }, 41 { 42 END_DEVICE_PATH_TYPE, 43 END_ENTIRE_DEVICE_PATH_SUBTYPE, 44 { 45 END_DEVICE_PATH_LENGTH, 46 0 47 } 48 } 49 } 50 }; 51 52 EFI_HANDLE mDriverImageHandle; 53 PCI_ROOT_BRIDGE_RESOURCE_APERTURE *mResAperture; 54 55 // 56 // Implementation 57 // 58 EFI_STATUS 59 EFIAPI 60 InitializePciHostBridge ( 61 IN EFI_HANDLE ImageHandle, 62 IN EFI_SYSTEM_TABLE *SystemTable 63 ) 64 /*++ 65 66 Routine Description: 67 68 Entry point of this driver. 69 70 Arguments: 71 72 ImageHandle - Image handle of this driver. 73 SystemTable - Pointer to standard EFI system table. 74 75 Returns: 76 77 EFI_SUCCESS - Succeed. 78 EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol. 79 80 --*/ 81 { 82 EFI_STATUS Status; 83 UINTN TotalRootBridgeFound; 84 PCI_HOST_BRIDGE_INSTANCE *HostBridge; 85 PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 86 UINT64 AllocAttributes; 87 EFI_PHYSICAL_ADDRESS BaseAddress; 88 89 PrivateData = NULL; 90 91 mDriverImageHandle = ImageHandle; 92 93 // 94 // Most systems in the world including complex servers 95 // have only one Host Bridge. Create Host Bridge Device Handle 96 // 97 Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PCI_HOST_BRIDGE_INSTANCE), (VOID **) &HostBridge); 98 ASSERT_EFI_ERROR (Status); 99 ZeroMem (HostBridge, sizeof (PCI_HOST_BRIDGE_INSTANCE)); 100 101 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE; 102 HostBridge->RootBridgeCount = 1; 103 HostBridge->ResourceSubmited = FALSE; 104 HostBridge->CanRestarted = TRUE; 105 // 106 // InitializeListHead (&HostBridge->Head); 107 // 108 HostBridge->ResAlloc.NotifyPhase = NotifyPhase; 109 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge; 110 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes; 111 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration; 112 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers; 113 HostBridge->ResAlloc.SubmitResources = SubmitResources; 114 HostBridge->ResAlloc.GetProposedResources = GetProposedResources; 115 HostBridge->ResAlloc.PreprocessController = PreprocessController; 116 117 Status = gBS->InstallProtocolInterface ( 118 &HostBridge->HostBridgeHandle, 119 &gEfiPciHostBridgeResourceAllocationProtocolGuid, 120 EFI_NATIVE_INTERFACE, 121 &HostBridge->ResAlloc 122 ); 123 if (EFI_ERROR (Status)) { 124 gBS->FreePool (HostBridge); 125 return EFI_DEVICE_ERROR; 126 } 127 128 Status = gBS->AllocatePool (EfiBootServicesData, 129 HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE), 130 (VOID **) &mResAperture); 131 ASSERT_EFI_ERROR (Status); 132 ZeroMem (mResAperture, HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE)); 133 134 DEBUG ((EFI_D_INFO, "Address of resource Aperture: %x\n", mResAperture)); 135 136 // 137 // Create Root Bridge Device Handle in this Host Bridge 138 // 139 InitializeListHead (&HostBridge->Head); 140 141 TotalRootBridgeFound = 0; 142 143 Status = gBS->AllocatePool ( EfiBootServicesData,sizeof (PCI_ROOT_BRIDGE_INSTANCE), (VOID **) &PrivateData); 144 ASSERT_EFI_ERROR (Status); 145 ZeroMem (PrivateData, sizeof (PCI_ROOT_BRIDGE_INSTANCE)); 146 147 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE; 148 PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[TotalRootBridgeFound]; 149 AllocAttributes = GetAllocAttributes (TotalRootBridgeFound); 150 151 SimpleIioRootBridgeConstructor ( 152 &PrivateData->Io, 153 HostBridge->HostBridgeHandle, 154 &(mResAperture[TotalRootBridgeFound]), 155 AllocAttributes 156 ); 157 // 158 // Update Root Bridge with UDS resource information 159 // 160 PrivateData->Aperture.BusBase = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE; 161 PrivateData->Aperture.BusLimit = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT; 162 PrivateData->Aperture.Mem32Base = PcdGet32 (PcdPciHostBridgeMemory32Base); 163 PrivateData->Aperture.Mem32Limit = PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1); 164 PrivateData->Aperture.IoBase = PcdGet16 (PcdPciHostBridgeIoBase); 165 PrivateData->Aperture.IoLimit = PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1); 166 167 DEBUG ((EFI_D_INFO, "PCI Host Bridge BusBase: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE)); 168 DEBUG ((EFI_D_INFO, "PCI Host Bridge BusLimit: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT)); 169 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Base: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base))); 170 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Limit: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1))); 171 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Base: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base))); 172 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Limit: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base) + (PcdGet64 (PcdPciHostBridgeMemory64Size) - 1))); 173 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoBase: %x\n", PcdGet16 (PcdPciHostBridgeIoBase))); 174 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoLimit: %x\n", PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1))); 175 176 PrivateData->Handle = NULL; 177 Status = gBS->InstallMultipleProtocolInterfaces ( 178 &PrivateData->Handle, 179 &gEfiDevicePathProtocolGuid, 180 PrivateData->DevicePath, 181 &gEfiPciRootBridgeIoProtocolGuid, 182 &PrivateData->Io, 183 NULL 184 ); 185 ASSERT_EFI_ERROR (Status); 186 187 InsertTailList (&HostBridge->Head, &PrivateData->Link); 188 TotalRootBridgeFound++; // This is a valid rootbridge so imcrement total root bridges found 189 190 // 191 // Add PCIE base into Runtime memory so that it can be reported in E820 table 192 // 193 Status = gDS->AddMemorySpace ( 194 EfiGcdMemoryTypeMemoryMappedIo, 195 PcdGet64 (PcdPciExpressBaseAddress), 196 PcdGet64 (PcdPciExpressSize), 197 EFI_MEMORY_RUNTIME | EFI_MEMORY_UC 198 ); 199 ASSERT_EFI_ERROR(Status); 200 201 BaseAddress = PcdGet64 (PcdPciExpressBaseAddress); 202 203 Status = gDS->AllocateMemorySpace ( 204 EfiGcdAllocateAddress, 205 EfiGcdMemoryTypeMemoryMappedIo, 206 0, 207 PcdGet64 (PcdPciExpressSize), 208 &BaseAddress, 209 ImageHandle, 210 NULL 211 ); 212 ASSERT_EFI_ERROR(Status); 213 214 Status = gDS->SetMemorySpaceAttributes ( 215 PcdGet64 (PcdPciExpressBaseAddress), 216 PcdGet64 (PcdPciExpressSize), 217 EFI_MEMORY_RUNTIME 218 ); 219 ASSERT_EFI_ERROR (Status); 220 221 if (PcdGet16 (PcdPciHostBridgeIoSize) > 0) { 222 // 223 // At present, we use up the first 4k for fixed ranges like 224 // ICH GPIO, ACPI and ISA devices. The first 4k is not 225 // tracked through GCD. It should be. 226 // 227 Status = gDS->AddIoSpace ( 228 EfiGcdIoTypeIo, 229 PcdGet16(PcdPciHostBridgeIoBase), 230 PcdGet16(PcdPciHostBridgeIoSize) 231 ); 232 ASSERT_EFI_ERROR (Status); 233 } 234 235 if (PcdGet32(PcdPciHostBridgeMemory32Size) > 0) { 236 // 237 // Shouldn't the capabilities be UC? 238 // 239 Status = gDS->AddMemorySpace ( 240 EfiGcdMemoryTypeMemoryMappedIo, 241 PcdGet32(PcdPciHostBridgeMemory32Base), 242 PcdGet32(PcdPciHostBridgeMemory32Size), 243 0 244 ); 245 ASSERT_EFI_ERROR (Status); 246 } 247 248 return Status; 249 } 250 251 EFI_STATUS 252 EFIAPI 253 NotifyPhase ( 254 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 255 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase 256 ) 257 /*++ 258 259 Routine Description: 260 261 Enter a certain phase of the PCI enumeration process. 262 263 Arguments: 264 265 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. 266 Phase - The phase during enumeration. 267 268 Returns: 269 270 EFI_SUCCESS - Succeed. 271 EFI_INVALID_PARAMETER - Wrong phase parameter passed in. 272 EFI_NOT_READY - Resources have not been submitted yet. 273 274 --*/ 275 { 276 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 277 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 278 PCI_RESOURCE_TYPE Index; 279 EFI_LIST_ENTRY *List; 280 EFI_PHYSICAL_ADDRESS BaseAddress; 281 UINT64 AddrLen; 282 UINTN BitsOfAlignment; 283 UINT64 Alignment; 284 EFI_STATUS Status; 285 EFI_STATUS ReturnStatus; 286 PCI_RESOURCE_TYPE Index1; 287 PCI_RESOURCE_TYPE Index2; 288 BOOLEAN ResNodeHandled[TypeMax]; 289 UINT64 MaxAlignment; 290 291 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 292 293 switch (Phase) { 294 case EfiPciHostBridgeBeginEnumeration: 295 if (HostBridgeInstance->CanRestarted) { 296 // 297 // Reset Root Bridge 298 // 299 List = HostBridgeInstance->Head.ForwardLink; 300 301 while (List != &HostBridgeInstance->Head) { 302 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 303 for (Index = TypeIo; Index < TypeMax; Index++) { 304 RootBridgeInstance->ResAllocNode[Index].Type = Index; 305 RootBridgeInstance->ResAllocNode[Index].Base = 0; 306 RootBridgeInstance->ResAllocNode[Index].Length = 0; 307 RootBridgeInstance->ResAllocNode[Index].Status = ResNone; 308 } // for 309 310 List = List->ForwardLink; 311 } // while 312 313 HostBridgeInstance->ResourceSubmited = FALSE; 314 HostBridgeInstance->CanRestarted = TRUE; 315 } else { 316 // 317 // Can not restart 318 // 319 return EFI_NOT_READY; 320 } // if 321 break; 322 323 case EfiPciHostBridgeEndEnumeration: 324 return EFI_SUCCESS; 325 break; 326 327 case EfiPciHostBridgeBeginBusAllocation: 328 // 329 // No specific action is required here, can perform any chipset specific programing 330 // 331 HostBridgeInstance->CanRestarted = FALSE; 332 return EFI_SUCCESS; 333 break; 334 335 case EfiPciHostBridgeEndBusAllocation: 336 // 337 // No specific action is required here, can perform any chipset specific programing 338 // 339 // HostBridgeInstance->CanRestarted = FALSE; 340 // 341 return EFI_SUCCESS; 342 break; 343 344 case EfiPciHostBridgeBeginResourceAllocation: 345 // 346 // No specific action is required here, can perform any chipset specific programing 347 // 348 // HostBridgeInstance->CanRestarted = FALSE; 349 // 350 return EFI_SUCCESS; 351 break; 352 353 case EfiPciHostBridgeAllocateResources: 354 ReturnStatus = EFI_SUCCESS; 355 if (HostBridgeInstance->ResourceSubmited) { 356 List = HostBridgeInstance->Head.ForwardLink; 357 while (List != &HostBridgeInstance->Head) { 358 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) { 359 ResNodeHandled[Index1] = FALSE; 360 } 361 362 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 363 DEBUG ((EFI_D_INFO, "Address of RootBridgeInstance: %x)\n", RootBridgeInstance)); 364 DEBUG ((EFI_D_INFO, " Signature: %x\n", RootBridgeInstance->Signature)); 365 DEBUG ((EFI_D_INFO, " Bus Number Assigned: %x\n", RootBridgeInstance->BusNumberAssigned)); 366 DEBUG ((EFI_D_INFO, " Bus Scan Count: %x\n", RootBridgeInstance->BusScanCount)); 367 368 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) { 369 if (RootBridgeInstance->ResAllocNode[Index1].Status == ResNone) { 370 ResNodeHandled[Index1] = TRUE; 371 } else { 372 // 373 // Allocate the resource node with max alignment at first 374 // 375 MaxAlignment = 0; 376 Index = TypeMax; 377 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) { 378 if (ResNodeHandled[Index2]) { 379 continue; 380 } 381 if (MaxAlignment <= RootBridgeInstance->ResAllocNode[Index2].Alignment) { 382 MaxAlignment = RootBridgeInstance->ResAllocNode[Index2].Alignment; 383 Index = Index2; 384 } 385 } // for 386 387 if (Index < TypeMax) { 388 ResNodeHandled[Index] = TRUE; 389 } else { 390 ASSERT (FALSE); 391 } 392 393 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment; 394 395 // 396 // Get the number of '1' in Alignment. 397 // 398 for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) { 399 Alignment = RShiftU64 (Alignment, 1); 400 } 401 402 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 403 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment; 404 405 DEBUG ((EFI_D_INFO, "\n\nResource Type to assign : %x\n", Index)); 406 DEBUG ((EFI_D_INFO, " Length to allocate: %x\n", RootBridgeInstance->ResAllocNode[Index].Length)); 407 DEBUG ((EFI_D_INFO, " Aligment: %x\n", Alignment)); 408 409 switch (Index) { 410 case TypeIo: 411 if (RootBridgeInstance->Aperture.IoBase < RootBridgeInstance->Aperture.IoLimit) { 412 // 413 // It is impossible for 0xFFFF Alignment for IO16 414 // 415 if (BitsOfAlignment >= 16) 416 Alignment = 0; 417 418 BaseAddress = RootBridgeInstance->Aperture.IoBase; 419 420 // 421 // Have to make sure Aligment is handled seeing we are doing direct address allocation 422 // 423 if ((BaseAddress & ~(Alignment)) != BaseAddress) 424 BaseAddress = ((BaseAddress + Alignment) & ~(Alignment)); 425 426 while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.IoLimit + 1) { 427 428 Status = gDS->AllocateIoSpace ( EfiGcdAllocateAddress, EfiGcdIoTypeIo, BitsOfAlignment, 429 AddrLen, &BaseAddress, mDriverImageHandle, NULL ); 430 431 if (!EFI_ERROR (Status)) { 432 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress; 433 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; 434 goto TypeIoFound; 435 } 436 437 BaseAddress += (Alignment + 1); 438 } // while 439 440 } // if 441 442 TypeIoFound: 443 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { 444 // 445 // No Room at the Inn for this resources request 446 // 447 ReturnStatus = EFI_OUT_OF_RESOURCES; 448 } // if 449 450 break; 451 452 case TypeMem32: 453 if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) { 454 455 BaseAddress = RootBridgeInstance->Aperture.Mem32Base; 456 // 457 // Have to make sure Aligment is handled seeing we are doing direct address allocation 458 // 459 if ((BaseAddress & ~(Alignment)) != BaseAddress) 460 BaseAddress = ((BaseAddress + Alignment) & ~(Alignment)); 461 462 while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.Mem32Limit + 1) { 463 464 Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo, 465 BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL); 466 467 if (!EFI_ERROR (Status)) { 468 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress; 469 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; 470 goto TypeMem32Found; 471 } // if 472 473 BaseAddress += (Alignment + 1); 474 } // while 475 } // if 476 477 TypeMem32Found: 478 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { 479 // 480 // No Room at the Inn for this resources request 481 // 482 ReturnStatus = EFI_OUT_OF_RESOURCES; 483 } 484 485 break; 486 487 case TypePMem32: 488 StartTypePMem32: 489 if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) { 490 491 BaseAddress = RootBridgeInstance->Aperture.Mem32Limit + 1; 492 BaseAddress -= AddrLen; 493 494 // 495 // Have to make sure Aligment is handled seeing we are doing direct address allocation 496 // 497 if ((BaseAddress & ~(Alignment)) != BaseAddress) 498 BaseAddress = ((BaseAddress) & ~(Alignment)); 499 500 while(RootBridgeInstance->Aperture.Mem32Base <= BaseAddress) { 501 502 DEBUG ((EFI_D_INFO, " Attempting %x allocation at 0x%lx .....", Index, BaseAddress)); 503 Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo, 504 BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL); 505 506 if (!EFI_ERROR (Status)) { 507 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress; 508 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; 509 DEBUG ((EFI_D_INFO, "... Passed!!\n")); 510 goto TypePMem32Found; 511 } 512 DEBUG ((EFI_D_INFO, "... Failed!!\n")); 513 BaseAddress -= (Alignment + 1); 514 } // while 515 } // if 516 517 TypePMem32Found: 518 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { 519 // 520 // No Room at the Inn for this resources request 521 // 522 ReturnStatus = EFI_OUT_OF_RESOURCES; 523 } 524 525 break; 526 527 case TypeMem64: 528 case TypePMem64: 529 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { 530 // 531 // If 64-bit resourcing is not available, then try as PMem32 532 // 533 goto StartTypePMem32; 534 } 535 536 break; 537 538 default: 539 break; 540 } // End switch (Index) 541 542 DEBUG ((EFI_D_INFO, "Resource Type Assigned: %x\n", Index)); 543 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) { 544 DEBUG ((EFI_D_INFO, " Base Address Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Base)); 545 DEBUG ((EFI_D_INFO, " Length Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Length)); 546 } else { 547 DEBUG ((DEBUG_ERROR, " Resource Allocation failed! There was no room at the inn\n")); 548 } 549 550 } 551 } 552 553 List = List->ForwardLink; 554 } 555 556 if (ReturnStatus == EFI_OUT_OF_RESOURCES) { 557 DEBUG ((DEBUG_ERROR, "Resource allocation Failed. Continue booting the system.\n")); 558 } 559 560 // 561 // Set resource to zero for nodes where allocation fails 562 // 563 List = HostBridgeInstance->Head.ForwardLink; 564 while (List != &HostBridgeInstance->Head) { 565 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 566 for (Index = TypeIo; Index < TypeBus; Index++) { 567 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { 568 RootBridgeInstance->ResAllocNode[Index].Length = 0; 569 } 570 } 571 List = List->ForwardLink; 572 } 573 return ReturnStatus; 574 } else { 575 return EFI_NOT_READY; 576 } 577 // 578 // HostBridgeInstance->CanRestarted = FALSE; 579 // 580 break; 581 582 case EfiPciHostBridgeSetResources: 583 // 584 // HostBridgeInstance->CanRestarted = FALSE; 585 // 586 break; 587 588 case EfiPciHostBridgeFreeResources: 589 // 590 // HostBridgeInstance->CanRestarted = FALSE; 591 // 592 ReturnStatus = EFI_SUCCESS; 593 List = HostBridgeInstance->Head.ForwardLink; 594 while (List != &HostBridgeInstance->Head) { 595 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 596 for (Index = TypeIo; Index < TypeBus; Index++) { 597 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) { 598 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 599 BaseAddress = (EFI_PHYSICAL_ADDRESS) RootBridgeInstance->ResAllocNode[Index].Base; 600 switch (Index) { 601 case TypeIo: 602 Status = gDS->FreeIoSpace (BaseAddress, AddrLen); 603 if (EFI_ERROR (Status)) { 604 ReturnStatus = Status; 605 } 606 break; 607 608 case TypeMem32: 609 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen); 610 if (EFI_ERROR (Status)) { 611 ReturnStatus = Status; 612 } 613 break; 614 615 case TypePMem32: 616 break; 617 618 case TypeMem64: 619 break; 620 621 case TypePMem64: 622 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen); 623 if (EFI_ERROR (Status)) { 624 ReturnStatus = Status; 625 } 626 break; 627 628 default: 629 break; 630 } // end switch (Index) 631 632 RootBridgeInstance->ResAllocNode[Index].Type = Index; 633 RootBridgeInstance->ResAllocNode[Index].Base = 0; 634 RootBridgeInstance->ResAllocNode[Index].Length = 0; 635 RootBridgeInstance->ResAllocNode[Index].Status = ResNone; 636 } 637 } 638 639 List = List->ForwardLink; 640 } 641 642 HostBridgeInstance->ResourceSubmited = FALSE; 643 HostBridgeInstance->CanRestarted = TRUE; 644 return ReturnStatus; 645 break; 646 647 case EfiPciHostBridgeEndResourceAllocation: 648 // 649 // Resource enumeration is done. Perform any activities that 650 // must wait until that time. 651 // 652 break; 653 654 default: 655 return EFI_INVALID_PARAMETER; 656 } // End switch (Phase) 657 658 return EFI_SUCCESS; 659 } 660 661 EFI_STATUS 662 EFIAPI 663 GetNextRootBridge ( 664 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 665 IN OUT EFI_HANDLE *RootBridgeHandle 666 ) 667 /*++ 668 669 Routine Description: 670 Return the device handle of the next PCI root bridge that is associated with 671 this Host Bridge. 672 673 Arguments: 674 675 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 676 RootBridgeHandle - Returns the device handle of the next PCI Root Bridge. 677 On input, it holds the RootBridgeHandle returned by the most 678 recent call to GetNextRootBridge().The handle for the first 679 PCI Root Bridge is returned if RootBridgeHandle is NULL on input. 680 681 Returns: 682 683 EFI_SUCCESS - Succeed. 684 EFI_NOT_FOUND - Next PCI root bridge not found. 685 EFI_INVALID_PARAMETER - Wrong parameter passed in. 686 687 --*/ 688 { 689 BOOLEAN NoRootBridge; 690 EFI_LIST_ENTRY *List; 691 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 692 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 693 694 NoRootBridge = TRUE; 695 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 696 List = HostBridgeInstance->Head.ForwardLink; 697 698 while (List != &HostBridgeInstance->Head) { 699 NoRootBridge = FALSE; 700 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 701 if (*RootBridgeHandle == NULL) { 702 // 703 // Return the first Root Bridge Handle of the Host Bridge 704 // 705 *RootBridgeHandle = RootBridgeInstance->Handle; 706 return EFI_SUCCESS; 707 } else { 708 if (*RootBridgeHandle == RootBridgeInstance->Handle) { 709 // 710 // Get next if have 711 // 712 List = List->ForwardLink; 713 if (List != &HostBridgeInstance->Head) { 714 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 715 *RootBridgeHandle = RootBridgeInstance->Handle; 716 return EFI_SUCCESS; 717 } else { 718 return EFI_NOT_FOUND; 719 } 720 } 721 } 722 723 List = List->ForwardLink; 724 // 725 // end while 726 // 727 } 728 729 if (NoRootBridge) { 730 return EFI_NOT_FOUND; 731 } else { 732 return EFI_INVALID_PARAMETER; 733 } 734 } 735 736 EFI_STATUS 737 EFIAPI 738 GetAttributes ( 739 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 740 IN EFI_HANDLE RootBridgeHandle, 741 OUT UINT64 *Attributes 742 ) 743 /*++ 744 745 Routine Description: 746 Returns the attributes of a PCI Root Bridge. 747 748 Arguments: 749 750 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 751 RootBridgeHandle - The device handle of the PCI Root Bridge 752 that the caller is interested in. 753 Attributes - The pointer to attributes of the PCI Root Bridge. 754 755 Returns: 756 757 EFI_SUCCESS - Succeed. 758 EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or 759 RootBridgeHandle is not an EFI_HANDLE 760 that was returned on a previous call to 761 GetNextRootBridge(). 762 763 --*/ 764 { 765 EFI_LIST_ENTRY *List; 766 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 767 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 768 769 if (Attributes == NULL) { 770 return EFI_INVALID_PARAMETER; 771 } 772 773 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 774 List = HostBridgeInstance->Head.ForwardLink; 775 776 while (List != &HostBridgeInstance->Head) { 777 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 778 if (RootBridgeHandle == RootBridgeInstance->Handle) { 779 *Attributes = RootBridgeInstance->RootBridgeAllocAttrib; 780 return EFI_SUCCESS; 781 } 782 783 List = List->ForwardLink; 784 } 785 // 786 // RootBridgeHandle is not an EFI_HANDLE 787 // that was returned on a previous call to GetNextRootBridge() 788 // 789 return EFI_INVALID_PARAMETER; 790 } 791 792 EFI_STATUS 793 EFIAPI 794 StartBusEnumeration ( 795 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 796 IN EFI_HANDLE RootBridgeHandle, 797 OUT VOID **Configuration 798 ) 799 /*++ 800 801 Routine Description: 802 This is the request from the PCI enumerator to set up 803 the specified PCI Root Bridge for bus enumeration process. 804 805 Arguments: 806 807 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 808 RootBridgeHandle - The PCI Root Bridge to be set up. 809 Configuration - Pointer to the pointer to the PCI bus resource descriptor. 810 811 Returns: 812 813 EFI_SUCCESS - Succeed. 814 EFI_OUT_OF_RESOURCES - Not enough pool to be allocated. 815 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle. 816 817 --*/ 818 { 819 EFI_LIST_ENTRY *List; 820 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 821 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 822 VOID *Buffer; 823 UINT8 *Temp; 824 EFI_STATUS Status; 825 UINTN BusStart; 826 UINTN BusEnd; 827 UINT64 BusReserve; 828 829 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 830 List = HostBridgeInstance->Head.ForwardLink; 831 832 while (List != &HostBridgeInstance->Head) { 833 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 834 if (RootBridgeHandle == RootBridgeInstance->Handle) { 835 // 836 // Set up the Root Bridge for Bus Enumeration 837 // 838 BusStart = RootBridgeInstance->Aperture.BusBase; 839 BusEnd = RootBridgeInstance->Aperture.BusLimit; 840 BusReserve = RootBridgeInstance->Aperture.BusReserve; 841 // 842 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR 843 // 844 Status = gBS->AllocatePool ( 845 EfiBootServicesData, 846 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), 847 &Buffer 848 ); 849 if (EFI_ERROR (Status)) { 850 return EFI_OUT_OF_RESOURCES; 851 } 852 853 Temp = (UINT8 *) Buffer; 854 855 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; 856 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len = 0x2B; 857 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; 858 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->GenFlag = 0; 859 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->SpecificFlag = 0; 860 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrSpaceGranularity = 0; 861 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMin = BusStart; 862 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMax = BusReserve; 863 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrTranslationOffset = 0; 864 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrLen = BusEnd - BusStart + 1; 865 866 Temp = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 867 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = ACPI_END_TAG_DESCRIPTOR; 868 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0; 869 870 *Configuration = Buffer; 871 return EFI_SUCCESS; 872 } 873 874 List = List->ForwardLink; 875 } 876 877 return EFI_INVALID_PARAMETER; 878 } 879 880 EFI_STATUS 881 EFIAPI 882 SetBusNumbers ( 883 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 884 IN EFI_HANDLE RootBridgeHandle, 885 IN VOID *Configuration 886 ) 887 /*++ 888 889 Routine Description: 890 This function programs the PCI Root Bridge hardware so that 891 it decodes the specified PCI bus range. 892 893 Arguments: 894 895 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 896 RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed. 897 Configuration - The pointer to the PCI bus resource descriptor. 898 899 Returns: 900 901 EFI_SUCCESS - Succeed. 902 EFI_INVALID_PARAMETER - Wrong parameters passed in. 903 904 --*/ 905 { 906 EFI_LIST_ENTRY *List; 907 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 908 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 909 UINT8 *Ptr; 910 UINTN BusStart; 911 UINTN BusEnd; 912 UINTN BusLen; 913 914 if (Configuration == NULL) { 915 return EFI_INVALID_PARAMETER; 916 } 917 918 Ptr = Configuration; 919 920 // 921 // Check the Configuration is valid 922 // 923 if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) { 924 return EFI_INVALID_PARAMETER; 925 } 926 927 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) { 928 return EFI_INVALID_PARAMETER; 929 } 930 931 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 932 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { 933 return EFI_INVALID_PARAMETER; 934 } 935 936 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 937 List = HostBridgeInstance->Head.ForwardLink; 938 939 Ptr = Configuration; 940 941 while (List != &HostBridgeInstance->Head) { 942 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 943 if (RootBridgeHandle == RootBridgeInstance->Handle) { 944 BusStart = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrRangeMin; 945 BusLen = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrLen; 946 BusEnd = BusStart + BusLen - 1; 947 948 if (BusStart > BusEnd) { 949 return EFI_INVALID_PARAMETER; 950 } 951 952 if ((BusStart < RootBridgeInstance->Aperture.BusBase) || (BusEnd > RootBridgeInstance->Aperture.BusLimit)) { 953 return EFI_INVALID_PARAMETER; 954 } 955 // 956 // Update the Bus Range 957 // 958 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart; 959 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen; 960 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated; 961 RootBridgeInstance->BusScanCount++; 962 if (RootBridgeInstance->BusScanCount > 0) { 963 // 964 // Only care about the 2nd PCI bus scanning 965 // 966 RootBridgeInstance->BusNumberAssigned = TRUE; 967 } 968 969 return EFI_SUCCESS; 970 } 971 972 List = List->ForwardLink; 973 } 974 975 return EFI_INVALID_PARAMETER; 976 } 977 978 EFI_STATUS 979 EFIAPI 980 SubmitResources ( 981 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 982 IN EFI_HANDLE RootBridgeHandle, 983 IN VOID *Configuration 984 ) 985 /*++ 986 987 Routine Description: 988 989 Submits the I/O and memory resource requirements for the specified PCI Root Bridge. 990 991 Arguments: 992 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 993 RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements. 994 are being submitted. 995 Configuration - The pointer to the PCI I/O and PCI memory resource descriptor. 996 997 Returns: 998 999 EFI_SUCCESS - Succeed. 1000 EFI_INVALID_PARAMETER - Wrong parameters passed in. 1001 1002 --*/ 1003 { 1004 EFI_LIST_ENTRY *List; 1005 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1006 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1007 UINT8 *Temp; 1008 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr; 1009 UINT64 AddrLen; 1010 UINT64 Alignment; 1011 UINT64 Value; 1012 1013 // 1014 // Check the input parameter: Configuration 1015 // 1016 if (Configuration == NULL) { 1017 return EFI_INVALID_PARAMETER; 1018 } 1019 1020 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1021 List = HostBridgeInstance->Head.ForwardLink; 1022 1023 Temp = (UINT8 *) Configuration; 1024 while (List != &HostBridgeInstance->Head) { 1025 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1026 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1027 // 1028 // Check the resource descriptors. 1029 // If the Configuration includes one or more invalid resource descriptors, all the resource 1030 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER. 1031 // 1032 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) { 1033 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; 1034 DEBUG ((EFI_D_INFO, " ptr->ResType:%x \n",ptr->ResType)); 1035 DEBUG ((EFI_D_INFO, " ptr->AddrLen:0x%lx AddrRangeMin:0x%lx AddrRangeMax:0x%lx\n\n",ptr->AddrLen,ptr->AddrRangeMin,ptr->AddrRangeMax)); 1036 1037 switch (ptr->ResType) { 1038 case ACPI_ADDRESS_SPACE_TYPE_MEM: 1039 if (ptr->AddrSpaceGranularity != 32 && ptr->AddrSpaceGranularity != 64) { 1040 return EFI_INVALID_PARAMETER; 1041 } 1042 if (ptr->AddrSpaceGranularity == 32 && ptr->AddrLen > 0xffffffff) { 1043 return EFI_INVALID_PARAMETER; 1044 } 1045 // 1046 // If the PCI root bridge does not support separate windows for nonprefetchable and 1047 // prefetchable memory, then the PCI bus driver needs to include requests for 1048 // prefetchable memory in the nonprefetchable memory pool. 1049 // 1050 if ((RootBridgeInstance->RootBridgeAllocAttrib & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 && 1051 ((ptr->SpecificFlag & (BIT2 | BIT1)) != 0)) { 1052 return EFI_INVALID_PARAMETER; 1053 } 1054 case ACPI_ADDRESS_SPACE_TYPE_IO: 1055 // 1056 // Check aligment, it should be of the form 2^n-1 1057 // 1058 Value = Power2MaxMemory (ptr->AddrRangeMax + 1); 1059 if (Value != (ptr->AddrRangeMax + 1)) { 1060 CpuDeadLoop(); 1061 return EFI_INVALID_PARAMETER; 1062 } 1063 break; 1064 case ACPI_ADDRESS_SPACE_TYPE_BUS: 1065 default: 1066 return EFI_INVALID_PARAMETER; 1067 } 1068 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; 1069 } 1070 if (*Temp != ACPI_END_TAG_DESCRIPTOR) { 1071 return EFI_INVALID_PARAMETER; 1072 } 1073 1074 Temp = (UINT8 *) Configuration; 1075 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) { 1076 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; 1077 1078 switch (ptr->ResType) { 1079 case ACPI_ADDRESS_SPACE_TYPE_MEM: 1080 AddrLen = (UINT64) ptr->AddrLen; 1081 Alignment = (UINT64) ptr->AddrRangeMax; 1082 if (ptr->AddrSpaceGranularity == 32) { 1083 if (ptr->SpecificFlag == 0x06) { 1084 // 1085 // Apply from GCD 1086 // 1087 RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted; 1088 } else { 1089 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen; 1090 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment; 1091 RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested; 1092 HostBridgeInstance->ResourceSubmited = TRUE; 1093 } 1094 } 1095 1096 if (ptr->AddrSpaceGranularity == 64) { 1097 if (ptr->SpecificFlag == 0x06) { 1098 RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted; 1099 } else { 1100 RootBridgeInstance->ResAllocNode[TypeMem64].Length = AddrLen; 1101 RootBridgeInstance->ResAllocNode[TypeMem64].Alignment = Alignment; 1102 RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted; 1103 HostBridgeInstance->ResourceSubmited = TRUE; 1104 } 1105 } 1106 break; 1107 1108 case ACPI_ADDRESS_SPACE_TYPE_IO: 1109 AddrLen = (UINT64) ptr->AddrLen; 1110 Alignment = (UINT64) ptr->AddrRangeMax; 1111 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen; 1112 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment; 1113 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested; 1114 HostBridgeInstance->ResourceSubmited = TRUE; 1115 break; 1116 1117 default: 1118 break; 1119 } 1120 1121 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 1122 } 1123 1124 return EFI_SUCCESS; 1125 } 1126 1127 List = List->ForwardLink; 1128 } 1129 1130 return EFI_INVALID_PARAMETER; 1131 } 1132 1133 EFI_STATUS 1134 EFIAPI 1135 GetProposedResources ( 1136 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1137 IN EFI_HANDLE RootBridgeHandle, 1138 OUT VOID **Configuration 1139 ) 1140 /*++ 1141 1142 Routine Description: 1143 This function returns the proposed resource settings for the specified 1144 PCI Root Bridge. 1145 1146 Arguments: 1147 1148 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 1149 RootBridgeHandle - The PCI Root Bridge handle. 1150 Configuration - The pointer to the pointer to the PCI I/O 1151 and memory resource descriptor. 1152 1153 Returns: 1154 1155 EFI_SUCCESS - Succeed. 1156 EFI_OUT_OF_RESOURCES - Not enough pool to be allocated. 1157 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle. 1158 1159 --*/ 1160 { 1161 EFI_LIST_ENTRY *List; 1162 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1163 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1164 UINTN Index; 1165 UINTN Number; 1166 VOID *Buffer; 1167 UINT8 *Temp; 1168 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr; 1169 EFI_STATUS Status; 1170 UINT64 ResStatus; 1171 1172 Buffer = NULL; 1173 Number = 0; 1174 // 1175 // Get the Host Bridge Instance from the resource allocation protocol 1176 // 1177 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1178 List = HostBridgeInstance->Head.ForwardLink; 1179 1180 // 1181 // Enumerate the root bridges in this host bridge 1182 // 1183 while (List != &HostBridgeInstance->Head) { 1184 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1185 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1186 for (Index = 0; Index < TypeBus; Index++) { 1187 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { 1188 Number++; 1189 } 1190 } 1191 1192 if (Number > 0) { 1193 Status = gBS->AllocatePool ( 1194 EfiBootServicesData, 1195 Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), 1196 &Buffer 1197 ); 1198 1199 if (EFI_ERROR (Status)) { 1200 return EFI_OUT_OF_RESOURCES; 1201 } 1202 1203 ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); 1204 } 1205 1206 ASSERT (Buffer != NULL); 1207 Temp = Buffer; 1208 for (Index = 0; Index < TypeBus; Index++) { 1209 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { 1210 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; 1211 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status; 1212 1213 switch (Index) { 1214 1215 case TypeIo: 1216 // 1217 // Io 1218 // 1219 ptr->Desc = 0x8A; 1220 ptr->Len = 0x2B; 1221 ptr->ResType = 1; 1222 ptr->GenFlag = 0; 1223 ptr->SpecificFlag = 0; 1224 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base; 1225 ptr->AddrRangeMax = 0; 1226 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1227 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1228 break; 1229 1230 case TypeMem32: 1231 // 1232 // Memory 32 1233 // 1234 ptr->Desc = 0x8A; 1235 ptr->Len = 0x2B; 1236 ptr->ResType = 0; 1237 ptr->GenFlag = 0; 1238 ptr->SpecificFlag = 0; 1239 ptr->AddrSpaceGranularity = 32; 1240 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base; 1241 ptr->AddrRangeMax = 0; 1242 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1243 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1244 break; 1245 1246 case TypePMem32: 1247 // 1248 // Prefetch memory 32 1249 // 1250 ptr->Desc = 0x8A; 1251 ptr->Len = 0x2B; 1252 ptr->ResType = 0; 1253 ptr->GenFlag = 0; 1254 ptr->SpecificFlag = 6; 1255 ptr->AddrSpaceGranularity = 32; 1256 ptr->AddrRangeMin = 0; 1257 ptr->AddrRangeMax = 0; 1258 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT; 1259 ptr->AddrLen = 0; 1260 break; 1261 1262 case TypeMem64: 1263 // 1264 // Memory 64 1265 // 1266 ptr->Desc = 0x8A; 1267 ptr->Len = 0x2B; 1268 ptr->ResType = 0; 1269 ptr->GenFlag = 0; 1270 ptr->SpecificFlag = 0; 1271 ptr->AddrSpaceGranularity = 64; 1272 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base; 1273 ptr->AddrRangeMax = 0; 1274 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1275 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1276 break; 1277 1278 case TypePMem64: 1279 // 1280 // Prefetch memory 64 1281 // 1282 ptr->Desc = 0x8A; 1283 ptr->Len = 0x2B; 1284 ptr->ResType = 0; 1285 ptr->GenFlag = 0; 1286 ptr->SpecificFlag = 6; 1287 ptr->AddrSpaceGranularity = 64; 1288 ptr->AddrRangeMin = 0; 1289 ptr->AddrRangeMax = 0; 1290 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT; 1291 ptr->AddrLen = 0; 1292 break; 1293 } 1294 1295 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 1296 } 1297 } 1298 1299 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = 0x79; 1300 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0; 1301 1302 *Configuration = Buffer; 1303 1304 return EFI_SUCCESS; 1305 } 1306 1307 List = List->ForwardLink; 1308 } 1309 1310 return EFI_INVALID_PARAMETER; 1311 } 1312 1313 EFI_STATUS 1314 EFIAPI 1315 PreprocessController ( 1316 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1317 IN EFI_HANDLE RootBridgeHandle, 1318 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, 1319 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase 1320 ) 1321 /*++ 1322 1323 Routine Description: 1324 This function is called for all the PCI controllers that the PCI 1325 bus driver finds. Can be used to Preprogram the controller. 1326 1327 Arguments: 1328 1329 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 1330 RootBridgeHandle - The PCI Root Bridge handle. 1331 PciAddress - Address of the controller on the PCI bus. 1332 Phase - The Phase during resource allocation. 1333 1334 Returns: 1335 1336 EFI_SUCCESS - Succeed. 1337 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle. 1338 1339 --*/ 1340 { 1341 BOOLEAN RootBridgeFound; 1342 EFI_LIST_ENTRY *List; 1343 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1344 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1345 1346 if (RootBridgeHandle == NULL) { 1347 return EFI_INVALID_PARAMETER; 1348 } 1349 1350 RootBridgeFound = FALSE; 1351 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1352 List = HostBridgeInstance->Head.ForwardLink; 1353 1354 while (List != &HostBridgeInstance->Head) { 1355 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1356 1357 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1358 RootBridgeFound = TRUE; 1359 break; 1360 } 1361 // 1362 // Get next if have 1363 // 1364 List = List->ForwardLink; 1365 } 1366 1367 if (RootBridgeFound == FALSE) { 1368 return EFI_INVALID_PARAMETER; 1369 } 1370 1371 return EFI_SUCCESS; 1372 } 1373 1374 UINT64 1375 Power2MaxMemory ( 1376 IN UINT64 MemoryLength 1377 ) 1378 /*++ 1379 1380 Routine Description: 1381 1382 Calculate maximum memory length that can be fit to a mtrr. 1383 1384 Arguments: 1385 1386 MemoryLength - Input memory length. 1387 1388 Returns: 1389 1390 Returned Maximum length. 1391 1392 --*/ 1393 { 1394 UINT64 Result; 1395 1396 if (RShiftU64 (MemoryLength, 32)) { 1397 Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32); 1398 } else { 1399 Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength); 1400 } 1401 1402 return Result; 1403 } 1404