]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute
[mirror_edk2.git] / OvmfPkg / VirtioPciDeviceDxe / VirtioPciDevice.c
1 /** @file
2
3 This driver produces Virtio Device Protocol instances for Virtio PCI devices.
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
9 This program and the accompanying materials are licensed and made available
10 under the terms and conditions of the BSD License which accompanies this
11 distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
15 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 **/
18
19 #include <IndustryStandard/Pci.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/UefiLib.h>
25
26 #include "VirtioPciDevice.h"
27
28 STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {
29 0, // Revision
30 0, // SubSystemDeviceId
31 VirtioPciGetDeviceFeatures, // GetDeviceFeatures
32 VirtioPciSetGuestFeatures, // SetGuestFeatures
33 VirtioPciSetQueueAddress, // SetQueueAddress
34 VirtioPciSetQueueSel, // SetQueueSel
35 VirtioPciSetQueueNotify, // SetQueueNotify
36 VirtioPciSetQueueAlignment, // SetQueueAlignment
37 VirtioPciSetPageSize, // SetPageSize
38 VirtioPciGetQueueSize, // GetQueueNumMax
39 VirtioPciSetQueueSize, // SetQueueNum
40 VirtioPciGetDeviceStatus, // GetDeviceStatus
41 VirtioPciSetDeviceStatus, // SetDeviceStatus
42 VirtioPciDeviceWrite, // WriteDevice
43 VirtioPciDeviceRead // ReadDevice
44 };
45
46 /**
47
48 Read a word from Region 0 of the device specified by PciIo.
49
50 Region 0 must be an iomem region. This is an internal function for the PCI
51 implementation of the protocol.
52
53 @param[in] Dev Virtio PCI device.
54
55 @param[in] FieldOffset Source offset.
56
57 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
58
59 @param[in] BufferSize Number of bytes available in the target buffer. Must
60 equal FieldSize.
61
62 @param[out] Buffer Target buffer.
63
64
65 @return Status code returned by PciIo->Io.Read().
66
67 **/
68 EFI_STATUS
69 EFIAPI
70 VirtioPciIoRead (
71 IN VIRTIO_PCI_DEVICE *Dev,
72 IN UINTN FieldOffset,
73 IN UINTN FieldSize,
74 IN UINTN BufferSize,
75 OUT VOID *Buffer
76 )
77 {
78 UINTN Count;
79 EFI_PCI_IO_PROTOCOL_WIDTH Width;
80 EFI_PCI_IO_PROTOCOL *PciIo;
81
82 ASSERT (FieldSize == BufferSize);
83
84 PciIo = Dev->PciIo;
85 Count = 1;
86
87 switch (FieldSize) {
88 case 1:
89 Width = EfiPciIoWidthUint8;
90 break;
91
92 case 2:
93 Width = EfiPciIoWidthUint16;
94 break;
95
96 case 8:
97 //
98 // The 64bit PCI I/O is broken down into two 32bit reads to prevent
99 // any alignment or width issues.
100 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
101 //
102 // The I/O operations are carried out exactly as requested. The caller
103 // is responsible for any alignment and I/O width issues which the
104 // bus, device, platform, or type of I/O might require. For example on
105 // some platforms, width requests of EfiPciIoWidthUint64 do not work.
106 //
107 Count = 2;
108
109 //
110 // fall through
111 //
112 case 4:
113 Width = EfiPciIoWidthUint32;
114 break;
115
116 default:
117 ASSERT (FALSE);
118 return EFI_INVALID_PARAMETER;
119 }
120
121 return PciIo->Io.Read (
122 PciIo,
123 Width,
124 PCI_BAR_IDX0,
125 FieldOffset,
126 Count,
127 Buffer
128 );
129 }
130
131 /**
132
133 Write a word into Region 0 of the device specified by PciIo.
134
135 Region 0 must be an iomem region. This is an internal function for the PCI
136 implementation of the protocol.
137
138 @param[in] Dev Virtio PCI device.
139
140 @param[in] FieldOffset Destination offset.
141
142 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
143
144 @param[in] Value Little endian value to write, converted to UINT64.
145 The least significant FieldSize bytes will be used.
146
147
148 @return Status code returned by PciIo->Io.Write().
149
150 **/
151 EFI_STATUS
152 EFIAPI
153 VirtioPciIoWrite (
154 IN VIRTIO_PCI_DEVICE *Dev,
155 IN UINTN FieldOffset,
156 IN UINTN FieldSize,
157 IN UINT64 Value
158 )
159 {
160 UINTN Count;
161 EFI_PCI_IO_PROTOCOL_WIDTH Width;
162 EFI_PCI_IO_PROTOCOL *PciIo;
163
164 PciIo = Dev->PciIo;
165 Count = 1;
166
167 switch (FieldSize) {
168 case 1:
169 Width = EfiPciIoWidthUint8;
170 break;
171
172 case 2:
173 Width = EfiPciIoWidthUint16;
174 break;
175
176 case 8:
177 //
178 // The 64bit PCI I/O is broken down into two 32bit writes to prevent
179 // any alignment or width issues.
180 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
181 //
182 // The I/O operations are carried out exactly as requested. The caller
183 // is responsible for any alignment and I/O width issues which the
184 // bus, device, platform, or type of I/O might require. For example on
185 // some platforms, width requests of EfiPciIoWidthUint64 do not work
186 //
187 Count = Count * 2;
188
189 //
190 // fall through
191 //
192 case 4:
193 Width = EfiPciIoWidthUint32;
194 break;
195
196 default:
197 ASSERT (FALSE);
198 return EFI_INVALID_PARAMETER;
199 }
200
201 return PciIo->Io.Write (
202 PciIo,
203 Width,
204 PCI_BAR_IDX0,
205 FieldOffset,
206 Count,
207 &Value
208 );
209 }
210
211 /**
212
213 Device probe function for this driver.
214
215 The DXE core calls this function for any given device in order to see if the
216 driver can drive the device.
217
218 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
219 incorporating this driver (independently of
220 any device).
221
222 @param[in] DeviceHandle The device to probe.
223
224 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
225
226
227 @retval EFI_SUCCESS The driver supports the device being probed.
228
229 @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support
230 the device.
231
232 @return Error codes from the OpenProtocol() boot service or
233 the PciIo protocol.
234
235 **/
236 STATIC
237 EFI_STATUS
238 EFIAPI
239 VirtioPciDeviceBindingSupported (
240 IN EFI_DRIVER_BINDING_PROTOCOL *This,
241 IN EFI_HANDLE DeviceHandle,
242 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
243 )
244 {
245 EFI_STATUS Status;
246 EFI_PCI_IO_PROTOCOL *PciIo;
247 PCI_TYPE00 Pci;
248
249 //
250 // Attempt to open the device with the PciIo set of interfaces. On success,
251 // the protocol is "instantiated" for the PCI device. Covers duplicate open
252 // attempts (EFI_ALREADY_STARTED).
253 //
254 Status = gBS->OpenProtocol (
255 DeviceHandle, // candidate device
256 &gEfiPciIoProtocolGuid, // for generic PCI access
257 (VOID **)&PciIo, // handle to instantiate
258 This->DriverBindingHandle, // requestor driver identity
259 DeviceHandle, // ControllerHandle, according to
260 // the UEFI Driver Model
261 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to
262 // the device; to be released
263 );
264 if (EFI_ERROR (Status)) {
265 return Status;
266 }
267
268 //
269 // Read entire PCI configuration header for more extensive check ahead.
270 //
271 Status = PciIo->Pci.Read (
272 PciIo, // (protocol, device)
273 // handle
274 EfiPciIoWidthUint32, // access width & copy
275 // mode
276 0, // Offset
277 sizeof Pci / sizeof (UINT32), // Count
278 &Pci // target buffer
279 );
280
281 if (Status == EFI_SUCCESS) {
282 //
283 // virtio-0.9.5, 2.1 PCI Discovery
284 //
285 if ((Pci.Hdr.VendorId == VIRTIO_VENDOR_ID) &&
286 (Pci.Hdr.DeviceId >= 0x1000) &&
287 (Pci.Hdr.DeviceId <= 0x103F) &&
288 (Pci.Hdr.RevisionID == 0x00)) {
289 Status = EFI_SUCCESS;
290 } else {
291 Status = EFI_UNSUPPORTED;
292 }
293 }
294
295 //
296 // We needed PCI IO access only transitorily, to see whether we support the
297 // device or not.
298 //
299 gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
300 This->DriverBindingHandle, DeviceHandle);
301
302 return Status;
303 }
304
305 /**
306
307 Initialize the VirtIo PCI Device
308
309 @param[in, out] Dev The driver instance to configure. The caller is
310 responsible for Device->PciIo's validity (ie. working IO
311 access to the underlying virtio-pci device).
312
313 @retval EFI_SUCCESS Setup complete.
314
315 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
316 provided address offset and read size.
317
318 @return Error codes from PciIo->Pci.Read().
319
320 **/
321 STATIC
322 EFI_STATUS
323 EFIAPI
324 VirtioPciInit (
325 IN OUT VIRTIO_PCI_DEVICE *Device
326 )
327 {
328 EFI_STATUS Status;
329 EFI_PCI_IO_PROTOCOL *PciIo;
330 PCI_TYPE00 Pci;
331
332 ASSERT (Device != NULL);
333 PciIo = Device->PciIo;
334 ASSERT (PciIo != NULL);
335 ASSERT (PciIo->Pci.Read != NULL);
336
337 Status = PciIo->Pci.Read (
338 PciIo, // (protocol, device)
339 // handle
340 EfiPciIoWidthUint32, // access width & copy
341 // mode
342 0, // Offset
343 sizeof (Pci) / sizeof (UINT32), // Count
344 &Pci // target buffer
345 );
346 if (EFI_ERROR (Status)) {
347 return Status;
348 }
349
350 //
351 // Copy protocol template
352 //
353 CopyMem (&Device->VirtioDevice, &mDeviceProtocolTemplate,
354 sizeof (VIRTIO_DEVICE_PROTOCOL));
355
356 //
357 // Initialize the protocol interface attributes
358 //
359 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);
360 Device->VirtioDevice.SubSystemDeviceId = Pci.Device.SubsystemID;
361
362 //
363 // Note: We don't support the MSI-X capability. If we did,
364 // the offset would become 24 after enabling MSI-X.
365 //
366 Device->DeviceSpecificConfigurationOffset =
367 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;
368
369 return EFI_SUCCESS;
370 }
371
372 /**
373
374 Uninitialize the internals of a virtio-pci device that has been successfully
375 set up with VirtioPciInit().
376
377 @param[in, out] Dev The device to clean up.
378
379 **/
380
381 STATIC
382 VOID
383 EFIAPI
384 VirtioPciUninit (
385 IN OUT VIRTIO_PCI_DEVICE *Device
386 )
387 {
388 // Note: This function mirrors VirtioPciInit() that does not allocate any
389 // resources - there's nothing to free here.
390 }
391
392 /**
393
394 After we've pronounced support for a specific device in
395 DriverBindingSupported(), we start managing said device (passed in by the
396 Driver Execution Environment) with the following service.
397
398 See DriverBindingSupported() for specification references.
399
400 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
401 incorporating this driver (independently of
402 any device).
403
404 @param[in] DeviceHandle The supported device to drive.
405
406 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
407
408
409 @retval EFI_SUCCESS Driver instance has been created and
410 initialized for the virtio-pci device, it
411 is now accessible via VIRTIO_DEVICE_PROTOCOL.
412
413 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
414
415 @return Error codes from the OpenProtocol() boot
416 service, the PciIo protocol, VirtioPciInit(),
417 or the InstallProtocolInterface() boot service.
418
419 **/
420 STATIC
421 EFI_STATUS
422 EFIAPI
423 VirtioPciDeviceBindingStart (
424 IN EFI_DRIVER_BINDING_PROTOCOL *This,
425 IN EFI_HANDLE DeviceHandle,
426 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
427 )
428 {
429 VIRTIO_PCI_DEVICE *Device;
430 EFI_STATUS Status;
431
432 Device = (VIRTIO_PCI_DEVICE *) AllocateZeroPool (sizeof *Device);
433 if (Device == NULL) {
434 return EFI_OUT_OF_RESOURCES;
435 }
436
437 Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
438 (VOID **)&Device->PciIo, This->DriverBindingHandle,
439 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
440 if (EFI_ERROR (Status)) {
441 goto FreeVirtioPci;
442 }
443
444 //
445 // We must retain and ultimately restore the original PCI attributes of the
446 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
447 // 18.3.2 Start() and Stop().
448 //
449 // The third parameter ("Attributes", input) is ignored by the Get operation.
450 // The fourth parameter ("Result", output) is ignored by the Enable and Set
451 // operations.
452 //
453 // For virtio-pci we only need IO space access.
454 //
455 Status = Device->PciIo->Attributes (Device->PciIo,
456 EfiPciIoAttributeOperationGet, 0, &Device->OriginalPciAttributes);
457 if (EFI_ERROR (Status)) {
458 goto ClosePciIo;
459 }
460
461 Status = Device->PciIo->Attributes (
462 Device->PciIo,
463 EfiPciIoAttributeOperationEnable,
464 (EFI_PCI_IO_ATTRIBUTE_IO |
465 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
466 NULL
467 );
468 if (EFI_ERROR (Status)) {
469 goto ClosePciIo;
470 }
471
472 //
473 // PCI IO access granted, configure protocol instance
474 //
475
476 Status = VirtioPciInit (Device);
477 if (EFI_ERROR (Status)) {
478 goto RestorePciAttributes;
479 }
480
481 //
482 // Setup complete, attempt to export the driver instance's VirtioDevice
483 // interface.
484 //
485 Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE;
486 Status = gBS->InstallProtocolInterface (&DeviceHandle,
487 &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,
488 &Device->VirtioDevice);
489 if (EFI_ERROR (Status)) {
490 goto UninitDev;
491 }
492
493 return EFI_SUCCESS;
494
495 UninitDev:
496 VirtioPciUninit (Device);
497
498 RestorePciAttributes:
499 Device->PciIo->Attributes (Device->PciIo, EfiPciIoAttributeOperationSet,
500 Device->OriginalPciAttributes, NULL);
501
502 ClosePciIo:
503 gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
504 This->DriverBindingHandle, DeviceHandle);
505
506 FreeVirtioPci:
507 FreePool (Device);
508
509 return Status;
510 }
511
512 /**
513
514 Stop driving the Virtio PCI device
515
516 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
517 incorporating this driver (independently of any
518 device).
519
520 @param[in] DeviceHandle Stop driving this device.
521
522 @param[in] NumberOfChildren Since this function belongs to a device driver
523 only (as opposed to a bus driver), the caller
524 environment sets NumberOfChildren to zero, and
525 we ignore it.
526
527 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
528
529 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
530 configuration attributes have been restored.
531
532 @return Error codes from the OpenProtocol() or
533 CloseProtocol(), UninstallProtocolInterface()
534 boot services.
535
536 **/
537 STATIC
538 EFI_STATUS
539 EFIAPI
540 VirtioPciDeviceBindingStop (
541 IN EFI_DRIVER_BINDING_PROTOCOL *This,
542 IN EFI_HANDLE DeviceHandle,
543 IN UINTN NumberOfChildren,
544 IN EFI_HANDLE *ChildHandleBuffer
545 )
546 {
547 EFI_STATUS Status;
548 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;
549 VIRTIO_PCI_DEVICE *Device;
550
551 Status = gBS->OpenProtocol (
552 DeviceHandle, // candidate device
553 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface
554 (VOID **)&VirtioDevice, // target pointer
555 This->DriverBindingHandle, // requestor driver identity
556 DeviceHandle, // requesting lookup for dev.
557 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
558 );
559 if (EFI_ERROR (Status)) {
560 return Status;
561 }
562
563 Device = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);
564
565 //
566 // Handle Stop() requests for in-use driver instances gracefully.
567 //
568 Status = gBS->UninstallProtocolInterface (DeviceHandle,
569 &gVirtioDeviceProtocolGuid, &Device->VirtioDevice);
570 if (EFI_ERROR (Status)) {
571 return Status;
572 }
573
574 VirtioPciUninit (Device);
575
576 Device->PciIo->Attributes (Device->PciIo, EfiPciIoAttributeOperationSet,
577 Device->OriginalPciAttributes, NULL);
578
579 Status = gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
580 This->DriverBindingHandle, DeviceHandle);
581
582 FreePool (Device);
583
584 return Status;
585 }
586
587
588 //
589 // The static object that groups the Supported() (ie. probe), Start() and
590 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
591 // C, 10.1 EFI Driver Binding Protocol.
592 //
593 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
594 &VirtioPciDeviceBindingSupported,
595 &VirtioPciDeviceBindingStart,
596 &VirtioPciDeviceBindingStop,
597 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
598 NULL, // ImageHandle, to be overwritten by
599 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
600 NULL // DriverBindingHandle, ditto
601 };
602
603
604 //
605 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
606 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
607 // in English, for display on standard console devices. This is recommended for
608 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
609 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
610 //
611 STATIC
612 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
613 { "eng;en", L"Virtio PCI Driver" },
614 { NULL, NULL }
615 };
616
617 STATIC
618 EFI_COMPONENT_NAME_PROTOCOL gComponentName;
619
620 EFI_STATUS
621 EFIAPI
622 VirtioPciGetDriverName (
623 IN EFI_COMPONENT_NAME_PROTOCOL *This,
624 IN CHAR8 *Language,
625 OUT CHAR16 **DriverName
626 )
627 {
628 return LookupUnicodeString2 (
629 Language,
630 This->SupportedLanguages,
631 mDriverNameTable,
632 DriverName,
633 (BOOLEAN)(This == &gComponentName) // Iso639Language
634 );
635 }
636
637 EFI_STATUS
638 EFIAPI
639 VirtioPciGetDeviceName (
640 IN EFI_COMPONENT_NAME_PROTOCOL *This,
641 IN EFI_HANDLE DeviceHandle,
642 IN EFI_HANDLE ChildHandle,
643 IN CHAR8 *Language,
644 OUT CHAR16 **ControllerName
645 )
646 {
647 return EFI_UNSUPPORTED;
648 }
649
650 STATIC
651 EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
652 &VirtioPciGetDriverName,
653 &VirtioPciGetDeviceName,
654 "eng" // SupportedLanguages, ISO 639-2 language codes
655 };
656
657 STATIC
658 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
659 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioPciGetDriverName,
660 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioPciGetDeviceName,
661 "en" // SupportedLanguages, RFC 4646 language codes
662 };
663
664
665 //
666 // Entry point of this driver.
667 //
668 EFI_STATUS
669 EFIAPI
670 VirtioPciDeviceEntryPoint (
671 IN EFI_HANDLE ImageHandle,
672 IN EFI_SYSTEM_TABLE *SystemTable
673 )
674 {
675 return EfiLibInstallDriverBindingComponentName2 (
676 ImageHandle,
677 SystemTable,
678 &gDriverBinding,
679 ImageHandle,
680 &gComponentName,
681 &gComponentName2
682 );
683 }