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