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