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 This program and the accompanying materials are licensed and made available
11 under the terms and conditions of the BSD License which accompanies this
12 distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
16 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include <IndustryStandard/Pci.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/DebugLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/UefiLib.h>
27 #include "VirtioPciDevice.h"
29 STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate
= {
31 0, // SubSystemDeviceId
32 VirtioPciGetDeviceFeatures
, // GetDeviceFeatures
33 VirtioPciSetGuestFeatures
, // SetGuestFeatures
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
45 VirtioPciAllocateSharedPages
, // AllocateSharedPages
46 VirtioPciFreeSharedPages
, // FreeSharedPages
47 VirtioPciMapSharedBuffer
, // MapSharedBuffer
48 VirtioPciUnmapSharedBuffer
, // UnmapSharedBuffer
53 Read a word from Region 0 of the device specified by PciIo.
55 Region 0 must be an iomem region. This is an internal function for the PCI
56 implementation of the protocol.
58 @param[in] Dev Virtio PCI device.
60 @param[in] FieldOffset Source offset.
62 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
64 @param[in] BufferSize Number of bytes available in the target buffer. Must
67 @param[out] Buffer Target buffer.
70 @return Status code returned by PciIo->Io.Read().
76 IN VIRTIO_PCI_DEVICE
*Dev
,
84 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
85 EFI_PCI_IO_PROTOCOL
*PciIo
;
87 ASSERT (FieldSize
== BufferSize
);
94 Width
= EfiPciIoWidthUint8
;
98 Width
= EfiPciIoWidthUint16
;
103 // The 64bit PCI I/O is broken down into two 32bit reads to prevent
104 // any alignment or width issues.
105 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
107 // The I/O operations are carried out exactly as requested. The caller
108 // is responsible for any alignment and I/O width issues which the
109 // bus, device, platform, or type of I/O might require. For example on
110 // some platforms, width requests of EfiPciIoWidthUint64 do not work.
118 Width
= EfiPciIoWidthUint32
;
123 return EFI_INVALID_PARAMETER
;
126 return PciIo
->Io
.Read (
138 Write a word into Region 0 of the device specified by PciIo.
140 Region 0 must be an iomem region. This is an internal function for the PCI
141 implementation of the protocol.
143 @param[in] Dev Virtio PCI device.
145 @param[in] FieldOffset Destination offset.
147 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
149 @param[in] Value Little endian value to write, converted to UINT64.
150 The least significant FieldSize bytes will be used.
153 @return Status code returned by PciIo->Io.Write().
159 IN VIRTIO_PCI_DEVICE
*Dev
,
160 IN UINTN FieldOffset
,
166 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
167 EFI_PCI_IO_PROTOCOL
*PciIo
;
174 Width
= EfiPciIoWidthUint8
;
178 Width
= EfiPciIoWidthUint16
;
183 // The 64bit PCI I/O is broken down into two 32bit writes to prevent
184 // any alignment or width issues.
185 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
187 // The I/O operations are carried out exactly as requested. The caller
188 // is responsible for any alignment and I/O width issues which the
189 // bus, device, platform, or type of I/O might require. For example on
190 // some platforms, width requests of EfiPciIoWidthUint64 do not work
198 Width
= EfiPciIoWidthUint32
;
203 return EFI_INVALID_PARAMETER
;
206 return PciIo
->Io
.Write (
218 Device probe function for this driver.
220 The DXE core calls this function for any given device in order to see if the
221 driver can drive the device.
223 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
224 incorporating this driver (independently of
227 @param[in] DeviceHandle The device to probe.
229 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
232 @retval EFI_SUCCESS The driver supports the device being probed.
234 @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support
237 @return Error codes from the OpenProtocol() boot service or
244 VirtioPciDeviceBindingSupported (
245 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
246 IN EFI_HANDLE DeviceHandle
,
247 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
251 EFI_PCI_IO_PROTOCOL
*PciIo
;
255 // Attempt to open the device with the PciIo set of interfaces. On success,
256 // the protocol is "instantiated" for the PCI device. Covers duplicate open
257 // attempts (EFI_ALREADY_STARTED).
259 Status
= gBS
->OpenProtocol (
260 DeviceHandle
, // candidate device
261 &gEfiPciIoProtocolGuid
, // for generic PCI access
262 (VOID
**)&PciIo
, // handle to instantiate
263 This
->DriverBindingHandle
, // requestor driver identity
264 DeviceHandle
, // ControllerHandle, according to
265 // the UEFI Driver Model
266 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive PciIo access to
267 // the device; to be released
269 if (EFI_ERROR (Status
)) {
274 // Read entire PCI configuration header for more extensive check ahead.
276 Status
= PciIo
->Pci
.Read (
277 PciIo
, // (protocol, device)
279 EfiPciIoWidthUint32
, // access width & copy
282 sizeof Pci
/ sizeof (UINT32
), // Count
283 &Pci
// target buffer
286 if (Status
== EFI_SUCCESS
) {
288 // virtio-0.9.5, 2.1 PCI Discovery
290 if ((Pci
.Hdr
.VendorId
== VIRTIO_VENDOR_ID
) &&
291 (Pci
.Hdr
.DeviceId
>= 0x1000) &&
292 (Pci
.Hdr
.DeviceId
<= 0x103F) &&
293 (Pci
.Hdr
.RevisionID
== 0x00)) {
294 Status
= EFI_SUCCESS
;
296 Status
= EFI_UNSUPPORTED
;
301 // We needed PCI IO access only transitorily, to see whether we support the
304 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
305 This
->DriverBindingHandle
, DeviceHandle
);
312 Initialize the VirtIo PCI Device
314 @param[in, out] Dev The driver instance to configure. The caller is
315 responsible for Device->PciIo's validity (ie. working IO
316 access to the underlying virtio-pci device).
318 @retval EFI_SUCCESS Setup complete.
320 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
321 provided address offset and read size.
323 @return Error codes from PciIo->Pci.Read().
330 IN OUT VIRTIO_PCI_DEVICE
*Device
334 EFI_PCI_IO_PROTOCOL
*PciIo
;
337 ASSERT (Device
!= NULL
);
338 PciIo
= Device
->PciIo
;
339 ASSERT (PciIo
!= NULL
);
340 ASSERT (PciIo
->Pci
.Read
!= NULL
);
342 Status
= PciIo
->Pci
.Read (
343 PciIo
, // (protocol, device)
345 EfiPciIoWidthUint32
, // access width & copy
348 sizeof (Pci
) / sizeof (UINT32
), // Count
349 &Pci
// target buffer
351 if (EFI_ERROR (Status
)) {
356 // Copy protocol template
358 CopyMem (&Device
->VirtioDevice
, &mDeviceProtocolTemplate
,
359 sizeof (VIRTIO_DEVICE_PROTOCOL
));
362 // Initialize the protocol interface attributes
364 Device
->VirtioDevice
.Revision
= VIRTIO_SPEC_REVISION (0, 9, 5);
365 Device
->VirtioDevice
.SubSystemDeviceId
= Pci
.Device
.SubsystemID
;
368 // Note: We don't support the MSI-X capability. If we did,
369 // the offset would become 24 after enabling MSI-X.
371 Device
->DeviceSpecificConfigurationOffset
=
372 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI
;
379 Uninitialize the internals of a virtio-pci device that has been successfully
380 set up with VirtioPciInit().
382 @param[in, out] Dev The device to clean up.
390 IN OUT VIRTIO_PCI_DEVICE
*Device
393 // Note: This function mirrors VirtioPciInit() that does not allocate any
394 // resources - there's nothing to free here.
399 After we've pronounced support for a specific device in
400 DriverBindingSupported(), we start managing said device (passed in by the
401 Driver Execution Environment) with the following service.
403 See DriverBindingSupported() for specification references.
405 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
406 incorporating this driver (independently of
409 @param[in] DeviceHandle The supported device to drive.
411 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
414 @retval EFI_SUCCESS Driver instance has been created and
415 initialized for the virtio-pci device, it
416 is now accessible via VIRTIO_DEVICE_PROTOCOL.
418 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
420 @return Error codes from the OpenProtocol() boot
421 service, the PciIo protocol, VirtioPciInit(),
422 or the InstallProtocolInterface() boot service.
428 VirtioPciDeviceBindingStart (
429 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
430 IN EFI_HANDLE DeviceHandle
,
431 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
434 VIRTIO_PCI_DEVICE
*Device
;
437 Device
= (VIRTIO_PCI_DEVICE
*) AllocateZeroPool (sizeof *Device
);
438 if (Device
== NULL
) {
439 return EFI_OUT_OF_RESOURCES
;
442 Status
= gBS
->OpenProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
443 (VOID
**)&Device
->PciIo
, This
->DriverBindingHandle
,
444 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
445 if (EFI_ERROR (Status
)) {
450 // We must retain and ultimately restore the original PCI attributes of the
451 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
452 // 18.3.2 Start() and Stop().
454 // The third parameter ("Attributes", input) is ignored by the Get operation.
455 // The fourth parameter ("Result", output) is ignored by the Enable and Set
458 // For virtio-pci we only need IO space access.
460 Status
= Device
->PciIo
->Attributes (Device
->PciIo
,
461 EfiPciIoAttributeOperationGet
, 0, &Device
->OriginalPciAttributes
);
462 if (EFI_ERROR (Status
)) {
466 Status
= Device
->PciIo
->Attributes (
468 EfiPciIoAttributeOperationEnable
,
469 (EFI_PCI_IO_ATTRIBUTE_IO
|
470 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
),
473 if (EFI_ERROR (Status
)) {
478 // PCI IO access granted, configure protocol instance
481 Status
= VirtioPciInit (Device
);
482 if (EFI_ERROR (Status
)) {
483 goto RestorePciAttributes
;
487 // Setup complete, attempt to export the driver instance's VirtioDevice
490 Device
->Signature
= VIRTIO_PCI_DEVICE_SIGNATURE
;
491 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
492 &gVirtioDeviceProtocolGuid
, EFI_NATIVE_INTERFACE
,
493 &Device
->VirtioDevice
);
494 if (EFI_ERROR (Status
)) {
501 VirtioPciUninit (Device
);
503 RestorePciAttributes
:
504 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
505 Device
->OriginalPciAttributes
, NULL
);
508 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
509 This
->DriverBindingHandle
, DeviceHandle
);
519 Stop driving the Virtio PCI device
521 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
522 incorporating this driver (independently of any
525 @param[in] DeviceHandle Stop driving this device.
527 @param[in] NumberOfChildren Since this function belongs to a device driver
528 only (as opposed to a bus driver), the caller
529 environment sets NumberOfChildren to zero, and
532 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
534 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
535 configuration attributes have been restored.
537 @return Error codes from the OpenProtocol() or
538 CloseProtocol(), UninstallProtocolInterface()
545 VirtioPciDeviceBindingStop (
546 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
547 IN EFI_HANDLE DeviceHandle
,
548 IN UINTN NumberOfChildren
,
549 IN EFI_HANDLE
*ChildHandleBuffer
553 VIRTIO_DEVICE_PROTOCOL
*VirtioDevice
;
554 VIRTIO_PCI_DEVICE
*Device
;
556 Status
= gBS
->OpenProtocol (
557 DeviceHandle
, // candidate device
558 &gVirtioDeviceProtocolGuid
, // retrieve the VirtIo iface
559 (VOID
**)&VirtioDevice
, // target pointer
560 This
->DriverBindingHandle
, // requestor driver identity
561 DeviceHandle
, // requesting lookup for dev.
562 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
564 if (EFI_ERROR (Status
)) {
568 Device
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice
);
571 // Handle Stop() requests for in-use driver instances gracefully.
573 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
574 &gVirtioDeviceProtocolGuid
, &Device
->VirtioDevice
);
575 if (EFI_ERROR (Status
)) {
579 VirtioPciUninit (Device
);
581 Device
->PciIo
->Attributes (Device
->PciIo
, EfiPciIoAttributeOperationSet
,
582 Device
->OriginalPciAttributes
, NULL
);
584 Status
= gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
585 This
->DriverBindingHandle
, DeviceHandle
);
594 // The static object that groups the Supported() (ie. probe), Start() and
595 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
596 // C, 10.1 EFI Driver Binding Protocol.
598 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
599 &VirtioPciDeviceBindingSupported
,
600 &VirtioPciDeviceBindingStart
,
601 &VirtioPciDeviceBindingStop
,
602 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
603 NULL
, // ImageHandle, to be overwritten by
604 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
605 NULL
// DriverBindingHandle, ditto
610 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
611 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
612 // in English, for display on standard console devices. This is recommended for
613 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
614 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
617 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
618 { "eng;en", L
"Virtio PCI Driver" },
623 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
627 VirtioPciGetDriverName (
628 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
630 OUT CHAR16
**DriverName
633 return LookupUnicodeString2 (
635 This
->SupportedLanguages
,
638 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
644 VirtioPciGetDeviceName (
645 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
646 IN EFI_HANDLE DeviceHandle
,
647 IN EFI_HANDLE ChildHandle
,
649 OUT CHAR16
**ControllerName
652 return EFI_UNSUPPORTED
;
656 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
657 &VirtioPciGetDriverName
,
658 &VirtioPciGetDeviceName
,
659 "eng" // SupportedLanguages, ISO 639-2 language codes
663 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
664 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioPciGetDriverName
,
665 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioPciGetDeviceName
,
666 "en" // SupportedLanguages, RFC 4646 language codes
671 // Entry point of this driver.
675 VirtioPciDeviceEntryPoint (
676 IN EFI_HANDLE ImageHandle
,
677 IN EFI_SYSTEM_TABLE
*SystemTable
680 return EfiLibInstallDriverBindingComponentName2 (