]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenIoPciDxe/XenIoPciDxe.c
UefiCpuPkg CpuCommFeaturesLib: Fix GP fault issue about ProcTrace
[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
25#define PCI_VENDOR_ID_XEN 0x5853\r
26#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001\r
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
56 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
57 IN EFI_HANDLE DeviceHandle,\r
58 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
59 )\r
60{\r
61 EFI_STATUS Status;\r
62 EFI_PCI_IO_PROTOCOL *PciIo;\r
63 PCI_TYPE00 Pci;\r
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
99 (Pci.Hdr.DeviceId == PCI_DEVICE_ID_XEN_PLATFORM)) {\r
100 Status = EFI_SUCCESS;\r
101 } else {\r
102 Status = EFI_UNSUPPORTED;\r
103 }\r
104 }\r
105\r
106 //\r
107 // We needed PCI IO access only transitorily, to see whether we support the\r
108 // device or not.\r
109 //\r
110 gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
111 This->DriverBindingHandle, DeviceHandle);\r
112\r
113 return Status;\r
114}\r
115\r
116/**\r
117\r
118 After we've pronounced support for a specific device in\r
119 DriverBindingSupported(), we start managing said device (passed in by the\r
694673c9 120 Driver Execution Environment) with the following service.\r
f2162d34
AB
121\r
122 See DriverBindingSupported() for specification references.\r
123\r
124 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
125 incorporating this driver (independently of\r
126 any device).\r
127\r
128 @param[in] DeviceHandle The supported device to drive.\r
129\r
130 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.\r
131\r
132\r
133 @retval EFI_SUCCESS The device was started.\r
134\r
135 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
136\r
137 @return Error codes from the OpenProtocol() boot\r
138 service, the PciIo protocol or the\r
139 InstallProtocolInterface() boot service.\r
140\r
141**/\r
142STATIC\r
143EFI_STATUS\r
144EFIAPI\r
145XenIoPciDeviceBindingStart (\r
146 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
147 IN EFI_HANDLE DeviceHandle,\r
148 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
149 )\r
150{\r
151 EFI_STATUS Status;\r
152 XENIO_PROTOCOL *XenIo;\r
153 EFI_PCI_IO_PROTOCOL *PciIo;\r
154 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;\r
155\r
156 XenIo = (XENIO_PROTOCOL *) AllocateZeroPool (sizeof *XenIo);\r
157 if (XenIo == NULL) {\r
158 return EFI_OUT_OF_RESOURCES;\r
159 }\r
160\r
161 Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
162 (VOID **)&PciIo, This->DriverBindingHandle,\r
163 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
164 if (EFI_ERROR (Status)) {\r
165 goto FreeXenIo;\r
166 }\r
167\r
168 //\r
169 // The BAR1 of this PCI device is used for shared memory and is supposed to\r
170 // look like MMIO. The address space of the BAR1 will be used to map the\r
171 // Grant Table.\r
172 //\r
173 Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc);\r
174 ASSERT_EFI_ERROR (Status);\r
175 ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);\r
176\r
177 /* Get a Memory address for mapping the Grant Table. */\r
178 DEBUG ((EFI_D_INFO, "XenIoPci: BAR at %LX\n", BarDesc->AddrRangeMin));\r
179 XenIo->GrantTableAddress = BarDesc->AddrRangeMin;\r
180 FreePool (BarDesc);\r
181\r
182 Status = gBS->InstallProtocolInterface (&DeviceHandle,\r
183 &gXenIoProtocolGuid, EFI_NATIVE_INTERFACE, XenIo);\r
184\r
185 if (!EFI_ERROR (Status)) {\r
186 return EFI_SUCCESS;\r
187 }\r
188\r
189 gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
190 This->DriverBindingHandle, DeviceHandle);\r
191\r
192FreeXenIo:\r
193 FreePool (XenIo);\r
194\r
195 return Status;\r
196}\r
197\r
198/**\r
199\r
200 Stop driving the XenIo PCI device\r
201\r
202 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
203 incorporating this driver (independently of any\r
204 device).\r
205\r
206 @param[in] DeviceHandle Stop driving this device.\r
207\r
208 @param[in] NumberOfChildren Since this function belongs to a device driver\r
209 only (as opposed to a bus driver), the caller\r
210 environment sets NumberOfChildren to zero, and\r
211 we ignore it.\r
212\r
213 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).\r
214\r
215 @retval EFI_SUCCESS Driver instance has been stopped and the PCI\r
216 configuration attributes have been restored.\r
217\r
218 @return Error codes from the OpenProtocol() or\r
219 CloseProtocol(), UninstallProtocolInterface()\r
220 boot services.\r
221\r
222**/\r
223STATIC\r
224EFI_STATUS\r
225EFIAPI\r
226XenIoPciDeviceBindingStop (\r
227 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
228 IN EFI_HANDLE DeviceHandle,\r
229 IN UINTN NumberOfChildren,\r
230 IN EFI_HANDLE *ChildHandleBuffer\r
231 )\r
232{\r
233 EFI_STATUS Status;\r
234 XENIO_PROTOCOL *XenIo;\r
235\r
236 Status = gBS->OpenProtocol (\r
237 DeviceHandle, // candidate device\r
238 &gXenIoProtocolGuid, // retrieve the XenIo iface\r
239 (VOID **)&XenIo, // target pointer\r
240 This->DriverBindingHandle, // requestor driver identity\r
241 DeviceHandle, // requesting lookup for dev.\r
242 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
243 );\r
244 if (EFI_ERROR (Status)) {\r
245 return Status;\r
246 }\r
247\r
248 //\r
249 // Handle Stop() requests for in-use driver instances gracefully.\r
250 //\r
251 Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
252 &gXenIoProtocolGuid, XenIo);\r
253 if (EFI_ERROR (Status)) {\r
254 return Status;\r
255 }\r
256\r
257 Status = gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
258 This->DriverBindingHandle, DeviceHandle);\r
259\r
260 FreePool (XenIo);\r
261\r
262 return Status;\r
263}\r
264\r
265\r
266//\r
267// The static object that groups the Supported() (ie. probe), Start() and\r
268// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
269// C, 10.1 EFI Driver Binding Protocol.\r
270//\r
271STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
272 &XenIoPciDeviceBindingSupported,\r
273 &XenIoPciDeviceBindingStart,\r
274 &XenIoPciDeviceBindingStop,\r
275 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers\r
276 NULL, // ImageHandle, to be overwritten by\r
277 // EfiLibInstallDriverBindingComponentName2() in XenIoPciDeviceEntryPoint()\r
278 NULL // DriverBindingHandle, ditto\r
279};\r
280\r
281\r
282//\r
283// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and\r
284// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name\r
285// in English, for display on standard console devices. This is recommended for\r
286// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's\r
287// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.\r
288//\r
289STATIC\r
290EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
291 { "eng;en", L"XenIo PCI Driver" },\r
292 { NULL, NULL }\r
293};\r
294\r
295STATIC\r
296EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
297\r
298EFI_STATUS\r
299EFIAPI\r
300XenIoPciGetDriverName (\r
301 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
302 IN CHAR8 *Language,\r
303 OUT CHAR16 **DriverName\r
304 )\r
305{\r
306 return LookupUnicodeString2 (\r
307 Language,\r
308 This->SupportedLanguages,\r
309 mDriverNameTable,\r
310 DriverName,\r
311 (BOOLEAN)(This == &gComponentName) // Iso639Language\r
312 );\r
313}\r
314\r
315EFI_STATUS\r
316EFIAPI\r
317XenIoPciGetDeviceName (\r
318 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
319 IN EFI_HANDLE DeviceHandle,\r
320 IN EFI_HANDLE ChildHandle,\r
321 IN CHAR8 *Language,\r
322 OUT CHAR16 **ControllerName\r
323 )\r
324{\r
325 return EFI_UNSUPPORTED;\r
326}\r
327\r
328STATIC\r
329EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
330 &XenIoPciGetDriverName,\r
331 &XenIoPciGetDeviceName,\r
332 "eng" // SupportedLanguages, ISO 639-2 language codes\r
333};\r
334\r
335STATIC\r
336EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
337 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &XenIoPciGetDriverName,\r
338 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &XenIoPciGetDeviceName,\r
339 "en" // SupportedLanguages, RFC 4646 language codes\r
340};\r
341\r
342\r
343//\r
344// Entry point of this driver.\r
345//\r
346EFI_STATUS\r
347EFIAPI\r
348XenIoPciDeviceEntryPoint (\r
349 IN EFI_HANDLE ImageHandle,\r
350 IN EFI_SYSTEM_TABLE *SystemTable\r
351 )\r
352{\r
353 return EfiLibInstallDriverBindingComponentName2 (\r
354 ImageHandle,\r
355 SystemTable,\r
356 &gDriverBinding,\r
357 ImageHandle,\r
358 &gComponentName,\r
359 &gComponentName2\r
360 );\r
361}\r