3 This driver produces Virtio Device Protocol instances for Virtio PCI devices.
5 Copyright (C) 2012, Red Hat, Inc.
6 Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
7 Copyright (C) 2013, ARM Ltd.
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
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.
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>
26 #include "VirtioPciDevice.h"
28 STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate
= {
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
48 Read a word from Region 0 of the device specified by PciIo.
50 Region 0 must be an iomem region. This is an internal function for the PCI
51 implementation of the protocol.
53 @param[in] Dev Virtio PCI device.
55 @param[in] FieldOffset Source offset.
57 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
59 @param[in] BufferSize Number of bytes available in the target buffer. Must
62 @param[out] Buffer Target buffer.
65 @return Status code returned by PciIo->Io.Read().
71 IN VIRTIO_PCI_DEVICE
*Dev
,
79 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
80 EFI_PCI_IO_PROTOCOL
*PciIo
;
82 ASSERT (FieldSize
== BufferSize
);
89 Width
= EfiPciIoWidthUint8
;
93 Width
= EfiPciIoWidthUint16
;
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():
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.
113 Width
= EfiPciIoWidthUint32
;
118 return EFI_INVALID_PARAMETER
;
121 return PciIo
->Io
.Read (
133 Write a word into Region 0 of the device specified by PciIo.
135 Region 0 must be an iomem region. This is an internal function for the PCI
136 implementation of the protocol.
138 @param[in] Dev Virtio PCI device.
140 @param[in] FieldOffset Destination offset.
142 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
144 @param[in] Value Little endian value to write, converted to UINT64.
145 The least significant FieldSize bytes will be used.
148 @return Status code returned by PciIo->Io.Write().
154 IN VIRTIO_PCI_DEVICE
*Dev
,
155 IN UINTN FieldOffset
,
161 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
162 EFI_PCI_IO_PROTOCOL
*PciIo
;
169 Width
= EfiPciIoWidthUint8
;
173 Width
= EfiPciIoWidthUint16
;
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():
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
193 Width
= EfiPciIoWidthUint32
;
198 return EFI_INVALID_PARAMETER
;
201 return PciIo
->Io
.Write (
213 Device probe function for this driver.
215 The DXE core calls this function for any given device in order to see if the
216 driver can drive the device.
218 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
219 incorporating this driver (independently of
222 @param[in] DeviceHandle The device to probe.
224 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
227 @retval EFI_SUCCESS The driver supports the device being probed.
229 @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support
232 @return Error codes from the OpenProtocol() boot service or
239 VirtioPciDeviceBindingSupported (
240 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
241 IN EFI_HANDLE DeviceHandle
,
242 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
246 EFI_PCI_IO_PROTOCOL
*PciIo
;
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).
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
264 if (EFI_ERROR (Status
)) {
269 // Read entire PCI configuration header for more extensive check ahead.
271 Status
= PciIo
->Pci
.Read (
272 PciIo
, // (protocol, device)
274 EfiPciIoWidthUint32
, // access width & copy
277 sizeof Pci
/ sizeof (UINT32
), // Count
278 &Pci
// target buffer
281 if (Status
== EFI_SUCCESS
) {
283 // virtio-0.9.5, 2.1 PCI Discovery
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
;
291 Status
= EFI_UNSUPPORTED
;
296 // We needed PCI IO access only transitorily, to see whether we support the
299 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
300 This
->DriverBindingHandle
, DeviceHandle
);
307 Initialize the VirtIo PCI Device
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).
313 @retval EFI_SUCCESS Setup complete.
315 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
316 provided address offset and read size.
318 @return Error codes from PciIo->Pci.Read().
325 IN OUT VIRTIO_PCI_DEVICE
*Device
329 EFI_PCI_IO_PROTOCOL
*PciIo
;
332 ASSERT (Device
!= NULL
);
333 PciIo
= Device
->PciIo
;
334 ASSERT (PciIo
!= NULL
);
335 ASSERT (PciIo
->Pci
.Read
!= NULL
);
337 Status
= PciIo
->Pci
.Read (
338 PciIo
, // (protocol, device)
340 EfiPciIoWidthUint32
, // access width & copy
343 sizeof (Pci
) / sizeof (UINT32
), // Count
344 &Pci
// target buffer
346 if (EFI_ERROR (Status
)) {
351 // Copy protocol template
353 CopyMem (&Device
->VirtioDevice
, &mDeviceProtocolTemplate
,
354 sizeof (VIRTIO_DEVICE_PROTOCOL
));
357 // Initialize the protocol interface attributes
359 Device
->VirtioDevice
.Revision
= VIRTIO_SPEC_REVISION (0, 9, 5);
360 Device
->VirtioDevice
.SubSystemDeviceId
= Pci
.Device
.SubsystemID
;
363 // Note: We don't support the MSI-X capability. If we did,
364 // the offset would become 24 after enabling MSI-X.
366 Device
->DeviceSpecificConfigurationOffset
=
367 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI
;
374 Uninitialize the internals of a virtio-pci device that has been successfully
375 set up with VirtioPciInit().
377 @param[in, out] Dev The device to clean up.
385 IN OUT VIRTIO_PCI_DEVICE
*Device
388 // Note: This function mirrors VirtioPciInit() that does not allocate any
389 // resources - there's nothing to free here.
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.
398 See DriverBindingSupported() for specification references.
400 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
401 incorporating this driver (independently of
404 @param[in] DeviceHandle The supported device to drive.
406 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
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.
413 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
415 @return Error codes from the OpenProtocol() boot
416 service, the PciIo protocol, VirtioPciInit(),
417 or the InstallProtocolInterface() boot service.
423 VirtioPciDeviceBindingStart (
424 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
425 IN EFI_HANDLE DeviceHandle
,
426 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
429 VIRTIO_PCI_DEVICE
*Device
;
432 Device
= (VIRTIO_PCI_DEVICE
*) AllocateZeroPool (sizeof *Device
);
433 if (Device
== NULL
) {
434 return EFI_OUT_OF_RESOURCES
;
437 Status
= gBS
->OpenProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
438 (VOID
**)&Device
->PciIo
, This
->DriverBindingHandle
,
439 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
440 if (EFI_ERROR (Status
)) {
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().
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
453 // For virtio-pci we only need IO space access.
455 Status
= Device
->PciIo
->Attributes (Device
->PciIo
,
456 EfiPciIoAttributeOperationGet
, 0, &Device
->OriginalPciAttributes
);
457 if (EFI_ERROR (Status
)) {
461 Status
= Device
->PciIo
->Attributes (Device
->PciIo
,
462 EfiPciIoAttributeOperationEnable
,
463 EFI_PCI_IO_ATTRIBUTE_IO
, NULL
);
464 if (EFI_ERROR (Status
)) {
469 // PCI IO access granted, configure protocol instance
472 Status
= VirtioPciInit (Device
);
473 if (EFI_ERROR (Status
)) {
474 goto RestorePciAttributes
;
478 // Setup complete, attempt to export the driver instance's VirtioDevice
481 Device
->Signature
= VIRTIO_PCI_DEVICE_SIGNATURE
;
482 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
483 &gVirtioDeviceProtocolGuid
, EFI_NATIVE_INTERFACE
,
484 &Device
->VirtioDevice
);
485 if (EFI_ERROR (Status
)) {
492 VirtioPciUninit (Device
);
494 RestorePciAttributes
:
495 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
496 Device
->OriginalPciAttributes
, NULL
);
499 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
500 This
->DriverBindingHandle
, DeviceHandle
);
510 Stop driving the Virtio PCI device
512 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
513 incorporating this driver (independently of any
516 @param[in] DeviceHandle Stop driving this device.
518 @param[in] NumberOfChildren Since this function belongs to a device driver
519 only (as opposed to a bus driver), the caller
520 environment sets NumberOfChildren to zero, and
523 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
525 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
526 configuration attributes have been restored.
528 @return Error codes from the OpenProtocol() or
529 CloseProtocol(), UninstallProtocolInterface()
536 VirtioPciDeviceBindingStop (
537 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
538 IN EFI_HANDLE DeviceHandle
,
539 IN UINTN NumberOfChildren
,
540 IN EFI_HANDLE
*ChildHandleBuffer
544 VIRTIO_DEVICE_PROTOCOL
*VirtioDevice
;
545 VIRTIO_PCI_DEVICE
*Device
;
547 Status
= gBS
->OpenProtocol (
548 DeviceHandle
, // candidate device
549 &gVirtioDeviceProtocolGuid
, // retrieve the VirtIo iface
550 (VOID
**)&VirtioDevice
, // target pointer
551 This
->DriverBindingHandle
, // requestor driver identity
552 DeviceHandle
, // requesting lookup for dev.
553 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
555 if (EFI_ERROR (Status
)) {
559 Device
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice
);
562 // Handle Stop() requests for in-use driver instances gracefully.
564 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
565 &gVirtioDeviceProtocolGuid
, &Device
->VirtioDevice
);
566 if (EFI_ERROR (Status
)) {
570 VirtioPciUninit (Device
);
572 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
573 Device
->OriginalPciAttributes
, NULL
);
575 Status
= gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
576 This
->DriverBindingHandle
, DeviceHandle
);
585 // The static object that groups the Supported() (ie. probe), Start() and
586 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
587 // C, 10.1 EFI Driver Binding Protocol.
589 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
590 &VirtioPciDeviceBindingSupported
,
591 &VirtioPciDeviceBindingStart
,
592 &VirtioPciDeviceBindingStop
,
593 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
594 NULL
, // ImageHandle, to be overwritten by
595 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
596 NULL
// DriverBindingHandle, ditto
601 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
602 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
603 // in English, for display on standard console devices. This is recommended for
604 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
605 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
608 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
609 { "eng;en", L
"Virtio PCI Driver" },
614 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
618 VirtioPciGetDriverName (
619 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
621 OUT CHAR16
**DriverName
624 return LookupUnicodeString2 (
626 This
->SupportedLanguages
,
629 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
635 VirtioPciGetDeviceName (
636 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
637 IN EFI_HANDLE DeviceHandle
,
638 IN EFI_HANDLE ChildHandle
,
640 OUT CHAR16
**ControllerName
643 return EFI_UNSUPPORTED
;
647 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
648 &VirtioPciGetDriverName
,
649 &VirtioPciGetDeviceName
,
650 "eng" // SupportedLanguages, ISO 639-2 language codes
654 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
655 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioPciGetDriverName
,
656 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioPciGetDeviceName
,
657 "en" // SupportedLanguages, RFC 4646 language codes
662 // Entry point of this driver.
666 VirtioPciDeviceEntryPoint (
667 IN EFI_HANDLE ImageHandle
,
668 IN EFI_SYSTEM_TABLE
*SystemTable
671 return EfiLibInstallDriverBindingComponentName2 (