Home | History | Annotate | Download | only in PciHostBridgeDxe
      1 /** @file
      2 *  Implementation of the PCI Root Bridge Protocol for 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 #include <Library/DevicePathLib.h>
     19 #include <Library/DmaLib.h>
     20 
     21 #define CPUIO_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->CpuIo)
     22 #define METRONOME_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->Metronome)
     23 
     24 /**
     25  * PCI Root Bridge Instance Templates
     26  */
     27 STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH  gDevicePathTemplate = {
     28     {
     29       { ACPI_DEVICE_PATH,
     30         ACPI_DP,
     31         { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
     32           (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }
     33       },
     34       EISA_PNP_ID (0x0A03),
     35       0
     36     },
     37     {
     38       END_DEVICE_PATH_TYPE,
     39       END_ENTIRE_DEVICE_PATH_SUBTYPE,
     40       { END_DEVICE_PATH_LENGTH, 0 }
     41     }
     42 };
     43 
     44 STATIC CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL gIoTemplate = {
     45     0,
     46     PciRbPollMem,
     47     PciRbPollIo,
     48     {
     49       PciRbMemRead,
     50       PciRbMemWrite
     51     },
     52     {
     53       PciRbIoRead,
     54       PciRbIoWrite
     55     },
     56     {
     57       PciRbPciRead,
     58       PciRbPciWrite
     59     },
     60     PciRbCopyMem,
     61     PciRbMap,
     62     PciRbUnMap,
     63     PciRbAllocateBuffer,
     64     PciRbFreeBuffer,
     65     PciRbFlush,
     66     PciRbGetAttributes,
     67     PciRbSetAttributes,
     68     PciRbConfiguration,
     69     0
     70   };
     71 
     72 typedef struct {
     73     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     SpaceDesp[ResTypeMax+1];
     74     EFI_ACPI_END_TAG_DESCRIPTOR           EndDesp;
     75 } RESOURCE_CONFIGURATION;
     76 
     77 
     78 RESOURCE_CONFIGURATION Configuration = {
     79    {{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_IO , 0, 0, 0, 0, 0, 0, 0},
     80     {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 32, 0, 0, 0, 0},
     81     {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 32, 0, 0, 0, 0},
     82     {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 64, 0, 0, 0, 0},
     83     {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 64, 0, 0, 0, 0},
     84     {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_BUS, 0, 0, 0, 0, 255, 0, 255}},
     85     {ACPI_END_TAG_DESCRIPTOR, 0}
     86 };
     87 
     88 
     89 EFI_STATUS
     90 PciRbPollMem (
     91   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
     92   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
     93   IN  UINT64                                   Address,
     94   IN  UINT64                                   Mask,
     95   IN  UINT64                                   Value,
     96   IN  UINT64                                   Delay,
     97   OUT UINT64                                   *Result
     98   )
     99 {
    100   EFI_STATUS                      Status;
    101   UINT64                          NumberOfTicks;
    102   UINT32                          Remainder;
    103   PCI_ROOT_BRIDGE_INSTANCE        *RootBridgeInstance;
    104   EFI_METRONOME_ARCH_PROTOCOL     *Metronome;
    105 
    106   PCI_TRACE ("PciRbPollMem()");
    107 
    108   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    109   Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
    110 
    111   if (Result == NULL) {
    112     return EFI_INVALID_PARAMETER;
    113   }
    114 
    115   if (Width > EfiPciWidthUint64) {
    116     return EFI_INVALID_PARAMETER;
    117   }
    118 
    119   // No matter what, always do a single poll.
    120   Status = This->Mem.Read (This, Width, Address, 1, Result);
    121   if (EFI_ERROR (Status)) {
    122     return Status;
    123   }
    124   if ((*Result & Mask) == Value) {
    125     return EFI_SUCCESS;
    126   }
    127 
    128   if (Delay == 0) {
    129     return EFI_SUCCESS;
    130   }
    131 
    132   NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
    133   if (Remainder != 0) {
    134     NumberOfTicks += 1;
    135   }
    136   NumberOfTicks += 1;
    137 
    138   while (NumberOfTicks) {
    139     Metronome->WaitForTick (Metronome, 1);
    140 
    141     Status = This->Mem.Read (This, Width, Address, 1, Result);
    142     if (EFI_ERROR (Status)) {
    143       return Status;
    144     }
    145 
    146     if ((*Result & Mask) == Value) {
    147       return EFI_SUCCESS;
    148     }
    149 
    150     NumberOfTicks -= 1;
    151   }
    152 
    153   return EFI_TIMEOUT;
    154 }
    155 
    156 EFI_STATUS
    157 PciRbPollIo (
    158   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
    159   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    160   IN  UINT64                                   Address,
    161   IN  UINT64                                   Mask,
    162   IN  UINT64                                   Value,
    163   IN  UINT64                                   Delay,
    164   OUT UINT64                                   *Result
    165   )
    166 {
    167   EFI_STATUS                      Status;
    168   UINT64                          NumberOfTicks;
    169   UINT32                          Remainder;
    170   PCI_ROOT_BRIDGE_INSTANCE        *RootBridgeInstance;
    171   EFI_METRONOME_ARCH_PROTOCOL     *Metronome;
    172 
    173   PCI_TRACE ("PciRbPollIo()");
    174 
    175   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    176   Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
    177 
    178   if (Result == NULL) {
    179     return EFI_INVALID_PARAMETER;
    180   }
    181 
    182   if (Width > EfiPciWidthUint64) {
    183     return EFI_INVALID_PARAMETER;
    184   }
    185 
    186   // No matter what, always do a single poll.
    187   Status = This->Io.Read (This, Width, Address, 1, Result);
    188   if (EFI_ERROR (Status)) {
    189     return Status;
    190   }
    191   if ((*Result & Mask) == Value) {
    192     return EFI_SUCCESS;
    193   }
    194 
    195   if (Delay == 0) {
    196     return EFI_SUCCESS;
    197   }
    198 
    199   NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
    200   if (Remainder != 0) {
    201     NumberOfTicks += 1;
    202   }
    203   NumberOfTicks += 1;
    204 
    205   while (NumberOfTicks) {
    206     Metronome->WaitForTick (Metronome, 1);
    207 
    208     Status = This->Io.Read (This, Width, Address, 1, Result);
    209     if (EFI_ERROR (Status)) {
    210         return Status;
    211     }
    212 
    213     if ((*Result & Mask) == Value) {
    214         return EFI_SUCCESS;
    215     }
    216 
    217     NumberOfTicks -= 1;
    218   }
    219 
    220   return EFI_TIMEOUT;
    221 }
    222 
    223 EFI_STATUS
    224 PciRbMemRead (
    225   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    226   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    227   IN     UINT64                                   Address,
    228   IN     UINTN                                    Count,
    229   IN OUT VOID                                     *Buffer
    230   )
    231 {
    232   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
    233   EFI_CPU_IO2_PROTOCOL        *CpuIo;
    234 
    235   PCI_TRACE ("PciRbMemRead()");
    236 
    237   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    238   CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
    239 
    240   if (Buffer == NULL) {
    241     return EFI_INVALID_PARAMETER;
    242   }
    243 
    244   if (Width >= EfiPciWidthMaximum) {
    245     return EFI_INVALID_PARAMETER;
    246   }
    247 
    248   if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
    249       ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
    250     return EFI_INVALID_PARAMETER;
    251   }
    252 
    253   return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
    254 }
    255 
    256 EFI_STATUS
    257 PciRbMemWrite (
    258   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    259   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    260   IN     UINT64                                   Address,
    261   IN     UINTN                                    Count,
    262   IN OUT VOID                                     *Buffer
    263   )
    264 {
    265   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
    266   EFI_CPU_IO2_PROTOCOL        *CpuIo;
    267 
    268   PCI_TRACE ("PciRbMemWrite()");
    269 
    270   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    271   CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
    272 
    273   if (Buffer == NULL) {
    274     return EFI_INVALID_PARAMETER;
    275   }
    276 
    277   if (Width >= EfiPciWidthMaximum) {
    278     return EFI_INVALID_PARAMETER;
    279   }
    280 
    281   if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
    282       ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
    283     return EFI_INVALID_PARAMETER;
    284   }
    285 
    286   return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
    287 }
    288 
    289 EFI_STATUS
    290 PciRbIoRead (
    291   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    292   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    293   IN     UINT64                                   Address,
    294   IN     UINTN                                    Count,
    295   IN OUT VOID                                     *Buffer
    296   )
    297 {
    298   PCI_TRACE ("PciRbIoRead()");
    299 
    300   if (Buffer == NULL) {
    301     return EFI_INVALID_PARAMETER;
    302   }
    303 
    304   if (Width >= EfiPciWidthMaximum) {
    305     return EFI_INVALID_PARAMETER;
    306   }
    307 
    308   // IO currently unsupported
    309   return EFI_INVALID_PARAMETER;
    310 }
    311 
    312 EFI_STATUS
    313 PciRbIoWrite (
    314   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    315   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    316   IN     UINT64                                   Address,
    317   IN     UINTN                                    Count,
    318   IN OUT VOID                                     *Buffer
    319   )
    320 {
    321   PCI_TRACE ("PciRbIoWrite()");
    322 
    323   if (Buffer == NULL) {
    324     return EFI_INVALID_PARAMETER;
    325   }
    326 
    327   if (Width >= EfiPciWidthMaximum) {
    328     return EFI_INVALID_PARAMETER;
    329   }
    330 
    331   // IO currently unsupported
    332   return EFI_INVALID_PARAMETER;
    333 }
    334 
    335 EFI_STATUS
    336 PciRbPciRead (
    337   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    338   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    339   IN     UINT64                                   EfiAddress,
    340   IN     UINTN                                    Count,
    341   IN OUT VOID                                     *Buffer
    342   )
    343 {
    344   UINT32                      Offset;
    345   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
    346   EFI_CPU_IO2_PROTOCOL        *CpuIo;
    347   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
    348   UINT64                      Address;
    349 
    350   EfiPciAddress  = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
    351   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    352   CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
    353 
    354   if (Buffer == NULL) {
    355     return EFI_INVALID_PARAMETER;
    356   }
    357 
    358   if (Width >= EfiPciWidthMaximum) {
    359     return EFI_INVALID_PARAMETER;
    360   }
    361 
    362   if (EfiPciAddress->ExtendedRegister) {
    363     Offset = EfiPciAddress->ExtendedRegister;
    364   } else {
    365     Offset = EfiPciAddress->Register;
    366   }
    367 
    368   // The UEFI PCI enumerator scans for devices at all possible addresses,
    369   // and ignores some PCI rules - this results in some hardware being
    370   // detected multiple times. We work around this by faking absent
    371   // devices
    372   if ((EfiPciAddress->Bus == 0) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
    373     *((UINT32 *)Buffer) = 0xffffffff;
    374     return EFI_SUCCESS;
    375   }
    376   if ((EfiPciAddress->Bus == 1) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
    377     *((UINT32 *)Buffer) = 0xffffffff;
    378     return EFI_SUCCESS;
    379   }
    380 
    381   // Work around incorrect class ID in the root bridge
    382   if ((EfiPciAddress->Bus == 0) && (EfiPciAddress->Device == 0) && (EfiPciAddress->Function == 0) && (Offset == 8)) {
    383     *((UINT32 *)Buffer) = 0x06040001;
    384     return EFI_SUCCESS;
    385    }
    386 
    387   Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
    388                          (EfiPciAddress->Device << 15) |
    389                          (EfiPciAddress->Function << 12) | Offset);
    390 
    391   if ((Address < PCI_ECAM_BASE) || (Address > PCI_ECAM_BASE + PCI_ECAM_SIZE)) {
    392     return EFI_INVALID_PARAMETER;
    393   }
    394 
    395   return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
    396 }
    397 
    398 EFI_STATUS
    399 PciRbPciWrite (
    400   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    401   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    402   IN     UINT64                                   EfiAddress,
    403   IN     UINTN                                    Count,
    404   IN OUT VOID                                     *Buffer
    405   )
    406 {
    407   UINT32                      Offset;
    408   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
    409   EFI_CPU_IO2_PROTOCOL        *CpuIo;
    410   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
    411   UINT64                      Address;
    412 
    413   EfiPciAddress  = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
    414   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    415   CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
    416 
    417   if (Buffer == NULL) {
    418     return EFI_INVALID_PARAMETER;
    419   }
    420 
    421   if (Width >= EfiPciWidthMaximum) {
    422     return EFI_INVALID_PARAMETER;
    423   }
    424 
    425   if (EfiPciAddress->ExtendedRegister)
    426     Offset = EfiPciAddress->ExtendedRegister;
    427   else
    428     Offset = EfiPciAddress->Register;
    429 
    430   Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
    431                          (EfiPciAddress->Device << 15) |
    432                          (EfiPciAddress->Function << 12) | Offset);
    433 
    434   if (Address < PCI_ECAM_BASE || Address > PCI_ECAM_BASE + PCI_ECAM_SIZE) {
    435     return EFI_INVALID_PARAMETER;
    436   }
    437 
    438   return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
    439 }
    440 
    441 EFI_STATUS
    442 PciRbCopyMem (
    443   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    444   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
    445   IN     UINT64                                   DestAddress,
    446   IN     UINT64                                   SrcAddress,
    447   IN     UINTN                                    Count
    448   )
    449 {
    450   EFI_STATUS  Status;
    451   BOOLEAN     Direction;
    452   UINTN       Stride;
    453   UINTN       Index;
    454   UINT64      Result;
    455 
    456   PCI_TRACE ("PciRbCopyMem()");
    457 
    458   if (Width > EfiPciWidthUint64) {
    459     return EFI_INVALID_PARAMETER;
    460   }
    461 
    462   if (DestAddress == SrcAddress) {
    463     return EFI_SUCCESS;
    464   }
    465 
    466   Stride = (UINTN)(1 << Width);
    467 
    468   Direction = TRUE;
    469   if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
    470     Direction   = FALSE;
    471     SrcAddress  = SrcAddress  + (Count-1) * Stride;
    472     DestAddress = DestAddress + (Count-1) * Stride;
    473   }
    474 
    475   for (Index = 0; Index < Count; Index++) {
    476     Status = PciRbMemRead (
    477                This,
    478                Width,
    479                SrcAddress,
    480                1,
    481                &Result
    482                );
    483     if (EFI_ERROR (Status)) {
    484       return Status;
    485     }
    486     Status = PciRbMemWrite (
    487                This,
    488                Width,
    489                DestAddress,
    490                1,
    491                &Result
    492                );
    493     if (EFI_ERROR (Status)) {
    494       return Status;
    495     }
    496     if (Direction) {
    497       SrcAddress  += Stride;
    498       DestAddress += Stride;
    499     } else {
    500       SrcAddress  -= Stride;
    501       DestAddress -= Stride;
    502     }
    503   }
    504   return EFI_SUCCESS;
    505 }
    506 
    507 EFI_STATUS
    508 PciRbMap (
    509   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                *This,
    510   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
    511   IN     VOID                                       *HostAddress,
    512   IN OUT UINTN                                      *NumberOfBytes,
    513   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
    514   OUT    VOID                                       **Mapping
    515   )
    516 {
    517   DMA_MAP_OPERATION   DmaOperation;
    518 
    519   PCI_TRACE ("PciRbMap()");
    520 
    521   if (Operation == EfiPciOperationBusMasterRead ||
    522       Operation == EfiPciOperationBusMasterRead64) {
    523     DmaOperation = MapOperationBusMasterRead;
    524   } else if (Operation == EfiPciOperationBusMasterWrite ||
    525              Operation == EfiPciOperationBusMasterWrite64) {
    526     DmaOperation = MapOperationBusMasterWrite;
    527   } else if (Operation == EfiPciOperationBusMasterCommonBuffer ||
    528              Operation == EfiPciOperationBusMasterCommonBuffer64) {
    529     DmaOperation = MapOperationBusMasterCommonBuffer;
    530   } else {
    531     return EFI_INVALID_PARAMETER;
    532   }
    533   return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
    534 }
    535 
    536 EFI_STATUS
    537 PciRbUnMap (
    538   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
    539   IN  VOID                                     *Mapping
    540   )
    541 {
    542   PCI_TRACE ("PciRbUnMap()");
    543   return DmaUnmap (Mapping);
    544 }
    545 
    546 EFI_STATUS
    547 PciRbAllocateBuffer (
    548   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    549   IN     EFI_ALLOCATE_TYPE                        Type,
    550   IN     EFI_MEMORY_TYPE                          MemoryType,
    551   IN     UINTN                                    Pages,
    552   IN OUT VOID                                     **HostAddress,
    553   IN     UINT64                                   Attributes
    554   )
    555 {
    556   PCI_TRACE ("PciRbAllocateBuffer()");
    557 
    558   if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
    559     return EFI_UNSUPPORTED;
    560   }
    561 
    562   return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
    563 }
    564 
    565 EFI_STATUS
    566 PciRbFreeBuffer (
    567   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
    568   IN  UINTN                                    Pages,
    569   IN  VOID                                     *HostAddress
    570   )
    571 {
    572   PCI_TRACE ("PciRbFreeBuffer()");
    573   return DmaFreeBuffer (Pages, HostAddress);
    574 }
    575 
    576 EFI_STATUS
    577 PciRbFlush (
    578   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
    579   )
    580 {
    581   PCI_TRACE ("PciRbFlush()");
    582 
    583   //TODO: Not supported yet
    584 
    585   return EFI_SUCCESS;
    586 }
    587 
    588 EFI_STATUS
    589 PciRbSetAttributes (
    590   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
    591   IN     UINT64                                   Attributes,
    592   IN OUT UINT64                                   *ResourceBase,
    593   IN OUT UINT64                                   *ResourceLength
    594   )
    595 {
    596   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
    597 
    598   PCI_TRACE ("PciRbSetAttributes()");
    599 
    600   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    601 
    602   if (Attributes) {
    603     if ((Attributes & (~(RootBridgeInstance->Supports))) != 0) {
    604       return EFI_UNSUPPORTED;
    605     }
    606   }
    607 
    608   //TODO: Cannot allowed to change attributes
    609   if (Attributes & ~RootBridgeInstance->Attributes) {
    610     return EFI_UNSUPPORTED;
    611   }
    612 
    613   return EFI_SUCCESS;
    614 }
    615 
    616 EFI_STATUS
    617 PciRbGetAttributes (
    618   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
    619   OUT UINT64                                   *Supported,
    620   OUT UINT64                                   *Attributes
    621   )
    622 {
    623   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
    624 
    625   PCI_TRACE ("PciRbGetAttributes()");
    626 
    627   RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    628 
    629   if (Attributes == NULL && Supported == NULL) {
    630     return EFI_INVALID_PARAMETER;
    631   }
    632 
    633   // Set the return value for Supported and Attributes
    634   if (Supported) {
    635     *Supported  = RootBridgeInstance->Supports;
    636   }
    637 
    638   if (Attributes) {
    639     *Attributes = RootBridgeInstance->Attributes;
    640   }
    641 
    642   return EFI_SUCCESS;
    643 }
    644 
    645 EFI_STATUS
    646 PciRbConfiguration (
    647   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
    648   OUT VOID                                     **Resources
    649   )
    650 {
    651   PCI_ROOT_BRIDGE_INSTANCE              *RootBridge;
    652   UINTN                                 Index;
    653 
    654   PCI_TRACE ("PciRbConfiguration()");
    655 
    656   RootBridge = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
    657 
    658   for (Index = 0; Index < ResTypeMax; Index++) {
    659     //if (ResAlloc[Index].Length != 0) => Resource allocated
    660     if (RootBridge->ResAlloc[Index].Length != 0) {
    661       Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base;
    662       Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1;
    663       Configuration.SpaceDesp[Index].AddrLen      = RootBridge->ResAlloc[Index].Length;
    664     }
    665   }
    666 
    667   // Set up Configuration for the bus
    668   Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart;
    669   Configuration.SpaceDesp[Index].AddrLen      = RootBridge->BusLength;
    670 
    671   *Resources = &Configuration;
    672   return EFI_SUCCESS;
    673 }
    674 
    675 EFI_STATUS
    676 PciRbConstructor (
    677   IN  PCI_HOST_BRIDGE_INSTANCE *HostBridge,
    678   IN  UINT32 PciAcpiUid,
    679   IN  UINT64 MemAllocAttributes
    680   )
    681 {
    682   PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
    683   EFI_STATUS Status;
    684 
    685   PCI_TRACE ("PciRbConstructor()");
    686 
    687   // Allocate Memory for the Instance from a Template
    688   RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
    689   if (RootBridge == NULL) {
    690     PCI_TRACE ("PciRbConstructor(): ERROR: Out of Resources");
    691     return EFI_OUT_OF_RESOURCES;
    692   }
    693   RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
    694   CopyMem (&(RootBridge->DevicePath), &gDevicePathTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH));
    695   CopyMem (&(RootBridge->Io), &gIoTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));
    696 
    697   // Set Parent Handle
    698   RootBridge->Io.ParentHandle = HostBridge->Handle;
    699 
    700   // Attach the Root Bridge to the PCI Host Bridge Instance
    701   RootBridge->HostBridge = HostBridge;
    702 
    703   // Set Device Path for this Root Bridge
    704   RootBridge->DevicePath.Acpi.UID = PciAcpiUid;
    705 
    706   RootBridge->BusStart  = FixedPcdGet32 (PcdPciBusMin);
    707   RootBridge->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
    708 
    709   // PCI Attributes
    710   RootBridge->Supports = 0;
    711   RootBridge->Attributes = 0;
    712 
    713   // Install Protocol Instances. It will also generate a device handle for the PCI Root Bridge
    714   Status = gBS->InstallMultipleProtocolInterfaces (
    715                       &RootBridge->Handle,
    716                       &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
    717                       &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
    718                       NULL
    719                       );
    720   ASSERT (RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
    721   if (EFI_ERROR (Status)) {
    722     PCI_TRACE ("PciRbConstructor(): ERROR: Fail to install Protocol Interfaces");
    723     FreePool (RootBridge);
    724     return EFI_DEVICE_ERROR;
    725   }
    726 
    727   HostBridge->RootBridge = RootBridge;
    728   return EFI_SUCCESS;
    729 }
    730 
    731 EFI_STATUS
    732 PciRbDestructor (
    733   IN  PCI_ROOT_BRIDGE_INSTANCE* RootBridge
    734   )
    735 {
    736   EFI_STATUS Status;
    737 
    738   Status = gBS->UninstallMultipleProtocolInterfaces (
    739                         RootBridge->Handle,
    740                         &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
    741                         &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
    742                         NULL
    743                         );
    744 
    745   FreePool (RootBridge);
    746 
    747   return Status;
    748 }
    749