Home | History | Annotate | Download | only in PciHostBridgeDxe
      1 /** @file
      2 *  Implementation of the Pci Host Bridge Resource Allocation for the Xpress-RICH3 PCIe Root Complex
      3 *
      4 *  Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
      5 *
      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 
     18 EFI_STATUS
     19 PciHbRaNotifyPhase (
     20   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
     21   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE     Phase
     22   )
     23 {
     24   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
     25   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
     26   EFI_STATUS                  Status;
     27   EFI_PHYSICAL_ADDRESS        BaseAddress;
     28   UINT64                      AddrLen;
     29   UINTN                       BitsOfAlignment;
     30 
     31   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
     32 
     33   PCI_TRACE ("PciHbRaNotifyPhase()");
     34 
     35   // Check RootBridge Signature
     36   ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
     37 
     38   // The enumeration cannot be restarted after the process has been further than the first phase
     39   if (Phase == EfiPciHostBridgeBeginEnumeration) {
     40     if (!HostBridgeInstance->CanRestarted) {
     41       return EFI_NOT_READY;
     42     }
     43   } else {
     44     HostBridgeInstance->CanRestarted = FALSE;
     45   }
     46 
     47   switch (Phase) {
     48   case EfiPciHostBridgeBeginEnumeration:
     49     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginEnumeration)");
     50     // Resets the host bridge PCI apertures and internal data structures
     51     Status = HWPciRbInit (HostBridgeInstance->CpuIo);
     52     if (EFI_ERROR (Status)) {
     53       return Status;
     54     }
     55     break;
     56 
     57   case EfiPciHostBridgeBeginBusAllocation:
     58     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginBusAllocation)");
     59     // The bus allocation phase is about to begin
     60     break;
     61 
     62   case EfiPciHostBridgeEndBusAllocation:
     63     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndBusAllocation)");
     64     // The bus allocation and bus programming phase is complete. All the PCI-to-PCI bridges have been given and written back
     65     // a bus number range into their configuration
     66     break;
     67 
     68   case EfiPciHostBridgeBeginResourceAllocation:
     69     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginResourceAllocation)");
     70     // The resource allocation phase is about to begin.
     71     break;
     72 
     73   case EfiPciHostBridgeAllocateResources:
     74     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeAllocateResources)");
     75     // Allocates resources per previously submitted requests for all the PCI root bridges. The resources have been submitted to
     76     // PciHbRaSubmitResources() before.
     77 
     78     RootBridgeInstance = HostBridgeInstance->RootBridge;
     79     if (RootBridgeInstance->ResAlloc[ResTypeIo].Length != 0) {
     80       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeIo].Alignment) + 1;     // Get the number of '1' in Alignment
     81       AddrLen = RootBridgeInstance->ResAlloc[ResTypeIo].Length;
     82 
     83       Status = gDS->AllocateIoSpace (
     84                   EfiGcdAllocateAnySearchBottomUp,
     85                   EfiGcdIoTypeIo,
     86                   BitsOfAlignment,
     87                   AddrLen,
     88                   &BaseAddress,
     89                   HostBridgeInstance->ImageHandle,
     90                   NULL
     91                );
     92       // If error then ResAlloc[n].Base ==0
     93       if (!EFI_ERROR (Status)) {
     94         RootBridgeInstance->ResAlloc[ResTypeIo].Base   = (UINTN)BaseAddress;
     95       }
     96     }
     97 
     98     if (RootBridgeInstance->ResAlloc[ResTypeMem32].Length != 0) {
     99       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem32].Alignment) + 1;  // Get the number of '1' in Alignment
    100       AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem32].Length;
    101 
    102       // Top of the 32bit PCI Memory space
    103       BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
    104 
    105       Status = gDS->AllocateMemorySpace (
    106                   EfiGcdAllocateMaxAddressSearchTopDown,
    107                   EfiGcdMemoryTypeMemoryMappedIo,
    108                   BitsOfAlignment,
    109                   AddrLen,
    110                   &BaseAddress,
    111                   HostBridgeInstance->ImageHandle,
    112                   NULL
    113                );
    114 
    115       // Ensure the allocation is in the 32bit PCI memory space
    116       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
    117         RootBridgeInstance->ResAlloc[ResTypeMem32].Base   = (UINTN)BaseAddress;
    118       }
    119     }
    120     if (RootBridgeInstance->ResAlloc[ResTypePMem32].Length != 0) {
    121       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem32].Alignment) + 1;  // Get the number of '1' in Alignment
    122       AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem32].Length;
    123 
    124       // Top of the 32bit PCI Memory space
    125       BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
    126 
    127       Status = gDS->AllocateMemorySpace (
    128                   EfiGcdAllocateMaxAddressSearchTopDown,
    129                   EfiGcdMemoryTypeMemoryMappedIo,
    130                   BitsOfAlignment,
    131                   AddrLen,
    132                   &BaseAddress,
    133                   HostBridgeInstance->ImageHandle,
    134                   NULL
    135                );
    136 
    137       // Ensure the allocation is in the 32bit PCI memory space
    138       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
    139         RootBridgeInstance->ResAlloc[ResTypePMem32].Base = (UINTN)BaseAddress;
    140       }
    141     }
    142     if (RootBridgeInstance->ResAlloc[ResTypeMem64].Length != 0) {
    143       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem64].Alignment) + 1;  // Get the number of '1' in Alignment
    144       AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem64].Length;
    145 
    146       // Top of the 64bit PCI Memory space
    147       BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
    148 
    149       Status = gDS->AllocateMemorySpace (
    150                   EfiGcdAllocateMaxAddressSearchTopDown,
    151                   EfiGcdMemoryTypeMemoryMappedIo,
    152                   BitsOfAlignment,
    153                   AddrLen,
    154                   &BaseAddress,
    155                   HostBridgeInstance->ImageHandle,
    156                   NULL
    157                );
    158 
    159       // Ensure the allocation is in the 64bit PCI memory space
    160       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
    161         RootBridgeInstance->ResAlloc[ResTypeMem64].Base   = (UINTN)BaseAddress;
    162       }
    163     }
    164     if (RootBridgeInstance->ResAlloc[ResTypePMem64].Length != 0) {
    165       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem64].Alignment) + 1;  //Get the number of '1' in Alignment
    166       AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem64].Length;
    167 
    168       // Top of the 64bit PCI Memory space
    169       BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
    170 
    171       Status = gDS->AllocateMemorySpace (
    172                   EfiGcdAllocateMaxAddressSearchTopDown,
    173                   EfiGcdMemoryTypeMemoryMappedIo,
    174                   BitsOfAlignment,
    175                   AddrLen,
    176                   &BaseAddress,
    177                   HostBridgeInstance->ImageHandle,
    178                   NULL
    179                );
    180 
    181       // Ensure the allocation is in the 64bit PCI memory space
    182       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
    183         RootBridgeInstance->ResAlloc[ResTypePMem64].Base   = (UINTN)BaseAddress;
    184       }
    185     }
    186 
    187     break;
    188 
    189   case EfiPciHostBridgeSetResources:
    190     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeSetResources)");
    191     // Programs the host bridge hardware to decode previously allocated resources (proposed resources)
    192     // for all the PCI root bridges. The PCI bus driver will now program the resources
    193     break;
    194 
    195   case EfiPciHostBridgeFreeResources:
    196     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeFreeResources)");
    197     // Deallocates resources that were previously allocated for all the PCI root bridges and resets the
    198     // I/O and memory apertures to their initial state.*/
    199     break;
    200 
    201   case EfiPciHostBridgeEndResourceAllocation:
    202     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndResourceAllocation)");
    203     break;
    204 
    205   case EfiPciHostBridgeEndEnumeration:
    206     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndEnumeration)");
    207     break;
    208 
    209   default:
    210     DEBUG ((EFI_D_INFO, "PciHbRaNotifyPhase(Phase:%d)\n", Phase));
    211     ASSERT (0);
    212   }
    213 
    214   return EFI_SUCCESS;
    215 }
    216 
    217 /**
    218  * PciHbRaGetNextRootBridge() returns the next root bridge attached to the 'This' PCI Host Bridge.
    219  * As we have only got one PCI Root Bridge in this PCI interface, we return either this root bridge
    220  * if it the first time we call this function (*RootBridgeHandle == NULL) or we return EFI_NOT_FOUND
    221  **/
    222 EFI_STATUS
    223 PciHbRaGetNextRootBridge (
    224   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
    225   IN OUT EFI_HANDLE                                    *RootBridgeHandle
    226   )
    227 {
    228   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
    229 
    230   PCI_TRACE ("PciHbRaGetNextRootBridge()");
    231 
    232   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    233   ASSERT (HostBridgeInstance->RootBridge != NULL);
    234 
    235   //Check RootBridge Signature
    236   ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
    237 
    238   if (*RootBridgeHandle == NULL) {
    239     *RootBridgeHandle = HostBridgeInstance->RootBridge->Handle;
    240     return EFI_SUCCESS;
    241   } else if (*RootBridgeHandle == HostBridgeInstance->RootBridge->Handle) {
    242     return EFI_NOT_FOUND;
    243   } else {
    244     return EFI_INVALID_PARAMETER;
    245   }
    246 }
    247 
    248 /** PciHbRaGetAllocAttributes() returns the resource allocation attributes supported by this PCI Root Bridge.
    249  *  A PCI Root bridge could support these types :
    250  *      - EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM : does not support separate windows for nonprefetchable and prefetchable memory.
    251  *      - EFI_PCI_HOST_BRIDGE_MEM64_DECODE : supports 64-bit memory windows
    252  **/
    253 EFI_STATUS
    254 PciHbRaGetAllocAttributes (
    255   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
    256   IN  EFI_HANDLE                                        RootBridgeHandle,
    257   OUT UINT64                                           *Attributes
    258   )
    259 {
    260   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
    261 
    262   PCI_TRACE ("PciHbRaGetAllocAttributes()");
    263 
    264   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    265 
    266   // Check if the RootBridgeHandle is the one managed by this PCI Host Bridge
    267   ASSERT (HostBridgeInstance->RootBridge != NULL);
    268   if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
    269     return EFI_INVALID_PARAMETER;
    270   }
    271 
    272   *Attributes = HostBridgeInstance->RootBridge->MemAllocAttributes;
    273   return EFI_SUCCESS;
    274 }
    275 
    276 EFI_STATUS
    277 PciHbRaStartBusEnumeration (
    278   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
    279   IN  EFI_HANDLE                                        RootBridgeHandle,
    280   OUT VOID                                            **Configuration
    281   )
    282 {
    283   VOID    *Buffer;
    284   UINT8   *Ptr;
    285   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
    286 
    287   // Fill an ACPI descriptor table with the Bus Number Range. This information will be used by the PCI Bus driver
    288   // to set bus numbers to PCI-to-PCI bridge.
    289   PCI_TRACE ("PciHbRaStartBusEnumeration()");
    290 
    291   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    292 
    293   Buffer = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
    294   if (Buffer == NULL) {
    295     return EFI_OUT_OF_RESOURCES;
    296   }
    297 
    298   Ptr = (UINT8 *)Buffer;
    299 
    300   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;    // QWORD Address space Descriptor
    301   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Len  = 0x2B;    // Length of this descriptor in bytes not including the first two fields
    302   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;  // Resource Type Bus Number Range
    303   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->GenFlag = 0;
    304   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->SpecificFlag = 0;
    305   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrSpaceGranularity = 0;
    306   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin = HostBridgeInstance->RootBridge->BusStart;   // Bus Start
    307   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMax = 0;    // Bus Max
    308   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrTranslationOffset = 0;
    309   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
    310 
    311   Ptr = Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
    312   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
    313   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
    314 
    315   *Configuration = Buffer;
    316   return EFI_SUCCESS;
    317 }
    318 
    319 EFI_STATUS
    320 PciHbRaSetBusNumbers (
    321   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
    322   IN EFI_HANDLE                                         RootBridgeHandle,
    323   IN VOID                                              *Configuration
    324   )
    325 {
    326   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
    327   UINT8                       *Ptr;
    328   UINTN                       BusStart;
    329   UINTN                       BusEnd;
    330   UINTN                       BusLen;
    331 
    332   PCI_TRACE ("PciHbRaSetBusNumbers()");
    333 
    334   Ptr = Configuration;
    335   if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
    336     return EFI_INVALID_PARAMETER;
    337   }
    338 
    339   // Check if the passed ACPI descriptor table define a Bus Number Range
    340   if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
    341     return EFI_INVALID_PARAMETER;
    342   }
    343 
    344   // Check if the Configuration only passed one ACPI Descriptor (+ End Descriptor)
    345   if (*((UINT8*)(Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR))) != ACPI_END_TAG_DESCRIPTOR) {
    346     return EFI_INVALID_PARAMETER;
    347   }
    348 
    349   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    350   ASSERT (HostBridgeInstance->RootBridge != NULL);
    351   if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
    352     return EFI_INVALID_PARAMETER;
    353   }
    354 
    355   BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
    356   BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
    357   BusEnd = BusStart + BusLen - 1;
    358 
    359   ASSERT (BusStart <= BusEnd); // We should at least have PCI_BUS_ROOT and PCI_SWITCH_BUS
    360   ASSERT ((BusStart >= HostBridgeInstance->RootBridge->BusStart) && (BusLen <= HostBridgeInstance->RootBridge->BusLength));
    361 
    362   HostBridgeInstance->RootBridge->BusStart  = BusStart;
    363   HostBridgeInstance->RootBridge->BusLength = BusLen;
    364 
    365   return EFI_SUCCESS;
    366 }
    367 
    368 /**
    369  * This function is used to submit all the I/O and memory resources that are required by the specified
    370  * PCI root bridge.
    371  **/
    372 EFI_STATUS
    373 PciHbRaSubmitResources (
    374   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
    375   IN EFI_HANDLE                                         RootBridgeHandle,
    376   IN VOID                                              *Configuration
    377   )
    378 {
    379   PCI_HOST_BRIDGE_INSTANCE            *HostBridgeInstance;
    380   PCI_ROOT_BRIDGE_INSTANCE            *RootBridgeInstance;
    381   UINT8                               *Ptr;
    382   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
    383   PCI_RESOURCE_TYPE                   ResType;
    384 
    385   PCI_TRACE ("PciHbRaSubmitResources()");
    386 
    387   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    388 
    389   if (Configuration == NULL) {
    390     return EFI_INVALID_PARAMETER;
    391   }
    392 
    393   // Check if the ACPI Descriptor tables is conformed
    394   Ptr = (UINT8 *)Configuration;
    395   while (*Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // QWORD Address Space descriptor
    396     Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
    397   }
    398   if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { // End tag
    399     return EFI_INVALID_PARAMETER;
    400   }
    401 
    402   // Check the RootBridgeHandle
    403   RootBridgeInstance = HostBridgeInstance->RootBridge;
    404   ASSERT (RootBridgeInstance != NULL);
    405   if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
    406     return EFI_INVALID_PARAMETER;
    407   }
    408 
    409   Ptr = (UINT8 *)Configuration;
    410   while ( *Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // While the entry is an ACPI Descriptor Table
    411     Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
    412 
    413     // Check if the description is valid
    414     if (Desc->AddrLen > 0xffffffff) {
    415       return EFI_INVALID_PARAMETER;
    416     }
    417 
    418     if ((Desc->AddrRangeMax >= 0xffffffff) || (Desc->AddrRangeMax != (GetPowerOfTwo64 (Desc->AddrRangeMax + 1) - 1))) {
    419       return EFI_INVALID_PARAMETER;
    420     }
    421 
    422     switch (Desc->ResType) {
    423     case ACPI_ADDRESS_SPACE_TYPE_MEM:
    424       // Check invalid Address Space Granularity
    425       if ((Desc->AddrSpaceGranularity != 32) && (Desc->AddrSpaceGranularity != 64)) {
    426         return EFI_INVALID_PARAMETER;
    427       }
    428 
    429       // check the memory resource request is supported by PCI root bridge
    430       if (RootBridgeInstance->MemAllocAttributes == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Desc->SpecificFlag == 0x06) {
    431         return EFI_INVALID_PARAMETER;
    432       }
    433 
    434       if (Desc->AddrSpaceGranularity == 32) {
    435         if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
    436           ResType = ResTypePMem32;
    437         } else {
    438           ResType = ResTypeMem32;
    439         }
    440       } else {
    441         if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
    442           ResType = ResTypePMem64;
    443         } else {
    444           ResType = ResTypeMem64;
    445         }
    446       }
    447       RootBridgeInstance->ResAlloc[ResType].Length = Desc->AddrLen;
    448       RootBridgeInstance->ResAlloc[ResType].Alignment = Desc->AddrRangeMax;
    449       RootBridgeInstance->ResAlloc[ResType].Base = Desc->AddrRangeMin;
    450       break;
    451     case ACPI_ADDRESS_SPACE_TYPE_IO:
    452       RootBridgeInstance->ResAlloc[ResTypeIo].Length = Desc->AddrLen;
    453       RootBridgeInstance->ResAlloc[ResTypeIo].Alignment = Desc->AddrRangeMax;
    454       RootBridgeInstance->ResAlloc[ResTypeIo].Base = 0;
    455       break;
    456     default:
    457       ASSERT (0); // Could be the case Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS
    458       break;
    459     }
    460     Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
    461   }
    462 
    463   return EFI_SUCCESS;
    464 }
    465 
    466 /** Returns the proposed resource settings for the specified PCI root bridge. The resources have been submitted by
    467   * PciHbRaSubmitResources() before
    468   **/
    469 EFI_STATUS
    470 PciHbRaGetProposedResources (
    471   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
    472   IN  EFI_HANDLE                                        RootBridgeHandle,
    473   OUT VOID                                            **Configuration
    474   )
    475 {
    476   PCI_HOST_BRIDGE_INSTANCE            *HostBridgeInstance;
    477   PCI_ROOT_BRIDGE_INSTANCE            *RootBridgeInstance;
    478   UINT32                              i;
    479   UINT32                              ResAllocCount;
    480   VOID                                *Buffer;
    481   UINT8                               *Ptr;
    482   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
    483 
    484   PCI_TRACE ("PciHbRaGetProposedResources()");
    485 
    486   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    487 
    488   // Check the RootBridgeHandle
    489   RootBridgeInstance = HostBridgeInstance->RootBridge;
    490   ASSERT (RootBridgeInstance != NULL);
    491   if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
    492     return EFI_INVALID_PARAMETER;
    493   }
    494 
    495   // Count the number of Resource Allocated for this Root Bridge
    496   ResAllocCount = 0;
    497   for (i = 0; i < ResTypeMax; i++) {
    498     if (RootBridgeInstance->ResAlloc[i].Length != 0)  ResAllocCount++;
    499   }
    500 
    501   if (ResAllocCount ==  0) {
    502     return EFI_INVALID_PARAMETER;
    503   }
    504 
    505   Buffer = AllocateZeroPool (ResAllocCount * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
    506   if (Buffer == NULL) {
    507     return EFI_OUT_OF_RESOURCES;
    508   }
    509 
    510   Ptr = Buffer;
    511   for (i = 0; i < ResTypeMax; i++) {
    512     if (RootBridgeInstance->ResAlloc[i].Length != 0) {    // Base != 0 if the resource has been allocated
    513       Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
    514 
    515       Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
    516       Desc->Len  = 0x2B;
    517       Desc->GenFlag = 0;
    518       Desc->AddrRangeMax = 0;
    519 
    520       switch (i) {
    521       case ResTypeIo:
    522         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
    523         Desc->SpecificFlag = 0;
    524         Desc->AddrSpaceGranularity = 0;
    525         break;
    526       case ResTypeMem32:
    527         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
    528         Desc->SpecificFlag = 0;
    529         Desc->AddrSpaceGranularity = 32;
    530         break;
    531       case ResTypePMem32:
    532         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
    533         Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
    534         Desc->AddrSpaceGranularity = 32;
    535         break;
    536       case ResTypeMem64:
    537         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
    538         Desc->SpecificFlag = 0;
    539         Desc->AddrSpaceGranularity = 64;
    540         break;
    541       case ResTypePMem64:
    542         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
    543         Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
    544         Desc->AddrSpaceGranularity = 64;
    545         break;
    546       }
    547       Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
    548       Desc->AddrTranslationOffset = (RootBridgeInstance->ResAlloc[i].Base != 0) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
    549       Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
    550       Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
    551     }
    552   }
    553 
    554   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
    555   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
    556 
    557   *Configuration = Buffer;
    558   return EFI_SUCCESS;
    559 }
    560 
    561 EFI_STATUS
    562 PciHbRaPreprocessController (
    563   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
    564   IN  EFI_HANDLE                                        RootBridgeHandle,
    565   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       PciAddress,
    566   IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE      Phase
    567   )
    568 {
    569   PCI_HOST_BRIDGE_INSTANCE*   HostBridge;
    570   PCI_ROOT_BRIDGE_INSTANCE*   RootBridge;
    571   UINT32                      CapabilityPtr;
    572   UINT32                      CapabilityEntry;
    573   UINT16                      CapabilityID;
    574   UINT32                      DeviceCapability;
    575 
    576   PCI_TRACE ("PciHbRaPreprocessController()");
    577 
    578   if (FeaturePcdGet (PcdPciMaxPayloadFixup)) {
    579     // Do Max payload fixup for every devices
    580     if (Phase == EfiPciBeforeResourceCollection) {
    581       // Get RootBridge Instance from Host Bridge Instance
    582       HostBridge = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
    583       RootBridge = HostBridge->RootBridge;
    584 
    585       // Get the first PCI Capability
    586       CapabilityPtr = PCI_CAPBILITY_POINTER_OFFSET;
    587       RootBridge->Io.Pci.Read (
    588           &RootBridge->Io,
    589           EfiPciWidthUint8,
    590           EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
    591           1,
    592           &CapabilityPtr
    593       );
    594       CapabilityPtr &= 0x1FF;
    595 
    596       // Get Pci Express Capability
    597       while (CapabilityPtr != 0) {
    598         RootBridge->Io.Pci.Read (
    599             &RootBridge->Io,
    600             EfiPciWidthUint16,
    601             EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
    602             1,
    603             &CapabilityEntry
    604             );
    605 
    606         CapabilityID = (UINT8)CapabilityEntry;
    607 
    608         // Is PCIe capability ?
    609         if (CapabilityID == EFI_PCI_CAPABILITY_ID_PCIEXP) {
    610           // Get PCIe Device Capabilities
    611           RootBridge->Io.Pci.Read (
    612               &RootBridge->Io,
    613               EfiPciWidthUint32,
    614               EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
    615               1,
    616               &DeviceCapability
    617               );
    618 
    619           // Force the Max Payload to 128 Bytes (128 Bytes Max Payload Size = 0)
    620           DeviceCapability &= ~ ((UINT32)(0x7 << 5 ));
    621           // Max Read Request Size to 128 Bytes (128 Bytes Max Read Request Size = 0)
    622           DeviceCapability &= ~ ((UINT32)(0x7 << 12));
    623           // Enable all error reporting
    624           DeviceCapability |= 0xF;
    625 
    626           RootBridge->Io.Pci.Write (
    627               &RootBridge->Io,
    628               EfiPciWidthUint32,
    629               EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
    630               1,
    631               &DeviceCapability
    632               );
    633 
    634           return EFI_SUCCESS;
    635         }
    636         CapabilityPtr = (CapabilityEntry >> 8) & 0xFF;
    637       }
    638     }
    639   }
    640 
    641   return EFI_SUCCESS;
    642 }
    643