3 This driver produces Block I/O Protocol instances for virtio-blk devices.
5 The implementation is basic:
7 - No attach/detach (ie. removable media).
9 - Although the non-blocking interfaces of EFI_BLOCK_IO2_PROTOCOL could be a
10 good match for multiple in-flight virtio-blk requests, we stick to
11 synchronous requests and EFI_BLOCK_IO_PROTOCOL for now.
13 Copyright (C) 2012, Red Hat, Inc.
15 This program and the accompanying materials are licensed and made available
16 under the terms and conditions of the BSD License which accompanies this
17 distribution. The full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
21 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 #include <IndustryStandard/Pci.h>
26 #include <IndustryStandard/VirtioBlk.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/DebugLib.h>
29 #include <Library/MemoryAllocationLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/UefiLib.h>
32 #include <Library/VirtioLib.h>
34 #include "VirtioBlk.h"
38 Convenience macros to read and write region 0 IO space elements of the
39 virtio-blk PCI device, for configuration purposes.
41 The following macros make it possible to specify only the "core parameters"
42 for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
43 returns, the transaction will have been completed.
45 @param[in] Dev Pointer to the VBLK_DEV structure whose PCI IO space
46 we're accessing. Dev->PciIo must be valid.
48 @param[in] Field A field name from VBLK_HDR, identifying the virtio-blk
49 configuration item to access.
51 @param[in] Value (VIRTIO_CFG_WRITE() only.) The value to write to the
52 selected configuration item.
54 @param[out] Pointer (VIRTIO_CFG_READ() only.) The object to receive the
55 value read from the configuration item. Its type must be
56 one of UINT8, UINT16, UINT32, UINT64.
59 @return Status code returned by VirtioWrite() / VirtioRead().
63 #define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \
65 OFFSET_OF_VBLK (Field), \
66 SIZE_OF_VBLK (Field), \
70 #define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \
72 OFFSET_OF_VBLK (Field), \
73 SIZE_OF_VBLK (Field), \
80 // UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
81 // Driver Writer's Guide for UEFI 2.3.1 v1.01,
82 // 24.2 Block I/O Protocol Implementations
87 IN EFI_BLOCK_IO_PROTOCOL
*This
,
88 IN BOOLEAN ExtendedVerification
92 // If we managed to initialize and install the driver, then the device is
100 Verify correctness of the read/write (not flush) request submitted to the
101 EFI_BLOCK_IO_PROTOCOL instance.
103 This function provides most verification steps described in:
105 UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
107 - EFI_BLOCK_IO_PROTOCOL.ReadBlocks()
108 - EFI_BLOCK_IO_PROTOCOL.WriteBlocks()
110 Driver Writer's Guide for UEFI 2.3.1 v1.01,
111 - 24.2.2. ReadBlocks() and ReadBlocksEx() Implementation
112 - 24.2.3 WriteBlocks() and WriteBlockEx() Implementation
114 Request sizes are limited to 1 GB (checked). This is not a practical
115 limitation, just conformance to virtio-0.9.5, 2.3.2 Descriptor Table: "no
116 descriptor chain may be more than 2^32 bytes long in total".
118 Some Media characteristics are hardcoded in VirtioBlkInit() below (like
119 non-removable media, no restriction on buffer alignment etc); we rely on
120 those here without explicit mention.
122 @param[in] Media The EFI_BLOCK_IO_MEDIA characteristics for
123 this driver instance, extracted from the
124 underlying virtio-blk device at initialization
125 time. We validate the request against this set
129 @param[in] Lba Logical Block Address: number of logical
130 blocks to skip from the beginning of the
133 @param[in] PositiveBufferSize Size of buffer to transfer, in bytes. The
134 caller is responsible to ensure this parameter
137 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
141 @@return Validation result to be forwarded outwards by
142 ReadBlocks() and WriteBlocks, as required by
149 VerifyReadWriteRequest (
150 IN EFI_BLOCK_IO_MEDIA
*Media
,
152 IN UINTN PositiveBufferSize
,
153 IN BOOLEAN RequestIsWrite
158 ASSERT (PositiveBufferSize
> 0);
160 if (PositiveBufferSize
> SIZE_1GB
||
161 PositiveBufferSize
% Media
->BlockSize
> 0) {
162 return EFI_BAD_BUFFER_SIZE
;
164 BlockCount
= PositiveBufferSize
/ Media
->BlockSize
;
167 // Avoid unsigned wraparound on either side in the second comparison.
169 if (Lba
> Media
->LastBlock
|| BlockCount
- 1 > Media
->LastBlock
- Lba
) {
170 return EFI_INVALID_PARAMETER
;
173 if (RequestIsWrite
&& Media
->ReadOnly
) {
174 return EFI_WRITE_PROTECTED
;
185 Format a read / write / flush request as three consecutive virtio
186 descriptors, push them to the host, and poll for the response.
188 This is the main workhorse function. Two use cases are supported, read/write
189 and flush. The function may only be called after the request parameters have
191 - specific checks in ReadBlocks() / WriteBlocks() / FlushBlocks(), and
192 - VerifyReadWriteRequest() (for read/write only).
194 Parameters handled commonly:
196 @param[in] Dev The virtio-blk device the request is targeted
201 @param[in] Lba Must be zero.
203 @param[in] BufferSize Must be zero.
205 @param[in out] Buffer Ignored by the function.
207 @param[in] RequestIsWrite Must be TRUE.
211 @param[in] Lba Logical Block Address: number of logical blocks
212 to skip from the beginning of the device.
214 @param[in] BufferSize Size of buffer to transfer, in bytes. The caller
215 is responsible to ensure this parameter is
218 @param[in out] Buffer The guest side area to read data from the device
219 into, or write data to the device from.
221 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
224 Return values are common to both use cases, and are appropriate to be
225 forwarded by the EFI_BLOCK_IO_PROTOCOL functions (ReadBlocks(),
226 WriteBlocks(), FlushBlocks()).
229 @retval EFI_SUCCESS Transfer complete.
231 @retval EFI_DEVICE_ERROR Failed to notify host side via PCI write, or
232 unable to parse host response, or host response
233 is not VIRTIO_BLK_S_OK.
244 IN OUT
volatile VOID
*Buffer
,
245 IN BOOLEAN RequestIsWrite
249 volatile VIRTIO_BLK_REQ Request
;
250 volatile UINT8 HostStatus
;
251 DESC_INDICES Indices
;
253 BlockSize
= Dev
->BlockIoMedia
.BlockSize
;
256 // ensured by VirtioBlkInit()
258 ASSERT (BlockSize
> 0);
259 ASSERT (BlockSize
% 512 == 0);
262 // ensured by contract above, plus VerifyReadWriteRequest()
264 ASSERT (BufferSize
% BlockSize
== 0);
267 // Prepare virtio-blk request header, setting zero size for flush.
268 // IO Priority is homogeneously 0.
270 Request
.Type
= RequestIsWrite
?
271 (BufferSize
== 0 ? VIRTIO_BLK_T_FLUSH
: VIRTIO_BLK_T_OUT
) :
274 Request
.Sector
= Lba
* (BlockSize
/ 512);
276 VirtioPrepare (&Dev
->Ring
, &Indices
);
279 // preset a host status for ourselves that we do not accept as success
281 HostStatus
= VIRTIO_BLK_S_IOERR
;
284 // ensured by VirtioBlkInit() -- this predicate, in combination with the
285 // lock-step progress, ensures we don't have to track free descriptors.
287 ASSERT (Dev
->Ring
.QueueSize
>= 3);
290 // virtio-blk header in first desc
292 VirtioAppendDesc (&Dev
->Ring
, (UINTN
) &Request
, sizeof Request
,
293 VRING_DESC_F_NEXT
, &Indices
);
296 // data buffer for read/write in second desc
298 if (BufferSize
> 0) {
300 // From virtio-0.9.5, 2.3.2 Descriptor Table:
301 // "no descriptor chain may be more than 2^32 bytes long in total".
303 // The predicate is ensured by the call contract above (for flush), or
304 // VerifyReadWriteRequest() (for read/write). It also implies that
305 // converting BufferSize to UINT32 will not truncate it.
307 ASSERT (BufferSize
<= SIZE_1GB
);
310 // VRING_DESC_F_WRITE is interpreted from the host's point of view.
312 VirtioAppendDesc (&Dev
->Ring
, (UINTN
) Buffer
, (UINT32
) BufferSize
,
313 VRING_DESC_F_NEXT
| (RequestIsWrite
? 0 : VRING_DESC_F_WRITE
),
318 // host status in last (second or third) desc
320 VirtioAppendDesc (&Dev
->Ring
, (UINTN
) &HostStatus
, sizeof HostStatus
,
321 VRING_DESC_F_WRITE
, &Indices
);
324 // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
326 if (VirtioFlush (Dev
->PciIo
, 0, &Dev
->Ring
, &Indices
) == EFI_SUCCESS
&&
327 HostStatus
== VIRTIO_BLK_S_OK
) {
331 return EFI_DEVICE_ERROR
;
337 ReadBlocks() operation for virtio-blk.
340 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
341 Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
342 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
343 ReadBlocksEx() Implementation.
345 Parameter checks and conformant return values are implemented in
346 VerifyReadWriteRequest() and SynchronousRequest().
348 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
355 VirtioBlkReadBlocks (
356 IN EFI_BLOCK_IO_PROTOCOL
*This
,
366 if (BufferSize
== 0) {
370 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
371 Status
= VerifyReadWriteRequest (
375 FALSE
// RequestIsWrite
377 if (EFI_ERROR (Status
)) {
381 return SynchronousRequest (
386 FALSE
// RequestIsWrite
392 WriteBlocks() operation for virtio-blk.
395 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
396 Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
397 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
398 WriteBlockEx() Implementation.
400 Parameter checks and conformant return values are implemented in
401 VerifyReadWriteRequest() and SynchronousRequest().
403 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
410 VirtioBlkWriteBlocks (
411 IN EFI_BLOCK_IO_PROTOCOL
*This
,
421 if (BufferSize
== 0) {
425 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
426 Status
= VerifyReadWriteRequest (
430 TRUE
// RequestIsWrite
432 if (EFI_ERROR (Status
)) {
436 return SynchronousRequest (
441 TRUE
// RequestIsWrite
448 FlushBlocks() operation for virtio-blk.
451 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
452 Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
453 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
454 FlushBlocksEx() Implementation.
456 If the underlying virtio-blk device doesn't support flushing (ie.
457 write-caching), then this function should not be called by higher layers,
458 according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
459 Should they do nonetheless, we do nothing, successfully.
465 VirtioBlkFlushBlocks (
466 IN EFI_BLOCK_IO_PROTOCOL
*This
471 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
472 return Dev
->BlockIoMedia
.WriteCaching
?
478 TRUE
// RequestIsWrite
486 Device probe function for this driver.
488 The DXE core calls this function for any given device in order to see if the
489 driver can drive the device.
491 Specs relevant in the general sense:
493 - UEFI Spec 2.3.1 + Errata C:
494 - 6.3 Protocol Handler Services -- for accessing the underlying device
495 - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
497 - Driver Writer's Guide for UEFI 2.3.1 v1.01:
498 - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
500 - 9 Driver Binding Protocol -- for exporting ourselves
502 Specs relevant in the specific sense:
503 - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
504 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
505 Guidelines, 18.3 PCI drivers.
507 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
508 incorporating this driver (independently of
511 @param[in] DeviceHandle The device to probe.
513 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
516 @retval EFI_SUCCESS The driver supports the device being probed.
518 @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
521 @return Error codes from the OpenProtocol() boot service or
528 VirtioBlkDriverBindingSupported (
529 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
530 IN EFI_HANDLE DeviceHandle
,
531 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
535 EFI_PCI_IO_PROTOCOL
*PciIo
;
539 // Attempt to open the device with the PciIo set of interfaces. On success,
540 // the protocol is "instantiated" for the PCI device. Covers duplicate open
541 // attempts (EFI_ALREADY_STARTED).
543 Status
= gBS
->OpenProtocol (
544 DeviceHandle
, // candidate device
545 &gEfiPciIoProtocolGuid
, // for generic PCI access
546 (VOID
**)&PciIo
, // handle to instantiate
547 This
->DriverBindingHandle
, // requestor driver identity
548 DeviceHandle
, // ControllerHandle, according to
549 // the UEFI Driver Model
550 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive PciIo access to
551 // the device; to be released
553 if (EFI_ERROR (Status
)) {
558 // Read entire PCI configuration header for more extensive check ahead.
560 Status
= PciIo
->Pci
.Read (
561 PciIo
, // (protocol, device)
563 EfiPciIoWidthUint32
, // access width & copy
566 sizeof Pci
/ sizeof (UINT32
), // Count
567 &Pci
// target buffer
570 if (Status
== EFI_SUCCESS
) {
572 // virtio-0.9.5, 2.1 PCI Discovery
574 Status
= (Pci
.Hdr
.VendorId
== 0x1AF4 &&
575 Pci
.Hdr
.DeviceId
>= 0x1000 && Pci
.Hdr
.DeviceId
<= 0x103F &&
576 Pci
.Hdr
.RevisionID
== 0x00 &&
577 Pci
.Device
.SubsystemID
== 0x02) ? EFI_SUCCESS
: EFI_UNSUPPORTED
;
581 // We needed PCI IO access only transitorily, to see whether we support the
584 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
585 This
->DriverBindingHandle
, DeviceHandle
);
592 Set up all BlockIo and virtio-blk aspects of this driver for the specified
595 @param[in out] Dev The driver instance to configure. The caller is
596 responsible for Dev->PciIo's validity (ie. working IO
597 access to the underlying virtio-blk PCI device).
599 @retval EFI_SUCCESS Setup complete.
601 @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
602 virtio-blk attributes the host provides.
604 @return Error codes from VirtioRingInit() or
605 VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE().
625 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
627 NextDevStat
= 0; // step 1 -- reset device
628 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
629 if (EFI_ERROR (Status
)) {
633 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
634 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
635 if (EFI_ERROR (Status
)) {
639 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
640 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
641 if (EFI_ERROR (Status
)) {
646 // step 4a -- retrieve and validate features
648 Status
= VIRTIO_CFG_READ (Dev
, Generic
.VhdrDeviceFeatureBits
, &Features
);
649 if (EFI_ERROR (Status
)) {
652 Status
= VIRTIO_CFG_READ (Dev
, VhdrCapacity
, &NumSectors
);
653 if (EFI_ERROR (Status
)) {
656 if (NumSectors
== 0) {
657 Status
= EFI_UNSUPPORTED
;
661 if (Features
& VIRTIO_BLK_F_BLK_SIZE
) {
662 Status
= VIRTIO_CFG_READ (Dev
, VhdrBlkSize
, &BlockSize
);
663 if (EFI_ERROR (Status
)) {
666 if (BlockSize
== 0 || BlockSize
% 512 != 0 ||
667 NumSectors
% (BlockSize
/ 512) != 0) {
669 // We can only handle a logical block consisting of whole sectors,
670 // and only a disk composed of whole logical blocks.
672 Status
= EFI_UNSUPPORTED
;
681 // step 4b -- allocate virtqueue
683 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrQueueSelect
, 0);
684 if (EFI_ERROR (Status
)) {
687 Status
= VIRTIO_CFG_READ (Dev
, Generic
.VhdrQueueSize
, &QueueSize
);
688 if (EFI_ERROR (Status
)) {
691 if (QueueSize
< 3) { // SynchronousRequest() uses at most three descriptors
692 Status
= EFI_UNSUPPORTED
;
696 Status
= VirtioRingInit (QueueSize
, &Dev
->Ring
);
697 if (EFI_ERROR (Status
)) {
702 // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything
703 // fails from here on, we must release the ring resources.
705 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrQueueAddress
,
706 (UINTN
) Dev
->Ring
.Base
>> EFI_PAGE_SHIFT
);
707 if (EFI_ERROR (Status
)) {
712 // step 5 -- Report understood features. There are no virtio-blk specific
713 // features to negotiate in virtio-0.9.5, plus we do not want any of the
714 // device-independent (known or unknown) VIRTIO_F_* capabilities (see
717 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrGuestFeatureBits
, 0);
718 if (EFI_ERROR (Status
)) {
723 // step 6 -- initialization complete
725 NextDevStat
|= VSTAT_DRIVER_OK
;
726 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
727 if (EFI_ERROR (Status
)) {
732 // Populate the exported interface's attributes; see UEFI spec v2.3.1 +
733 // Errata C, 12.8 EFI Block I/O Protocol. We stick to the lowest possible
734 // EFI_BLOCK_IO_PROTOCOL revision for now.
736 Dev
->BlockIo
.Revision
= 0;
737 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
738 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
739 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
740 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
741 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
742 Dev
->BlockIoMedia
.MediaId
= 0;
743 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
744 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
745 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
746 Dev
->BlockIoMedia
.ReadOnly
= !!(Features
& VIRTIO_BLK_F_RO
);
747 Dev
->BlockIoMedia
.WriteCaching
= !!(Features
& VIRTIO_BLK_F_FLUSH
);
748 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
749 Dev
->BlockIoMedia
.IoAlign
= 0;
750 Dev
->BlockIoMedia
.LastBlock
= NumSectors
/ (BlockSize
/ 512) - 1;
754 VirtioRingUninit (&Dev
->Ring
);
758 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
759 // Status. PCI IO access failure here should not mask the original error.
761 NextDevStat
|= VSTAT_FAILED
;
762 VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
764 return Status
; // reached only via Failed above
770 Uninitialize the internals of a virtio-blk device that has been successfully
771 set up with VirtioBlkInit().
773 @param[in out] Dev The device to clean up.
785 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
786 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
787 // the old comms area.
789 VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, 0);
791 VirtioRingUninit (&Dev
->Ring
);
793 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
794 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
800 After we've pronounced support for a specific device in
801 DriverBindingSupported(), we start managing said device (passed in by the
802 Driver Exeuction Environment) with the following service.
804 See DriverBindingSupported() for specification references.
806 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
807 incorporating this driver (independently of
810 @param[in] DeviceHandle The supported device to drive.
812 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
815 @retval EFI_SUCCESS Driver instance has been created and
816 initialized for the virtio-blk PCI device, it
817 is now accessibla via EFI_BLOCK_IO_PROTOCOL.
819 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
821 @return Error codes from the OpenProtocol() boot
822 service, the PciIo protocol, VirtioBlkInit(),
823 or the InstallProtocolInterface() boot service.
829 VirtioBlkDriverBindingStart (
830 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
831 IN EFI_HANDLE DeviceHandle
,
832 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
838 Dev
= (VBLK_DEV
*) AllocateZeroPool (sizeof *Dev
);
840 return EFI_OUT_OF_RESOURCES
;
843 Status
= gBS
->OpenProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
844 (VOID
**)&Dev
->PciIo
, This
->DriverBindingHandle
,
845 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
846 if (EFI_ERROR (Status
)) {
851 // We must retain and ultimately restore the original PCI attributes of the
852 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
853 // 18.3.2 Start() and Stop().
855 // The third parameter ("Attributes", input) is ignored by the Get operation.
856 // The fourth parameter ("Result", output) is ignored by the Enable and Set
859 // For virtio-blk we only need IO space access.
861 Status
= Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationGet
,
862 0, &Dev
->OriginalPciAttributes
);
863 if (EFI_ERROR (Status
)) {
867 Status
= Dev
->PciIo
->Attributes (Dev
->PciIo
,
868 EfiPciIoAttributeOperationEnable
,
869 EFI_PCI_IO_ATTRIBUTE_IO
, NULL
);
870 if (EFI_ERROR (Status
)) {
875 // PCI IO access granted, configure virtio-blk device.
877 Status
= VirtioBlkInit (Dev
);
878 if (EFI_ERROR (Status
)) {
879 goto RestorePciAttributes
;
883 // Setup complete, attempt to export the driver instance's BlockIo interface.
885 Dev
->Signature
= VBLK_SIG
;
886 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
887 &gEfiBlockIoProtocolGuid
, EFI_NATIVE_INTERFACE
,
889 if (EFI_ERROR (Status
)) {
896 VirtioBlkUninit (Dev
);
898 RestorePciAttributes
:
899 Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationSet
,
900 Dev
->OriginalPciAttributes
, NULL
);
903 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
904 This
->DriverBindingHandle
, DeviceHandle
);
915 Stop driving a virtio-blk device and remove its BlockIo interface.
917 This function replays the success path of DriverBindingStart() in reverse.
918 The host side virtio-blk device is reset, so that the OS boot loader or the
919 OS may reinitialize it.
921 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
922 incorporating this driver (independently of any
925 @param[in] DeviceHandle Stop driving this device.
927 @param[in] NumberOfChildren Since this function belongs to a device driver
928 only (as opposed to a bus driver), the caller
929 environment sets NumberOfChildren to zero, and
932 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
938 VirtioBlkDriverBindingStop (
939 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
940 IN EFI_HANDLE DeviceHandle
,
941 IN UINTN NumberOfChildren
,
942 IN EFI_HANDLE
*ChildHandleBuffer
948 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
951 // If DriverBindingStop() is called with the driver instance still in use,
952 // or any of the parameters are invalid, we've caught a bug.
954 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
955 &gEfiBlockIoProtocolGuid
, &Dev
->BlockIo
);
956 ASSERT (Status
== EFI_SUCCESS
);
958 VirtioBlkUninit (Dev
);
960 Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationSet
,
961 Dev
->OriginalPciAttributes
, NULL
);
963 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
964 This
->DriverBindingHandle
, DeviceHandle
);
973 // The static object that groups the Supported() (ie. probe), Start() and
974 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
975 // C, 10.1 EFI Driver Binding Protocol.
977 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
978 &VirtioBlkDriverBindingSupported
,
979 &VirtioBlkDriverBindingStart
,
980 &VirtioBlkDriverBindingStop
,
981 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
982 NULL
, // ImageHandle, to be overwritten by
983 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
984 NULL
// DriverBindingHandle, ditto
989 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
990 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
991 // in English, for display on standard console devices. This is recommended for
992 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
993 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
995 // Device type names ("Virtio Block Device") are not formatted because the
996 // driver supports only that device type. Therefore the driver name suffices
997 // for unambiguous identification.
1001 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1002 { "eng;en", L
"Virtio Block Driver" },
1007 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1011 VirtioBlkGetDriverName (
1012 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1014 OUT CHAR16
**DriverName
1017 return LookupUnicodeString2 (
1019 This
->SupportedLanguages
,
1022 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1028 VirtioBlkGetDeviceName (
1029 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1030 IN EFI_HANDLE DeviceHandle
,
1031 IN EFI_HANDLE ChildHandle
,
1033 OUT CHAR16
**ControllerName
1036 return EFI_UNSUPPORTED
;
1040 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1041 &VirtioBlkGetDriverName
,
1042 &VirtioBlkGetDeviceName
,
1043 "eng" // SupportedLanguages, ISO 639-2 language codes
1047 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1048 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioBlkGetDriverName
,
1049 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioBlkGetDeviceName
,
1050 "en" // SupportedLanguages, RFC 4646 language codes
1055 // Entry point of this driver.
1059 VirtioBlkEntryPoint (
1060 IN EFI_HANDLE ImageHandle
,
1061 IN EFI_SYSTEM_TABLE
*SystemTable
1064 return EfiLibInstallDriverBindingComponentName2 (