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 (
463 EfiPciIoAttributeOperationEnable
,
464 (EFI_PCI_IO_ATTRIBUTE_IO
|
465 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
),
468 if (EFI_ERROR (Status
)) {
473 // PCI IO access granted, configure protocol instance
476 Status
= VirtioPciInit (Device
);
477 if (EFI_ERROR (Status
)) {
478 goto RestorePciAttributes
;
482 // Setup complete, attempt to export the driver instance's VirtioDevice
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
)) {
496 VirtioPciUninit (Device
);
498 RestorePciAttributes
:
499 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
500 Device
->OriginalPciAttributes
, NULL
);
503 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
504 This
->DriverBindingHandle
, DeviceHandle
);
514 Stop driving the Virtio PCI device
516 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
517 incorporating this driver (independently of any
520 @param[in] DeviceHandle Stop driving this device.
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
527 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
529 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
530 configuration attributes have been restored.
532 @return Error codes from the OpenProtocol() or
533 CloseProtocol(), UninstallProtocolInterface()
540 VirtioPciDeviceBindingStop (
541 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
542 IN EFI_HANDLE DeviceHandle
,
543 IN UINTN NumberOfChildren
,
544 IN EFI_HANDLE
*ChildHandleBuffer
548 VIRTIO_DEVICE_PROTOCOL
*VirtioDevice
;
549 VIRTIO_PCI_DEVICE
*Device
;
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
559 if (EFI_ERROR (Status
)) {
563 Device
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice
);
566 // Handle Stop() requests for in-use driver instances gracefully.
568 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
569 &gVirtioDeviceProtocolGuid
, &Device
->VirtioDevice
);
570 if (EFI_ERROR (Status
)) {
574 VirtioPciUninit (Device
);
576 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
577 Device
->OriginalPciAttributes
, NULL
);
579 Status
= gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
580 This
->DriverBindingHandle
, DeviceHandle
);
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.
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
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.
612 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
613 { "eng;en", L
"Virtio PCI Driver" },
618 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
622 VirtioPciGetDriverName (
623 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
625 OUT CHAR16
**DriverName
628 return LookupUnicodeString2 (
630 This
->SupportedLanguages
,
633 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
639 VirtioPciGetDeviceName (
640 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
641 IN EFI_HANDLE DeviceHandle
,
642 IN EFI_HANDLE ChildHandle
,
644 OUT CHAR16
**ControllerName
647 return EFI_UNSUPPORTED
;
651 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
652 &VirtioPciGetDriverName
,
653 &VirtioPciGetDeviceName
,
654 "eng" // SupportedLanguages, ISO 639-2 language codes
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
666 // Entry point of this driver.
670 VirtioPciDeviceEntryPoint (
671 IN EFI_HANDLE ImageHandle
,
672 IN EFI_SYSTEM_TABLE
*SystemTable
675 return EfiLibInstallDriverBindingComponentName2 (