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