]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 (
77 DeviceHandle,
78 &gEdkiiNonDiscoverableDeviceProtocolGuid,
79 (VOID **)&Device,
80 This->DriverBindingHandle,
81 DeviceHandle,
82 EFI_OPEN_PROTOCOL_BY_DRIVER
83 );
84 if (EFI_ERROR (Status)) {
85 return Status;
86 }
87
88 Status = EFI_UNSUPPORTED;
89 for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
90 if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices[Idx])) {
91 Status = EFI_SUCCESS;
92 break;
93 }
94 }
95
96 if (EFI_ERROR (Status)) {
97 goto CloseProtocol;
98 }
99
100 //
101 // We only support MMIO devices, so iterate over the resources to ensure
102 // that they only describe things that we can handle
103 //
104 for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
105 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3))
106 {
107 if ((Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||
108 (Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM))
109 {
110 Status = EFI_UNSUPPORTED;
111 break;
112 }
113 }
114
115 CloseProtocol:
116 gBS->CloseProtocol (
117 DeviceHandle,
118 &gEdkiiNonDiscoverableDeviceProtocolGuid,
119 This->DriverBindingHandle,
120 DeviceHandle
121 );
122
123 return Status;
124 }
125
126 /**
127 This routine is called right after the .Supported() called and
128 Start this driver on ControllerHandle.
129
130 @param This Protocol instance pointer.
131 @param DeviceHandle Handle of device to bind driver to.
132 @param RemainingDevicePath A pointer to the device path.
133 it should be ignored by device driver.
134
135 @retval EFI_SUCCESS This driver is added to this device.
136 @retval other Some error occurs when binding this driver to this device.
137
138 **/
139 STATIC
140 EFI_STATUS
141 EFIAPI
142 NonDiscoverablePciDeviceStart (
143 IN EFI_DRIVER_BINDING_PROTOCOL *This,
144 IN EFI_HANDLE DeviceHandle,
145 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
146 )
147 {
148 NON_DISCOVERABLE_PCI_DEVICE *Dev;
149 EFI_STATUS Status;
150
151 ASSERT (mUniqueIdCounter < MAX_NON_DISCOVERABLE_PCI_DEVICE_ID);
152 if (mUniqueIdCounter >= MAX_NON_DISCOVERABLE_PCI_DEVICE_ID) {
153 return EFI_OUT_OF_RESOURCES;
154 }
155
156 Dev = AllocateZeroPool (sizeof *Dev);
157 if (Dev == NULL) {
158 return EFI_OUT_OF_RESOURCES;
159 }
160
161 Status = gBS->OpenProtocol (
162 DeviceHandle,
163 &gEdkiiNonDiscoverableDeviceProtocolGuid,
164 (VOID **)&Dev->Device,
165 This->DriverBindingHandle,
166 DeviceHandle,
167 EFI_OPEN_PROTOCOL_BY_DRIVER
168 );
169 if (EFI_ERROR (Status)) {
170 goto FreeDev;
171 }
172
173 InitializePciIoProtocol (Dev);
174
175 //
176 // Setup complete, attempt to export the driver instance's
177 // EFI_PCI_IO_PROTOCOL interface.
178 //
179 Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;
180 Status = gBS->InstallProtocolInterface (
181 &DeviceHandle,
182 &gEfiPciIoProtocolGuid,
183 EFI_NATIVE_INTERFACE,
184 &Dev->PciIo
185 );
186 if (EFI_ERROR (Status)) {
187 goto CloseProtocol;
188 }
189
190 Dev->UniqueId = mUniqueIdCounter++;
191
192 return EFI_SUCCESS;
193
194 CloseProtocol:
195 gBS->CloseProtocol (
196 DeviceHandle,
197 &gEdkiiNonDiscoverableDeviceProtocolGuid,
198 This->DriverBindingHandle,
199 DeviceHandle
200 );
201
202 FreeDev:
203 FreePool (Dev);
204
205 return Status;
206 }
207
208 /**
209 Stop this driver on ControllerHandle.
210
211 @param This Protocol instance pointer.
212 @param DeviceHandle Handle of device to stop driver on.
213 @param NumberOfChildren Not used.
214 @param ChildHandleBuffer Not used.
215
216 @retval EFI_SUCCESS This driver is removed from this device.
217 @retval other Some error occurs when removing this driver from this device.
218
219 **/
220 STATIC
221 EFI_STATUS
222 EFIAPI
223 NonDiscoverablePciDeviceStop (
224 IN EFI_DRIVER_BINDING_PROTOCOL *This,
225 IN EFI_HANDLE DeviceHandle,
226 IN UINTN NumberOfChildren,
227 IN EFI_HANDLE *ChildHandleBuffer
228 )
229 {
230 EFI_STATUS Status;
231 EFI_PCI_IO_PROTOCOL *PciIo;
232 NON_DISCOVERABLE_PCI_DEVICE *Dev;
233
234 Status = gBS->OpenProtocol (
235 DeviceHandle,
236 &gEfiPciIoProtocolGuid,
237 (VOID **)&PciIo,
238 This->DriverBindingHandle,
239 DeviceHandle,
240 EFI_OPEN_PROTOCOL_GET_PROTOCOL
241 );
242 if (EFI_ERROR (Status)) {
243 return Status;
244 }
245
246 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
247
248 //
249 // Handle Stop() requests for in-use driver instances gracefully.
250 //
251 Status = gBS->UninstallProtocolInterface (
252 DeviceHandle,
253 &gEfiPciIoProtocolGuid,
254 &Dev->PciIo
255 );
256 if (EFI_ERROR (Status)) {
257 return Status;
258 }
259
260 gBS->CloseProtocol (
261 DeviceHandle,
262 &gEdkiiNonDiscoverableDeviceProtocolGuid,
263 This->DriverBindingHandle,
264 DeviceHandle
265 );
266
267 FreePool (Dev);
268
269 return EFI_SUCCESS;
270 }
271
272 //
273 // The static object that groups the Supported() (ie. probe), Start() and
274 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
275 // C, 10.1 EFI Driver Binding Protocol.
276 //
277 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
278 &NonDiscoverablePciDeviceSupported,
279 &NonDiscoverablePciDeviceStart,
280 &NonDiscoverablePciDeviceStop,
281 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
282 NULL,
283 NULL
284 };
285
286 /**
287 Entry point of this driver.
288
289 @param ImageHandle Image handle this driver.
290 @param SystemTable Pointer to the System Table.
291
292 @retval EFI_SUCCESS The entry point is executed successfully.
293 @retval other Some error occurred when executing this entry point.
294
295 **/
296 EFI_STATUS
297 EFIAPI
298 NonDiscoverablePciDeviceDxeEntryPoint (
299 IN EFI_HANDLE ImageHandle,
300 IN EFI_SYSTEM_TABLE *SystemTable
301 )
302 {
303 EFI_STATUS Status;
304
305 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
306 ASSERT_EFI_ERROR (Status);
307
308 return EfiLibInstallDriverBindingComponentName2 (
309 ImageHandle,
310 SystemTable,
311 &gDriverBinding,
312 ImageHandle,
313 &gComponentName,
314 &gComponentName2
315 );
316 }