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.
14 Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
15 Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
17 SPDX-License-Identifier: BSD-2-Clause-Patent
21 #include <IndustryStandard/VirtioBlk.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/UefiLib.h>
27 #include <Library/VirtioLib.h>
29 #include "VirtioBlk.h"
33 Convenience macros to read and write region 0 IO space elements of the
34 virtio-blk device, for configuration purposes.
36 The following macros make it possible to specify only the "core parameters"
37 for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
38 returns, the transaction will have been completed.
40 @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space
41 we're accessing. Dev->VirtIo must be valid.
43 @param[in] Field A field name from VBLK_HDR, identifying the virtio-blk
44 configuration item to access.
46 @param[in] Value (VIRTIO_CFG_WRITE() only.) The value to write to the
47 selected configuration item.
49 @param[out] Pointer (VIRTIO_CFG_READ() only.) The object to receive the
50 value read from the configuration item. Its type must be
51 one of UINT8, UINT16, UINT32, UINT64.
54 @return Status code returned by Virtio->WriteDevice() /
59 #define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
61 OFFSET_OF_VBLK (Field), \
62 SIZE_OF_VBLK (Field), \
66 #define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
68 OFFSET_OF_VBLK (Field), \
69 SIZE_OF_VBLK (Field), \
76 // UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
77 // Driver Writer's Guide for UEFI 2.3.1 v1.01,
78 // 24.2 Block I/O Protocol Implementations
83 IN EFI_BLOCK_IO_PROTOCOL
*This
,
84 IN BOOLEAN ExtendedVerification
88 // If we managed to initialize and install the driver, then the device is
96 Verify correctness of the read/write (not flush) request submitted to the
97 EFI_BLOCK_IO_PROTOCOL instance.
99 This function provides most verification steps described in:
101 UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
103 - EFI_BLOCK_IO_PROTOCOL.ReadBlocks()
104 - EFI_BLOCK_IO_PROTOCOL.WriteBlocks()
106 Driver Writer's Guide for UEFI 2.3.1 v1.01,
107 - 24.2.2. ReadBlocks() and ReadBlocksEx() Implementation
108 - 24.2.3 WriteBlocks() and WriteBlockEx() Implementation
110 Request sizes are limited to 1 GB (checked). This is not a practical
111 limitation, just conformance to virtio-0.9.5, 2.3.2 Descriptor Table: "no
112 descriptor chain may be more than 2^32 bytes long in total".
114 Some Media characteristics are hardcoded in VirtioBlkInit() below (like
115 non-removable media, no restriction on buffer alignment etc); we rely on
116 those here without explicit mention.
118 @param[in] Media The EFI_BLOCK_IO_MEDIA characteristics for
119 this driver instance, extracted from the
120 underlying virtio-blk device at initialization
121 time. We validate the request against this set
125 @param[in] Lba Logical Block Address: number of logical
126 blocks to skip from the beginning of the
129 @param[in] PositiveBufferSize Size of buffer to transfer, in bytes. The
130 caller is responsible to ensure this parameter
133 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
137 @@return Validation result to be forwarded outwards by
138 ReadBlocks() and WriteBlocks, as required by
145 VerifyReadWriteRequest (
146 IN EFI_BLOCK_IO_MEDIA
*Media
,
148 IN UINTN PositiveBufferSize
,
149 IN BOOLEAN RequestIsWrite
154 ASSERT (PositiveBufferSize
> 0);
156 if (PositiveBufferSize
> SIZE_1GB
||
157 PositiveBufferSize
% Media
->BlockSize
> 0) {
158 return EFI_BAD_BUFFER_SIZE
;
160 BlockCount
= PositiveBufferSize
/ Media
->BlockSize
;
163 // Avoid unsigned wraparound on either side in the second comparison.
165 if (Lba
> Media
->LastBlock
|| BlockCount
- 1 > Media
->LastBlock
- Lba
) {
166 return EFI_INVALID_PARAMETER
;
169 if (RequestIsWrite
&& Media
->ReadOnly
) {
170 return EFI_WRITE_PROTECTED
;
181 Format a read / write / flush request as three consecutive virtio
182 descriptors, push them to the host, and poll for the response.
184 This is the main workhorse function. Two use cases are supported, read/write
185 and flush. The function may only be called after the request parameters have
187 - specific checks in ReadBlocks() / WriteBlocks() / FlushBlocks(), and
188 - VerifyReadWriteRequest() (for read/write only).
190 Parameters handled commonly:
192 @param[in] Dev The virtio-blk device the request is targeted
197 @param[in] Lba Must be zero.
199 @param[in] BufferSize Must be zero.
201 @param[in out] Buffer Ignored by the function.
203 @param[in] RequestIsWrite Must be TRUE.
207 @param[in] Lba Logical Block Address: number of logical blocks
208 to skip from the beginning of the device.
210 @param[in] BufferSize Size of buffer to transfer, in bytes. The caller
211 is responsible to ensure this parameter is
214 @param[in out] Buffer The guest side area to read data from the device
215 into, or write data to the device from.
217 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
220 Return values are common to both use cases, and are appropriate to be
221 forwarded by the EFI_BLOCK_IO_PROTOCOL functions (ReadBlocks(),
222 WriteBlocks(), FlushBlocks()).
225 @retval EFI_SUCCESS Transfer complete.
227 @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
228 unable to parse host response, or host response
229 is not VIRTIO_BLK_S_OK or failed to map Buffer
230 for a bus master operation.
241 IN OUT
volatile VOID
*Buffer
,
242 IN BOOLEAN RequestIsWrite
246 volatile VIRTIO_BLK_REQ Request
;
247 volatile UINT8
*HostStatus
;
248 VOID
*HostStatusBuffer
;
249 DESC_INDICES Indices
;
250 VOID
*RequestMapping
;
253 EFI_PHYSICAL_ADDRESS BufferDeviceAddress
;
254 EFI_PHYSICAL_ADDRESS HostStatusDeviceAddress
;
255 EFI_PHYSICAL_ADDRESS RequestDeviceAddress
;
257 EFI_STATUS UnmapStatus
;
259 BlockSize
= Dev
->BlockIoMedia
.BlockSize
;
262 // Set BufferMapping and BufferDeviceAddress to suppress incorrect
263 // compiler/analyzer warnings.
265 BufferMapping
= NULL
;
266 BufferDeviceAddress
= 0;
269 // ensured by VirtioBlkInit()
271 ASSERT (BlockSize
> 0);
272 ASSERT (BlockSize
% 512 == 0);
275 // ensured by contract above, plus VerifyReadWriteRequest()
277 ASSERT (BufferSize
% BlockSize
== 0);
280 // Prepare virtio-blk request header, setting zero size for flush.
281 // IO Priority is homogeneously 0.
283 Request
.Type
= RequestIsWrite
?
284 (BufferSize
== 0 ? VIRTIO_BLK_T_FLUSH
: VIRTIO_BLK_T_OUT
) :
287 Request
.Sector
= MultU64x32(Lba
, BlockSize
/ 512);
290 // Host status is bi-directional (we preset with a value and expect the
291 // device to update it). Allocate a host status buffer which can be mapped
292 // to access equally by both processor and the device.
294 Status
= Dev
->VirtIo
->AllocateSharedPages (
296 EFI_SIZE_TO_PAGES (sizeof *HostStatus
),
299 if (EFI_ERROR (Status
)) {
300 return EFI_DEVICE_ERROR
;
303 HostStatus
= HostStatusBuffer
;
306 // Map virtio-blk request header (must be done after request header is
309 Status
= VirtioMapAllBytesInSharedBuffer (
311 VirtioOperationBusMasterRead
,
314 &RequestDeviceAddress
,
317 if (EFI_ERROR (Status
)) {
318 Status
= EFI_DEVICE_ERROR
;
319 goto FreeHostStatusBuffer
;
325 if (BufferSize
> 0) {
326 Status
= VirtioMapAllBytesInSharedBuffer (
329 VirtioOperationBusMasterRead
:
330 VirtioOperationBusMasterWrite
),
333 &BufferDeviceAddress
,
336 if (EFI_ERROR (Status
)) {
337 Status
= EFI_DEVICE_ERROR
;
338 goto UnmapRequestBuffer
;
343 // preset a host status for ourselves that we do not accept as success
345 *HostStatus
= VIRTIO_BLK_S_IOERR
;
348 // Map the Status Buffer with VirtioOperationBusMasterCommonBuffer so that
349 // both processor and device can access it.
351 Status
= VirtioMapAllBytesInSharedBuffer (
353 VirtioOperationBusMasterCommonBuffer
,
356 &HostStatusDeviceAddress
,
359 if (EFI_ERROR (Status
)) {
360 Status
= EFI_DEVICE_ERROR
;
361 goto UnmapDataBuffer
;
364 VirtioPrepare (&Dev
->Ring
, &Indices
);
367 // ensured by VirtioBlkInit() -- this predicate, in combination with the
368 // lock-step progress, ensures we don't have to track free descriptors.
370 ASSERT (Dev
->Ring
.QueueSize
>= 3);
373 // virtio-blk header in first desc
377 RequestDeviceAddress
,
384 // data buffer for read/write in second desc
386 if (BufferSize
> 0) {
388 // From virtio-0.9.5, 2.3.2 Descriptor Table:
389 // "no descriptor chain may be more than 2^32 bytes long in total".
391 // The predicate is ensured by the call contract above (for flush), or
392 // VerifyReadWriteRequest() (for read/write). It also implies that
393 // converting BufferSize to UINT32 will not truncate it.
395 ASSERT (BufferSize
<= SIZE_1GB
);
398 // VRING_DESC_F_WRITE is interpreted from the host's point of view.
404 VRING_DESC_F_NEXT
| (RequestIsWrite
? 0 : VRING_DESC_F_WRITE
),
410 // host status in last (second or third) desc
414 HostStatusDeviceAddress
,
421 // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
423 if (VirtioFlush (Dev
->VirtIo
, 0, &Dev
->Ring
, &Indices
,
424 NULL
) == EFI_SUCCESS
&&
425 *HostStatus
== VIRTIO_BLK_S_OK
) {
426 Status
= EFI_SUCCESS
;
428 Status
= EFI_DEVICE_ERROR
;
431 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, StatusMapping
);
434 if (BufferSize
> 0) {
435 UnmapStatus
= Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, BufferMapping
);
436 if (EFI_ERROR (UnmapStatus
) && !RequestIsWrite
&& !EFI_ERROR (Status
)) {
438 // Data from the bus master may not reach the caller; fail the request.
440 Status
= EFI_DEVICE_ERROR
;
445 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, RequestMapping
);
447 FreeHostStatusBuffer
:
448 Dev
->VirtIo
->FreeSharedPages (
450 EFI_SIZE_TO_PAGES (sizeof *HostStatus
),
460 ReadBlocks() operation for virtio-blk.
463 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
464 Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
465 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
466 ReadBlocksEx() Implementation.
468 Parameter checks and conformant return values are implemented in
469 VerifyReadWriteRequest() and SynchronousRequest().
471 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
478 VirtioBlkReadBlocks (
479 IN EFI_BLOCK_IO_PROTOCOL
*This
,
489 if (BufferSize
== 0) {
493 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
494 Status
= VerifyReadWriteRequest (
498 FALSE
// RequestIsWrite
500 if (EFI_ERROR (Status
)) {
504 return SynchronousRequest (
509 FALSE
// RequestIsWrite
515 WriteBlocks() operation for virtio-blk.
518 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
519 Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
520 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
521 WriteBlockEx() Implementation.
523 Parameter checks and conformant return values are implemented in
524 VerifyReadWriteRequest() and SynchronousRequest().
526 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
533 VirtioBlkWriteBlocks (
534 IN EFI_BLOCK_IO_PROTOCOL
*This
,
544 if (BufferSize
== 0) {
548 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
549 Status
= VerifyReadWriteRequest (
553 TRUE
// RequestIsWrite
555 if (EFI_ERROR (Status
)) {
559 return SynchronousRequest (
564 TRUE
// RequestIsWrite
571 FlushBlocks() operation for virtio-blk.
574 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
575 Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
576 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
577 FlushBlocksEx() Implementation.
579 If the underlying virtio-blk device doesn't support flushing (ie.
580 write-caching), then this function should not be called by higher layers,
581 according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
582 Should they do nonetheless, we do nothing, successfully.
588 VirtioBlkFlushBlocks (
589 IN EFI_BLOCK_IO_PROTOCOL
*This
594 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
595 return Dev
->BlockIoMedia
.WriteCaching
?
601 TRUE
// RequestIsWrite
609 Device probe function for this driver.
611 The DXE core calls this function for any given device in order to see if the
612 driver can drive the device.
614 Specs relevant in the general sense:
616 - UEFI Spec 2.3.1 + Errata C:
617 - 6.3 Protocol Handler Services -- for accessing the underlying device
618 - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
620 - Driver Writer's Guide for UEFI 2.3.1 v1.01:
621 - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
623 - 9 Driver Binding Protocol -- for exporting ourselves
625 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
626 incorporating this driver (independently of
629 @param[in] DeviceHandle The device to probe.
631 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
634 @retval EFI_SUCCESS The driver supports the device being probed.
636 @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
639 @return Error codes from the OpenProtocol() boot service or
646 VirtioBlkDriverBindingSupported (
647 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
648 IN EFI_HANDLE DeviceHandle
,
649 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
653 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
656 // Attempt to open the device with the VirtIo set of interfaces. On success,
657 // the protocol is "instantiated" for the VirtIo device. Covers duplicate
658 // open attempts (EFI_ALREADY_STARTED).
660 Status
= gBS
->OpenProtocol (
661 DeviceHandle
, // candidate device
662 &gVirtioDeviceProtocolGuid
, // for generic VirtIo access
663 (VOID
**)&VirtIo
, // handle to instantiate
664 This
->DriverBindingHandle
, // requestor driver identity
665 DeviceHandle
, // ControllerHandle, according to
666 // the UEFI Driver Model
667 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive VirtIo access to
668 // the device; to be released
670 if (EFI_ERROR (Status
)) {
674 if (VirtIo
->SubSystemDeviceId
!= VIRTIO_SUBSYSTEM_BLOCK_DEVICE
) {
675 Status
= EFI_UNSUPPORTED
;
679 // We needed VirtIo access only transitorily, to see whether we support the
682 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
683 This
->DriverBindingHandle
, DeviceHandle
);
690 Set up all BlockIo and virtio-blk aspects of this driver for the specified
693 @param[in out] Dev The driver instance to configure. The caller is
694 responsible for Dev->VirtIo's validity (ie. working IO
695 access to the underlying virtio-blk device).
697 @retval EFI_SUCCESS Setup complete.
699 @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
700 virtio-blk attributes the host provides.
702 @return Error codes from VirtioRingInit() or
703 VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE or
721 UINT8 PhysicalBlockExp
;
722 UINT8 AlignmentOffset
;
725 UINT64 RingBaseShift
;
727 PhysicalBlockExp
= 0;
732 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
734 NextDevStat
= 0; // step 1 -- reset device
735 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
736 if (EFI_ERROR (Status
)) {
740 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
741 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
742 if (EFI_ERROR (Status
)) {
746 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
747 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
748 if (EFI_ERROR (Status
)) {
753 // Set Page Size - MMIO VirtIo Specific
755 Status
= Dev
->VirtIo
->SetPageSize (Dev
->VirtIo
, EFI_PAGE_SIZE
);
756 if (EFI_ERROR (Status
)) {
761 // step 4a -- retrieve and validate features
763 Status
= Dev
->VirtIo
->GetDeviceFeatures (Dev
->VirtIo
, &Features
);
764 if (EFI_ERROR (Status
)) {
768 Status
= VIRTIO_CFG_READ (Dev
, Capacity
, &NumSectors
);
769 if (EFI_ERROR (Status
)) {
772 if (NumSectors
== 0) {
773 Status
= EFI_UNSUPPORTED
;
777 if (Features
& VIRTIO_BLK_F_BLK_SIZE
) {
778 Status
= VIRTIO_CFG_READ (Dev
, BlkSize
, &BlockSize
);
779 if (EFI_ERROR (Status
)) {
782 if (BlockSize
== 0 || BlockSize
% 512 != 0 ||
783 ModU64x32 (NumSectors
, BlockSize
/ 512) != 0) {
785 // We can only handle a logical block consisting of whole sectors,
786 // and only a disk composed of whole logical blocks.
788 Status
= EFI_UNSUPPORTED
;
796 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
797 Status
= VIRTIO_CFG_READ (Dev
, Topology
.PhysicalBlockExp
,
799 if (EFI_ERROR (Status
)) {
802 if (PhysicalBlockExp
>= 32) {
803 Status
= EFI_UNSUPPORTED
;
807 Status
= VIRTIO_CFG_READ (Dev
, Topology
.AlignmentOffset
, &AlignmentOffset
);
808 if (EFI_ERROR (Status
)) {
812 Status
= VIRTIO_CFG_READ (Dev
, Topology
.OptIoSize
, &OptIoSize
);
813 if (EFI_ERROR (Status
)) {
818 Features
&= VIRTIO_BLK_F_BLK_SIZE
| VIRTIO_BLK_F_TOPOLOGY
| VIRTIO_BLK_F_RO
|
819 VIRTIO_BLK_F_FLUSH
| VIRTIO_F_VERSION_1
|
820 VIRTIO_F_IOMMU_PLATFORM
;
823 // In virtio-1.0, feature negotiation is expected to complete before queue
824 // discovery, and the device can also reject the selected set of features.
826 if (Dev
->VirtIo
->Revision
>= VIRTIO_SPEC_REVISION (1, 0, 0)) {
827 Status
= Virtio10WriteFeatures (Dev
->VirtIo
, Features
, &NextDevStat
);
828 if (EFI_ERROR (Status
)) {
834 // step 4b -- allocate virtqueue
836 Status
= Dev
->VirtIo
->SetQueueSel (Dev
->VirtIo
, 0);
837 if (EFI_ERROR (Status
)) {
840 Status
= Dev
->VirtIo
->GetQueueNumMax (Dev
->VirtIo
, &QueueSize
);
841 if (EFI_ERROR (Status
)) {
844 if (QueueSize
< 3) { // SynchronousRequest() uses at most three descriptors
845 Status
= EFI_UNSUPPORTED
;
849 Status
= VirtioRingInit (Dev
->VirtIo
, QueueSize
, &Dev
->Ring
);
850 if (EFI_ERROR (Status
)) {
855 // If anything fails from here on, we must release the ring resources
857 Status
= VirtioRingMap (
863 if (EFI_ERROR (Status
)) {
868 // Additional steps for MMIO: align the queue appropriately, and set the
869 // size. If anything fails from here on, we must unmap the ring resources.
871 Status
= Dev
->VirtIo
->SetQueueNum (Dev
->VirtIo
, QueueSize
);
872 if (EFI_ERROR (Status
)) {
876 Status
= Dev
->VirtIo
->SetQueueAlign (Dev
->VirtIo
, EFI_PAGE_SIZE
);
877 if (EFI_ERROR (Status
)) {
882 // step 4c -- Report GPFN (guest-physical frame number) of queue.
884 Status
= Dev
->VirtIo
->SetQueueAddress (
889 if (EFI_ERROR (Status
)) {
895 // step 5 -- Report understood features.
897 if (Dev
->VirtIo
->Revision
< VIRTIO_SPEC_REVISION (1, 0, 0)) {
898 Features
&= ~(UINT64
)(VIRTIO_F_VERSION_1
| VIRTIO_F_IOMMU_PLATFORM
);
899 Status
= Dev
->VirtIo
->SetGuestFeatures (Dev
->VirtIo
, Features
);
900 if (EFI_ERROR (Status
)) {
906 // step 6 -- initialization complete
908 NextDevStat
|= VSTAT_DRIVER_OK
;
909 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
910 if (EFI_ERROR (Status
)) {
915 // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI
916 // Block I/O Protocol.
918 Dev
->BlockIo
.Revision
= 0;
919 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
920 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
921 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
922 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
923 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
924 Dev
->BlockIoMedia
.MediaId
= 0;
925 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
926 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
927 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
928 Dev
->BlockIoMedia
.ReadOnly
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_RO
) != 0);
929 Dev
->BlockIoMedia
.WriteCaching
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_FLUSH
) != 0);
930 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
931 Dev
->BlockIoMedia
.IoAlign
= 0;
932 Dev
->BlockIoMedia
.LastBlock
= DivU64x32 (NumSectors
,
933 BlockSize
/ 512) - 1;
935 DEBUG ((DEBUG_INFO
, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",
936 __FUNCTION__
, Dev
->BlockIoMedia
.BlockSize
,
937 Dev
->BlockIoMedia
.LastBlock
+ 1));
939 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
940 Dev
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
942 Dev
->BlockIoMedia
.LowestAlignedLba
= AlignmentOffset
;
943 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
= 1u << PhysicalBlockExp
;
944 Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
= OptIoSize
;
946 DEBUG ((DEBUG_INFO
, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",
947 __FUNCTION__
, Dev
->BlockIoMedia
.LowestAlignedLba
,
948 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
));
949 DEBUG ((DEBUG_INFO
, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",
950 __FUNCTION__
, Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
));
955 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
958 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
962 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
963 // Status. VirtIo access failure here should not mask the original error.
965 NextDevStat
|= VSTAT_FAILED
;
966 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
968 return Status
; // reached only via Failed above
974 Uninitialize the internals of a virtio-blk device that has been successfully
975 set up with VirtioBlkInit().
977 @param[in out] Dev The device to clean up.
989 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
990 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
991 // the old comms area.
993 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
995 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
996 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
998 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
999 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
1005 Event notification function enqueued by ExitBootServices().
1007 @param[in] Event Event whose notification function is being invoked.
1009 @param[in] Context Pointer to the VBLK_DEV structure.
1023 DEBUG ((DEBUG_VERBOSE
, "%a: Context=0x%p\n", __FUNCTION__
, Context
));
1025 // Reset the device. This causes the hypervisor to forget about the virtio
1028 // We allocated said ring in EfiBootServicesData type memory, and code
1029 // executing after ExitBootServices() is permitted to overwrite it.
1032 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
1037 After we've pronounced support for a specific device in
1038 DriverBindingSupported(), we start managing said device (passed in by the
1039 Driver Execution Environment) with the following service.
1041 See DriverBindingSupported() for specification references.
1043 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1044 incorporating this driver (independently of
1047 @param[in] DeviceHandle The supported device to drive.
1049 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
1052 @retval EFI_SUCCESS Driver instance has been created and
1053 initialized for the virtio-blk device, it
1054 is now accessible via EFI_BLOCK_IO_PROTOCOL.
1056 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1058 @return Error codes from the OpenProtocol() boot
1059 service, the VirtIo protocol, VirtioBlkInit(),
1060 or the InstallProtocolInterface() boot service.
1066 VirtioBlkDriverBindingStart (
1067 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1068 IN EFI_HANDLE DeviceHandle
,
1069 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1075 Dev
= (VBLK_DEV
*) AllocateZeroPool (sizeof *Dev
);
1077 return EFI_OUT_OF_RESOURCES
;
1080 Status
= gBS
->OpenProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1081 (VOID
**)&Dev
->VirtIo
, This
->DriverBindingHandle
,
1082 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
1083 if (EFI_ERROR (Status
)) {
1088 // VirtIo access granted, configure virtio-blk device.
1090 Status
= VirtioBlkInit (Dev
);
1091 if (EFI_ERROR (Status
)) {
1095 Status
= gBS
->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_CALLBACK
,
1096 &VirtioBlkExitBoot
, Dev
, &Dev
->ExitBoot
);
1097 if (EFI_ERROR (Status
)) {
1102 // Setup complete, attempt to export the driver instance's BlockIo interface.
1104 Dev
->Signature
= VBLK_SIG
;
1105 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
1106 &gEfiBlockIoProtocolGuid
, EFI_NATIVE_INTERFACE
,
1108 if (EFI_ERROR (Status
)) {
1115 gBS
->CloseEvent (Dev
->ExitBoot
);
1118 VirtioBlkUninit (Dev
);
1121 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1122 This
->DriverBindingHandle
, DeviceHandle
);
1133 Stop driving a virtio-blk device and remove its BlockIo interface.
1135 This function replays the success path of DriverBindingStart() in reverse.
1136 The host side virtio-blk device is reset, so that the OS boot loader or the
1137 OS may reinitialize it.
1139 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1140 incorporating this driver (independently of any
1143 @param[in] DeviceHandle Stop driving this device.
1145 @param[in] NumberOfChildren Since this function belongs to a device driver
1146 only (as opposed to a bus driver), the caller
1147 environment sets NumberOfChildren to zero, and
1150 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
1156 VirtioBlkDriverBindingStop (
1157 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1158 IN EFI_HANDLE DeviceHandle
,
1159 IN UINTN NumberOfChildren
,
1160 IN EFI_HANDLE
*ChildHandleBuffer
1164 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
1167 Status
= gBS
->OpenProtocol (
1168 DeviceHandle
, // candidate device
1169 &gEfiBlockIoProtocolGuid
, // retrieve the BlockIo iface
1170 (VOID
**)&BlockIo
, // target pointer
1171 This
->DriverBindingHandle
, // requestor driver identity
1172 DeviceHandle
, // requesting lookup for dev.
1173 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
1175 if (EFI_ERROR (Status
)) {
1179 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (BlockIo
);
1182 // Handle Stop() requests for in-use driver instances gracefully.
1184 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
1185 &gEfiBlockIoProtocolGuid
, &Dev
->BlockIo
);
1186 if (EFI_ERROR (Status
)) {
1190 gBS
->CloseEvent (Dev
->ExitBoot
);
1192 VirtioBlkUninit (Dev
);
1194 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1195 This
->DriverBindingHandle
, DeviceHandle
);
1204 // The static object that groups the Supported() (ie. probe), Start() and
1205 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1206 // C, 10.1 EFI Driver Binding Protocol.
1208 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
1209 &VirtioBlkDriverBindingSupported
,
1210 &VirtioBlkDriverBindingStart
,
1211 &VirtioBlkDriverBindingStop
,
1212 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1213 NULL
, // ImageHandle, to be overwritten by
1214 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
1215 NULL
// DriverBindingHandle, ditto
1220 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1221 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1222 // in English, for display on standard console devices. This is recommended for
1223 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1224 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1226 // Device type names ("Virtio Block Device") are not formatted because the
1227 // driver supports only that device type. Therefore the driver name suffices
1228 // for unambiguous identification.
1232 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1233 { "eng;en", L
"Virtio Block Driver" },
1238 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1242 VirtioBlkGetDriverName (
1243 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1245 OUT CHAR16
**DriverName
1248 return LookupUnicodeString2 (
1250 This
->SupportedLanguages
,
1253 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1259 VirtioBlkGetDeviceName (
1260 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1261 IN EFI_HANDLE DeviceHandle
,
1262 IN EFI_HANDLE ChildHandle
,
1264 OUT CHAR16
**ControllerName
1267 return EFI_UNSUPPORTED
;
1271 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1272 &VirtioBlkGetDriverName
,
1273 &VirtioBlkGetDeviceName
,
1274 "eng" // SupportedLanguages, ISO 639-2 language codes
1278 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1279 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioBlkGetDriverName
,
1280 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioBlkGetDeviceName
,
1281 "en" // SupportedLanguages, RFC 4646 language codes
1286 // Entry point of this driver.
1290 VirtioBlkEntryPoint (
1291 IN EFI_HANDLE ImageHandle
,
1292 IN EFI_SYSTEM_TABLE
*SystemTable
1295 return EfiLibInstallDriverBindingComponentName2 (