]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenIoPciDxe/XenIoPciDxe.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / XenIoPciDxe / XenIoPciDxe.c
CommitLineData
f2162d34
AB
1/** @file\r
2\r
3 Driver for the virtual Xen PCI device\r
4\r
5 Copyright (C) 2012, Red Hat, Inc.\r
694673c9 6 Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
f2162d34
AB
7 Copyright (C) 2013, ARM Ltd.\r
8 Copyright (C) 2015, Linaro Ltd.\r
9\r
b26f0cf9 10 SPDX-License-Identifier: BSD-2-Clause-Patent\r
f2162d34
AB
11\r
12**/\r
13\r
14#include <IndustryStandard/Acpi.h>\r
15#include <IndustryStandard/Pci.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/MemoryAllocationLib.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20#include <Library/UefiLib.h>\r
21\r
22#include <Protocol/PciIo.h>\r
23#include <Protocol/XenIo.h>\r
24\r
ac0a286f
MK
25#define PCI_VENDOR_ID_XEN 0x5853\r
26#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001\r
f2162d34
AB
27\r
28/**\r
29\r
30 Device probe function for this driver.\r
31\r
32 The DXE core calls this function for any given device in order to see if the\r
33 driver can drive the device.\r
34\r
35 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
36 incorporating this driver (independently of\r
37 any device).\r
38\r
39 @param[in] DeviceHandle The device to probe.\r
40\r
41 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.\r
42\r
43\r
44 @retval EFI_SUCCESS The driver supports the device being probed.\r
45\r
46 @retval EFI_UNSUPPORTED The driver does not support the device being probed.\r
47\r
48 @return Error codes from the OpenProtocol() boot service or\r
49 the PciIo protocol.\r
50\r
51**/\r
52STATIC\r
53EFI_STATUS\r
54EFIAPI\r
55XenIoPciDeviceBindingSupported (\r
ac0a286f
MK
56 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
57 IN EFI_HANDLE DeviceHandle,\r
58 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
f2162d34
AB
59 )\r
60{\r
ac0a286f
MK
61 EFI_STATUS Status;\r
62 EFI_PCI_IO_PROTOCOL *PciIo;\r
63 PCI_TYPE00 Pci;\r
f2162d34
AB
64\r
65 //\r
66 // Attempt to open the device with the PciIo set of interfaces. On success,\r
67 // the protocol is "instantiated" for the PCI device. Covers duplicate open\r
68 // attempts (EFI_ALREADY_STARTED).\r
69 //\r
70 Status = gBS->OpenProtocol (\r
71 DeviceHandle, // candidate device\r
72 &gEfiPciIoProtocolGuid, // for generic PCI access\r
73 (VOID **)&PciIo, // handle to instantiate\r
74 This->DriverBindingHandle, // requestor driver identity\r
75 DeviceHandle, // ControllerHandle, according to\r
76 // the UEFI Driver Model\r
77 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to\r
78 // the device; to be released\r
79 );\r
80 if (EFI_ERROR (Status)) {\r
81 return Status;\r
82 }\r
83\r
84 //\r
85 // Read entire PCI configuration header for more extensive check ahead.\r
86 //\r
87 Status = PciIo->Pci.Read (\r
88 PciIo, // (protocol, device)\r
89 // handle\r
90 EfiPciIoWidthUint32, // access width & copy\r
91 // mode\r
92 0, // Offset\r
93 sizeof Pci / sizeof (UINT32), // Count\r
94 &Pci // target buffer\r
95 );\r
96\r
97 if (Status == EFI_SUCCESS) {\r
98 if ((Pci.Hdr.VendorId == PCI_VENDOR_ID_XEN) &&\r
ac0a286f
MK
99 (Pci.Hdr.DeviceId == PCI_DEVICE_ID_XEN_PLATFORM))\r
100 {\r
f2162d34
AB
101 Status = EFI_SUCCESS;\r
102 } else {\r
103 Status = EFI_UNSUPPORTED;\r
104 }\r
105 }\r
106\r
107 //\r
108 // We needed PCI IO access only transitorily, to see whether we support the\r
109 // device or not.\r
110 //\r
ac0a286f
MK
111 gBS->CloseProtocol (\r
112 DeviceHandle,\r
113 &gEfiPciIoProtocolGuid,\r
114 This->DriverBindingHandle,\r
115 DeviceHandle\r
116 );\r
f2162d34
AB
117\r
118 return Status;\r
119}\r
120\r
121/**\r
122\r
123 After we've pronounced support for a specific device in\r
124 DriverBindingSupported(), we start managing said device (passed in by the\r
694673c9 125 Driver Execution Environment) with the following service.\r
f2162d34
AB
126\r
127 See DriverBindingSupported() for specification references.\r
128\r
129 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
130 incorporating this driver (independently of\r
131 any device).\r
132\r
133 @param[in] DeviceHandle The supported device to drive.\r
134\r
135 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.\r
136\r
137\r
138 @retval EFI_SUCCESS The device was started.\r
139\r
140 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
141\r
142 @return Error codes from the OpenProtocol() boot\r
143 service, the PciIo protocol or the\r
144 InstallProtocolInterface() boot service.\r
145\r
146**/\r
147STATIC\r
148EFI_STATUS\r
149EFIAPI\r
150XenIoPciDeviceBindingStart (\r
ac0a286f
MK
151 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
152 IN EFI_HANDLE DeviceHandle,\r
153 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
f2162d34
AB
154 )\r
155{\r
ac0a286f
MK
156 EFI_STATUS Status;\r
157 XENIO_PROTOCOL *XenIo;\r
158 EFI_PCI_IO_PROTOCOL *PciIo;\r
159 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;\r
f2162d34 160\r
ac0a286f 161 XenIo = (XENIO_PROTOCOL *)AllocateZeroPool (sizeof *XenIo);\r
f2162d34
AB
162 if (XenIo == NULL) {\r
163 return EFI_OUT_OF_RESOURCES;\r
164 }\r
165\r
ac0a286f
MK
166 Status = gBS->OpenProtocol (\r
167 DeviceHandle,\r
168 &gEfiPciIoProtocolGuid,\r
169 (VOID **)&PciIo,\r
170 This->DriverBindingHandle,\r
171 DeviceHandle,\r
172 EFI_OPEN_PROTOCOL_BY_DRIVER\r
173 );\r
f2162d34
AB
174 if (EFI_ERROR (Status)) {\r
175 goto FreeXenIo;\r
176 }\r
177\r
178 //\r
179 // The BAR1 of this PCI device is used for shared memory and is supposed to\r
180 // look like MMIO. The address space of the BAR1 will be used to map the\r
181 // Grant Table.\r
182 //\r
ac0a286f 183 Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID **)&BarDesc);\r
f2162d34
AB
184 ASSERT_EFI_ERROR (Status);\r
185 ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);\r
186\r
187 /* Get a Memory address for mapping the Grant Table. */\r
70d5086c 188 DEBUG ((DEBUG_INFO, "XenIoPci: BAR at %LX\n", BarDesc->AddrRangeMin));\r
f2162d34
AB
189 XenIo->GrantTableAddress = BarDesc->AddrRangeMin;\r
190 FreePool (BarDesc);\r
191\r
ac0a286f
MK
192 Status = gBS->InstallProtocolInterface (\r
193 &DeviceHandle,\r
194 &gXenIoProtocolGuid,\r
195 EFI_NATIVE_INTERFACE,\r
196 XenIo\r
197 );\r
f2162d34
AB
198\r
199 if (!EFI_ERROR (Status)) {\r
200 return EFI_SUCCESS;\r
201 }\r
202\r
ac0a286f
MK
203 gBS->CloseProtocol (\r
204 DeviceHandle,\r
205 &gEfiPciIoProtocolGuid,\r
206 This->DriverBindingHandle,\r
207 DeviceHandle\r
208 );\r
f2162d34
AB
209\r
210FreeXenIo:\r
211 FreePool (XenIo);\r
212\r
213 return Status;\r
214}\r
215\r
216/**\r
217\r
218 Stop driving the XenIo PCI device\r
219\r
220 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
221 incorporating this driver (independently of any\r
222 device).\r
223\r
224 @param[in] DeviceHandle Stop driving this device.\r
225\r
226 @param[in] NumberOfChildren Since this function belongs to a device driver\r
227 only (as opposed to a bus driver), the caller\r
228 environment sets NumberOfChildren to zero, and\r
229 we ignore it.\r
230\r
231 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).\r
232\r
233 @retval EFI_SUCCESS Driver instance has been stopped and the PCI\r
234 configuration attributes have been restored.\r
235\r
236 @return Error codes from the OpenProtocol() or\r
237 CloseProtocol(), UninstallProtocolInterface()\r
238 boot services.\r
239\r
240**/\r
241STATIC\r
242EFI_STATUS\r
243EFIAPI\r
244XenIoPciDeviceBindingStop (\r
ac0a286f
MK
245 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
246 IN EFI_HANDLE DeviceHandle,\r
247 IN UINTN NumberOfChildren,\r
248 IN EFI_HANDLE *ChildHandleBuffer\r
f2162d34
AB
249 )\r
250{\r
ac0a286f
MK
251 EFI_STATUS Status;\r
252 XENIO_PROTOCOL *XenIo;\r
f2162d34
AB
253\r
254 Status = gBS->OpenProtocol (\r
255 DeviceHandle, // candidate device\r
256 &gXenIoProtocolGuid, // retrieve the XenIo iface\r
257 (VOID **)&XenIo, // target pointer\r
258 This->DriverBindingHandle, // requestor driver identity\r
259 DeviceHandle, // requesting lookup for dev.\r
260 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
261 );\r
262 if (EFI_ERROR (Status)) {\r
263 return Status;\r
264 }\r
265\r
266 //\r
267 // Handle Stop() requests for in-use driver instances gracefully.\r
268 //\r
ac0a286f
MK
269 Status = gBS->UninstallProtocolInterface (\r
270 DeviceHandle,\r
271 &gXenIoProtocolGuid,\r
272 XenIo\r
273 );\r
f2162d34
AB
274 if (EFI_ERROR (Status)) {\r
275 return Status;\r
276 }\r
277\r
ac0a286f
MK
278 Status = gBS->CloseProtocol (\r
279 DeviceHandle,\r
280 &gEfiPciIoProtocolGuid,\r
281 This->DriverBindingHandle,\r
282 DeviceHandle\r
283 );\r
f2162d34
AB
284\r
285 FreePool (XenIo);\r
286\r
287 return Status;\r
288}\r
289\r
f2162d34
AB
290//\r
291// The static object that groups the Supported() (ie. probe), Start() and\r
292// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
293// C, 10.1 EFI Driver Binding Protocol.\r
294//\r
ac0a286f 295STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
f2162d34
AB
296 &XenIoPciDeviceBindingSupported,\r
297 &XenIoPciDeviceBindingStart,\r
298 &XenIoPciDeviceBindingStop,\r
299 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers\r
300 NULL, // ImageHandle, to be overwritten by\r
301 // EfiLibInstallDriverBindingComponentName2() in XenIoPciDeviceEntryPoint()\r
302 NULL // DriverBindingHandle, ditto\r
303};\r
304\r
f2162d34
AB
305//\r
306// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and\r
307// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name\r
308// in English, for display on standard console devices. This is recommended for\r
309// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's\r
310// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.\r
311//\r
312STATIC\r
ac0a286f 313EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
f2162d34
AB
314 { "eng;en", L"XenIo PCI Driver" },\r
315 { NULL, NULL }\r
316};\r
317\r
318STATIC\r
ac0a286f 319EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
f2162d34
AB
320\r
321EFI_STATUS\r
322EFIAPI\r
323XenIoPciGetDriverName (\r
ac0a286f
MK
324 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
325 IN CHAR8 *Language,\r
326 OUT CHAR16 **DriverName\r
f2162d34
AB
327 )\r
328{\r
329 return LookupUnicodeString2 (\r
330 Language,\r
331 This->SupportedLanguages,\r
332 mDriverNameTable,\r
333 DriverName,\r
334 (BOOLEAN)(This == &gComponentName) // Iso639Language\r
335 );\r
336}\r
337\r
338EFI_STATUS\r
339EFIAPI\r
340XenIoPciGetDeviceName (\r
ac0a286f
MK
341 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
342 IN EFI_HANDLE DeviceHandle,\r
343 IN EFI_HANDLE ChildHandle,\r
344 IN CHAR8 *Language,\r
345 OUT CHAR16 **ControllerName\r
f2162d34
AB
346 )\r
347{\r
348 return EFI_UNSUPPORTED;\r
349}\r
350\r
351STATIC\r
ac0a286f 352EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
f2162d34
AB
353 &XenIoPciGetDriverName,\r
354 &XenIoPciGetDeviceName,\r
355 "eng" // SupportedLanguages, ISO 639-2 language codes\r
356};\r
357\r
358STATIC\r
ac0a286f
MK
359EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
360 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&XenIoPciGetDriverName,\r
361 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&XenIoPciGetDeviceName,\r
f2162d34
AB
362 "en" // SupportedLanguages, RFC 4646 language codes\r
363};\r
364\r
f2162d34
AB
365//\r
366// Entry point of this driver.\r
367//\r
368EFI_STATUS\r
369EFIAPI\r
370XenIoPciDeviceEntryPoint (\r
ac0a286f
MK
371 IN EFI_HANDLE ImageHandle,\r
372 IN EFI_SYSTEM_TABLE *SystemTable\r
f2162d34
AB
373 )\r
374{\r
375 return EfiLibInstallDriverBindingComponentName2 (\r
376 ImageHandle,\r
377 SystemTable,\r
378 &gDriverBinding,\r
379 ImageHandle,\r
380 &gComponentName,\r
381 &gComponentName2\r
382 );\r
383}\r