Home | History | Annotate | Download | only in PciHostBridgeDxe
      1 /** @file
      2 
      3   Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
      4 
      5 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "PciHostBridge.h"
     17 #include "PciRootBridge.h"
     18 #include "PciHostResource.h"
     19 
     20 
     21 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
     22 EFI_CPU_IO2_PROTOCOL        *mCpuIo;
     23 
     24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {
     25   L"Mem", L"I/O", L"Bus"
     26 };
     27 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
     28   L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"
     29 };
     30 
     31 /**
     32   Ensure the compatibility of an IO space descriptor with the IO aperture.
     33 
     34   The IO space descriptor can come from the GCD IO space map, or it can
     35   represent a gap between two neighboring IO space descriptors. In the latter
     36   case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent.
     37 
     38   If the IO space descriptor already has type EfiGcdIoTypeIo, then no action is
     39   taken -- it is by definition compatible with the aperture.
     40 
     41   Otherwise, the intersection of the IO space descriptor is calculated with the
     42   aperture. If the intersection is the empty set (no overlap), no action is
     43   taken; the IO space descriptor is compatible with the aperture.
     44 
     45   Otherwise, the type of the descriptor is investigated again. If the type is
     46   EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with
     47   such a type), then an attempt is made to add the intersection as IO space to
     48   the GCD IO space map. This ensures continuity for the aperture, and the
     49   descriptor is deemed compatible with the aperture.
     50 
     51   Otherwise, the IO space descriptor is incompatible with the IO aperture.
     52 
     53   @param[in] Base        Base address of the aperture.
     54   @param[in] Length      Length of the aperture.
     55   @param[in] Descriptor  The descriptor to ensure compatibility with the
     56                          aperture for.
     57 
     58   @retval EFI_SUCCESS            The descriptor is compatible. The GCD IO space
     59                                  map may have been updated, for continuity
     60                                  within the aperture.
     61   @retval EFI_INVALID_PARAMETER  The descriptor is incompatible.
     62   @return                        Error codes from gDS->AddIoSpace().
     63 **/
     64 EFI_STATUS
     65 IntersectIoDescriptor (
     66   IN  UINT64                            Base,
     67   IN  UINT64                            Length,
     68   IN  CONST EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
     69   )
     70 {
     71   UINT64                                IntersectionBase;
     72   UINT64                                IntersectionEnd;
     73   EFI_STATUS                            Status;
     74 
     75   if (Descriptor->GcdIoType == EfiGcdIoTypeIo) {
     76     return EFI_SUCCESS;
     77   }
     78 
     79   IntersectionBase = MAX (Base, Descriptor->BaseAddress);
     80   IntersectionEnd = MIN (Base + Length,
     81                       Descriptor->BaseAddress + Descriptor->Length);
     82   if (IntersectionBase >= IntersectionEnd) {
     83     //
     84     // The descriptor and the aperture don't overlap.
     85     //
     86     return EFI_SUCCESS;
     87   }
     88 
     89   if (Descriptor->GcdIoType == EfiGcdIoTypeNonExistent) {
     90     Status = gDS->AddIoSpace (EfiGcdIoTypeIo, IntersectionBase,
     91                     IntersectionEnd - IntersectionBase);
     92 
     93     DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE,
     94       "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__,
     95       IntersectionBase, IntersectionEnd, Status));
     96     return Status;
     97   }
     98 
     99   DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u conflicts with "
    100     "aperture [%Lx, %Lx)\n", gEfiCallerBaseName, __FUNCTION__,
    101     Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length,
    102     (UINT32)Descriptor->GcdIoType, Base, Base + Length));
    103   return EFI_INVALID_PARAMETER;
    104 }
    105 
    106 /**
    107   Add IO space to GCD.
    108   The routine checks the GCD database and only adds those which are
    109   not added in the specified range to GCD.
    110 
    111   @param Base   Base address of the IO space.
    112   @param Length Length of the IO space.
    113 
    114   @retval EFI_SUCCES The IO space was added successfully.
    115 **/
    116 EFI_STATUS
    117 AddIoSpace (
    118   IN  UINT64                        Base,
    119   IN  UINT64                        Length
    120   )
    121 {
    122   EFI_STATUS                        Status;
    123   UINTN                             Index;
    124   UINTN                             NumberOfDescriptors;
    125   EFI_GCD_IO_SPACE_DESCRIPTOR       *IoSpaceMap;
    126 
    127   Status = gDS->GetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);
    128   if (EFI_ERROR (Status)) {
    129     DEBUG ((EFI_D_ERROR, "%a: %a: GetIoSpaceMap(): %r\n",
    130       gEfiCallerBaseName, __FUNCTION__, Status));
    131     return Status;
    132   }
    133 
    134   for (Index = 0; Index < NumberOfDescriptors; Index++) {
    135     Status = IntersectIoDescriptor (Base, Length, &IoSpaceMap[Index]);
    136     if (EFI_ERROR (Status)) {
    137       goto FreeIoSpaceMap;
    138     }
    139   }
    140 
    141   DEBUG_CODE (
    142     //
    143     // Make sure there are adjacent descriptors covering [Base, Base + Length).
    144     // It is possible that they have not been merged; merging can be prevented
    145     // by allocation.
    146     //
    147     UINT64                      CheckBase;
    148     EFI_STATUS                  CheckStatus;
    149     EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor;
    150 
    151     for (CheckBase = Base;
    152          CheckBase < Base + Length;
    153          CheckBase = Descriptor.BaseAddress + Descriptor.Length) {
    154       CheckStatus = gDS->GetIoSpaceDescriptor (CheckBase, &Descriptor);
    155       ASSERT_EFI_ERROR (CheckStatus);
    156       ASSERT (Descriptor.GcdIoType == EfiGcdIoTypeIo);
    157     }
    158     );
    159 
    160 FreeIoSpaceMap:
    161   FreePool (IoSpaceMap);
    162 
    163   return Status;
    164 }
    165 
    166 /**
    167   Ensure the compatibility of a memory space descriptor with the MMIO aperture.
    168 
    169   The memory space descriptor can come from the GCD memory space map, or it can
    170   represent a gap between two neighboring memory space descriptors. In the
    171   latter case, the GcdMemoryType field is expected to be
    172   EfiGcdMemoryTypeNonExistent.
    173 
    174   If the memory space descriptor already has type
    175   EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the
    176   required capabilities, then no action is taken -- it is by definition
    177   compatible with the aperture.
    178 
    179   Otherwise, the intersection of the memory space descriptor is calculated with
    180   the aperture. If the intersection is the empty set (no overlap), no action is
    181   taken; the memory space descriptor is compatible with the aperture.
    182 
    183   Otherwise, the type of the descriptor is investigated again. If the type is
    184   EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with
    185   such a type), then an attempt is made to add the intersection as MMIO space
    186   to the GCD memory space map, with the specified capabilities. This ensures
    187   continuity for the aperture, and the descriptor is deemed compatible with the
    188   aperture.
    189 
    190   Otherwise, the memory space descriptor is incompatible with the MMIO
    191   aperture.
    192 
    193   @param[in] Base         Base address of the aperture.
    194   @param[in] Length       Length of the aperture.
    195   @param[in] Capabilities Capabilities required by the aperture.
    196   @param[in] Descriptor   The descriptor to ensure compatibility with the
    197                           aperture for.
    198 
    199   @retval EFI_SUCCESS            The descriptor is compatible. The GCD memory
    200                                  space map may have been updated, for
    201                                  continuity within the aperture.
    202   @retval EFI_INVALID_PARAMETER  The descriptor is incompatible.
    203   @return                        Error codes from gDS->AddMemorySpace().
    204 **/
    205 EFI_STATUS
    206 IntersectMemoryDescriptor (
    207   IN  UINT64                                Base,
    208   IN  UINT64                                Length,
    209   IN  UINT64                                Capabilities,
    210   IN  CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
    211   )
    212 {
    213   UINT64                                    IntersectionBase;
    214   UINT64                                    IntersectionEnd;
    215   EFI_STATUS                                Status;
    216 
    217   if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo &&
    218       (Descriptor->Capabilities & Capabilities) == Capabilities) {
    219     return EFI_SUCCESS;
    220   }
    221 
    222   IntersectionBase = MAX (Base, Descriptor->BaseAddress);
    223   IntersectionEnd = MIN (Base + Length,
    224                       Descriptor->BaseAddress + Descriptor->Length);
    225   if (IntersectionBase >= IntersectionEnd) {
    226     //
    227     // The descriptor and the aperture don't overlap.
    228     //
    229     return EFI_SUCCESS;
    230   }
    231 
    232   if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
    233     Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo,
    234                     IntersectionBase, IntersectionEnd - IntersectionBase,
    235                     Capabilities);
    236 
    237     DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE,
    238       "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__,
    239       IntersectionBase, IntersectionEnd, Status));
    240     return Status;
    241   }
    242 
    243   DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
    244     "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName, __FUNCTION__,
    245     Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length,
    246     (UINT32)Descriptor->GcdMemoryType, Descriptor->Capabilities,
    247     Base, Base + Length, Capabilities));
    248   return EFI_INVALID_PARAMETER;
    249 }
    250 
    251 /**
    252   Add MMIO space to GCD.
    253   The routine checks the GCD database and only adds those which are
    254   not added in the specified range to GCD.
    255 
    256   @param Base         Base address of the MMIO space.
    257   @param Length       Length of the MMIO space.
    258   @param Capabilities Capabilities of the MMIO space.
    259 
    260   @retval EFI_SUCCES The MMIO space was added successfully.
    261 **/
    262 EFI_STATUS
    263 AddMemoryMappedIoSpace (
    264   IN  UINT64                            Base,
    265   IN  UINT64                            Length,
    266   IN  UINT64                            Capabilities
    267   )
    268 {
    269   EFI_STATUS                            Status;
    270   UINTN                                 Index;
    271   UINTN                                 NumberOfDescriptors;
    272   EFI_GCD_MEMORY_SPACE_DESCRIPTOR       *MemorySpaceMap;
    273 
    274   Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
    275   if (EFI_ERROR (Status)) {
    276     DEBUG ((EFI_D_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n",
    277       gEfiCallerBaseName, __FUNCTION__, Status));
    278     return Status;
    279   }
    280 
    281   for (Index = 0; Index < NumberOfDescriptors; Index++) {
    282     Status = IntersectMemoryDescriptor (Base, Length, Capabilities,
    283                &MemorySpaceMap[Index]);
    284     if (EFI_ERROR (Status)) {
    285       goto FreeMemorySpaceMap;
    286     }
    287   }
    288 
    289   DEBUG_CODE (
    290     //
    291     // Make sure there are adjacent descriptors covering [Base, Base + Length).
    292     // It is possible that they have not been merged; merging can be prevented
    293     // by allocation and different capabilities.
    294     //
    295     UINT64                          CheckBase;
    296     EFI_STATUS                      CheckStatus;
    297     EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
    298 
    299     for (CheckBase = Base;
    300          CheckBase < Base + Length;
    301          CheckBase = Descriptor.BaseAddress + Descriptor.Length) {
    302       CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);
    303       ASSERT_EFI_ERROR (CheckStatus);
    304       ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);
    305       ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);
    306     }
    307     );
    308 
    309 FreeMemorySpaceMap:
    310   FreePool (MemorySpaceMap);
    311 
    312   return Status;
    313 }
    314 
    315 /**
    316 
    317   Entry point of this driver.
    318 
    319   @param ImageHandle  Image handle of this driver.
    320   @param SystemTable  Pointer to standard EFI system table.
    321 
    322   @retval EFI_SUCCESS       Succeed.
    323   @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
    324 
    325 **/
    326 EFI_STATUS
    327 EFIAPI
    328 InitializePciHostBridge (
    329   IN EFI_HANDLE         ImageHandle,
    330   IN EFI_SYSTEM_TABLE   *SystemTable
    331   )
    332 {
    333   EFI_STATUS                  Status;
    334   PCI_HOST_BRIDGE_INSTANCE    *HostBridge;
    335   PCI_ROOT_BRIDGE_INSTANCE    *RootBridge;
    336   PCI_ROOT_BRIDGE             *RootBridges;
    337   UINTN                       RootBridgeCount;
    338   UINTN                       Index;
    339   PCI_ROOT_BRIDGE_APERTURE    *MemApertures[4];
    340   UINTN                       MemApertureIndex;
    341   BOOLEAN                     ResourceAssigned;
    342   LIST_ENTRY                  *Link;
    343 
    344   RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
    345   if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
    346     return EFI_UNSUPPORTED;
    347   }
    348 
    349   Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
    350   ASSERT_EFI_ERROR (Status);
    351   Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);
    352   ASSERT_EFI_ERROR (Status);
    353 
    354   //
    355   // Most systems in the world including complex servers have only one Host Bridge.
    356   //
    357   HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
    358   ASSERT (HostBridge != NULL);
    359 
    360   HostBridge->Signature        = PCI_HOST_BRIDGE_SIGNATURE;
    361   HostBridge->CanRestarted     = TRUE;
    362   InitializeListHead (&HostBridge->RootBridges);
    363   ResourceAssigned             = FALSE;
    364 
    365   //
    366   // Create Root Bridge Device Handle in this Host Bridge
    367   //
    368   for (Index = 0; Index < RootBridgeCount; Index++) {
    369     //
    370     // Create Root Bridge Handle Instance
    371     //
    372     RootBridge = CreateRootBridge (&RootBridges[Index]);
    373     ASSERT (RootBridge != NULL);
    374     if (RootBridge == NULL) {
    375       continue;
    376     }
    377 
    378     //
    379     // Make sure all root bridges share the same ResourceAssigned value.
    380     //
    381     if (Index == 0) {
    382       ResourceAssigned = RootBridges[Index].ResourceAssigned;
    383     } else {
    384       ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
    385     }
    386 
    387     if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
    388       Status = AddIoSpace (
    389                  RootBridges[Index].Io.Base,
    390                  RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
    391                  );
    392       ASSERT_EFI_ERROR (Status);
    393       if (ResourceAssigned) {
    394         Status = gDS->AllocateIoSpace (
    395                         EfiGcdAllocateAddress,
    396                         EfiGcdIoTypeIo,
    397                         0,
    398                         RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
    399                         &RootBridges[Index].Io.Base,
    400                         gImageHandle,
    401                         NULL
    402                         );
    403         ASSERT_EFI_ERROR (Status);
    404       }
    405     }
    406 
    407     //
    408     // Add all the Mem/PMem aperture to GCD
    409     // Mem/PMem shouldn't overlap with each other
    410     // Root bridge which needs to combine MEM and PMEM should only report
    411     // the MEM aperture in Mem
    412     //
    413     MemApertures[0] = &RootBridges[Index].Mem;
    414     MemApertures[1] = &RootBridges[Index].MemAbove4G;
    415     MemApertures[2] = &RootBridges[Index].PMem;
    416     MemApertures[3] = &RootBridges[Index].PMemAbove4G;
    417 
    418     for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
    419       if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
    420         Status = AddMemoryMappedIoSpace (
    421                    MemApertures[MemApertureIndex]->Base,
    422                    MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
    423                    EFI_MEMORY_UC
    424                    );
    425         ASSERT_EFI_ERROR (Status);
    426         Status = gDS->SetMemorySpaceAttributes (
    427                         MemApertures[MemApertureIndex]->Base,
    428                         MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
    429                         EFI_MEMORY_UC
    430                         );
    431         if (EFI_ERROR (Status)) {
    432           DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
    433         }
    434         if (ResourceAssigned) {
    435           Status = gDS->AllocateMemorySpace (
    436                           EfiGcdAllocateAddress,
    437                           EfiGcdMemoryTypeMemoryMappedIo,
    438                           0,
    439                           MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
    440                           &MemApertures[MemApertureIndex]->Base,
    441                           gImageHandle,
    442                           NULL
    443                           );
    444           ASSERT_EFI_ERROR (Status);
    445         }
    446       }
    447     }
    448     //
    449     // Insert Root Bridge Handle Instance
    450     //
    451     InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
    452   }
    453 
    454   //
    455   // When resources were assigned, it's not needed to expose
    456   // PciHostBridgeResourceAllocation protocol.
    457   //
    458   if (!ResourceAssigned) {
    459     HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
    460     HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
    461     HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
    462     HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
    463     HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
    464     HostBridge->ResAlloc.SubmitResources = SubmitResources;
    465     HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
    466     HostBridge->ResAlloc.PreprocessController = PreprocessController;
    467 
    468     Status = gBS->InstallMultipleProtocolInterfaces (
    469                     &HostBridge->Handle,
    470                     &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
    471                     NULL
    472                     );
    473     ASSERT_EFI_ERROR (Status);
    474   }
    475 
    476   for (Link = GetFirstNode (&HostBridge->RootBridges)
    477        ; !IsNull (&HostBridge->RootBridges, Link)
    478        ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    479        ) {
    480     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
    481     RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
    482 
    483     Status = gBS->InstallMultipleProtocolInterfaces (
    484                     &RootBridge->Handle,
    485                     &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,
    486                     &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,
    487                     NULL
    488                     );
    489     ASSERT_EFI_ERROR (Status);
    490   }
    491   PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
    492   return Status;
    493 }
    494 
    495 /**
    496   This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
    497 
    498   @param HostBridge The Host Bridge Instance where the resource adjustment happens.
    499 **/
    500 VOID
    501 ResourceConflict (
    502   IN  PCI_HOST_BRIDGE_INSTANCE *HostBridge
    503   )
    504 {
    505   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
    506   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
    507   EFI_ACPI_END_TAG_DESCRIPTOR       *End;
    508   PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;
    509   LIST_ENTRY                        *Link;
    510   UINTN                             RootBridgeCount;
    511   PCI_RESOURCE_TYPE                 Index;
    512   PCI_RES_NODE                      *ResAllocNode;
    513 
    514   RootBridgeCount = 0;
    515   for (Link = GetFirstNode (&HostBridge->RootBridges)
    516        ; !IsNull (&HostBridge->RootBridges, Link)
    517        ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    518        ) {
    519     RootBridgeCount++;
    520   }
    521 
    522   Resources = AllocatePool (
    523                 RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +
    524                 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
    525                 );
    526   ASSERT (Resources != NULL);
    527 
    528   for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources
    529        ; !IsNull (&HostBridge->RootBridges, Link)
    530        ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    531        ) {
    532     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
    533     for (Index = TypeIo; Index < TypeMax; Index++) {
    534       ResAllocNode = &RootBridge->ResAllocNode[Index];
    535 
    536       Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
    537       Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
    538       Descriptor->AddrRangeMin = ResAllocNode->Base;
    539       Descriptor->AddrRangeMax = ResAllocNode->Alignment;
    540       Descriptor->AddrLen = ResAllocNode->Length;
    541       switch (ResAllocNode->Type) {
    542 
    543       case TypeIo:
    544         Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
    545         break;
    546 
    547       case TypePMem32:
    548         Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
    549       case TypeMem32:
    550         Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
    551         Descriptor->AddrSpaceGranularity = 32;
    552         break;
    553 
    554       case TypePMem64:
    555         Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
    556       case TypeMem64:
    557         Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
    558         Descriptor->AddrSpaceGranularity = 64;
    559         break;
    560 
    561       case TypeBus:
    562         Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
    563         break;
    564 
    565       default:
    566         break;
    567       }
    568 
    569       Descriptor++;
    570     }
    571     //
    572     // Terminate the root bridge resources.
    573     //
    574     End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
    575     End->Desc = ACPI_END_TAG_DESCRIPTOR;
    576     End->Checksum = 0x0;
    577 
    578     Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);
    579   }
    580   //
    581   // Terminate the host bridge resources.
    582   //
    583   End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
    584   End->Desc = ACPI_END_TAG_DESCRIPTOR;
    585   End->Checksum = 0x0;
    586 
    587   DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));
    588   PciHostBridgeResourceConflict (HostBridge->Handle, Resources);
    589   FreePool (Resources);
    590 }
    591 
    592 /**
    593   Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
    594   from GCD range [BaseAddress, Limit).
    595 
    596   @param Mmio            TRUE for MMIO and FALSE for IO.
    597   @param Length          Length of the resource to allocate.
    598   @param BitsOfAlignment Alignment of the resource to allocate.
    599   @param BaseAddress     The starting address the allocation is from.
    600   @param Limit           The ending address the allocation is to.
    601 
    602   @retval  The base address of the allocated resource or MAX_UINT64 if allocation
    603            fails.
    604 **/
    605 UINT64
    606 AllocateResource (
    607   BOOLEAN Mmio,
    608   UINT64  Length,
    609   UINTN   BitsOfAlignment,
    610   UINT64  BaseAddress,
    611   UINT64  Limit
    612   )
    613 {
    614   EFI_STATUS Status;
    615 
    616   if (BaseAddress < Limit) {
    617     //
    618     // Have to make sure Aligment is handled since we are doing direct address allocation
    619     //
    620     BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));
    621 
    622     while (BaseAddress + Length <= Limit + 1) {
    623       if (Mmio) {
    624         Status = gDS->AllocateMemorySpace (
    625                         EfiGcdAllocateAddress,
    626                         EfiGcdMemoryTypeMemoryMappedIo,
    627                         BitsOfAlignment,
    628                         Length,
    629                         &BaseAddress,
    630                         gImageHandle,
    631                         NULL
    632                         );
    633       } else {
    634         Status = gDS->AllocateIoSpace (
    635                         EfiGcdAllocateAddress,
    636                         EfiGcdIoTypeIo,
    637                         BitsOfAlignment,
    638                         Length,
    639                         &BaseAddress,
    640                         gImageHandle,
    641                         NULL
    642                         );
    643       }
    644 
    645       if (!EFI_ERROR (Status)) {
    646         return BaseAddress;
    647       }
    648       BaseAddress += LShiftU64 (1, BitsOfAlignment);
    649     }
    650   }
    651   return MAX_UINT64;
    652 }
    653 
    654 /**
    655 
    656   Enter a certain phase of the PCI enumeration process.
    657 
    658   @param This   The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
    659   @param Phase  The phase during enumeration.
    660 
    661   @retval EFI_SUCCESS            Succeed.
    662   @retval EFI_INVALID_PARAMETER  Wrong phase parameter passed in.
    663   @retval EFI_NOT_READY          Resources have not been submitted yet.
    664 
    665 **/
    666 EFI_STATUS
    667 EFIAPI
    668 NotifyPhase (
    669   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
    670   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
    671   )
    672 {
    673   PCI_HOST_BRIDGE_INSTANCE              *HostBridge;
    674   PCI_ROOT_BRIDGE_INSTANCE              *RootBridge;
    675   LIST_ENTRY                            *Link;
    676   EFI_PHYSICAL_ADDRESS                  BaseAddress;
    677   UINTN                                 BitsOfAlignment;
    678   UINT64                                Alignment;
    679   EFI_STATUS                            Status;
    680   EFI_STATUS                            ReturnStatus;
    681   PCI_RESOURCE_TYPE                     Index;
    682   PCI_RESOURCE_TYPE                     Index1;
    683   PCI_RESOURCE_TYPE                     Index2;
    684   BOOLEAN                               ResNodeHandled[TypeMax];
    685   UINT64                                MaxAlignment;
    686 
    687   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
    688 
    689   switch (Phase) {
    690   case EfiPciHostBridgeBeginEnumeration:
    691     if (!HostBridge->CanRestarted) {
    692       return EFI_NOT_READY;
    693     }
    694     //
    695     // Reset Root Bridge
    696     //
    697     for (Link = GetFirstNode (&HostBridge->RootBridges)
    698           ; !IsNull (&HostBridge->RootBridges, Link)
    699           ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    700           ) {
    701       RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
    702       for (Index = TypeIo; Index < TypeMax; Index++) {
    703         RootBridge->ResAllocNode[Index].Type   = Index;
    704         RootBridge->ResAllocNode[Index].Base   = 0;
    705         RootBridge->ResAllocNode[Index].Length = 0;
    706         RootBridge->ResAllocNode[Index].Status = ResNone;
    707 
    708         RootBridge->ResourceSubmitted = FALSE;
    709       }
    710     }
    711 
    712     HostBridge->CanRestarted = TRUE;
    713     break;
    714 
    715   case EfiPciHostBridgeBeginBusAllocation:
    716     //
    717     // No specific action is required here, can perform any chipset specific programing
    718     //
    719     HostBridge->CanRestarted = FALSE;
    720     break;
    721 
    722   case EfiPciHostBridgeEndBusAllocation:
    723     //
    724     // No specific action is required here, can perform any chipset specific programing
    725     //
    726     break;
    727 
    728   case EfiPciHostBridgeBeginResourceAllocation:
    729     //
    730     // No specific action is required here, can perform any chipset specific programing
    731     //
    732     break;
    733 
    734   case EfiPciHostBridgeAllocateResources:
    735     ReturnStatus = EFI_SUCCESS;
    736 
    737     //
    738     // Make sure the resource for all root bridges has been submitted.
    739     //
    740     for (Link = GetFirstNode (&HostBridge->RootBridges)
    741          ; !IsNull (&HostBridge->RootBridges, Link)
    742          ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    743          ) {
    744       RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
    745       if (!RootBridge->ResourceSubmitted) {
    746         return EFI_NOT_READY;
    747       }
    748     }
    749 
    750     DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
    751     for (Link = GetFirstNode (&HostBridge->RootBridges)
    752          ; !IsNull (&HostBridge->RootBridges, Link)
    753          ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    754          ) {
    755       for (Index = TypeIo; Index < TypeBus; Index++) {
    756         ResNodeHandled[Index] = FALSE;
    757       }
    758 
    759       RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
    760       DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));
    761 
    762       for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
    763         if (RootBridge->ResAllocNode[Index1].Status == ResNone) {
    764           ResNodeHandled[Index1] = TRUE;
    765         } else {
    766           //
    767           // Allocate the resource node with max alignment at first
    768           //
    769           MaxAlignment = 0;
    770           Index = TypeMax;
    771           for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
    772             if (ResNodeHandled[Index2]) {
    773               continue;
    774             }
    775             if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {
    776               MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;
    777               Index = Index2;
    778             }
    779           }
    780 
    781           ASSERT (Index < TypeMax);
    782           ResNodeHandled[Index] = TRUE;
    783           Alignment = RootBridge->ResAllocNode[Index].Alignment;
    784           BitsOfAlignment = LowBitSet64 (Alignment + 1);
    785           BaseAddress = MAX_UINT64;
    786 
    787           switch (Index) {
    788           case TypeIo:
    789             BaseAddress = AllocateResource (
    790                             FALSE,
    791                             RootBridge->ResAllocNode[Index].Length,
    792                             MIN (15, BitsOfAlignment),
    793                             ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
    794                             RootBridge->Io.Limit
    795                             );
    796             break;
    797 
    798           case TypeMem64:
    799             BaseAddress = AllocateResource (
    800                             TRUE,
    801                             RootBridge->ResAllocNode[Index].Length,
    802                             MIN (63, BitsOfAlignment),
    803                             ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
    804                             RootBridge->MemAbove4G.Limit
    805                             );
    806             if (BaseAddress != MAX_UINT64) {
    807               break;
    808             }
    809             //
    810             // If memory above 4GB is not available, try memory below 4GB
    811             //
    812 
    813           case TypeMem32:
    814             BaseAddress = AllocateResource (
    815                             TRUE,
    816                             RootBridge->ResAllocNode[Index].Length,
    817                             MIN (31, BitsOfAlignment),
    818                             ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
    819                             RootBridge->Mem.Limit
    820                             );
    821             break;
    822 
    823           case TypePMem64:
    824             BaseAddress = AllocateResource (
    825                             TRUE,
    826                             RootBridge->ResAllocNode[Index].Length,
    827                             MIN (63, BitsOfAlignment),
    828                             ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
    829                             RootBridge->PMemAbove4G.Limit
    830                             );
    831             if (BaseAddress != MAX_UINT64) {
    832               break;
    833             }
    834             //
    835             // If memory above 4GB is not available, try memory below 4GB
    836             //
    837           case TypePMem32:
    838             BaseAddress = AllocateResource (
    839                             TRUE,
    840                             RootBridge->ResAllocNode[Index].Length,
    841                             MIN (31, BitsOfAlignment),
    842                             ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
    843                             RootBridge->PMem.Limit
    844                             );
    845             break;
    846 
    847           default:
    848             ASSERT (FALSE);
    849             break;
    850           }
    851 
    852           DEBUG ((DEBUG_INFO, "  %s: Base/Length/Alignment = %lx/%lx/%lx - ",
    853                   mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));
    854           if (BaseAddress != MAX_UINT64) {
    855             RootBridge->ResAllocNode[Index].Base = BaseAddress;
    856             RootBridge->ResAllocNode[Index].Status = ResAllocated;
    857             DEBUG ((DEBUG_INFO, "Success\n"));
    858           } else {
    859             ReturnStatus = EFI_OUT_OF_RESOURCES;
    860             DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));
    861           }
    862         }
    863       }
    864     }
    865 
    866     if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
    867       ResourceConflict (HostBridge);
    868     }
    869 
    870     //
    871     // Set resource to zero for nodes where allocation fails
    872     //
    873     for (Link = GetFirstNode (&HostBridge->RootBridges)
    874           ; !IsNull (&HostBridge->RootBridges, Link)
    875           ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    876           ) {
    877       RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
    878       for (Index = TypeIo; Index < TypeBus; Index++) {
    879         if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {
    880           RootBridge->ResAllocNode[Index].Length = 0;
    881         }
    882       }
    883     }
    884     return ReturnStatus;
    885 
    886   case EfiPciHostBridgeSetResources:
    887     //
    888     // HostBridgeInstance->CanRestarted = FALSE;
    889     //
    890     break;
    891 
    892   case EfiPciHostBridgeFreeResources:
    893     //
    894     // HostBridgeInstance->CanRestarted = FALSE;
    895     //
    896     ReturnStatus = EFI_SUCCESS;
    897     for (Link = GetFirstNode (&HostBridge->RootBridges)
    898          ; !IsNull (&HostBridge->RootBridges, Link)
    899          ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    900          ) {
    901       RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
    902       for (Index = TypeIo; Index < TypeBus; Index++) {
    903         if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
    904           switch (Index) {
    905           case TypeIo:
    906             Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
    907             if (EFI_ERROR (Status)) {
    908               ReturnStatus = Status;
    909             }
    910             break;
    911 
    912           case TypeMem32:
    913           case TypePMem32:
    914           case TypeMem64:
    915           case TypePMem64:
    916             Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
    917             if (EFI_ERROR (Status)) {
    918               ReturnStatus = Status;
    919             }
    920             break;
    921 
    922           default:
    923             ASSERT (FALSE);
    924             break;
    925           }
    926 
    927           RootBridge->ResAllocNode[Index].Type = Index;
    928           RootBridge->ResAllocNode[Index].Base = 0;
    929           RootBridge->ResAllocNode[Index].Length = 0;
    930           RootBridge->ResAllocNode[Index].Status = ResNone;
    931         }
    932       }
    933 
    934       RootBridge->ResourceSubmitted = FALSE;
    935     }
    936 
    937     HostBridge->CanRestarted = TRUE;
    938     return ReturnStatus;
    939 
    940   case EfiPciHostBridgeEndResourceAllocation:
    941     //
    942     // The resource allocation phase is completed.  No specific action is required
    943     // here. This notification can be used to perform any chipset specific programming.
    944     //
    945     break;
    946 
    947   case EfiPciHostBridgeEndEnumeration:
    948     //
    949     // The Host Bridge Enumeration is completed. No specific action is required here.
    950     // This notification can be used to perform any chipset specific programming.
    951     //
    952     break;
    953 
    954   default:
    955     return EFI_INVALID_PARAMETER;
    956   }
    957 
    958   return EFI_SUCCESS;
    959 }
    960 
    961 /**
    962 
    963   Return the device handle of the next PCI root bridge that is associated with
    964   this Host Bridge.
    965 
    966   @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
    967   @param RootBridgeHandle  Returns the device handle of the next PCI Root Bridge.
    968                            On input, it holds the RootBridgeHandle returned by the most
    969                            recent call to GetNextRootBridge().The handle for the first
    970                            PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
    971 
    972   @retval EFI_SUCCESS            Succeed.
    973   @retval EFI_NOT_FOUND          Next PCI root bridge not found.
    974   @retval EFI_INVALID_PARAMETER  Wrong parameter passed in.
    975 
    976 **/
    977 EFI_STATUS
    978 EFIAPI
    979 GetNextRootBridge (
    980   IN     EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
    981   IN OUT EFI_HANDLE                                       *RootBridgeHandle
    982   )
    983 {
    984   BOOLEAN                   ReturnNext;
    985   LIST_ENTRY                *Link;
    986   PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
    987   PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
    988 
    989   if (RootBridgeHandle == NULL) {
    990     return EFI_INVALID_PARAMETER;
    991   }
    992 
    993   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
    994   ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);
    995 
    996   for (Link = GetFirstNode (&HostBridge->RootBridges)
    997       ; !IsNull (&HostBridge->RootBridges, Link)
    998       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
    999       ) {
   1000     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
   1001     if (ReturnNext) {
   1002       *RootBridgeHandle = RootBridge->Handle;
   1003       return EFI_SUCCESS;
   1004     }
   1005 
   1006     ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);
   1007   }
   1008 
   1009   if (ReturnNext) {
   1010     ASSERT (IsNull (&HostBridge->RootBridges, Link));
   1011     return EFI_NOT_FOUND;
   1012   } else {
   1013     return EFI_INVALID_PARAMETER;
   1014   }
   1015 }
   1016 
   1017 /**
   1018 
   1019   Returns the attributes of a PCI Root Bridge.
   1020 
   1021   @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
   1022   @param RootBridgeHandle  The device handle of the PCI Root Bridge
   1023                            that the caller is interested in.
   1024   @param Attributes        The pointer to attributes of the PCI Root Bridge.
   1025 
   1026   @retval EFI_SUCCESS            Succeed.
   1027   @retval EFI_INVALID_PARAMETER  Attributes parameter passed in is NULL or
   1028                                  RootBridgeHandle is not an EFI_HANDLE
   1029                                  that was returned on a previous call to
   1030                                  GetNextRootBridge().
   1031 
   1032 **/
   1033 EFI_STATUS
   1034 EFIAPI
   1035 GetAttributes (
   1036   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1037   IN  EFI_HANDLE                                       RootBridgeHandle,
   1038   OUT UINT64                                           *Attributes
   1039   )
   1040 {
   1041   LIST_ENTRY                *Link;
   1042   PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
   1043   PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
   1044 
   1045   if (Attributes == NULL) {
   1046     return EFI_INVALID_PARAMETER;
   1047   }
   1048 
   1049   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
   1050   for (Link = GetFirstNode (&HostBridge->RootBridges)
   1051       ; !IsNull (&HostBridge->RootBridges, Link)
   1052       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
   1053       ) {
   1054     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
   1055     if (RootBridgeHandle == RootBridge->Handle) {
   1056       *Attributes = RootBridge->AllocationAttributes;
   1057       return EFI_SUCCESS;
   1058     }
   1059   }
   1060 
   1061   return EFI_INVALID_PARAMETER;
   1062 }
   1063 
   1064 /**
   1065 
   1066   This is the request from the PCI enumerator to set up
   1067   the specified PCI Root Bridge for bus enumeration process.
   1068 
   1069   @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
   1070   @param RootBridgeHandle  The PCI Root Bridge to be set up.
   1071   @param Configuration     Pointer to the pointer to the PCI bus resource descriptor.
   1072 
   1073   @retval EFI_SUCCESS            Succeed.
   1074   @retval EFI_OUT_OF_RESOURCES   Not enough pool to be allocated.
   1075   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.
   1076 
   1077 **/
   1078 EFI_STATUS
   1079 EFIAPI
   1080 StartBusEnumeration (
   1081   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1082   IN  EFI_HANDLE                                       RootBridgeHandle,
   1083   OUT VOID                                             **Configuration
   1084   )
   1085 {
   1086   LIST_ENTRY                *Link;
   1087   PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
   1088   PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
   1089   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
   1090   EFI_ACPI_END_TAG_DESCRIPTOR       *End;
   1091 
   1092   if (Configuration == NULL) {
   1093     return EFI_INVALID_PARAMETER;
   1094   }
   1095 
   1096   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
   1097   for (Link = GetFirstNode (&HostBridge->RootBridges)
   1098        ; !IsNull (&HostBridge->RootBridges, Link)
   1099        ; Link = GetNextNode (&HostBridge->RootBridges, Link)
   1100        ) {
   1101     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
   1102     if (RootBridgeHandle == RootBridge->Handle) {
   1103       *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
   1104       if (*Configuration == NULL) {
   1105         return EFI_OUT_OF_RESOURCES;
   1106       }
   1107 
   1108       Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;
   1109       Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1110       Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
   1111       Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_BUS;
   1112       Descriptor->GenFlag               = 0;
   1113       Descriptor->SpecificFlag          = 0;
   1114       Descriptor->AddrSpaceGranularity  = 0;
   1115       Descriptor->AddrRangeMin          = RootBridge->Bus.Base;
   1116       Descriptor->AddrRangeMax          = 0;
   1117       Descriptor->AddrTranslationOffset = 0;
   1118       Descriptor->AddrLen               = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
   1119 
   1120       End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
   1121       End->Desc = ACPI_END_TAG_DESCRIPTOR;
   1122       End->Checksum = 0x0;
   1123 
   1124       return EFI_SUCCESS;
   1125     }
   1126   }
   1127 
   1128   return EFI_INVALID_PARAMETER;
   1129 }
   1130 
   1131 /**
   1132 
   1133   This function programs the PCI Root Bridge hardware so that
   1134   it decodes the specified PCI bus range.
   1135 
   1136   @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
   1137   @param RootBridgeHandle  The PCI Root Bridge whose bus range is to be programmed.
   1138   @param Configuration     The pointer to the PCI bus resource descriptor.
   1139 
   1140   @retval EFI_SUCCESS            Succeed.
   1141   @retval EFI_INVALID_PARAMETER  Wrong parameters passed in.
   1142 
   1143 **/
   1144 EFI_STATUS
   1145 EFIAPI
   1146 SetBusNumbers (
   1147   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1148   IN EFI_HANDLE                                       RootBridgeHandle,
   1149   IN VOID                                             *Configuration
   1150   )
   1151 {
   1152   LIST_ENTRY                *Link;
   1153   PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
   1154   PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
   1155   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
   1156   EFI_ACPI_END_TAG_DESCRIPTOR       *End;
   1157 
   1158   if (Configuration == NULL) {
   1159     return EFI_INVALID_PARAMETER;
   1160   }
   1161 
   1162   Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
   1163   End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
   1164 
   1165   //
   1166   // Check the Configuration is valid
   1167   //
   1168   if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||
   1169       (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||
   1170       (End->Desc != ACPI_END_TAG_DESCRIPTOR)
   1171      ) {
   1172     return EFI_INVALID_PARAMETER;
   1173   }
   1174 
   1175   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
   1176   for (Link = GetFirstNode (&HostBridge->RootBridges)
   1177        ; !IsNull (&HostBridge->RootBridges, Link)
   1178        ; Link = GetNextNode (&HostBridge->RootBridges, Link)
   1179        ) {
   1180     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
   1181     if (RootBridgeHandle == RootBridge->Handle) {
   1182 
   1183       if (Descriptor->AddrLen == 0) {
   1184         return EFI_INVALID_PARAMETER;
   1185       }
   1186 
   1187       if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||
   1188           (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)
   1189          ) {
   1190         return EFI_INVALID_PARAMETER;
   1191       }
   1192       //
   1193       // Update the Bus Range
   1194       //
   1195       RootBridge->ResAllocNode[TypeBus].Base    = Descriptor->AddrRangeMin;
   1196       RootBridge->ResAllocNode[TypeBus].Length  = Descriptor->AddrLen;
   1197       RootBridge->ResAllocNode[TypeBus].Status  = ResAllocated;
   1198       return EFI_SUCCESS;
   1199     }
   1200   }
   1201 
   1202   return EFI_INVALID_PARAMETER;
   1203 }
   1204 
   1205 /**
   1206 
   1207   Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
   1208 
   1209   @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
   1210   @param RootBridgeHandle  The PCI Root Bridge whose I/O and memory resource requirements.
   1211                            are being submitted.
   1212   @param Configuration     The pointer to the PCI I/O and PCI memory resource descriptor.
   1213 
   1214   @retval EFI_SUCCESS            Succeed.
   1215   @retval EFI_INVALID_PARAMETER  Wrong parameters passed in.
   1216 **/
   1217 EFI_STATUS
   1218 EFIAPI
   1219 SubmitResources (
   1220   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1221   IN EFI_HANDLE                                       RootBridgeHandle,
   1222   IN VOID                                             *Configuration
   1223   )
   1224 {
   1225   LIST_ENTRY                        *Link;
   1226   PCI_HOST_BRIDGE_INSTANCE          *HostBridge;
   1227   PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;
   1228   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
   1229   PCI_RESOURCE_TYPE                 Type;
   1230 
   1231   //
   1232   // Check the input parameter: Configuration
   1233   //
   1234   if (Configuration == NULL) {
   1235     return EFI_INVALID_PARAMETER;
   1236   }
   1237 
   1238   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
   1239   for (Link = GetFirstNode (&HostBridge->RootBridges)
   1240        ; !IsNull (&HostBridge->RootBridges, Link)
   1241        ; Link = GetNextNode (&HostBridge->RootBridges, Link)
   1242        ) {
   1243     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
   1244     if (RootBridgeHandle == RootBridge->Handle) {
   1245       DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));
   1246       //
   1247       // Check the resource descriptors.
   1248       // If the Configuration includes one or more invalid resource descriptors, all the resource
   1249       // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
   1250       //
   1251       for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
   1252         if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {
   1253           return EFI_INVALID_PARAMETER;
   1254         }
   1255 
   1256         DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
   1257                 mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
   1258                 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""
   1259                 ));
   1260         DEBUG ((EFI_D_INFO, "      Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));
   1261         switch (Descriptor->ResType) {
   1262         case ACPI_ADDRESS_SPACE_TYPE_MEM:
   1263           if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {
   1264             return EFI_INVALID_PARAMETER;
   1265           }
   1266           if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {
   1267             return EFI_INVALID_PARAMETER;
   1268           }
   1269           //
   1270           // If the PCI root bridge does not support separate windows for nonprefetchable and
   1271           // prefetchable memory, then the PCI bus driver needs to include requests for
   1272           // prefetchable memory in the nonprefetchable memory pool.
   1273           //
   1274           if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&
   1275               ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)
   1276              ) {
   1277             return EFI_INVALID_PARAMETER;
   1278           }
   1279         case ACPI_ADDRESS_SPACE_TYPE_IO:
   1280           //
   1281           // Check aligment, it should be of the form 2^n-1
   1282           //
   1283           if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {
   1284             return EFI_INVALID_PARAMETER;
   1285           }
   1286           break;
   1287         default:
   1288           ASSERT (FALSE);
   1289           break;
   1290         }
   1291       }
   1292       if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
   1293         return EFI_INVALID_PARAMETER;
   1294       }
   1295 
   1296       for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
   1297         if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
   1298           if (Descriptor->AddrSpaceGranularity == 32) {
   1299             if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
   1300               Type = TypePMem32;
   1301             } else {
   1302               Type = TypeMem32;
   1303             }
   1304           } else {
   1305             ASSERT (Descriptor->AddrSpaceGranularity == 64);
   1306             if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
   1307               Type = TypePMem64;
   1308             } else {
   1309               Type = TypeMem64;
   1310             }
   1311           }
   1312         } else {
   1313           ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);
   1314           Type = TypeIo;
   1315         }
   1316         RootBridge->ResAllocNode[Type].Length    = Descriptor->AddrLen;
   1317         RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;
   1318         RootBridge->ResAllocNode[Type].Status    = ResSubmitted;
   1319       }
   1320       RootBridge->ResourceSubmitted = TRUE;
   1321       return EFI_SUCCESS;
   1322     }
   1323   }
   1324 
   1325   return EFI_INVALID_PARAMETER;
   1326 }
   1327 
   1328 /**
   1329 
   1330   This function returns the proposed resource settings for the specified
   1331   PCI Root Bridge.
   1332 
   1333   @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
   1334   @param RootBridgeHandle  The PCI Root Bridge handle.
   1335   @param Configuration     The pointer to the pointer to the PCI I/O
   1336                            and memory resource descriptor.
   1337 
   1338   @retval EFI_SUCCESS            Succeed.
   1339   @retval EFI_OUT_OF_RESOURCES   Not enough pool to be allocated.
   1340   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.
   1341 
   1342 **/
   1343 EFI_STATUS
   1344 EFIAPI
   1345 GetProposedResources (
   1346   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1347   IN  EFI_HANDLE                                       RootBridgeHandle,
   1348   OUT VOID                                             **Configuration
   1349   )
   1350 {
   1351   LIST_ENTRY                        *Link;
   1352   PCI_HOST_BRIDGE_INSTANCE          *HostBridge;
   1353   PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;
   1354   UINTN                             Index;
   1355   UINTN                             Number;
   1356   VOID                              *Buffer;
   1357   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
   1358   EFI_ACPI_END_TAG_DESCRIPTOR       *End;
   1359   UINT64                            ResStatus;
   1360 
   1361   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
   1362   for (Link = GetFirstNode (&HostBridge->RootBridges)
   1363       ; !IsNull (&HostBridge->RootBridges, Link)
   1364       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
   1365       ) {
   1366     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
   1367     if (RootBridgeHandle == RootBridge->Handle) {
   1368       for (Index = 0, Number = 0; Index < TypeBus; Index++) {
   1369         if (RootBridge->ResAllocNode[Index].Status != ResNone) {
   1370           Number++;
   1371         }
   1372       }
   1373 
   1374       Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
   1375       if (Buffer == NULL) {
   1376         return EFI_OUT_OF_RESOURCES;
   1377       }
   1378 
   1379       Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;
   1380       for (Index = 0; Index < TypeBus; Index++) {
   1381         ResStatus = RootBridge->ResAllocNode[Index].Status;
   1382         if (ResStatus != ResNone) {
   1383           Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1384           Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;
   1385           Descriptor->GenFlag               = 0;
   1386           Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base;
   1387           Descriptor->AddrRangeMax          = 0;
   1388           Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
   1389           Descriptor->AddrLen               = RootBridge->ResAllocNode[Index].Length;
   1390 
   1391           switch (Index) {
   1392 
   1393           case TypeIo:
   1394             Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_IO;
   1395             break;
   1396 
   1397           case TypePMem32:
   1398             Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
   1399           case TypeMem32:
   1400             Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1401             Descriptor->AddrSpaceGranularity = 32;
   1402             break;
   1403 
   1404           case TypePMem64:
   1405             Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
   1406           case TypeMem64:
   1407             Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1408             Descriptor->AddrSpaceGranularity = 64;
   1409             break;
   1410           }
   1411 
   1412           Descriptor++;
   1413         }
   1414       }
   1415       End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
   1416       End->Desc      = ACPI_END_TAG_DESCRIPTOR;
   1417       End->Checksum  = 0;
   1418 
   1419       *Configuration = Buffer;
   1420 
   1421       return EFI_SUCCESS;
   1422     }
   1423   }
   1424 
   1425   return EFI_INVALID_PARAMETER;
   1426 }
   1427 
   1428 /**
   1429 
   1430   This function is called for all the PCI controllers that the PCI
   1431   bus driver finds. Can be used to Preprogram the controller.
   1432 
   1433   @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
   1434   @param RootBridgeHandle  The PCI Root Bridge handle.
   1435   @param PciAddress        Address of the controller on the PCI bus.
   1436   @param Phase             The Phase during resource allocation.
   1437 
   1438   @retval EFI_SUCCESS            Succeed.
   1439   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.
   1440 
   1441 **/
   1442 EFI_STATUS
   1443 EFIAPI
   1444 PreprocessController (
   1445   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL          *This,
   1446   IN  EFI_HANDLE                                                RootBridgeHandle,
   1447   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS               PciAddress,
   1448   IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE              Phase
   1449   )
   1450 {
   1451   LIST_ENTRY                *Link;
   1452   PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
   1453   PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
   1454 
   1455   if ((UINT32) Phase > EfiPciBeforeResourceCollection) {
   1456     return EFI_INVALID_PARAMETER;
   1457   }
   1458 
   1459   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
   1460   for (Link = GetFirstNode (&HostBridge->RootBridges)
   1461        ; !IsNull (&HostBridge->RootBridges, Link)
   1462        ; Link = GetNextNode (&HostBridge->RootBridges, Link)
   1463        ) {
   1464     RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
   1465     if (RootBridgeHandle == RootBridge->Handle) {
   1466       return EFI_SUCCESS;
   1467     }
   1468   }
   1469 
   1470   return EFI_INVALID_PARAMETER;
   1471 }
   1472