]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NonDiscoverablePciDeviceDxe / NonDiscoverablePciDeviceDxe.c
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 //
20 // We only support the following device types
21 //
22 STATIC
23 CONST EFI_GUID * CONST
24 SupportedNonDiscoverableDevices [] = {
25 &gEdkiiNonDiscoverableAhciDeviceGuid,
26 &gEdkiiNonDiscoverableEhciDeviceGuid,
27 &gEdkiiNonDiscoverableNvmeDeviceGuid,
28 &gEdkiiNonDiscoverableOhciDeviceGuid,
29 &gEdkiiNonDiscoverableSdhciDeviceGuid,
30 &gEdkiiNonDiscoverableUfsDeviceGuid,
31 &gEdkiiNonDiscoverableUhciDeviceGuid,
32 &gEdkiiNonDiscoverableXhciDeviceGuid,
33 };
34
35 //
36 // Probe, start and stop functions of this driver, called by the DXE core for
37 // specific devices.
38 //
39 // The following specifications document these interfaces:
40 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
41 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
42 //
43 // The implementation follows:
44 // - Driver Writer's Guide for UEFI 2.3.1 v1.01
45 // - 5.1.3.4 OpenProtocol() and CloseProtocol()
46 // - UEFI Spec 2.3.1 + Errata C
47 // - 6.3 Protocol Handler Services
48 //
49
50 STATIC
51 EFI_STATUS
52 EFIAPI
53 NonDiscoverablePciDeviceSupported (
54 IN EFI_DRIVER_BINDING_PROTOCOL *This,
55 IN EFI_HANDLE DeviceHandle,
56 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
57 )
58 {
59 NON_DISCOVERABLE_DEVICE *Device;
60 EFI_STATUS Status;
61 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
62 INTN Idx;
63
64 Status = gBS->OpenProtocol (DeviceHandle,
65 &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
66 This->DriverBindingHandle, DeviceHandle,
67 EFI_OPEN_PROTOCOL_BY_DRIVER);
68 if (EFI_ERROR (Status)) {
69 return Status;
70 }
71
72 //
73 // Restricted to DMA coherent for now
74 //
75 Status = EFI_UNSUPPORTED;
76 if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
77 goto CloseProtocol;
78 }
79
80 for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
81 if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
82 Status = EFI_SUCCESS;
83 break;
84 }
85 }
86
87 if (EFI_ERROR (Status)) {
88 goto CloseProtocol;
89 }
90
91 //
92 // We only support MMIO devices, so iterate over the resources to ensure
93 // that they only describe things that we can handle
94 //
95 for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
96 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
97 if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
98 Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
99 Status = EFI_UNSUPPORTED;
100 break;
101 }
102 }
103
104 CloseProtocol:
105 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
106 This->DriverBindingHandle, DeviceHandle);
107
108 return Status;
109 }
110
111 STATIC
112 EFI_STATUS
113 EFIAPI
114 NonDiscoverablePciDeviceStart (
115 IN EFI_DRIVER_BINDING_PROTOCOL *This,
116 IN EFI_HANDLE DeviceHandle,
117 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
118 )
119 {
120 NON_DISCOVERABLE_PCI_DEVICE *Dev;
121 EFI_STATUS Status;
122
123 Dev = AllocateZeroPool (sizeof *Dev);
124 if (Dev == NULL) {
125 return EFI_OUT_OF_RESOURCES;
126 }
127
128 Status = gBS->OpenProtocol (DeviceHandle,
129 &gEdkiiNonDiscoverableDeviceProtocolGuid,
130 (VOID **)&Dev->Device, This->DriverBindingHandle,
131 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
132 if (EFI_ERROR (Status)) {
133 goto FreeDev;
134 }
135
136 InitializePciIoProtocol (Dev);
137
138 //
139 // Setup complete, attempt to export the driver instance's
140 // EFI_PCI_IO_PROTOCOL interface.
141 //
142 Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;
143 Status = gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
144 EFI_NATIVE_INTERFACE, &Dev->PciIo);
145 if (EFI_ERROR (Status)) {
146 goto CloseProtocol;
147 }
148
149 return EFI_SUCCESS;
150
151 CloseProtocol:
152 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
153 This->DriverBindingHandle, DeviceHandle);
154
155 FreeDev:
156 FreePool (Dev);
157
158 return Status;
159 }
160
161
162 STATIC
163 EFI_STATUS
164 EFIAPI
165 NonDiscoverablePciDeviceStop (
166 IN EFI_DRIVER_BINDING_PROTOCOL *This,
167 IN EFI_HANDLE DeviceHandle,
168 IN UINTN NumberOfChildren,
169 IN EFI_HANDLE *ChildHandleBuffer
170 )
171 {
172 EFI_STATUS Status;
173 EFI_PCI_IO_PROTOCOL *PciIo;
174 NON_DISCOVERABLE_PCI_DEVICE *Dev;
175
176 Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
177 (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
178 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
179 if (EFI_ERROR (Status)) {
180 return Status;
181 }
182
183 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
184
185 //
186 // Handle Stop() requests for in-use driver instances gracefully.
187 //
188 Status = gBS->UninstallProtocolInterface (DeviceHandle,
189 &gEfiPciIoProtocolGuid, &Dev->PciIo);
190 if (EFI_ERROR (Status)) {
191 return Status;
192 }
193
194 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
195 This->DriverBindingHandle, DeviceHandle);
196
197 FreePool (Dev);
198
199 return EFI_SUCCESS;
200 }
201
202
203 //
204 // The static object that groups the Supported() (ie. probe), Start() and
205 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
206 // C, 10.1 EFI Driver Binding Protocol.
207 //
208 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
209 &NonDiscoverablePciDeviceSupported,
210 &NonDiscoverablePciDeviceStart,
211 &NonDiscoverablePciDeviceStop,
212 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
213 NULL,
214 NULL
215 };
216
217 //
218 // Entry point of this driver.
219 //
220 EFI_STATUS
221 EFIAPI
222 NonDiscoverablePciDeviceDxeEntryPoint (
223 IN EFI_HANDLE ImageHandle,
224 IN EFI_SYSTEM_TABLE *SystemTable
225 )
226 {
227 return EfiLibInstallDriverBindingComponentName2 (
228 ImageHandle,
229 SystemTable,
230 &gDriverBinding,
231 ImageHandle,
232 &gComponentName,
233 &gComponentName2
234 );
235 }