Home | History | Annotate | Download | only in PciBusDxe
      1 /** @file
      2   Driver Binding functions for PCI Bus module.
      3 
      4   Single PCI bus driver instance will manager all PCI Root Bridges in one EFI based firmware,
      5   since all PCI Root Bridges' resources need to be managed together.
      6   Supported() function will try to get PCI Root Bridge IO Protocol.
      7   Start() function will get PCI Host Bridge Resource Allocation Protocol to manage all
      8   PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
      9   PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
     10 
     11 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
     12 This program and the accompanying materials
     13 are licensed and made available under the terms and conditions of the BSD License
     14 which accompanies this distribution.  The full text of the license may be found at
     15 http://opensource.org/licenses/bsd-license.php
     16 
     17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     19 
     20 **/
     21 
     22 #include "PciBus.h"
     23 
     24 //
     25 // PCI Bus Driver Global Variables
     26 //
     27 EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {
     28   PciBusDriverBindingSupported,
     29   PciBusDriverBindingStart,
     30   PciBusDriverBindingStop,
     31   0xa,
     32   NULL,
     33   NULL
     34 };
     35 
     36 EFI_HANDLE                                    gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
     37 EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *gIncompatiblePciDeviceSupport = NULL;
     38 UINTN                                         gPciHostBridgeNumber = 0;
     39 BOOLEAN                                       gFullEnumeration     = TRUE;
     40 UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
     41 UINT64                                        gAllZero             = 0;
     42 
     43 EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
     44 EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
     45 
     46 
     47 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {
     48   PciHotPlugRequestNotify
     49 };
     50 
     51 /**
     52   The Entry Point for PCI Bus module. The user code starts with this function.
     53 
     54   Installs driver module protocols and. Creates virtual device handles for ConIn,
     55   ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
     56   Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
     57   Installs Graphics Output protocol and/or UGA Draw protocol if needed.
     58 
     59   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
     60   @param[in] SystemTable    A pointer to the EFI System Table.
     61 
     62   @retval EFI_SUCCESS       The entry point is executed successfully.
     63   @retval other             Some error occurred when executing this entry point.
     64 
     65 **/
     66 EFI_STATUS
     67 EFIAPI
     68 PciBusEntryPoint (
     69   IN EFI_HANDLE         ImageHandle,
     70   IN EFI_SYSTEM_TABLE   *SystemTable
     71   )
     72 {
     73   EFI_STATUS  Status;
     74   EFI_HANDLE  Handle;
     75 
     76   //
     77   // Initializes PCI devices pool
     78   //
     79   InitializePciDevicePool ();
     80 
     81   //
     82   // Install driver model protocol(s).
     83   //
     84   Status = EfiLibInstallDriverBindingComponentName2 (
     85              ImageHandle,
     86              SystemTable,
     87              &gPciBusDriverBinding,
     88              ImageHandle,
     89              &gPciBusComponentName,
     90              &gPciBusComponentName2
     91              );
     92   ASSERT_EFI_ERROR (Status);
     93 
     94   if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
     95     //
     96     // If Hot Plug is supported, install EFI PCI Hot Plug Request protocol.
     97     //
     98     Handle = NULL;
     99     Status = gBS->InstallProtocolInterface (
    100                     &Handle,
    101                     &gEfiPciHotPlugRequestProtocolGuid,
    102                     EFI_NATIVE_INTERFACE,
    103                     &mPciHotPlugRequest
    104                     );
    105   }
    106 
    107   return Status;
    108 }
    109 
    110 /**
    111   Test to see if this driver supports ControllerHandle. Any ControllerHandle
    112   than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.
    113 
    114   @param  This                Protocol instance pointer.
    115   @param  Controller          Handle of device to test.
    116   @param  RemainingDevicePath Optional parameter use to pick a specific child
    117                               device to start.
    118 
    119   @retval EFI_SUCCESS         This driver supports this device.
    120   @retval EFI_ALREADY_STARTED This driver is already running on this device.
    121   @retval other               This driver does not support this device.
    122 
    123 **/
    124 EFI_STATUS
    125 EFIAPI
    126 PciBusDriverBindingSupported (
    127   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
    128   IN EFI_HANDLE                     Controller,
    129   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
    130   )
    131 {
    132   EFI_STATUS                      Status;
    133   EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
    134   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
    135   EFI_DEV_PATH_PTR                Node;
    136 
    137   //
    138   // Check RemainingDevicePath validation
    139   //
    140   if (RemainingDevicePath != NULL) {
    141     //
    142     // Check if RemainingDevicePath is the End of Device Path Node,
    143     // if yes, go on checking other conditions
    144     //
    145     if (!IsDevicePathEnd (RemainingDevicePath)) {
    146       //
    147       // If RemainingDevicePath isn't the End of Device Path Node,
    148       // check its validation
    149       //
    150       Node.DevPath = RemainingDevicePath;
    151       if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
    152           Node.DevPath->SubType != HW_PCI_DP         ||
    153           DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {
    154         return EFI_UNSUPPORTED;
    155       }
    156     }
    157   }
    158 
    159   //
    160   // Check if Pci Root Bridge IO protocol is installed by platform
    161   //
    162   Status = gBS->OpenProtocol (
    163                   Controller,
    164                   &gEfiPciRootBridgeIoProtocolGuid,
    165                   (VOID **) &PciRootBridgeIo,
    166                   This->DriverBindingHandle,
    167                   Controller,
    168                   EFI_OPEN_PROTOCOL_BY_DRIVER
    169                   );
    170   if (Status == EFI_ALREADY_STARTED) {
    171     return EFI_SUCCESS;
    172   }
    173 
    174   if (EFI_ERROR (Status)) {
    175     return Status;
    176   }
    177 
    178   //
    179   // Close the I/O Abstraction(s) used to perform the supported test
    180   //
    181   gBS->CloseProtocol (
    182         Controller,
    183         &gEfiPciRootBridgeIoProtocolGuid,
    184         This->DriverBindingHandle,
    185         Controller
    186         );
    187 
    188   //
    189   // Open the EFI Device Path protocol needed to perform the supported test
    190   //
    191   Status = gBS->OpenProtocol (
    192                   Controller,
    193                   &gEfiDevicePathProtocolGuid,
    194                   (VOID **) &ParentDevicePath,
    195                   This->DriverBindingHandle,
    196                   Controller,
    197                   EFI_OPEN_PROTOCOL_BY_DRIVER
    198                   );
    199   if (Status == EFI_ALREADY_STARTED) {
    200     return EFI_SUCCESS;
    201   }
    202 
    203   if (EFI_ERROR (Status)) {
    204     return Status;
    205   }
    206 
    207   //
    208   // Close protocol, don't use device path protocol in the Support() function
    209   //
    210   gBS->CloseProtocol (
    211         Controller,
    212         &gEfiDevicePathProtocolGuid,
    213         This->DriverBindingHandle,
    214         Controller
    215         );
    216 
    217   return EFI_SUCCESS;
    218 }
    219 
    220 /**
    221   Start this driver on ControllerHandle and enumerate Pci bus and start
    222   all device under PCI bus.
    223 
    224   @param  This                 Protocol instance pointer.
    225   @param  Controller           Handle of device to bind driver to.
    226   @param  RemainingDevicePath  Optional parameter use to pick a specific child
    227                                device to start.
    228 
    229   @retval EFI_SUCCESS          This driver is added to ControllerHandle.
    230   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
    231   @retval other                This driver does not support this device.
    232 
    233 **/
    234 EFI_STATUS
    235 EFIAPI
    236 PciBusDriverBindingStart (
    237   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    238   IN EFI_HANDLE                   Controller,
    239   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    240   )
    241 {
    242   EFI_STATUS                Status;
    243   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
    244 
    245   //
    246   // Check RemainingDevicePath validation
    247   //
    248   if (RemainingDevicePath != NULL) {
    249     //
    250     // Check if RemainingDevicePath is the End of Device Path Node,
    251     // if yes, return EFI_SUCCESS
    252     //
    253     if (IsDevicePathEnd (RemainingDevicePath)) {
    254       return EFI_SUCCESS;
    255     }
    256   }
    257 
    258   gBS->LocateProtocol (
    259          &gEfiIncompatiblePciDeviceSupportProtocolGuid,
    260          NULL,
    261          (VOID **) &gIncompatiblePciDeviceSupport
    262          );
    263 
    264   //
    265   // If PCI Platform protocol is available, get it now.
    266   // If the platform implements this, it must be installed before BDS phase
    267   //
    268   gPciPlatformProtocol = NULL;
    269   gBS->LocateProtocol (
    270         &gEfiPciPlatformProtocolGuid,
    271         NULL,
    272         (VOID **) &gPciPlatformProtocol
    273         );
    274 
    275   //
    276   // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
    277   //
    278   if (gPciPlatformProtocol == NULL) {
    279     gPciOverrideProtocol = NULL;
    280     gBS->LocateProtocol (
    281           &gEfiPciOverrideProtocolGuid,
    282           NULL,
    283           (VOID **) &gPciOverrideProtocol
    284           );
    285   }
    286 
    287   if (PcdGetBool (PcdPciDisableBusEnumeration)) {
    288     gFullEnumeration = FALSE;
    289   } else {
    290     gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));
    291   }
    292 
    293   //
    294   // Open Device Path Protocol for PCI root bridge
    295   //
    296   Status = gBS->OpenProtocol (
    297                   Controller,
    298                   &gEfiDevicePathProtocolGuid,
    299                   (VOID **) &ParentDevicePath,
    300                   This->DriverBindingHandle,
    301                   Controller,
    302                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    303                   );
    304   ASSERT_EFI_ERROR (Status);
    305 
    306   //
    307   // Report Status Code to indicate PCI bus starts
    308   //
    309   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    310     EFI_PROGRESS_CODE,
    311     (EFI_IO_BUS_PCI | EFI_IOB_PC_INIT),
    312     ParentDevicePath
    313     );
    314 
    315   //
    316   // Enumerate the entire host bridge
    317   // After enumeration, a database that records all the device information will be created
    318   //
    319   //
    320   Status = PciEnumerator (Controller);
    321 
    322   if (EFI_ERROR (Status)) {
    323     return Status;
    324   }
    325 
    326   //
    327   // Start all the devices under the entire host bridge.
    328   //
    329   StartPciDevices (Controller);
    330 
    331   return EFI_SUCCESS;
    332 }
    333 
    334 /**
    335   Stop this driver on ControllerHandle. Support stopping any child handles
    336   created by this driver.
    337 
    338   @param  This              Protocol instance pointer.
    339   @param  Controller        Handle of device to stop driver on.
    340   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    341                             children is zero stop the entire bus driver.
    342   @param  ChildHandleBuffer List of Child Handles to Stop.
    343 
    344   @retval EFI_SUCCESS       This driver is removed ControllerHandle.
    345   @retval other             This driver was not removed from this device.
    346 
    347 **/
    348 EFI_STATUS
    349 EFIAPI
    350 PciBusDriverBindingStop (
    351   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
    352   IN  EFI_HANDLE                    Controller,
    353   IN  UINTN                         NumberOfChildren,
    354   IN  EFI_HANDLE                    *ChildHandleBuffer
    355   )
    356 {
    357   EFI_STATUS  Status;
    358   UINTN       Index;
    359   BOOLEAN     AllChildrenStopped;
    360 
    361   if (NumberOfChildren == 0) {
    362     //
    363     // Close the bus driver
    364     //
    365     gBS->CloseProtocol (
    366           Controller,
    367           &gEfiDevicePathProtocolGuid,
    368           This->DriverBindingHandle,
    369           Controller
    370           );
    371     gBS->CloseProtocol (
    372           Controller,
    373           &gEfiPciRootBridgeIoProtocolGuid,
    374           This->DriverBindingHandle,
    375           Controller
    376           );
    377 
    378     DestroyRootBridgeByHandle (
    379       Controller
    380       );
    381 
    382     return EFI_SUCCESS;
    383   }
    384 
    385   //
    386   // Stop all the children
    387   //
    388 
    389   AllChildrenStopped = TRUE;
    390 
    391   for (Index = 0; Index < NumberOfChildren; Index++) {
    392 
    393     //
    394     // De register all the pci device
    395     //
    396     Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
    397 
    398     if (EFI_ERROR (Status)) {
    399       AllChildrenStopped = FALSE;
    400     }
    401   }
    402 
    403   if (!AllChildrenStopped) {
    404     return EFI_DEVICE_ERROR;
    405   }
    406 
    407   return EFI_SUCCESS;
    408 }
    409 
    410