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