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.
8 Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
10 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <IndustryStandard/Pci.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiLib.h>
21 #include "VirtioPciDevice.h"
23 STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate
= {
25 0, // SubSystemDeviceId
26 VirtioPciGetDeviceFeatures
, // GetDeviceFeatures
27 VirtioPciSetGuestFeatures
, // SetGuestFeatures
28 VirtioPciSetQueueAddress
, // SetQueueAddress
29 VirtioPciSetQueueSel
, // SetQueueSel
30 VirtioPciSetQueueNotify
, // SetQueueNotify
31 VirtioPciSetQueueAlignment
, // SetQueueAlignment
32 VirtioPciSetPageSize
, // SetPageSize
33 VirtioPciGetQueueSize
, // GetQueueNumMax
34 VirtioPciSetQueueSize
, // SetQueueNum
35 VirtioPciGetDeviceStatus
, // GetDeviceStatus
36 VirtioPciSetDeviceStatus
, // SetDeviceStatus
37 VirtioPciDeviceWrite
, // WriteDevice
38 VirtioPciDeviceRead
, // ReadDevice
39 VirtioPciAllocateSharedPages
, // AllocateSharedPages
40 VirtioPciFreeSharedPages
, // FreeSharedPages
41 VirtioPciMapSharedBuffer
, // MapSharedBuffer
42 VirtioPciUnmapSharedBuffer
, // UnmapSharedBuffer
47 Read a word from Region 0 of the device specified by PciIo.
49 Region 0 must be an iomem region. This is an internal function for the PCI
50 implementation of the protocol.
52 @param[in] Dev Virtio PCI device.
54 @param[in] FieldOffset Source offset.
56 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
58 @param[in] BufferSize Number of bytes available in the target buffer. Must
61 @param[out] Buffer Target buffer.
64 @return Status code returned by PciIo->Io.Read().
70 IN VIRTIO_PCI_DEVICE
*Dev
,
78 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
79 EFI_PCI_IO_PROTOCOL
*PciIo
;
81 ASSERT (FieldSize
== BufferSize
);
88 Width
= EfiPciIoWidthUint8
;
92 Width
= EfiPciIoWidthUint16
;
97 // The 64bit PCI I/O is broken down into two 32bit reads to prevent
98 // any alignment or width issues.
99 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
101 // The I/O operations are carried out exactly as requested. The caller
102 // is responsible for any alignment and I/O width issues which the
103 // bus, device, platform, or type of I/O might require. For example on
104 // some platforms, width requests of EfiPciIoWidthUint64 do not work.
112 Width
= EfiPciIoWidthUint32
;
117 return EFI_INVALID_PARAMETER
;
120 return PciIo
->Io
.Read (
132 Write a word into Region 0 of the device specified by PciIo.
134 Region 0 must be an iomem region. This is an internal function for the PCI
135 implementation of the protocol.
137 @param[in] Dev Virtio PCI device.
139 @param[in] FieldOffset Destination offset.
141 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
143 @param[in] Value Little endian value to write, converted to UINT64.
144 The least significant FieldSize bytes will be used.
147 @return Status code returned by PciIo->Io.Write().
153 IN VIRTIO_PCI_DEVICE
*Dev
,
154 IN UINTN FieldOffset
,
160 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
161 EFI_PCI_IO_PROTOCOL
*PciIo
;
168 Width
= EfiPciIoWidthUint8
;
172 Width
= EfiPciIoWidthUint16
;
177 // The 64bit PCI I/O is broken down into two 32bit writes to prevent
178 // any alignment or width issues.
179 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
181 // The I/O operations are carried out exactly as requested. The caller
182 // is responsible for any alignment and I/O width issues which the
183 // bus, device, platform, or type of I/O might require. For example on
184 // some platforms, width requests of EfiPciIoWidthUint64 do not work
192 Width
= EfiPciIoWidthUint32
;
197 return EFI_INVALID_PARAMETER
;
200 return PciIo
->Io
.Write (
212 Device probe function for this driver.
214 The DXE core calls this function for any given device in order to see if the
215 driver can drive the device.
217 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
218 incorporating this driver (independently of
221 @param[in] DeviceHandle The device to probe.
223 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
226 @retval EFI_SUCCESS The driver supports the device being probed.
228 @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support
231 @return Error codes from the OpenProtocol() boot service or
238 VirtioPciDeviceBindingSupported (
239 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
240 IN EFI_HANDLE DeviceHandle
,
241 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
245 EFI_PCI_IO_PROTOCOL
*PciIo
;
249 // Attempt to open the device with the PciIo set of interfaces. On success,
250 // the protocol is "instantiated" for the PCI device. Covers duplicate open
251 // attempts (EFI_ALREADY_STARTED).
253 Status
= gBS
->OpenProtocol (
254 DeviceHandle
, // candidate device
255 &gEfiPciIoProtocolGuid
, // for generic PCI access
256 (VOID
**)&PciIo
, // handle to instantiate
257 This
->DriverBindingHandle
, // requestor driver identity
258 DeviceHandle
, // ControllerHandle, according to
259 // the UEFI Driver Model
260 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive PciIo access to
261 // the device; to be released
263 if (EFI_ERROR (Status
)) {
268 // Read entire PCI configuration header for more extensive check ahead.
270 Status
= PciIo
->Pci
.Read (
271 PciIo
, // (protocol, device)
273 EfiPciIoWidthUint32
, // access width & copy
276 sizeof Pci
/ sizeof (UINT32
), // Count
277 &Pci
// target buffer
280 if (Status
== EFI_SUCCESS
) {
282 // virtio-0.9.5, 2.1 PCI Discovery
284 if ((Pci
.Hdr
.VendorId
== VIRTIO_VENDOR_ID
) &&
285 (Pci
.Hdr
.DeviceId
>= 0x1000) &&
286 (Pci
.Hdr
.DeviceId
<= 0x103F) &&
287 (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
301 &gEfiPciIoProtocolGuid
,
302 This
->DriverBindingHandle
,
311 Initialize the VirtIo PCI Device
313 @param[in, out] Dev The driver instance to configure. The caller is
314 responsible for Device->PciIo's validity (ie. working IO
315 access to the underlying virtio-pci device).
317 @retval EFI_SUCCESS Setup complete.
319 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
320 provided address offset and read size.
322 @return Error codes from PciIo->Pci.Read().
329 IN OUT VIRTIO_PCI_DEVICE
*Device
333 EFI_PCI_IO_PROTOCOL
*PciIo
;
336 ASSERT (Device
!= NULL
);
337 PciIo
= Device
->PciIo
;
338 ASSERT (PciIo
!= NULL
);
339 ASSERT (PciIo
->Pci
.Read
!= NULL
);
341 Status
= PciIo
->Pci
.Read (
342 PciIo
, // (protocol, device)
344 EfiPciIoWidthUint32
, // access width & copy
347 sizeof (Pci
) / sizeof (UINT32
), // Count
348 &Pci
// target buffer
350 if (EFI_ERROR (Status
)) {
355 // Copy protocol template
358 &Device
->VirtioDevice
,
359 &mDeviceProtocolTemplate
,
360 sizeof (VIRTIO_DEVICE_PROTOCOL
)
364 // Initialize the protocol interface attributes
366 Device
->VirtioDevice
.Revision
= VIRTIO_SPEC_REVISION (0, 9, 5);
367 Device
->VirtioDevice
.SubSystemDeviceId
= Pci
.Device
.SubsystemID
;
370 // Note: We don't support the MSI-X capability. If we did,
371 // the offset would become 24 after enabling MSI-X.
373 Device
->DeviceSpecificConfigurationOffset
=
374 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI
;
381 Uninitialize the internals of a virtio-pci device that has been successfully
382 set up with VirtioPciInit().
384 @param[in, out] Dev The device to clean up.
391 IN OUT VIRTIO_PCI_DEVICE
*Device
394 // Note: This function mirrors VirtioPciInit() that does not allocate any
395 // resources - there's nothing to free here.
400 After we've pronounced support for a specific device in
401 DriverBindingSupported(), we start managing said device (passed in by the
402 Driver Execution Environment) with the following service.
404 See DriverBindingSupported() for specification references.
406 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
407 incorporating this driver (independently of
410 @param[in] DeviceHandle The supported device to drive.
412 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
415 @retval EFI_SUCCESS Driver instance has been created and
416 initialized for the virtio-pci device, it
417 is now accessible via VIRTIO_DEVICE_PROTOCOL.
419 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
421 @return Error codes from the OpenProtocol() boot
422 service, the PciIo protocol, VirtioPciInit(),
423 or the InstallProtocolInterface() boot service.
429 VirtioPciDeviceBindingStart (
430 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
431 IN EFI_HANDLE DeviceHandle
,
432 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
435 VIRTIO_PCI_DEVICE
*Device
;
438 Device
= (VIRTIO_PCI_DEVICE
*)AllocateZeroPool (sizeof *Device
);
439 if (Device
== NULL
) {
440 return EFI_OUT_OF_RESOURCES
;
443 Status
= gBS
->OpenProtocol (
445 &gEfiPciIoProtocolGuid
,
446 (VOID
**)&Device
->PciIo
,
447 This
->DriverBindingHandle
,
449 EFI_OPEN_PROTOCOL_BY_DRIVER
451 if (EFI_ERROR (Status
)) {
456 // We must retain and ultimately restore the original PCI attributes of the
457 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
458 // 18.3.2 Start() and Stop().
460 // The third parameter ("Attributes", input) is ignored by the Get operation.
461 // The fourth parameter ("Result", output) is ignored by the Enable and Set
464 // For virtio-pci we only need IO space access.
466 Status
= Device
->PciIo
->Attributes (
468 EfiPciIoAttributeOperationGet
,
470 &Device
->OriginalPciAttributes
472 if (EFI_ERROR (Status
)) {
476 Status
= Device
->PciIo
->Attributes (
478 EfiPciIoAttributeOperationEnable
,
479 (EFI_PCI_IO_ATTRIBUTE_IO
|
480 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
),
483 if (EFI_ERROR (Status
)) {
488 // PCI IO access granted, configure protocol instance
491 Status
= VirtioPciInit (Device
);
492 if (EFI_ERROR (Status
)) {
493 goto RestorePciAttributes
;
497 // Setup complete, attempt to export the driver instance's VirtioDevice
500 Device
->Signature
= VIRTIO_PCI_DEVICE_SIGNATURE
;
501 Status
= gBS
->InstallProtocolInterface (
503 &gVirtioDeviceProtocolGuid
,
504 EFI_NATIVE_INTERFACE
,
505 &Device
->VirtioDevice
507 if (EFI_ERROR (Status
)) {
514 VirtioPciUninit (Device
);
516 RestorePciAttributes
:
517 Device
->PciIo
->Attributes (
519 EfiPciIoAttributeOperationSet
,
520 Device
->OriginalPciAttributes
,
527 &gEfiPciIoProtocolGuid
,
528 This
->DriverBindingHandle
,
540 Stop driving the Virtio PCI device
542 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
543 incorporating this driver (independently of any
546 @param[in] DeviceHandle Stop driving this device.
548 @param[in] NumberOfChildren Since this function belongs to a device driver
549 only (as opposed to a bus driver), the caller
550 environment sets NumberOfChildren to zero, and
553 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
555 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
556 configuration attributes have been restored.
558 @return Error codes from the OpenProtocol() or
559 CloseProtocol(), UninstallProtocolInterface()
566 VirtioPciDeviceBindingStop (
567 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
568 IN EFI_HANDLE DeviceHandle
,
569 IN UINTN NumberOfChildren
,
570 IN EFI_HANDLE
*ChildHandleBuffer
574 VIRTIO_DEVICE_PROTOCOL
*VirtioDevice
;
575 VIRTIO_PCI_DEVICE
*Device
;
577 Status
= gBS
->OpenProtocol (
578 DeviceHandle
, // candidate device
579 &gVirtioDeviceProtocolGuid
, // retrieve the VirtIo iface
580 (VOID
**)&VirtioDevice
, // target pointer
581 This
->DriverBindingHandle
, // requestor driver identity
582 DeviceHandle
, // requesting lookup for dev.
583 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
585 if (EFI_ERROR (Status
)) {
589 Device
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice
);
592 // Handle Stop() requests for in-use driver instances gracefully.
594 Status
= gBS
->UninstallProtocolInterface (
596 &gVirtioDeviceProtocolGuid
,
597 &Device
->VirtioDevice
599 if (EFI_ERROR (Status
)) {
603 VirtioPciUninit (Device
);
605 Device
->PciIo
->Attributes (
607 EfiPciIoAttributeOperationSet
,
608 Device
->OriginalPciAttributes
,
612 Status
= gBS
->CloseProtocol (
614 &gEfiPciIoProtocolGuid
,
615 This
->DriverBindingHandle
,
625 // The static object that groups the Supported() (ie. probe), Start() and
626 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
627 // C, 10.1 EFI Driver Binding Protocol.
629 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
630 &VirtioPciDeviceBindingSupported
,
631 &VirtioPciDeviceBindingStart
,
632 &VirtioPciDeviceBindingStop
,
633 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
634 NULL
, // ImageHandle, to be overwritten by
635 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
636 NULL
// DriverBindingHandle, ditto
640 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
641 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
642 // in English, for display on standard console devices. This is recommended for
643 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
644 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
647 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
648 { "eng;en", L
"Virtio PCI Driver" },
653 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
657 VirtioPciGetDriverName (
658 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
660 OUT CHAR16
**DriverName
663 return LookupUnicodeString2 (
665 This
->SupportedLanguages
,
668 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
674 VirtioPciGetDeviceName (
675 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
676 IN EFI_HANDLE DeviceHandle
,
677 IN EFI_HANDLE ChildHandle
,
679 OUT CHAR16
**ControllerName
682 return EFI_UNSUPPORTED
;
686 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
687 &VirtioPciGetDriverName
,
688 &VirtioPciGetDeviceName
,
689 "eng" // SupportedLanguages, ISO 639-2 language codes
693 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
694 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
)&VirtioPciGetDriverName
,
695 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
)&VirtioPciGetDeviceName
,
696 "en" // SupportedLanguages, RFC 4646 language codes
700 // Entry point of this driver.
704 VirtioPciDeviceEntryPoint (
705 IN EFI_HANDLE ImageHandle
,
706 IN EFI_SYSTEM_TABLE
*SystemTable
709 return EfiLibInstallDriverBindingComponentName2 (