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)) {
288 Status
= EFI_SUCCESS
;
290 Status
= EFI_UNSUPPORTED
;
295 // We needed PCI IO access only transitorily, to see whether we support the
298 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
299 This
->DriverBindingHandle
, DeviceHandle
);
306 Initialize the VirtIo PCI Device
308 @param[in, out] Dev The driver instance to configure. The caller is
309 responsible for Device->PciIo's validity (ie. working IO
310 access to the underlying virtio-pci device).
312 @retval EFI_SUCCESS Setup complete.
314 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
315 provided address offset and read size.
317 @return Error codes from PciIo->Pci.Read().
324 IN OUT VIRTIO_PCI_DEVICE
*Device
328 EFI_PCI_IO_PROTOCOL
*PciIo
;
331 ASSERT (Device
!= NULL
);
332 PciIo
= Device
->PciIo
;
333 ASSERT (PciIo
!= NULL
);
334 ASSERT (PciIo
->Pci
.Read
!= NULL
);
336 Status
= PciIo
->Pci
.Read (
337 PciIo
, // (protocol, device)
339 EfiPciIoWidthUint32
, // access width & copy
342 sizeof (Pci
) / sizeof (UINT32
), // Count
343 &Pci
// target buffer
345 if (EFI_ERROR (Status
)) {
350 // Copy protocol template
352 CopyMem (&Device
->VirtioDevice
, &mDeviceProtocolTemplate
,
353 sizeof (VIRTIO_DEVICE_PROTOCOL
));
356 // Initialize the protocol interface attributes
358 Device
->VirtioDevice
.Revision
= VIRTIO_SPEC_REVISION (0, 9, 5);
359 Device
->VirtioDevice
.SubSystemDeviceId
= Pci
.Device
.SubsystemID
;
362 // Note: We don't support the MSI-X capability. If we did,
363 // the offset would become 24 after enabling MSI-X.
365 Device
->DeviceSpecificConfigurationOffset
=
366 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI
;
373 Uninitialize the internals of a virtio-pci device that has been successfully
374 set up with VirtioPciInit().
376 @param[in, out] Dev The device to clean up.
384 IN OUT VIRTIO_PCI_DEVICE
*Device
387 // Note: This function mirrors VirtioPciInit() that does not allocate any
388 // resources - there's nothing to free here.
393 After we've pronounced support for a specific device in
394 DriverBindingSupported(), we start managing said device (passed in by the
395 Driver Execution Environment) with the following service.
397 See DriverBindingSupported() for specification references.
399 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
400 incorporating this driver (independently of
403 @param[in] DeviceHandle The supported device to drive.
405 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
408 @retval EFI_SUCCESS Driver instance has been created and
409 initialized for the virtio-pci device, it
410 is now accessible via VIRTIO_DEVICE_PROTOCOL.
412 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
414 @return Error codes from the OpenProtocol() boot
415 service, the PciIo protocol, VirtioPciInit(),
416 or the InstallProtocolInterface() boot service.
422 VirtioPciDeviceBindingStart (
423 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
424 IN EFI_HANDLE DeviceHandle
,
425 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
428 VIRTIO_PCI_DEVICE
*Device
;
431 Device
= (VIRTIO_PCI_DEVICE
*) AllocateZeroPool (sizeof *Device
);
432 if (Device
== NULL
) {
433 return EFI_OUT_OF_RESOURCES
;
436 Status
= gBS
->OpenProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
437 (VOID
**)&Device
->PciIo
, This
->DriverBindingHandle
,
438 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
439 if (EFI_ERROR (Status
)) {
444 // We must retain and ultimately restore the original PCI attributes of the
445 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
446 // 18.3.2 Start() and Stop().
448 // The third parameter ("Attributes", input) is ignored by the Get operation.
449 // The fourth parameter ("Result", output) is ignored by the Enable and Set
452 // For virtio-pci we only need IO space access.
454 Status
= Device
->PciIo
->Attributes (Device
->PciIo
,
455 EfiPciIoAttributeOperationGet
, 0, &Device
->OriginalPciAttributes
);
456 if (EFI_ERROR (Status
)) {
460 Status
= Device
->PciIo
->Attributes (
462 EfiPciIoAttributeOperationEnable
,
463 (EFI_PCI_IO_ATTRIBUTE_IO
|
464 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
),
467 if (EFI_ERROR (Status
)) {
472 // PCI IO access granted, configure protocol instance
475 Status
= VirtioPciInit (Device
);
476 if (EFI_ERROR (Status
)) {
477 goto RestorePciAttributes
;
481 // Setup complete, attempt to export the driver instance's VirtioDevice
484 Device
->Signature
= VIRTIO_PCI_DEVICE_SIGNATURE
;
485 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
486 &gVirtioDeviceProtocolGuid
, EFI_NATIVE_INTERFACE
,
487 &Device
->VirtioDevice
);
488 if (EFI_ERROR (Status
)) {
495 VirtioPciUninit (Device
);
497 RestorePciAttributes
:
498 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
499 Device
->OriginalPciAttributes
, NULL
);
502 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
503 This
->DriverBindingHandle
, DeviceHandle
);
513 Stop driving the Virtio PCI device
515 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
516 incorporating this driver (independently of any
519 @param[in] DeviceHandle Stop driving this device.
521 @param[in] NumberOfChildren Since this function belongs to a device driver
522 only (as opposed to a bus driver), the caller
523 environment sets NumberOfChildren to zero, and
526 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
528 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
529 configuration attributes have been restored.
531 @return Error codes from the OpenProtocol() or
532 CloseProtocol(), UninstallProtocolInterface()
539 VirtioPciDeviceBindingStop (
540 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
541 IN EFI_HANDLE DeviceHandle
,
542 IN UINTN NumberOfChildren
,
543 IN EFI_HANDLE
*ChildHandleBuffer
547 VIRTIO_DEVICE_PROTOCOL
*VirtioDevice
;
548 VIRTIO_PCI_DEVICE
*Device
;
550 Status
= gBS
->OpenProtocol (
551 DeviceHandle
, // candidate device
552 &gVirtioDeviceProtocolGuid
, // retrieve the VirtIo iface
553 (VOID
**)&VirtioDevice
, // target pointer
554 This
->DriverBindingHandle
, // requestor driver identity
555 DeviceHandle
, // requesting lookup for dev.
556 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
558 if (EFI_ERROR (Status
)) {
562 Device
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice
);
565 // Handle Stop() requests for in-use driver instances gracefully.
567 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
568 &gVirtioDeviceProtocolGuid
, &Device
->VirtioDevice
);
569 if (EFI_ERROR (Status
)) {
573 VirtioPciUninit (Device
);
575 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
576 Device
->OriginalPciAttributes
, NULL
);
578 Status
= gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
579 This
->DriverBindingHandle
, DeviceHandle
);
588 // The static object that groups the Supported() (ie. probe), Start() and
589 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
590 // C, 10.1 EFI Driver Binding Protocol.
592 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
593 &VirtioPciDeviceBindingSupported
,
594 &VirtioPciDeviceBindingStart
,
595 &VirtioPciDeviceBindingStop
,
596 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
597 NULL
, // ImageHandle, to be overwritten by
598 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
599 NULL
// DriverBindingHandle, ditto
604 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
605 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
606 // in English, for display on standard console devices. This is recommended for
607 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
608 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
611 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
612 { "eng;en", L
"Virtio PCI Driver" },
617 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
621 VirtioPciGetDriverName (
622 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
624 OUT CHAR16
**DriverName
627 return LookupUnicodeString2 (
629 This
->SupportedLanguages
,
632 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
638 VirtioPciGetDeviceName (
639 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
640 IN EFI_HANDLE DeviceHandle
,
641 IN EFI_HANDLE ChildHandle
,
643 OUT CHAR16
**ControllerName
646 return EFI_UNSUPPORTED
;
650 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
651 &VirtioPciGetDriverName
,
652 &VirtioPciGetDeviceName
,
653 "eng" // SupportedLanguages, ISO 639-2 language codes
657 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
658 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioPciGetDriverName
,
659 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioPciGetDeviceName
,
660 "en" // SupportedLanguages, RFC 4646 language codes
665 // Entry point of this driver.
669 VirtioPciDeviceEntryPoint (
670 IN EFI_HANDLE ImageHandle
,
671 IN EFI_SYSTEM_TABLE
*SystemTable
674 return EfiLibInstallDriverBindingComponentName2 (