Home | History | Annotate | Download | only in PciHostBridgeLib
      1 /** @file
      2   OVMF's instance of the PCI Host Bridge Library.
      3 
      4   Copyright (C) 2016, Red Hat, Inc.
      5   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
      6 
      7   This program and the accompanying materials are licensed and made available
      8   under the terms and conditions of the BSD License which accompanies this
      9   distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php.
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
     13   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 #include <PiDxe.h>
     17 
     18 #include <IndustryStandard/Pci.h>
     19 #include <IndustryStandard/Q35MchIch9.h>
     20 
     21 #include <Protocol/PciHostBridgeResourceAllocation.h>
     22 #include <Protocol/PciRootBridgeIo.h>
     23 
     24 #include <Library/BaseMemoryLib.h>
     25 #include <Library/DebugLib.h>
     26 #include <Library/DevicePathLib.h>
     27 #include <Library/MemoryAllocationLib.h>
     28 #include <Library/PciHostBridgeLib.h>
     29 #include <Library/PciLib.h>
     30 #include <Library/QemuFwCfgLib.h>
     31 #include "PciHostBridge.h"
     32 
     33 
     34 #pragma pack(1)
     35 typedef struct {
     36   ACPI_HID_DEVICE_PATH     AcpiDevicePath;
     37   EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
     38 } OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
     39 #pragma pack ()
     40 
     41 
     42 GLOBAL_REMOVE_IF_UNREFERENCED
     43 CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
     44   L"Mem", L"I/O", L"Bus"
     45 };
     46 
     47 
     48 STATIC
     49 CONST
     50 OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
     51   {
     52     {
     53       ACPI_DEVICE_PATH,
     54       ACPI_DP,
     55       {
     56         (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
     57         (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
     58       }
     59     },
     60     EISA_PNP_ID(0x0A03), // HID
     61     0                    // UID
     62   },
     63 
     64   {
     65     END_DEVICE_PATH_TYPE,
     66     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     67     {
     68       END_DEVICE_PATH_LENGTH,
     69       0
     70     }
     71   }
     72 };
     73 
     74 STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
     75 
     76 /**
     77   Initialize a PCI_ROOT_BRIDGE structure.
     78 
     79   @param[in]  Supports         Supported attributes.
     80 
     81   @param[in]  Attributes       Initial attributes.
     82 
     83   @param[in]  AllocAttributes  Allocation attributes.
     84 
     85   @param[in]  RootBusNumber    The bus number to store in RootBus.
     86 
     87   @param[in]  MaxSubBusNumber  The inclusive maximum bus number that can be
     88                                assigned to any subordinate bus found behind any
     89                                PCI bridge hanging off this root bus.
     90 
     91                                The caller is repsonsible for ensuring that
     92                                RootBusNumber <= MaxSubBusNumber. If
     93                                RootBusNumber equals MaxSubBusNumber, then the
     94                                root bus has no room for subordinate buses.
     95 
     96   @param[in]  Io               IO aperture.
     97 
     98   @param[in]  Mem              MMIO aperture.
     99 
    100   @param[in]  MemAbove4G       MMIO aperture above 4G.
    101 
    102   @param[in]  PMem             Prefetchable MMIO aperture.
    103 
    104   @param[in]  PMemAbove4G      Prefetchable MMIO aperture above 4G.
    105 
    106   @param[out] RootBus          The PCI_ROOT_BRIDGE structure (allocated by the
    107                                caller) that should be filled in by this
    108                                function.
    109 
    110   @retval EFI_SUCCESS           Initialization successful. A device path
    111                                 consisting of an ACPI device path node, with
    112                                 UID = RootBusNumber, has been allocated and
    113                                 linked into RootBus.
    114 
    115   @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
    116 **/
    117 EFI_STATUS
    118 InitRootBridge (
    119   IN  UINT64                   Supports,
    120   IN  UINT64                   Attributes,
    121   IN  UINT64                   AllocAttributes,
    122   IN  UINT8                    RootBusNumber,
    123   IN  UINT8                    MaxSubBusNumber,
    124   IN  PCI_ROOT_BRIDGE_APERTURE *Io,
    125   IN  PCI_ROOT_BRIDGE_APERTURE *Mem,
    126   IN  PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
    127   IN  PCI_ROOT_BRIDGE_APERTURE *PMem,
    128   IN  PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
    129   OUT PCI_ROOT_BRIDGE          *RootBus
    130   )
    131 {
    132   OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
    133 
    134   //
    135   // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
    136   //
    137   ZeroMem (RootBus, sizeof *RootBus);
    138 
    139   RootBus->Segment = 0;
    140 
    141   RootBus->Supports   = Supports;
    142   RootBus->Attributes = Attributes;
    143 
    144   RootBus->DmaAbove4G = FALSE;
    145 
    146   RootBus->AllocationAttributes = AllocAttributes;
    147   RootBus->Bus.Base  = RootBusNumber;
    148   RootBus->Bus.Limit = MaxSubBusNumber;
    149   CopyMem (&RootBus->Io, Io, sizeof (*Io));
    150   CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
    151   CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
    152   CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
    153   CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
    154 
    155   RootBus->NoExtendedConfigSpace = (PcdGet16 (PcdOvmfHostBridgePciDevId) !=
    156                                     INTEL_Q35_MCH_DEVICE_ID);
    157 
    158   DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
    159                  &mRootBridgeDevicePathTemplate);
    160   if (DevicePath == NULL) {
    161     DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
    162     return EFI_OUT_OF_RESOURCES;
    163   }
    164   DevicePath->AcpiDevicePath.UID = RootBusNumber;
    165   RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
    166 
    167   DEBUG ((EFI_D_INFO,
    168     "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
    169     __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
    170   return EFI_SUCCESS;
    171 }
    172 
    173 
    174 /**
    175   Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge().
    176 
    177   param[in] RootBus  The PCI_ROOT_BRIDGE structure, allocated by the caller and
    178                      initialized with InitRootBridge(), that should be
    179                      uninitialized. This function doesn't free RootBus.
    180 **/
    181 STATIC
    182 VOID
    183 UninitRootBridge (
    184   IN PCI_ROOT_BRIDGE *RootBus
    185   )
    186 {
    187   FreePool (RootBus->DevicePath);
    188 }
    189 
    190 
    191 /**
    192   Return all the root bridge instances in an array.
    193 
    194   @param Count  Return the count of root bridge instances.
    195 
    196   @return All the root bridge instances in an array.
    197           The array should be passed into PciHostBridgeFreeRootBridges()
    198           when it's not used.
    199 **/
    200 PCI_ROOT_BRIDGE *
    201 EFIAPI
    202 PciHostBridgeGetRootBridges (
    203   UINTN *Count
    204   )
    205 {
    206   EFI_STATUS           Status;
    207   FIRMWARE_CONFIG_ITEM FwCfgItem;
    208   UINTN                FwCfgSize;
    209   UINT64               ExtraRootBridges;
    210   PCI_ROOT_BRIDGE      *Bridges;
    211   UINTN                Initialized;
    212   UINTN                LastRootBridgeNumber;
    213   UINTN                RootBridgeNumber;
    214   UINT64               Attributes;
    215   UINT64               AllocationAttributes;
    216   PCI_ROOT_BRIDGE_APERTURE Io;
    217   PCI_ROOT_BRIDGE_APERTURE Mem;
    218   PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
    219 
    220   if (PcdGetBool (PcdPciDisableBusEnumeration)) {
    221     return ScanForRootBridges (Count);
    222   }
    223 
    224   Attributes = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
    225     EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
    226     EFI_PCI_ATTRIBUTE_ISA_IO_16 |
    227     EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
    228     EFI_PCI_ATTRIBUTE_VGA_MEMORY |
    229     EFI_PCI_ATTRIBUTE_VGA_IO_16 |
    230     EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
    231 
    232   AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
    233   if (PcdGet64 (PcdPciMmio64Size) > 0) {
    234     AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
    235     MemAbove4G.Base = PcdGet64 (PcdPciMmio64Base);
    236     MemAbove4G.Limit = PcdGet64 (PcdPciMmio64Base) +
    237                        PcdGet64 (PcdPciMmio64Size) - 1;
    238   } else {
    239     CopyMem (&MemAbove4G, &mNonExistAperture, sizeof (mNonExistAperture));
    240   }
    241 
    242   Io.Base = PcdGet64 (PcdPciIoBase);
    243   Io.Limit = PcdGet64 (PcdPciIoBase) + (PcdGet64 (PcdPciIoSize) - 1);
    244   Mem.Base = PcdGet64 (PcdPciMmio32Base);
    245   Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64 (PcdPciMmio32Size) - 1);
    246 
    247   *Count = 0;
    248 
    249   //
    250   // QEMU provides the number of extra root buses, shortening the exhaustive
    251   // search below. If there is no hint, the feature is missing.
    252   //
    253   Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
    254   if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridges) {
    255     ExtraRootBridges = 0;
    256   } else {
    257     QemuFwCfgSelectItem (FwCfgItem);
    258     QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);
    259 
    260     if (ExtraRootBridges > PCI_MAX_BUS) {
    261       DEBUG ((EFI_D_ERROR, "%a: invalid count of extra root buses (%Lu) "
    262         "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));
    263       return NULL;
    264     }
    265     DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
    266       __FUNCTION__, ExtraRootBridges));
    267   }
    268 
    269   //
    270   // Allocate the "main" root bridge, and any extra root bridges.
    271   //
    272   Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);
    273   if (Bridges == NULL) {
    274     DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
    275     return NULL;
    276   }
    277   Initialized = 0;
    278 
    279   //
    280   // The "main" root bus is always there.
    281   //
    282   LastRootBridgeNumber = 0;
    283 
    284   //
    285   // Scan all other root buses. If function 0 of any device on a bus returns a
    286   // VendorId register value different from all-bits-one, then that bus is
    287   // alive.
    288   //
    289   for (RootBridgeNumber = 1;
    290        RootBridgeNumber <= PCI_MAX_BUS && Initialized < ExtraRootBridges;
    291        ++RootBridgeNumber) {
    292     UINTN Device;
    293 
    294     for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
    295       if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
    296                        PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
    297         break;
    298       }
    299     }
    300     if (Device <= PCI_MAX_DEVICE) {
    301       //
    302       // Found the next root bus. We can now install the *previous* one,
    303       // because now we know how big a bus number range *that* one has, for any
    304       // subordinate buses that might exist behind PCI bridges hanging off it.
    305       //
    306       Status = InitRootBridge (
    307         Attributes,
    308         Attributes,
    309         AllocationAttributes,
    310         (UINT8) LastRootBridgeNumber,
    311         (UINT8) (RootBridgeNumber - 1),
    312         &Io,
    313         &Mem,
    314         &MemAbove4G,
    315         &mNonExistAperture,
    316         &mNonExistAperture,
    317         &Bridges[Initialized]
    318         );
    319       if (EFI_ERROR (Status)) {
    320         goto FreeBridges;
    321       }
    322       ++Initialized;
    323       LastRootBridgeNumber = RootBridgeNumber;
    324     }
    325   }
    326 
    327   //
    328   // Install the last root bus (which might be the only, ie. main, root bus, if
    329   // we've found no extra root buses).
    330   //
    331   Status = InitRootBridge (
    332     Attributes,
    333     Attributes,
    334     AllocationAttributes,
    335     (UINT8) LastRootBridgeNumber,
    336     PCI_MAX_BUS,
    337     &Io,
    338     &Mem,
    339     &MemAbove4G,
    340     &mNonExistAperture,
    341     &mNonExistAperture,
    342     &Bridges[Initialized]
    343     );
    344   if (EFI_ERROR (Status)) {
    345     goto FreeBridges;
    346   }
    347   ++Initialized;
    348 
    349   *Count = Initialized;
    350   return Bridges;
    351 
    352 FreeBridges:
    353   while (Initialized > 0) {
    354     --Initialized;
    355     UninitRootBridge (&Bridges[Initialized]);
    356   }
    357 
    358   FreePool (Bridges);
    359   return NULL;
    360 }
    361 
    362 
    363 /**
    364   Free the root bridge instances array returned from
    365   PciHostBridgeGetRootBridges().
    366 
    367   @param  The root bridge instances array.
    368   @param  The count of the array.
    369 **/
    370 VOID
    371 EFIAPI
    372 PciHostBridgeFreeRootBridges (
    373   PCI_ROOT_BRIDGE *Bridges,
    374   UINTN           Count
    375   )
    376 {
    377   if (Bridges == NULL && Count == 0) {
    378     return;
    379   }
    380   ASSERT (Bridges != NULL && Count > 0);
    381 
    382   do {
    383     --Count;
    384     UninitRootBridge (&Bridges[Count]);
    385   } while (Count > 0);
    386 
    387   FreePool (Bridges);
    388 }
    389 
    390 
    391 /**
    392   Inform the platform that the resource conflict happens.
    393 
    394   @param HostBridgeHandle Handle of the Host Bridge.
    395   @param Configuration    Pointer to PCI I/O and PCI memory resource
    396                           descriptors. The Configuration contains the resources
    397                           for all the root bridges. The resource for each root
    398                           bridge is terminated with END descriptor and an
    399                           additional END is appended indicating the end of the
    400                           entire resources. The resource descriptor field
    401                           values follow the description in
    402                           EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
    403                           .SubmitResources().
    404 **/
    405 VOID
    406 EFIAPI
    407 PciHostBridgeResourceConflict (
    408   EFI_HANDLE                        HostBridgeHandle,
    409   VOID                              *Configuration
    410   )
    411 {
    412   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
    413   UINTN                             RootBridgeIndex;
    414   DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));
    415 
    416   RootBridgeIndex = 0;
    417   Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
    418   while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
    419     DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
    420     for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
    421       ASSERT (Descriptor->ResType <
    422               ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr)
    423               );
    424       DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
    425               mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
    426               Descriptor->AddrLen, Descriptor->AddrRangeMax
    427               ));
    428       if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
    429         DEBUG ((EFI_D_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",
    430                 Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
    431                 ((Descriptor->SpecificFlag &
    432                   EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
    433                   ) != 0) ? L" (Prefetchable)" : L""
    434                 ));
    435       }
    436     }
    437     //
    438     // Skip the END descriptor for root bridge
    439     //
    440     ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
    441     Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
    442                    (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
    443                    );
    444   }
    445 }
    446