Home | History | Annotate | Download | only in NonDiscoverablePciDeviceDxe
      1 /** @file
      2 
      3   Copyright (C) 2016, Linaro Ltd. All rights reserved.<BR>
      4 
      5   This program and the accompanying materials are licensed and made available
      6   under the terms and conditions of the BSD License which accompanies this
      7   distribution. The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
     11   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "NonDiscoverablePciDeviceIo.h"
     16 
     17 #include <Protocol/DriverBinding.h>
     18 
     19 EFI_CPU_ARCH_PROTOCOL      *mCpu;
     20 
     21 //
     22 // We only support the following device types
     23 //
     24 STATIC
     25 CONST EFI_GUID * CONST
     26 SupportedNonDiscoverableDevices[] = {
     27   &gEdkiiNonDiscoverableAhciDeviceGuid,
     28   &gEdkiiNonDiscoverableEhciDeviceGuid,
     29   &gEdkiiNonDiscoverableNvmeDeviceGuid,
     30   &gEdkiiNonDiscoverableOhciDeviceGuid,
     31   &gEdkiiNonDiscoverableSdhciDeviceGuid,
     32   &gEdkiiNonDiscoverableUfsDeviceGuid,
     33   &gEdkiiNonDiscoverableUhciDeviceGuid,
     34   &gEdkiiNonDiscoverableXhciDeviceGuid,
     35 };
     36 
     37 //
     38 // Probe, start and stop functions of this driver, called by the DXE core for
     39 // specific devices.
     40 //
     41 // The following specifications document these interfaces:
     42 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
     43 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
     44 //
     45 // The implementation follows:
     46 // - Driver Writer's Guide for UEFI 2.3.1 v1.01
     47 //   - 5.1.3.4 OpenProtocol() and CloseProtocol()
     48 // - UEFI Spec 2.3.1 + Errata C
     49 //   -  6.3 Protocol Handler Services
     50 //
     51 
     52 /**
     53   Supported function of Driver Binding protocol for this driver.
     54   Test to see if this driver supports ControllerHandle.
     55 
     56   @param This                   Protocol instance pointer.
     57   @param DeviceHandle           Handle of device to test.
     58   @param RemainingDevicePath    A pointer to the device path.
     59                                 it should be ignored by device driver.
     60 
     61   @retval EFI_SUCCESS           This driver supports this device.
     62   @retval other                 This driver does not support this device.
     63 
     64 **/
     65 STATIC
     66 EFI_STATUS
     67 EFIAPI
     68 NonDiscoverablePciDeviceSupported (
     69   IN EFI_DRIVER_BINDING_PROTOCOL *This,
     70   IN EFI_HANDLE                  DeviceHandle,
     71   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
     72   )
     73 {
     74   NON_DISCOVERABLE_DEVICE             *Device;
     75   EFI_STATUS                          Status;
     76   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
     77   INTN                                Idx;
     78 
     79   Status = gBS->OpenProtocol (DeviceHandle,
     80                   &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
     81                   This->DriverBindingHandle, DeviceHandle,
     82                   EFI_OPEN_PROTOCOL_BY_DRIVER);
     83   if (EFI_ERROR (Status)) {
     84     return Status;
     85   }
     86 
     87   Status = EFI_UNSUPPORTED;
     88   for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
     89     if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
     90       Status = EFI_SUCCESS;
     91       break;
     92     }
     93   }
     94 
     95   if (EFI_ERROR (Status)) {
     96     goto CloseProtocol;
     97   }
     98 
     99   //
    100   // We only support MMIO devices, so iterate over the resources to ensure
    101   // that they only describe things that we can handle
    102   //
    103   for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
    104        Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
    105     if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
    106         Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
    107       Status = EFI_UNSUPPORTED;
    108       break;
    109     }
    110   }
    111 
    112 CloseProtocol:
    113   gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
    114          This->DriverBindingHandle, DeviceHandle);
    115 
    116   return Status;
    117 }
    118 
    119 /**
    120   This routine is called right after the .Supported() called and
    121   Start this driver on ControllerHandle.
    122 
    123   @param This                   Protocol instance pointer.
    124   @param DeviceHandle           Handle of device to bind driver to.
    125   @param RemainingDevicePath    A pointer to the device path.
    126                                 it should be ignored by device driver.
    127 
    128   @retval EFI_SUCCESS           This driver is added to this device.
    129   @retval other                 Some error occurs when binding this driver to this device.
    130 
    131 **/
    132 STATIC
    133 EFI_STATUS
    134 EFIAPI
    135 NonDiscoverablePciDeviceStart (
    136   IN EFI_DRIVER_BINDING_PROTOCOL *This,
    137   IN EFI_HANDLE                  DeviceHandle,
    138   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
    139   )
    140 {
    141   NON_DISCOVERABLE_PCI_DEVICE   *Dev;
    142   EFI_STATUS                    Status;
    143 
    144   Dev = AllocateZeroPool (sizeof *Dev);
    145   if (Dev == NULL) {
    146     return EFI_OUT_OF_RESOURCES;
    147   }
    148 
    149   Status = gBS->OpenProtocol (DeviceHandle,
    150                   &gEdkiiNonDiscoverableDeviceProtocolGuid,
    151                   (VOID **)&Dev->Device, This->DriverBindingHandle,
    152                   DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
    153   if (EFI_ERROR (Status)) {
    154     goto FreeDev;
    155   }
    156 
    157   InitializePciIoProtocol (Dev);
    158 
    159   //
    160   // Setup complete, attempt to export the driver instance's
    161   // EFI_PCI_IO_PROTOCOL interface.
    162   //
    163   Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;
    164   Status = gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
    165                   EFI_NATIVE_INTERFACE, &Dev->PciIo);
    166   if (EFI_ERROR (Status)) {
    167     goto CloseProtocol;
    168   }
    169 
    170   return EFI_SUCCESS;
    171 
    172 CloseProtocol:
    173   gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
    174          This->DriverBindingHandle, DeviceHandle);
    175 
    176 FreeDev:
    177   FreePool (Dev);
    178 
    179   return Status;
    180 }
    181 
    182 /**
    183   Stop this driver on ControllerHandle.
    184 
    185   @param This               Protocol instance pointer.
    186   @param DeviceHandle       Handle of device to stop driver on.
    187   @param NumberOfChildren   Not used.
    188   @param ChildHandleBuffer  Not used.
    189 
    190   @retval EFI_SUCCESS   This driver is removed from this device.
    191   @retval other         Some error occurs when removing this driver from this device.
    192 
    193 **/
    194 STATIC
    195 EFI_STATUS
    196 EFIAPI
    197 NonDiscoverablePciDeviceStop (
    198   IN EFI_DRIVER_BINDING_PROTOCOL *This,
    199   IN EFI_HANDLE                  DeviceHandle,
    200   IN UINTN                       NumberOfChildren,
    201   IN EFI_HANDLE                  *ChildHandleBuffer
    202   )
    203 {
    204   EFI_STATUS                      Status;
    205   EFI_PCI_IO_PROTOCOL             *PciIo;
    206   NON_DISCOVERABLE_PCI_DEVICE     *Dev;
    207 
    208   Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
    209                   (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
    210                   EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    211   if (EFI_ERROR (Status)) {
    212     return Status;
    213   }
    214 
    215   Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
    216 
    217   //
    218   // Handle Stop() requests for in-use driver instances gracefully.
    219   //
    220   Status = gBS->UninstallProtocolInterface (DeviceHandle,
    221                   &gEfiPciIoProtocolGuid, &Dev->PciIo);
    222   if (EFI_ERROR (Status)) {
    223     return Status;
    224   }
    225 
    226   gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
    227          This->DriverBindingHandle, DeviceHandle);
    228 
    229   FreePool (Dev);
    230 
    231   return EFI_SUCCESS;
    232 }
    233 
    234 
    235 //
    236 // The static object that groups the Supported() (ie. probe), Start() and
    237 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
    238 // C, 10.1 EFI Driver Binding Protocol.
    239 //
    240 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
    241   &NonDiscoverablePciDeviceSupported,
    242   &NonDiscoverablePciDeviceStart,
    243   &NonDiscoverablePciDeviceStop,
    244   0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
    245   NULL,
    246   NULL
    247 };
    248 
    249 /**
    250   Entry point of this driver.
    251 
    252   @param  ImageHandle     Image handle this driver.
    253   @param  SystemTable     Pointer to the System Table.
    254 
    255   @retval EFI_SUCCESS     The entry point is executed successfully.
    256   @retval other           Some error occurred when executing this entry point.
    257 
    258 **/
    259 EFI_STATUS
    260 EFIAPI
    261 NonDiscoverablePciDeviceDxeEntryPoint (
    262   IN EFI_HANDLE       ImageHandle,
    263   IN EFI_SYSTEM_TABLE *SystemTable
    264   )
    265 {
    266   EFI_STATUS      Status;
    267 
    268   Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
    269   ASSERT_EFI_ERROR(Status);
    270 
    271   return EfiLibInstallDriverBindingComponentName2 (
    272            ImageHandle,
    273            SystemTable,
    274            &gDriverBinding,
    275            ImageHandle,
    276            &gComponentName,
    277            &gComponentName2
    278            );
    279 }
    280