Home | History | Annotate | Download | only in PciHostBridgeDxe
      1 /** @file
      2   Provides the basic interfaces to abstract a PCI Host Bridge Resource
      3   Allocation
      4 
      5   Copyright (C) 2015, Red Hat, Inc.
      6   Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
      7 
      8   This program and the accompanying materials are licensed and made available
      9   under the terms and conditions of the BSD License which accompanies this
     10   distribution.  The full text of the license may be found at
     11   http://opensource.org/licenses/bsd-license.php
     12 
     13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include <Library/QemuFwCfgLib.h>
     19 
     20 #include "PciHostBridge.h"
     21 
     22 STATIC
     23 CONST
     24 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
     25   {
     26     {
     27       ACPI_DEVICE_PATH,
     28       ACPI_DP,
     29       {
     30         (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
     31         (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
     32       }
     33     },
     34     EISA_PNP_ID(0x0A03), // HID
     35     0                    // UID
     36   },
     37 
     38   {
     39     END_DEVICE_PATH_TYPE,
     40     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     41     {
     42       END_DEVICE_PATH_LENGTH,
     43       0
     44     }
     45   }
     46 };
     47 
     48 EFI_HANDLE mDriverImageHandle;
     49 
     50 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
     51   PCI_HOST_BRIDGE_SIGNATURE,  // Signature
     52   NULL,                       // HostBridgeHandle
     53   {NULL, NULL},               // Head
     54   FALSE,                      // ResourceSubiteed
     55   TRUE,                       // CanRestarted
     56   {
     57     NotifyPhase,
     58     GetNextRootBridge,
     59     GetAttributes,
     60     StartBusEnumeration,
     61     SetBusNumbers,
     62     SubmitResources,
     63     GetProposedResources,
     64     PreprocessController
     65   }
     66 };
     67 
     68 //
     69 // Implementation
     70 //
     71 
     72 /**
     73   Allocate and initialize a root bridge.
     74 
     75   param[in]  RootBusNumber     The bus number of the root bus (root bridge) to
     76                                create.
     77 
     78   param[in]  MaxSubBusNumber   The inclusive maximum bus number that can be
     79                                assigned to any subordinate bus found behind any
     80                                PCI bridge hanging off this root bus.
     81 
     82                                The caller is repsonsible for ensuring that
     83                                RootBusNumber <= MaxSubBusNumber. If
     84                                RootBusNumber equals MaxSubBusNumber, then the
     85                                root bus has no room for subordinate buses.
     86 
     87   param[in]  HostBridgeHandle  The EFI_HANDLE corresponding to the host bridge
     88                                that is the parent of the root bridge to create.
     89                                HostBridgeHandle is expected to have
     90                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
     91                                installed on it.
     92 
     93   param[out] RootBus           The private PCI_ROOT_BRIDGE_INSTANCE that has
     94                                been created as the result of the function call.
     95 
     96   @retval EFI_SUCCESS           Initialization successful. A new
     97                                 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL has been
     98                                 created as the child of HostBridgeHandle. A
     99                                 device path consisting of an ACPI device path
    100                                 node, with UID = RootBusNumber, has been
    101                                 installed on the same new handle.
    102 
    103   @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
    104 
    105   @return                       Error codes from
    106                                 gBS->InstallMultipleProtocolInterfaces().
    107 **/
    108 STATIC
    109 EFI_STATUS
    110 InitRootBridge (
    111   IN  UINT8                    RootBusNumber,
    112   IN  UINT8                    MaxSubBusNumber,
    113   IN  EFI_HANDLE               HostBridgeHandle,
    114   OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus
    115   )
    116 {
    117   PCI_ROOT_BRIDGE_INSTANCE          *PrivateData;
    118   PCI_ROOT_BRIDGE_RESOURCE_APERTURE ResAperture;
    119   EFI_STATUS                        Status;
    120 
    121   ASSERT (RootBusNumber <= MaxSubBusNumber);
    122 
    123   PrivateData = AllocateZeroPool (sizeof *PrivateData);
    124   if (PrivateData == NULL) {
    125     return EFI_OUT_OF_RESOURCES;
    126   }
    127 
    128   PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
    129 
    130   CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,
    131     sizeof mRootBridgeDevicePathTemplate);
    132   PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;
    133 
    134   ResAperture.BusBase  = RootBusNumber;
    135   ResAperture.BusLimit = MaxSubBusNumber;
    136   ResAperture.MemBase  = BASE_2GB;
    137   ResAperture.MemLimit = BASE_4GB - 1;
    138   ResAperture.IoBase   = 0;
    139   ResAperture.IoLimit  = MAX_UINT16;
    140   //
    141   // The function call below allocates no resources and performs no actions
    142   // that have to be rolled back on later failure. It always succeeds.
    143   //
    144   Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,
    145              EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM, &ResAperture);
    146   ASSERT_EFI_ERROR (Status);
    147 
    148   Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,
    149                   &gEfiDevicePathProtocolGuid,      &PrivateData->DevicePath,
    150                   &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
    151                   NULL);
    152   if (EFI_ERROR (Status)) {
    153     goto FreePrivateData;
    154   }
    155 
    156   DEBUG ((EFI_D_INFO,
    157     "%a: installed root bus %d, with room for %d subordinate bus(es)\n",
    158     __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
    159   *RootBus = PrivateData;
    160   return EFI_SUCCESS;
    161 
    162 FreePrivateData:
    163   FreePool (PrivateData);
    164   return Status;
    165 }
    166 
    167 
    168 /**
    169   Uninitialize and free a root bridge set up with InitRootBridge().
    170 
    171   On return, the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance and the device path
    172   will have been released, freeing RootBus->Handle as well.
    173 
    174   param[in] RootBus  The private PCI_ROOT_BRIDGE_INSTANCE that has been created
    175                      with InitRootBridge(), and should be released.
    176 **/
    177 STATIC
    178 VOID
    179 UninitRootBridge (
    180   IN PCI_ROOT_BRIDGE_INSTANCE *RootBus
    181   )
    182 {
    183   EFI_STATUS Status;
    184 
    185   Status = gBS->UninstallMultipleProtocolInterfaces (RootBus->Handle,
    186                   &gEfiDevicePathProtocolGuid,      &RootBus->DevicePath,
    187                   &gEfiPciRootBridgeIoProtocolGuid, &RootBus->Io,
    188                   NULL);
    189   ASSERT_EFI_ERROR (Status);
    190   FreePool (RootBus);
    191 }
    192 
    193 
    194 /**
    195   Entry point of this driver
    196 
    197   @param ImageHandle     Handle of driver image
    198   @param SystemTable     Point to EFI_SYSTEM_TABLE
    199 
    200   @retval EFI_OUT_OF_RESOURCES  Can not allocate memory resource
    201   @retval EFI_DEVICE_ERROR      Can not install the protocol instance
    202   @retval EFI_SUCCESS           Success to initialize the Pci host bridge.
    203 **/
    204 EFI_STATUS
    205 EFIAPI
    206 InitializePciHostBridge (
    207   IN EFI_HANDLE        ImageHandle,
    208   IN EFI_SYSTEM_TABLE  *SystemTable
    209   )
    210 {
    211   EFI_STATUS                  Status;
    212   FIRMWARE_CONFIG_ITEM        FwCfgItem;
    213   UINTN                       FwCfgSize;
    214   UINT64                      ExtraRootBridgesLeft;
    215   UINTN                       LastRootBridgeNumber;
    216   UINTN                       RootBridgeNumber;
    217   PCI_HOST_BRIDGE_INSTANCE    *HostBridge;
    218   PCI_ROOT_BRIDGE_INSTANCE    *RootBus;
    219   EFI_STATUS                  UninstallStatus;
    220 
    221   mDriverImageHandle = ImageHandle;
    222 
    223   //
    224   // Create Host Bridge Device Handle
    225   //
    226   HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
    227                  &mPciHostBridgeInstanceTemplate);
    228   if (HostBridge == NULL) {
    229     return EFI_OUT_OF_RESOURCES;
    230   }
    231 
    232   InitializeListHead (&HostBridge->Head);
    233 
    234   Status = gBS->InstallMultipleProtocolInterfaces (
    235                   &HostBridge->HostBridgeHandle,
    236                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
    237                   &HostBridge->ResAlloc,
    238                   NULL
    239                   );
    240   if (EFI_ERROR (Status)) {
    241     goto FreeHostBridge;
    242   }
    243 
    244   //
    245   // QEMU provides the number of extra root buses, shortening the exhaustive
    246   // search below. If there is no hint, the feature is missing.
    247   //
    248   Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
    249   if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridgesLeft) {
    250     ExtraRootBridgesLeft = 0;
    251   } else {
    252     QemuFwCfgSelectItem (FwCfgItem);
    253     QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridgesLeft);
    254     DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
    255       __FUNCTION__, ExtraRootBridgesLeft));
    256   }
    257 
    258   //
    259   // The "main" root bus is always there.
    260   //
    261   LastRootBridgeNumber = 0;
    262 
    263   //
    264   // Scan all other root buses. If function 0 of any device on a bus returns a
    265   // VendorId register value different from all-bits-one, then that bus is
    266   // alive.
    267   //
    268   for (RootBridgeNumber = 1;
    269        RootBridgeNumber < 256 && ExtraRootBridgesLeft > 0;
    270        ++RootBridgeNumber) {
    271     UINTN Device;
    272 
    273     for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) {
    274       if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
    275                        PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
    276         break;
    277       }
    278     }
    279     if (Device <= MAX_PCI_DEVICE_NUMBER) {
    280       //
    281       // Found the next root bus. We can now install the *previous* one,
    282       // because now we know how big a bus number range *that* one has, for any
    283       // subordinate buses that might exist behind PCI bridges hanging off it.
    284       //
    285       Status = InitRootBridge ((UINT8)LastRootBridgeNumber,
    286                  (UINT8)(RootBridgeNumber - 1), HostBridge->HostBridgeHandle,
    287                  &RootBus);
    288       if (EFI_ERROR (Status)) {
    289         goto RollbackProtocols;
    290       }
    291       InsertTailList (&HostBridge->Head, &RootBus->Link);
    292       LastRootBridgeNumber = RootBridgeNumber;
    293       --ExtraRootBridgesLeft;
    294     }
    295   }
    296 
    297   //
    298   // Install the last root bus (which might be the only, ie. main, root bus, if
    299   // we've found no extra root buses).
    300   //
    301   Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255,
    302              HostBridge->HostBridgeHandle, &RootBus);
    303   if (EFI_ERROR (Status)) {
    304     goto RollbackProtocols;
    305   }
    306   InsertTailList (&HostBridge->Head, &RootBus->Link);
    307 
    308   return EFI_SUCCESS;
    309 
    310 RollbackProtocols:
    311   while (!IsListEmpty (&HostBridge->Head)) {
    312     LIST_ENTRY *Entry;
    313 
    314     Entry = GetFirstNode (&HostBridge->Head);
    315     RemoveEntryList (Entry);
    316     RootBus = DRIVER_INSTANCE_FROM_LIST_ENTRY (Entry);
    317     UninitRootBridge (RootBus);
    318   }
    319   UninstallStatus = gBS->UninstallMultipleProtocolInterfaces (
    320                            HostBridge->HostBridgeHandle,
    321                            &gEfiPciHostBridgeResourceAllocationProtocolGuid,
    322                            &HostBridge->ResAlloc,
    323                            NULL
    324                            );
    325   ASSERT_EFI_ERROR (UninstallStatus);
    326 
    327 FreeHostBridge:
    328   FreePool (HostBridge);
    329 
    330   return Status;
    331 }
    332 
    333 
    334 /**
    335   These are the notifications from the PCI bus driver that it is about to enter
    336   a certain phase of the PCI enumeration process.
    337 
    338   This member function can be used to notify the host bridge driver to perform
    339   specific actions, including any chipset-specific initialization, so that the
    340   chipset is ready to enter the next phase. Eight notification points are
    341   defined at this time. See belows:
    342 
    343   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures
    344                                          and internal data structures. The PCI
    345                                          enumerator should issue this
    346                                          notification before starting a fresh
    347                                          enumeration process. Enumeration
    348                                          cannot be restarted after sending any
    349                                          other notification such as
    350                                          EfiPciHostBridgeBeginBusAllocation.
    351 
    352   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to
    353                                          begin. No specific action is required
    354                                          here. This notification can be used to
    355                                          perform any chipset-specific
    356                                          programming.
    357 
    358   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming
    359                                          phase is complete. No specific action
    360                                          is required here. This notification
    361                                          can be used to perform any
    362                                          chipset-specific programming.
    363 
    364   EfiPciHostBridgeBeginResourceAllocation
    365                                          The resource allocation phase is about
    366                                          to begin. No specific action is
    367                                          required here. This notification can
    368                                          be used to perform any
    369                                          chipset-specific programming.
    370 
    371   EfiPciHostBridgeAllocateResources      Allocates resources per previously
    372                                          submitted requests for all the PCI
    373                                          root bridges. These resource settings
    374                                          are returned on the next call to
    375                                          GetProposedResources(). Before calling
    376                                          NotifyPhase() with a Phase of
    377                                          EfiPciHostBridgeAllocateResource, the
    378                                          PCI bus enumerator is responsible for
    379                                          gathering I/O and memory requests for
    380                                          all the PCI root bridges and
    381                                          submitting these requests using
    382                                          SubmitResources(). This function pads
    383                                          the resource amount to suit the root
    384                                          bridge hardware, takes care of
    385                                          dependencies between the PCI root
    386                                          bridges, and calls the Global
    387                                          Coherency Domain (GCD) with the
    388                                          allocation request. In the case of
    389                                          padding, the allocated range could be
    390                                          bigger than what was requested.
    391 
    392   EfiPciHostBridgeSetResources           Programs the host bridge hardware to
    393                                          decode previously allocated resources
    394                                          (proposed resources) for all the PCI
    395                                          root bridges. After the hardware is
    396                                          programmed, reassigning resources will
    397                                          not be supported. The bus settings are
    398                                          not affected.
    399 
    400   EfiPciHostBridgeFreeResources          Deallocates resources that were
    401                                          previously allocated for all the PCI
    402                                          root bridges and resets the I/O and
    403                                          memory apertures to their initial
    404                                          state. The bus settings are not
    405                                          affected. If the request to allocate
    406                                          resources fails, the PCI enumerator
    407                                          can use this notification to
    408                                          deallocate previous resources, adjust
    409                                          the requests, and retry allocation.
    410 
    411   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is
    412                                          completed. No specific action is
    413                                          required here. This notification can
    414                                          be used to perform any chipsetspecific
    415                                          programming.
    416 
    417   @param[in] This                The instance pointer of
    418                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
    419 
    420   @param[in] Phase               The phase during enumeration
    421 
    422   @retval EFI_NOT_READY          This phase cannot be entered at this time. For
    423                                  example, this error is valid for a Phase of
    424                                  EfiPciHostBridgeAllocateResources if
    425                                  SubmitResources() has not been called for one
    426                                  or more PCI root bridges before this call
    427 
    428   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
    429                                  This error is valid for a Phase of
    430                                  EfiPciHostBridgeSetResources.
    431 
    432   @retval EFI_INVALID_PARAMETER  Invalid phase parameter
    433 
    434   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
    435                                  lack of resources. This error is valid for a
    436                                  Phase of EfiPciHostBridgeAllocateResources if
    437                                  the previously submitted resource requests
    438                                  cannot be fulfilled or were only partially
    439                                  fulfilled.
    440 
    441   @retval EFI_SUCCESS            The notification was accepted without any
    442                                  errors.
    443 **/
    444 EFI_STATUS
    445 EFIAPI
    446 NotifyPhase(
    447   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
    448   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
    449   )
    450 {
    451   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
    452   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
    453   PCI_RESOURCE_TYPE                     Index;
    454   LIST_ENTRY                            *List;
    455   EFI_PHYSICAL_ADDRESS                  BaseAddress;
    456   UINT64                                AddrLen;
    457   UINTN                                 BitsOfAlignment;
    458   EFI_STATUS                            Status;
    459   EFI_STATUS                            ReturnStatus;
    460 
    461   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    462 
    463   switch (Phase) {
    464 
    465   case EfiPciHostBridgeBeginEnumeration:
    466     if (HostBridgeInstance->CanRestarted) {
    467       //
    468       // Reset the Each Root Bridge
    469       //
    470       List = HostBridgeInstance->Head.ForwardLink;
    471 
    472       while (List != &HostBridgeInstance->Head) {
    473         RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    474         for (Index = TypeIo; Index < TypeMax; Index++) {
    475           RootBridgeInstance->ResAllocNode[Index].Type      = Index;
    476           RootBridgeInstance->ResAllocNode[Index].Base      = 0;
    477           RootBridgeInstance->ResAllocNode[Index].Length    = 0;
    478           RootBridgeInstance->ResAllocNode[Index].Status    = ResNone;
    479         }
    480 
    481         List = List->ForwardLink;
    482       }
    483 
    484       HostBridgeInstance->ResourceSubmited = FALSE;
    485       HostBridgeInstance->CanRestarted     = TRUE;
    486     } else {
    487       //
    488       // Can not restart
    489       //
    490       return EFI_NOT_READY;
    491     }
    492     break;
    493 
    494   case EfiPciHostBridgeEndEnumeration:
    495     break;
    496 
    497   case EfiPciHostBridgeBeginBusAllocation:
    498     //
    499     // No specific action is required here, can perform any chipset specific
    500     // programing
    501     //
    502     HostBridgeInstance->CanRestarted = FALSE;
    503     break;
    504 
    505   case EfiPciHostBridgeEndBusAllocation:
    506     //
    507     // No specific action is required here, can perform any chipset specific
    508     // programing
    509     //
    510     //HostBridgeInstance->CanRestarted = FALSE;
    511     break;
    512 
    513   case EfiPciHostBridgeBeginResourceAllocation:
    514     //
    515     // No specific action is required here, can perform any chipset specific
    516     // programing
    517     //
    518     //HostBridgeInstance->CanRestarted = FALSE;
    519     break;
    520 
    521   case EfiPciHostBridgeAllocateResources:
    522     ReturnStatus = EFI_SUCCESS;
    523     if (HostBridgeInstance->ResourceSubmited) {
    524       //
    525       // Take care of the resource dependencies between the root bridges
    526       //
    527       List = HostBridgeInstance->Head.ForwardLink;
    528 
    529       while (List != &HostBridgeInstance->Head) {
    530         RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    531         for (Index = TypeIo; Index < TypeBus; Index++) {
    532           if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
    533 
    534             AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
    535 
    536             //
    537             // Get the number of '1' in Alignment.
    538             //
    539             BitsOfAlignment =
    540               (UINTN)(HighBitSet64 (
    541                         RootBridgeInstance->ResAllocNode[Index].Alignment
    542                         ) + 1);
    543 
    544             switch (Index) {
    545 
    546               case TypeIo:
    547                 //
    548                 // It is impossible for this chipset to align 0xFFFF for IO16
    549                 // So clear it
    550                 //
    551                 if (BitsOfAlignment >= 16) {
    552                   BitsOfAlignment = 0;
    553                 }
    554 
    555                 Status = gDS->AllocateIoSpace (
    556                                 EfiGcdAllocateAnySearchBottomUp,
    557                                 EfiGcdIoTypeIo,
    558                                 BitsOfAlignment,
    559                                 AddrLen,
    560                                 &BaseAddress,
    561                                 mDriverImageHandle,
    562                                 NULL
    563                                 );
    564 
    565                 if (!EFI_ERROR (Status)) {
    566                   RootBridgeInstance->ResAllocNode[Index].Base   =
    567                     (UINTN)BaseAddress;
    568                   RootBridgeInstance->ResAllocNode[Index].Status =
    569                     ResAllocated;
    570                 } else {
    571                   ReturnStatus = Status;
    572                   if (Status != EFI_OUT_OF_RESOURCES) {
    573                     RootBridgeInstance->ResAllocNode[Index].Length = 0;
    574                   }
    575                 }
    576 
    577                 break;
    578 
    579 
    580               case TypeMem32:
    581                 //
    582                 // It is impossible for this chipset to align 0xFFFFFFFF for
    583                 // Mem32
    584                 // So clear it
    585                 //
    586 
    587                 if (BitsOfAlignment >= 32) {
    588                   BitsOfAlignment = 0;
    589                 }
    590 
    591                 Status = gDS->AllocateMemorySpace (
    592                                 EfiGcdAllocateAnySearchBottomUp,
    593                                 EfiGcdMemoryTypeMemoryMappedIo,
    594                                 BitsOfAlignment,
    595                                 AddrLen,
    596                                 &BaseAddress,
    597                                 mDriverImageHandle,
    598                                 NULL
    599                                 );
    600 
    601                 if (!EFI_ERROR (Status)) {
    602                   // We were able to allocate the PCI memory
    603                   RootBridgeInstance->ResAllocNode[Index].Base   =
    604                     (UINTN)BaseAddress;
    605                   RootBridgeInstance->ResAllocNode[Index].Status =
    606                     ResAllocated;
    607 
    608                 } else {
    609                   // Not able to allocate enough PCI memory
    610                   ReturnStatus = Status;
    611 
    612                   if (Status != EFI_OUT_OF_RESOURCES) {
    613                     RootBridgeInstance->ResAllocNode[Index].Length = 0;
    614                   }
    615                   ASSERT (FALSE);
    616                 }
    617                 break;
    618 
    619               case TypePMem32:
    620               case TypeMem64:
    621               case TypePMem64:
    622                   ReturnStatus = EFI_ABORTED;
    623                   break;
    624               default:
    625                 ASSERT (FALSE);
    626                 break;
    627               }; //end switch
    628           }
    629         }
    630 
    631         List = List->ForwardLink;
    632       }
    633 
    634       return ReturnStatus;
    635 
    636     } else {
    637       return EFI_NOT_READY;
    638     }
    639     break;
    640 
    641   case EfiPciHostBridgeSetResources:
    642     break;
    643 
    644   case EfiPciHostBridgeFreeResources:
    645     ReturnStatus = EFI_SUCCESS;
    646     List = HostBridgeInstance->Head.ForwardLink;
    647     while (List != &HostBridgeInstance->Head) {
    648       RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    649       for (Index = TypeIo; Index < TypeBus; Index++) {
    650         if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
    651           AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
    652           BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
    653           switch (Index) {
    654 
    655           case TypeIo:
    656             Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
    657             if (EFI_ERROR (Status)) {
    658               ReturnStatus = Status;
    659             }
    660             break;
    661 
    662           case TypeMem32:
    663             Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
    664             if (EFI_ERROR (Status)) {
    665               ReturnStatus = Status;
    666             }
    667             break;
    668 
    669           case TypePMem32:
    670             break;
    671 
    672           case TypeMem64:
    673             break;
    674 
    675           case TypePMem64:
    676             break;
    677 
    678           default:
    679             ASSERT (FALSE);
    680             break;
    681 
    682           }; //end switch
    683           RootBridgeInstance->ResAllocNode[Index].Type      = Index;
    684           RootBridgeInstance->ResAllocNode[Index].Base      = 0;
    685           RootBridgeInstance->ResAllocNode[Index].Length    = 0;
    686           RootBridgeInstance->ResAllocNode[Index].Status    = ResNone;
    687         }
    688       }
    689 
    690       List = List->ForwardLink;
    691     }
    692 
    693     HostBridgeInstance->ResourceSubmited = FALSE;
    694     HostBridgeInstance->CanRestarted     = TRUE;
    695     return ReturnStatus;
    696 
    697   case EfiPciHostBridgeEndResourceAllocation:
    698     HostBridgeInstance->CanRestarted = FALSE;
    699     break;
    700 
    701   default:
    702     return EFI_INVALID_PARAMETER;
    703   }
    704 
    705   return EFI_SUCCESS;
    706 }
    707 
    708 /**
    709   Return the device handle of the next PCI root bridge that is associated with
    710   this Host Bridge.
    711 
    712   This function is called multiple times to retrieve the device handles of all
    713   the PCI root bridges that are associated with this PCI host bridge. Each PCI
    714   host bridge is associated with one or more PCI root bridges. On each call,
    715   the handle that was returned by the previous call is passed into the
    716   interface, and on output the interface returns the device handle of the next
    717   PCI root bridge. The caller can use the handle to obtain the instance of the
    718   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
    719   PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
    720   enumerator must enumerate the PCI root bridges in the order that they are
    721   returned by this function.
    722 
    723   For D945 implementation, there is only one root bridge in PCI host bridge.
    724 
    725   @param[in]       This              The instance pointer of
    726                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
    727 
    728   @param[in, out]  RootBridgeHandle  Returns the device handle of the next PCI
    729                                      root bridge.
    730 
    731   @retval EFI_SUCCESS            If parameter RootBridgeHandle = NULL, then
    732                                  return the first Rootbridge handle of the
    733                                  specific Host bridge and return EFI_SUCCESS.
    734 
    735   @retval EFI_NOT_FOUND          Can not find the any more root bridge in
    736                                  specific host bridge.
    737 
    738   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not an EFI_HANDLE that was
    739                                  returned on a previous call to
    740                                  GetNextRootBridge().
    741 **/
    742 EFI_STATUS
    743 EFIAPI
    744 GetNextRootBridge(
    745   IN       EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
    746   IN OUT   EFI_HANDLE                                       *RootBridgeHandle
    747   )
    748 {
    749   BOOLEAN                               NoRootBridge;
    750   LIST_ENTRY                            *List;
    751   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
    752   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
    753 
    754   NoRootBridge = TRUE;
    755   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    756   List = HostBridgeInstance->Head.ForwardLink;
    757 
    758 
    759   while (List != &HostBridgeInstance->Head) {
    760     NoRootBridge = FALSE;
    761     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    762     if (*RootBridgeHandle == NULL) {
    763       //
    764       // Return the first Root Bridge Handle of the Host Bridge
    765       //
    766       *RootBridgeHandle = RootBridgeInstance->Handle;
    767       return EFI_SUCCESS;
    768     } else {
    769       if (*RootBridgeHandle == RootBridgeInstance->Handle) {
    770         //
    771         // Get next if have
    772         //
    773         List = List->ForwardLink;
    774         if (List!=&HostBridgeInstance->Head) {
    775           RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    776           *RootBridgeHandle = RootBridgeInstance->Handle;
    777           return EFI_SUCCESS;
    778         } else {
    779           return EFI_NOT_FOUND;
    780         }
    781       }
    782     }
    783 
    784     List = List->ForwardLink;
    785   } //end while
    786 
    787   if (NoRootBridge) {
    788     return EFI_NOT_FOUND;
    789   } else {
    790     return EFI_INVALID_PARAMETER;
    791   }
    792 }
    793 
    794 /**
    795   Returns the allocation attributes of a PCI root bridge.
    796 
    797   The function returns the allocation attributes of a specific PCI root bridge.
    798   The attributes can vary from one PCI root bridge to another. These attributes
    799   are different from the decode-related attributes that are returned by the
    800   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
    801   RootBridgeHandle parameter is used to specify the instance of the PCI root
    802   bridge. The device handles of all the root bridges that are associated with
    803   this host bridge must be obtained by calling GetNextRootBridge(). The
    804   attributes are static in the sense that they do not change during or after
    805   the enumeration process. The hardware may provide mechanisms to change the
    806   attributes on the fly, but such changes must be completed before
    807   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
    808   values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
    809   "Related Definitions" below. The caller uses these attributes to combine
    810   multiple resource requests.
    811 
    812   For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
    813   bus enumerator needs to include requests for the prefetchable memory in the
    814   nonprefetchable memory pool and not request any prefetchable memory.
    815 
    816   Attribute                             Description
    817   ------------------------------------  ---------------------------------------
    818   EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM  If this bit is set, then the PCI root
    819                                         bridge does not support separate
    820                                         windows for nonprefetchable and
    821                                         prefetchable memory. A PCI bus driver
    822                                         needs to include requests for
    823                                         prefetchable memory in the
    824                                         nonprefetchable memory pool.
    825 
    826   EFI_PCI_HOST_BRIDGE_MEM64_DECODE      If this bit is set, then the PCI root
    827                                         bridge supports 64-bit memory windows.
    828                                         If this bit is not set, the PCI bus
    829                                         driver needs to include requests for a
    830                                         64-bit memory address in the
    831                                         corresponding 32-bit memory pool.
    832 
    833   @param[in]   This               The instance pointer of
    834                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
    835 
    836   @param[in]   RootBridgeHandle   The device handle of the PCI root bridge in
    837                                   which the caller is interested. Type
    838                                   EFI_HANDLE is defined in
    839                                   InstallProtocolInterface() in the UEFI 2.0
    840                                   Specification.
    841 
    842   @param[out]  Attributes         The pointer to attribte of root bridge, it is
    843                                   output parameter
    844 
    845   @retval EFI_INVALID_PARAMETER   Attribute pointer is NULL
    846 
    847   @retval EFI_INVALID_PARAMETER   RootBridgehandle is invalid.
    848 
    849   @retval EFI_SUCCESS             Success to get attribute of interested root
    850                                   bridge.
    851 **/
    852 EFI_STATUS
    853 EFIAPI
    854 GetAttributes(
    855   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
    856   IN  EFI_HANDLE                                       RootBridgeHandle,
    857   OUT UINT64                                           *Attributes
    858   )
    859 {
    860   LIST_ENTRY                            *List;
    861   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
    862   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
    863 
    864   if (Attributes == NULL) {
    865     return EFI_INVALID_PARAMETER;
    866   }
    867 
    868   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    869   List = HostBridgeInstance->Head.ForwardLink;
    870 
    871   while (List != &HostBridgeInstance->Head) {
    872     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    873     if (RootBridgeHandle == RootBridgeInstance->Handle) {
    874       *Attributes = RootBridgeInstance->RootBridgeAttrib;
    875       return EFI_SUCCESS;
    876     }
    877     List = List->ForwardLink;
    878   }
    879 
    880   //
    881   // RootBridgeHandle is not an EFI_HANDLE
    882   // that was returned on a previous call to GetNextRootBridge()
    883   //
    884   return EFI_INVALID_PARAMETER;
    885 }
    886 
    887 /**
    888   Sets up the specified PCI root bridge for the bus enumeration process.
    889 
    890   This member function sets up the root bridge for bus enumeration and returns
    891   the PCI bus range over which the search should be performed in ACPI 2.0
    892   resource descriptor format.
    893 
    894   @param[in]   This              The
    895                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
    896                                  instance.
    897 
    898   @param[in]   RootBridgeHandle  The PCI Root Bridge to be set up.
    899 
    900   @param[out]  Configuration     Pointer to the pointer to the PCI bus resource
    901                                  descriptor.
    902 
    903   @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
    904 
    905   @retval EFI_OUT_OF_RESOURCES  Fail to allocate ACPI resource descriptor tag.
    906 
    907   @retval EFI_SUCCESS           Sucess to allocate ACPI resource descriptor.
    908 **/
    909 EFI_STATUS
    910 EFIAPI
    911 StartBusEnumeration(
    912   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
    913   IN  EFI_HANDLE                                       RootBridgeHandle,
    914   OUT VOID                                             **Configuration
    915   )
    916 {
    917   LIST_ENTRY                            *List;
    918   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
    919   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
    920   VOID                                  *Buffer;
    921   UINT8                                 *Temp;
    922   UINT64                                BusStart;
    923   UINT64                                BusEnd;
    924 
    925   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    926   List = HostBridgeInstance->Head.ForwardLink;
    927 
    928   while (List != &HostBridgeInstance->Head) {
    929     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    930     if (RootBridgeHandle == RootBridgeInstance->Handle) {
    931       //
    932       // Set up the Root Bridge for Bus Enumeration
    933       //
    934       BusStart = RootBridgeInstance->BusBase;
    935       BusEnd   = RootBridgeInstance->BusLimit;
    936       //
    937       // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
    938       //
    939 
    940       Buffer = AllocatePool (
    941                  sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
    942                  sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
    943                  );
    944       if (Buffer == NULL) {
    945         return EFI_OUT_OF_RESOURCES;
    946       }
    947 
    948       Temp = (UINT8 *)Buffer;
    949 
    950       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
    951       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len  = 0x2B;
    952       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
    953       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
    954       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
    955       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
    956       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
    957       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
    958       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
    959       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen =
    960         BusEnd - BusStart + 1;
    961 
    962       Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
    963       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
    964       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
    965 
    966       *Configuration = Buffer;
    967       return EFI_SUCCESS;
    968     }
    969     List = List->ForwardLink;
    970   }
    971 
    972   return EFI_INVALID_PARAMETER;
    973 }
    974 
    975 /**
    976   Programs the PCI root bridge hardware so that it decodes the specified PCI
    977   bus range.
    978 
    979   This member function programs the specified PCI root bridge to decode the bus
    980   range that is specified by the input parameter Configuration.
    981   The bus range information is specified in terms of the ACPI 2.0 resource
    982   descriptor format.
    983 
    984   @param[in] This              The
    985                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
    986                                instance
    987 
    988   @param[in] RootBridgeHandle  The PCI Root Bridge whose bus range is to be
    989                                programmed
    990 
    991   @param[in] Configuration     The pointer to the PCI bus resource descriptor
    992 
    993   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
    994                                  handle.
    995 
    996   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
    997 
    998   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
    999                                  2.0 resource descriptor.
   1000 
   1001   @retval EFI_INVALID_PARAMETER  Configuration does not include a valid ACPI
   1002                                  2.0 bus resource descriptor.
   1003 
   1004   @retval EFI_INVALID_PARAMETER  Configuration includes valid ACPI 2.0 resource
   1005                                  descriptors other than bus descriptors.
   1006 
   1007   @retval EFI_INVALID_PARAMETER  Configuration contains one or more invalid
   1008                                  ACPI resource descriptors.
   1009 
   1010   @retval EFI_INVALID_PARAMETER  "Address Range Minimum" is invalid for this
   1011                                  root bridge.
   1012 
   1013   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this
   1014                                  root bridge.
   1015 
   1016   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
   1017 
   1018   @retval EFI_SUCCESS            The bus range for the PCI root bridge was
   1019                                  programmed.
   1020 **/
   1021 EFI_STATUS
   1022 EFIAPI
   1023 SetBusNumbers(
   1024   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1025   IN EFI_HANDLE                                       RootBridgeHandle,
   1026   IN VOID                                             *Configuration
   1027   )
   1028 {
   1029   LIST_ENTRY                            *List;
   1030   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
   1031   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
   1032   UINT8                                 *Ptr;
   1033   UINTN                                 BusStart;
   1034   UINTN                                 BusEnd;
   1035   UINTN                                 BusLen;
   1036 
   1037   if (Configuration == NULL) {
   1038     return EFI_INVALID_PARAMETER;
   1039   }
   1040 
   1041   Ptr = Configuration;
   1042 
   1043   //
   1044   // Check the Configuration is valid
   1045   //
   1046   if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
   1047     return EFI_INVALID_PARAMETER;
   1048   }
   1049 
   1050   if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
   1051     return EFI_INVALID_PARAMETER;
   1052   }
   1053 
   1054   Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
   1055   if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
   1056     return EFI_INVALID_PARAMETER;
   1057   }
   1058 
   1059   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
   1060   List = HostBridgeInstance->Head.ForwardLink;
   1061 
   1062   Ptr = Configuration;
   1063 
   1064   while (List != &HostBridgeInstance->Head) {
   1065     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
   1066     if (RootBridgeHandle == RootBridgeInstance->Handle) {
   1067       EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
   1068 
   1069       Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
   1070       BusStart = (UINTN)Desc->AddrRangeMin;
   1071       BusLen = (UINTN)Desc->AddrLen;
   1072       BusEnd = BusStart + BusLen - 1;
   1073 
   1074       if (BusStart > BusEnd) {
   1075         return EFI_INVALID_PARAMETER;
   1076       }
   1077 
   1078       if ((BusStart < RootBridgeInstance->BusBase) ||
   1079           (BusEnd > RootBridgeInstance->BusLimit)) {
   1080         return EFI_INVALID_PARAMETER;
   1081       }
   1082 
   1083       //
   1084       // Update the Bus Range
   1085       //
   1086       RootBridgeInstance->ResAllocNode[TypeBus].Base   = BusStart;
   1087       RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
   1088       RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
   1089 
   1090       //
   1091       // Program the Root Bridge Hardware
   1092       //
   1093 
   1094       return EFI_SUCCESS;
   1095     }
   1096 
   1097     List = List->ForwardLink;
   1098   }
   1099 
   1100   return EFI_INVALID_PARAMETER;
   1101 }
   1102 
   1103 
   1104 /**
   1105   Submits the I/O and memory resource requirements for the specified PCI root
   1106   bridge.
   1107 
   1108   This function is used to submit all the I/O and memory resources that are
   1109   required by the specified PCI root bridge. The input parameter Configuration
   1110   is used to specify the following:
   1111   - The various types of resources that are required
   1112   - The associated lengths in terms of ACPI 2.0 resource descriptor format
   1113 
   1114   @param[in] This              Pointer to the
   1115                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
   1116                                instance.
   1117 
   1118   @param[in] RootBridgeHandle  The PCI root bridge whose I/O and memory
   1119                                resource requirements are being submitted.
   1120 
   1121   @param[in] Configuration     The pointer to the PCI I/O and PCI memory
   1122                                resource descriptor.
   1123 
   1124   @retval EFI_SUCCESS            The I/O and memory resource requests for a PCI
   1125                                  root bridge were accepted.
   1126 
   1127   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
   1128                                  handle.
   1129 
   1130   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
   1131 
   1132   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
   1133                                  2.0 resource descriptor.
   1134 
   1135   @retval EFI_INVALID_PARAMETER  Configuration includes requests for one or
   1136                                  more resource types that are not supported by
   1137                                  this PCI root bridge. This error will happen
   1138                                  if the caller did not combine resources
   1139                                  according to Attributes that were returned by
   1140                                  GetAllocAttributes().
   1141 
   1142   @retval EFI_INVALID_PARAMETER  Address Range Maximum" is invalid.
   1143 
   1144   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this PCI
   1145                                  root bridge.
   1146 
   1147   @retval EFI_INVALID_PARAMETER  "Address Space Granularity" is invalid for
   1148                                  this PCI root bridge.
   1149 **/
   1150 EFI_STATUS
   1151 EFIAPI
   1152 SubmitResources(
   1153   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1154   IN EFI_HANDLE                                       RootBridgeHandle,
   1155   IN VOID                                             *Configuration
   1156   )
   1157 {
   1158   LIST_ENTRY                            *List;
   1159   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
   1160   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
   1161   UINT8                                 *Temp;
   1162   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *Ptr;
   1163   UINT64                                AddrLen;
   1164   UINT64                                Alignment;
   1165 
   1166   //
   1167   // Check the input parameter: Configuration
   1168   //
   1169   if (Configuration == NULL) {
   1170     return EFI_INVALID_PARAMETER;
   1171   }
   1172 
   1173   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
   1174   List = HostBridgeInstance->Head.ForwardLink;
   1175 
   1176   Temp = (UINT8 *)Configuration;
   1177   while ( *Temp == 0x8A) {
   1178     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
   1179   }
   1180   if (*Temp != 0x79) {
   1181     return EFI_INVALID_PARAMETER;
   1182   }
   1183 
   1184   Temp = (UINT8 *)Configuration;
   1185   while (List != &HostBridgeInstance->Head) {
   1186     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
   1187     if (RootBridgeHandle == RootBridgeInstance->Handle) {
   1188       while ( *Temp == 0x8A) {
   1189         Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
   1190 
   1191         //
   1192         // Check Address Length
   1193         //
   1194         if (Ptr->AddrLen > 0xffffffff) {
   1195           return EFI_INVALID_PARAMETER;
   1196         }
   1197 
   1198         //
   1199         // Check address range alignment
   1200         //
   1201         if (Ptr->AddrRangeMax >= 0xffffffff ||
   1202             Ptr->AddrRangeMax != (GetPowerOfTwo64 (
   1203                                     Ptr->AddrRangeMax + 1) - 1)) {
   1204           return EFI_INVALID_PARAMETER;
   1205         }
   1206 
   1207         switch (Ptr->ResType) {
   1208 
   1209         case 0:
   1210 
   1211           //
   1212           // Check invalid Address Sapce Granularity
   1213           //
   1214           if (Ptr->AddrSpaceGranularity != 32) {
   1215             return EFI_INVALID_PARAMETER;
   1216           }
   1217 
   1218           //
   1219           // check the memory resource request is supported by PCI root bridge
   1220           //
   1221           if (RootBridgeInstance->RootBridgeAttrib ==
   1222                 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
   1223               Ptr->SpecificFlag == 0x06) {
   1224             return EFI_INVALID_PARAMETER;
   1225           }
   1226 
   1227           AddrLen = Ptr->AddrLen;
   1228           Alignment = Ptr->AddrRangeMax;
   1229           if (Ptr->AddrSpaceGranularity == 32) {
   1230             if (Ptr->SpecificFlag == 0x06) {
   1231               //
   1232               // Apply from GCD
   1233               //
   1234               RootBridgeInstance->ResAllocNode[TypePMem32].Status =
   1235                 ResSubmitted;
   1236             } else {
   1237               RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
   1238               RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =
   1239                 Alignment;
   1240               RootBridgeInstance->ResAllocNode[TypeMem32].Status =
   1241                 ResRequested;
   1242               HostBridgeInstance->ResourceSubmited = TRUE;
   1243             }
   1244           }
   1245 
   1246           if (Ptr->AddrSpaceGranularity == 64) {
   1247             if (Ptr->SpecificFlag == 0x06) {
   1248               RootBridgeInstance->ResAllocNode[TypePMem64].Status =
   1249                 ResSubmitted;
   1250             } else {
   1251               RootBridgeInstance->ResAllocNode[TypeMem64].Status =
   1252                 ResSubmitted;
   1253             }
   1254           }
   1255           break;
   1256 
   1257         case 1:
   1258           AddrLen = (UINTN) Ptr->AddrLen;
   1259           Alignment = (UINTN) Ptr->AddrRangeMax;
   1260           RootBridgeInstance->ResAllocNode[TypeIo].Length  = AddrLen;
   1261           RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
   1262           RootBridgeInstance->ResAllocNode[TypeIo].Status  = ResRequested;
   1263           HostBridgeInstance->ResourceSubmited = TRUE;
   1264           break;
   1265 
   1266         default:
   1267             break;
   1268         };
   1269 
   1270         Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
   1271       }
   1272 
   1273       return EFI_SUCCESS;
   1274     }
   1275 
   1276     List = List->ForwardLink;
   1277   }
   1278 
   1279   return EFI_INVALID_PARAMETER;
   1280 }
   1281 
   1282 /**
   1283    Returns the proposed resource settings for the specified PCI root bridge.
   1284 
   1285    This member function returns the proposed resource settings for the
   1286    specified PCI root bridge. The proposed resource settings are prepared when
   1287    NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
   1288    The output parameter Configuration specifies the following:
   1289    - The various types of resources, excluding bus resources, that are
   1290      allocated
   1291    - The associated lengths in terms of ACPI 2.0 resource descriptor format
   1292 
   1293    @param[in]  This              Pointer to the
   1294                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
   1295                                  instance.
   1296 
   1297    @param[in]  RootBridgeHandle  The PCI root bridge handle. Type EFI_HANDLE is
   1298                                  defined in InstallProtocolInterface() in the
   1299                                  UEFI 2.0 Specification.
   1300 
   1301    @param[out] Configuration     The pointer to the pointer to the PCI I/O and
   1302                                  memory resource descriptor.
   1303 
   1304    @retval EFI_SUCCESS            The requested parameters were returned.
   1305 
   1306    @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
   1307                                   handle.
   1308 
   1309    @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
   1310 
   1311    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
   1312                                   lack of resources.
   1313 **/
   1314 EFI_STATUS
   1315 EFIAPI
   1316 GetProposedResources(
   1317   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
   1318   IN  EFI_HANDLE                                       RootBridgeHandle,
   1319   OUT VOID                                             **Configuration
   1320   )
   1321 {
   1322   LIST_ENTRY                            *List;
   1323   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
   1324   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
   1325   UINTN                                 Index;
   1326   UINTN                                 Number;
   1327   VOID                                  *Buffer;
   1328   UINT8                                 *Temp;
   1329   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *Ptr;
   1330   UINT64                                ResStatus;
   1331 
   1332   Buffer = NULL;
   1333   Number = 0;
   1334   //
   1335   // Get the Host Bridge Instance from the resource allocation protocol
   1336   //
   1337   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
   1338   List = HostBridgeInstance->Head.ForwardLink;
   1339 
   1340   //
   1341   // Enumerate the root bridges in this host bridge
   1342   //
   1343   while (List != &HostBridgeInstance->Head) {
   1344     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
   1345     if (RootBridgeHandle == RootBridgeInstance->Handle) {
   1346       for (Index = 0; Index < TypeBus; Index ++) {
   1347         if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
   1348           Number ++;
   1349         }
   1350       }
   1351 
   1352       if (Number ==  0) {
   1353         return EFI_INVALID_PARAMETER;
   1354       }
   1355 
   1356       Buffer = AllocateZeroPool (
   1357                  Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
   1358                  sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
   1359                  );
   1360       if (Buffer == NULL) {
   1361         return EFI_OUT_OF_RESOURCES;
   1362       }
   1363 
   1364       Temp = Buffer;
   1365       for (Index = 0; Index < TypeBus; Index ++) {
   1366         if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
   1367           Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
   1368           ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
   1369 
   1370           switch (Index) {
   1371 
   1372           case TypeIo:
   1373             //
   1374             // Io
   1375             //
   1376             Ptr->Desc = 0x8A;
   1377             Ptr->Len  = 0x2B;
   1378             Ptr->ResType = 1;
   1379             Ptr->GenFlag = 0;
   1380             Ptr->SpecificFlag = 0;
   1381             Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
   1382             Ptr->AddrRangeMax = 0;
   1383             Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
   1384                                            EFI_RESOURCE_SATISFIED :
   1385                                            EFI_RESOURCE_LESS;
   1386             Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
   1387             break;
   1388 
   1389           case TypeMem32:
   1390             //
   1391             // Memory 32
   1392             //
   1393             Ptr->Desc = 0x8A;
   1394             Ptr->Len  = 0x2B;
   1395             Ptr->ResType = 0;
   1396             Ptr->GenFlag = 0;
   1397             Ptr->SpecificFlag = 0;
   1398             Ptr->AddrSpaceGranularity = 32;
   1399             Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
   1400             Ptr->AddrRangeMax = 0;
   1401             Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
   1402                                            EFI_RESOURCE_SATISFIED :
   1403                                            EFI_RESOURCE_LESS;
   1404             Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
   1405             break;
   1406 
   1407           case TypePMem32:
   1408             //
   1409             // Prefetch memory 32
   1410             //
   1411             Ptr->Desc = 0x8A;
   1412             Ptr->Len  = 0x2B;
   1413             Ptr->ResType = 0;
   1414             Ptr->GenFlag = 0;
   1415             Ptr->SpecificFlag = 6;
   1416             Ptr->AddrSpaceGranularity = 32;
   1417             Ptr->AddrRangeMin = 0;
   1418             Ptr->AddrRangeMax = 0;
   1419             Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
   1420             Ptr->AddrLen = 0;
   1421             break;
   1422 
   1423           case TypeMem64:
   1424             //
   1425             // Memory 64
   1426             //
   1427             Ptr->Desc = 0x8A;
   1428             Ptr->Len  = 0x2B;
   1429             Ptr->ResType = 0;
   1430             Ptr->GenFlag = 0;
   1431             Ptr->SpecificFlag = 0;
   1432             Ptr->AddrSpaceGranularity = 64;
   1433             Ptr->AddrRangeMin = 0;
   1434             Ptr->AddrRangeMax = 0;
   1435             Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
   1436             Ptr->AddrLen = 0;
   1437             break;
   1438 
   1439           case TypePMem64:
   1440             //
   1441             // Prefetch memory 64
   1442             //
   1443             Ptr->Desc = 0x8A;
   1444             Ptr->Len  = 0x2B;
   1445             Ptr->ResType = 0;
   1446             Ptr->GenFlag = 0;
   1447             Ptr->SpecificFlag = 6;
   1448             Ptr->AddrSpaceGranularity = 64;
   1449             Ptr->AddrRangeMin = 0;
   1450             Ptr->AddrRangeMax = 0;
   1451             Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
   1452             Ptr->AddrLen = 0;
   1453             break;
   1454           };
   1455 
   1456           Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
   1457         }
   1458       }
   1459 
   1460       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
   1461       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
   1462 
   1463       *Configuration = Buffer;
   1464 
   1465       return EFI_SUCCESS;
   1466     }
   1467 
   1468     List = List->ForwardLink;
   1469   }
   1470 
   1471   return EFI_INVALID_PARAMETER;
   1472 }
   1473 
   1474 /**
   1475   Provides the hooks from the PCI bus driver to every PCI controller
   1476   (device/function) at various stages of the PCI enumeration process that allow
   1477   the host bridge driver to preinitialize individual PCI controllers before
   1478   enumeration.
   1479 
   1480   This function is called during the PCI enumeration process. No specific
   1481   action is expected from this member function. It allows the host bridge
   1482   driver to preinitialize individual PCI controllers before enumeration.
   1483 
   1484   @param This              Pointer to the
   1485                            EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
   1486                            instance.
   1487 
   1488   @param RootBridgeHandle  The associated PCI root bridge handle. Type
   1489                            EFI_HANDLE is defined in InstallProtocolInterface()
   1490                            in the UEFI 2.0 Specification.
   1491 
   1492   @param PciAddress        The address of the PCI device on the PCI bus. This
   1493                            address can be passed to the
   1494                            EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
   1495                            access the PCI configuration space of the device.
   1496                            See Table 12-1 in the UEFI 2.0 Specification for the
   1497                            definition of
   1498                            EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
   1499 
   1500   @param Phase             The phase of the PCI device enumeration.
   1501 
   1502   @retval EFI_SUCCESS              The requested parameters were returned.
   1503 
   1504   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge
   1505                                    handle.
   1506 
   1507   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined
   1508                                    in
   1509                                   EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
   1510 
   1511   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error.
   1512                                    The PCI enumerator should not enumerate this
   1513                                    device, including its child devices if it is
   1514                                    a PCI-to-PCI bridge.
   1515 **/
   1516 EFI_STATUS
   1517 EFIAPI
   1518 PreprocessController (
   1519   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL        *This,
   1520   IN  EFI_HANDLE                                              RootBridgeHandle,
   1521   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS             PciAddress,
   1522   IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE            Phase
   1523   )
   1524 {
   1525   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
   1526   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
   1527   LIST_ENTRY                            *List;
   1528 
   1529   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
   1530   List = HostBridgeInstance->Head.ForwardLink;
   1531 
   1532   //
   1533   // Enumerate the root bridges in this host bridge
   1534   //
   1535   while (List != &HostBridgeInstance->Head) {
   1536     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
   1537     if (RootBridgeHandle == RootBridgeInstance->Handle) {
   1538       break;
   1539     }
   1540     List = List->ForwardLink;
   1541   }
   1542   if (List == &HostBridgeInstance->Head) {
   1543     return EFI_INVALID_PARAMETER;
   1544   }
   1545 
   1546   if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
   1547     return EFI_INVALID_PARAMETER;
   1548   }
   1549 
   1550   return EFI_SUCCESS;
   1551 }
   1552