3 This driver produces Virtio Device Protocol instances for Virtio PCI devices.
5 Copyright (C) 2012, Red Hat, Inc.
6 Copyright (c) 2012, 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 VirtioPciGetQueueAddress
, // GetQueueAddress
34 VirtioPciSetQueueAddress
, // SetQueueAddress
35 VirtioPciSetQueueSel
, // SetQueueSel
36 VirtioPciSetQueueNotify
, // SetQueueNotify
37 VirtioPciSetQueueAlignment
, // SetQueueAlignment
38 VirtioPciSetPageSize
, // SetPageSize
39 VirtioPciGetQueueSize
, // GetQueueNumMax
40 VirtioPciSetQueueSize
, // SetQueueNum
41 VirtioPciGetDeviceStatus
, // GetDeviceStatus
42 VirtioPciSetDeviceStatus
, // SetDeviceStatus
43 VirtioPciDeviceWrite
, // WriteDevice
44 VirtioPciDeviceRead
// ReadDevice
49 Read a word from Region 0 of the device specified by PciIo.
51 Region 0 must be an iomem region. This is an internal function for the PCI
52 implementation of the protocol.
54 @param[in] Dev Virtio PCI device.
56 @param[in] FieldOffset Source offset.
58 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
60 @param[in] BufferSize Number of bytes available in the target buffer. Must
63 @param[out] Buffer Target buffer.
66 @return Status code returned by PciIo->Io.Read().
72 IN VIRTIO_PCI_DEVICE
*Dev
,
80 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
81 EFI_PCI_IO_PROTOCOL
*PciIo
;
83 ASSERT (FieldSize
== BufferSize
);
90 Width
= EfiPciIoWidthUint8
;
94 Width
= EfiPciIoWidthUint16
;
99 // The 64bit PCI I/O is broken down into two 32bit reads to prevent
100 // any alignment or width issues.
101 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
103 // The I/O operations are carried out exactly as requested. The caller
104 // is responsible for any alignment and I/O width issues which the
105 // bus, device, platform, or type of I/O might require. For example on
106 // some platforms, width requests of EfiPciIoWidthUint64 do not work.
114 Width
= EfiPciIoWidthUint32
;
119 return EFI_INVALID_PARAMETER
;
122 return PciIo
->Io
.Read (
134 Write a word into Region 0 of the device specified by PciIo.
136 Region 0 must be an iomem region. This is an internal function for the PCI
137 implementation of the protocol.
139 @param[in] Dev Virtio PCI device.
141 @param[in] FieldOffset Destination offset.
143 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
145 @param[in] Value Little endian value to write, converted to UINT64.
146 The least significant FieldSize bytes will be used.
149 @return Status code returned by PciIo->Io.Write().
155 IN VIRTIO_PCI_DEVICE
*Dev
,
156 IN UINTN FieldOffset
,
162 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
163 EFI_PCI_IO_PROTOCOL
*PciIo
;
170 Width
= EfiPciIoWidthUint8
;
174 Width
= EfiPciIoWidthUint16
;
179 // The 64bit PCI I/O is broken down into two 32bit writes to prevent
180 // any alignment or width issues.
181 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
183 // The I/O operations are carried out exactly as requested. The caller
184 // is responsible for any alignment and I/O width issues which the
185 // bus, device, platform, or type of I/O might require. For example on
186 // some platforms, width requests of EfiPciIoWidthUint64 do not work
194 Width
= EfiPciIoWidthUint32
;
199 return EFI_INVALID_PARAMETER
;
202 return PciIo
->Io
.Write (
214 Device probe function for this driver.
216 The DXE core calls this function for any given device in order to see if the
217 driver can drive the device.
219 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
220 incorporating this driver (independently of
223 @param[in] DeviceHandle The device to probe.
225 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
228 @retval EFI_SUCCESS The driver supports the device being probed.
230 @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support
233 @return Error codes from the OpenProtocol() boot service or
240 VirtioPciDeviceBindingSupported (
241 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
242 IN EFI_HANDLE DeviceHandle
,
243 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
247 EFI_PCI_IO_PROTOCOL
*PciIo
;
251 // Attempt to open the device with the PciIo set of interfaces. On success,
252 // the protocol is "instantiated" for the PCI device. Covers duplicate open
253 // attempts (EFI_ALREADY_STARTED).
255 Status
= gBS
->OpenProtocol (
256 DeviceHandle
, // candidate device
257 &gEfiPciIoProtocolGuid
, // for generic PCI access
258 (VOID
**)&PciIo
, // handle to instantiate
259 This
->DriverBindingHandle
, // requestor driver identity
260 DeviceHandle
, // ControllerHandle, according to
261 // the UEFI Driver Model
262 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive PciIo access to
263 // the device; to be released
265 if (EFI_ERROR (Status
)) {
270 // Read entire PCI configuration header for more extensive check ahead.
272 Status
= PciIo
->Pci
.Read (
273 PciIo
, // (protocol, device)
275 EfiPciIoWidthUint32
, // access width & copy
278 sizeof Pci
/ sizeof (UINT32
), // Count
279 &Pci
// target buffer
282 if (Status
== EFI_SUCCESS
) {
284 // virtio-0.9.5, 2.1 PCI Discovery
286 if ((Pci
.Hdr
.VendorId
== VIRTIO_VENDOR_ID
) &&
287 (Pci
.Hdr
.DeviceId
>= 0x1000) &&
288 (Pci
.Hdr
.DeviceId
<= 0x103F) &&
289 (Pci
.Hdr
.RevisionID
== 0x00)) {
290 Status
= EFI_SUCCESS
;
292 Status
= EFI_UNSUPPORTED
;
297 // We needed PCI IO access only transitorily, to see whether we support the
300 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
301 This
->DriverBindingHandle
, DeviceHandle
);
308 Initialize the VirtIo PCI Device
310 @param[in, out] Dev The driver instance to configure. The caller is
311 responsible for Device->PciIo's validity (ie. working IO
312 access to the underlying virtio-pci device).
314 @retval EFI_SUCCESS Setup complete.
316 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
317 provided address offset and read size.
319 @return Error codes from PciIo->Pci.Read().
326 IN OUT VIRTIO_PCI_DEVICE
*Device
330 EFI_PCI_IO_PROTOCOL
*PciIo
;
333 ASSERT (Device
!= NULL
);
334 PciIo
= Device
->PciIo
;
335 ASSERT (PciIo
!= NULL
);
336 ASSERT (PciIo
->Pci
.Read
!= NULL
);
338 Status
= PciIo
->Pci
.Read (
339 PciIo
, // (protocol, device)
341 EfiPciIoWidthUint32
, // access width & copy
344 sizeof (Pci
) / sizeof (UINT32
), // Count
345 &Pci
// target buffer
347 if (EFI_ERROR (Status
)) {
352 // Copy protocol template
354 CopyMem (&Device
->VirtioDevice
, &mDeviceProtocolTemplate
,
355 sizeof (VIRTIO_DEVICE_PROTOCOL
));
358 // Initialize the protocol interface attributes
360 Device
->VirtioDevice
.Revision
= VIRTIO_SPEC_REVISION (0, 9, 5);
361 Device
->VirtioDevice
.SubSystemDeviceId
= Pci
.Device
.SubsystemID
;
364 // Note: We don't support the MSI-X capability. If we did,
365 // the offset would become 24 after enabling MSI-X.
367 Device
->DeviceSpecificConfigurationOffset
=
368 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI
;
375 Uninitialize the internals of a virtio-pci device that has been successfully
376 set up with VirtioPciInit().
378 @param[in, out] Dev The device to clean up.
386 IN OUT VIRTIO_PCI_DEVICE
*Device
389 // Note: This function mirrors VirtioPciInit() that does not allocate any
390 // resources - there's nothing to free here.
395 After we've pronounced support for a specific device in
396 DriverBindingSupported(), we start managing said device (passed in by the
397 Driver Exeuction Environment) with the following service.
399 See DriverBindingSupported() for specification references.
401 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
402 incorporating this driver (independently of
405 @param[in] DeviceHandle The supported device to drive.
407 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
410 @retval EFI_SUCCESS Driver instance has been created and
411 initialized for the virtio-pci device, it
412 is now accessible via VIRTIO_DEVICE_PROTOCOL.
414 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
416 @return Error codes from the OpenProtocol() boot
417 service, the PciIo protocol, VirtioPciInit(),
418 or the InstallProtocolInterface() boot service.
424 VirtioPciDeviceBindingStart (
425 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
426 IN EFI_HANDLE DeviceHandle
,
427 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
430 VIRTIO_PCI_DEVICE
*Device
;
433 Device
= (VIRTIO_PCI_DEVICE
*) AllocateZeroPool (sizeof *Device
);
434 if (Device
== NULL
) {
435 return EFI_OUT_OF_RESOURCES
;
438 Status
= gBS
->OpenProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
439 (VOID
**)&Device
->PciIo
, This
->DriverBindingHandle
,
440 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
441 if (EFI_ERROR (Status
)) {
446 // We must retain and ultimately restore the original PCI attributes of the
447 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
448 // 18.3.2 Start() and Stop().
450 // The third parameter ("Attributes", input) is ignored by the Get operation.
451 // The fourth parameter ("Result", output) is ignored by the Enable and Set
454 // For virtio-pci we only need IO space access.
456 Status
= Device
->PciIo
->Attributes (Device
->PciIo
,
457 EfiPciIoAttributeOperationGet
, 0, &Device
->OriginalPciAttributes
);
458 if (EFI_ERROR (Status
)) {
462 Status
= Device
->PciIo
->Attributes (Device
->PciIo
,
463 EfiPciIoAttributeOperationEnable
,
464 EFI_PCI_IO_ATTRIBUTE_IO
, NULL
);
465 if (EFI_ERROR (Status
)) {
470 // PCI IO access granted, configure protocol instance
473 Status
= VirtioPciInit (Device
);
474 if (EFI_ERROR (Status
)) {
475 goto RestorePciAttributes
;
479 // Setup complete, attempt to export the driver instance's VirtioDevice
482 Device
->Signature
= VIRTIO_PCI_DEVICE_SIGNATURE
;
483 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
484 &gVirtioDeviceProtocolGuid
, EFI_NATIVE_INTERFACE
,
485 &Device
->VirtioDevice
);
486 if (EFI_ERROR (Status
)) {
493 VirtioPciUninit (Device
);
495 RestorePciAttributes
:
496 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
497 Device
->OriginalPciAttributes
, NULL
);
500 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
501 This
->DriverBindingHandle
, DeviceHandle
);
511 Stop driving the Virtio PCI device
513 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
514 incorporating this driver (independently of any
517 @param[in] DeviceHandle Stop driving this device.
519 @param[in] NumberOfChildren Since this function belongs to a device driver
520 only (as opposed to a bus driver), the caller
521 environment sets NumberOfChildren to zero, and
524 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
526 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
527 configuration attributes have been restored.
529 @return Error codes from the OpenProtocol() or
530 CloseProtocol(), UninstallProtocolInterface()
537 VirtioPciDeviceBindingStop (
538 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
539 IN EFI_HANDLE DeviceHandle
,
540 IN UINTN NumberOfChildren
,
541 IN EFI_HANDLE
*ChildHandleBuffer
545 VIRTIO_DEVICE_PROTOCOL
*VirtioDevice
;
546 VIRTIO_PCI_DEVICE
*Device
;
548 Status
= gBS
->OpenProtocol (
549 DeviceHandle
, // candidate device
550 &gVirtioDeviceProtocolGuid
, // retrieve the VirtIo iface
551 (VOID
**)&VirtioDevice
, // target pointer
552 This
->DriverBindingHandle
, // requestor driver identity
553 DeviceHandle
, // requesting lookup for dev.
554 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
556 if (EFI_ERROR (Status
)) {
560 Device
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice
);
563 // Handle Stop() requests for in-use driver instances gracefully.
565 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
566 &gVirtioDeviceProtocolGuid
, &Device
->VirtioDevice
);
567 if (EFI_ERROR (Status
)) {
571 VirtioPciUninit (Device
);
573 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
574 Device
->OriginalPciAttributes
, NULL
);
576 Status
= gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
577 This
->DriverBindingHandle
, DeviceHandle
);
586 // The static object that groups the Supported() (ie. probe), Start() and
587 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
588 // C, 10.1 EFI Driver Binding Protocol.
590 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
591 &VirtioPciDeviceBindingSupported
,
592 &VirtioPciDeviceBindingStart
,
593 &VirtioPciDeviceBindingStop
,
594 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
595 NULL
, // ImageHandle, to be overwritten by
596 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
597 NULL
// DriverBindingHandle, ditto
602 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
603 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
604 // in English, for display on standard console devices. This is recommended for
605 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
606 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
609 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
610 { "eng;en", L
"Virtio PCI Driver" },
615 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
619 VirtioPciGetDriverName (
620 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
622 OUT CHAR16
**DriverName
625 return LookupUnicodeString2 (
627 This
->SupportedLanguages
,
630 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
636 VirtioPciGetDeviceName (
637 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
638 IN EFI_HANDLE DeviceHandle
,
639 IN EFI_HANDLE ChildHandle
,
641 OUT CHAR16
**ControllerName
644 return EFI_UNSUPPORTED
;
648 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
649 &VirtioPciGetDriverName
,
650 &VirtioPciGetDeviceName
,
651 "eng" // SupportedLanguages, ISO 639-2 language codes
655 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
656 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioPciGetDriverName
,
657 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioPciGetDeviceName
,
658 "en" // SupportedLanguages, RFC 4646 language codes
663 // Entry point of this driver.
667 VirtioPciDeviceEntryPoint (
668 IN EFI_HANDLE ImageHandle
,
669 IN EFI_SYSTEM_TABLE
*SystemTable
672 return EfiLibInstallDriverBindingComponentName2 (