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), \
75 // UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
76 // Driver Writer's Guide for UEFI 2.3.1 v1.01,
77 // 24.2 Block I/O Protocol Implementations
82 IN EFI_BLOCK_IO_PROTOCOL
*This
,
83 IN BOOLEAN ExtendedVerification
87 // If we managed to initialize and install the driver, then the device is
95 Verify correctness of the read/write (not flush) request submitted to the
96 EFI_BLOCK_IO_PROTOCOL instance.
98 This function provides most verification steps described in:
100 UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
102 - EFI_BLOCK_IO_PROTOCOL.ReadBlocks()
103 - EFI_BLOCK_IO_PROTOCOL.WriteBlocks()
105 Driver Writer's Guide for UEFI 2.3.1 v1.01,
106 - 24.2.2. ReadBlocks() and ReadBlocksEx() Implementation
107 - 24.2.3 WriteBlocks() and WriteBlockEx() Implementation
109 Request sizes are limited to 1 GB (checked). This is not a practical
110 limitation, just conformance to virtio-0.9.5, 2.3.2 Descriptor Table: "no
111 descriptor chain may be more than 2^32 bytes long in total".
113 Some Media characteristics are hardcoded in VirtioBlkInit() below (like
114 non-removable media, no restriction on buffer alignment etc); we rely on
115 those here without explicit mention.
117 @param[in] Media The EFI_BLOCK_IO_MEDIA characteristics for
118 this driver instance, extracted from the
119 underlying virtio-blk device at initialization
120 time. We validate the request against this set
124 @param[in] Lba Logical Block Address: number of logical
125 blocks to skip from the beginning of the
128 @param[in] PositiveBufferSize Size of buffer to transfer, in bytes. The
129 caller is responsible to ensure this parameter
132 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
136 @@return Validation result to be forwarded outwards by
137 ReadBlocks() and WriteBlocks, as required by
144 VerifyReadWriteRequest (
145 IN EFI_BLOCK_IO_MEDIA
*Media
,
147 IN UINTN PositiveBufferSize
,
148 IN BOOLEAN RequestIsWrite
153 ASSERT (PositiveBufferSize
> 0);
155 if ((PositiveBufferSize
> SIZE_1GB
) ||
156 (PositiveBufferSize
% Media
->BlockSize
> 0))
158 return EFI_BAD_BUFFER_SIZE
;
161 BlockCount
= PositiveBufferSize
/ Media
->BlockSize
;
164 // Avoid unsigned wraparound on either side in the second comparison.
166 if ((Lba
> Media
->LastBlock
) || (BlockCount
- 1 > Media
->LastBlock
- Lba
)) {
167 return EFI_INVALID_PARAMETER
;
170 if (RequestIsWrite
&& Media
->ReadOnly
) {
171 return EFI_WRITE_PROTECTED
;
179 Format a read / write / flush request as three consecutive virtio
180 descriptors, push them to the host, and poll for the response.
182 This is the main workhorse function. Two use cases are supported, read/write
183 and flush. The function may only be called after the request parameters have
185 - specific checks in ReadBlocks() / WriteBlocks() / FlushBlocks(), and
186 - VerifyReadWriteRequest() (for read/write only).
188 Parameters handled commonly:
190 @param[in] Dev The virtio-blk device the request is targeted
195 @param[in] Lba Must be zero.
197 @param[in] BufferSize Must be zero.
199 @param[in out] Buffer Ignored by the function.
201 @param[in] RequestIsWrite Must be TRUE.
205 @param[in] Lba Logical Block Address: number of logical blocks
206 to skip from the beginning of the device.
208 @param[in] BufferSize Size of buffer to transfer, in bytes. The caller
209 is responsible to ensure this parameter is
212 @param[in out] Buffer The guest side area to read data from the device
213 into, or write data to the device from.
215 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
218 Return values are common to both use cases, and are appropriate to be
219 forwarded by the EFI_BLOCK_IO_PROTOCOL functions (ReadBlocks(),
220 WriteBlocks(), FlushBlocks()).
223 @retval EFI_SUCCESS Transfer complete.
225 @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
226 unable to parse host response, or host response
227 is not VIRTIO_BLK_S_OK or failed to map Buffer
228 for a bus master operation.
238 IN OUT
volatile VOID
*Buffer
,
239 IN BOOLEAN RequestIsWrite
243 volatile VIRTIO_BLK_REQ Request
;
244 volatile UINT8
*HostStatus
;
245 VOID
*HostStatusBuffer
;
246 DESC_INDICES Indices
;
247 VOID
*RequestMapping
;
250 EFI_PHYSICAL_ADDRESS BufferDeviceAddress
;
251 EFI_PHYSICAL_ADDRESS HostStatusDeviceAddress
;
252 EFI_PHYSICAL_ADDRESS RequestDeviceAddress
;
254 EFI_STATUS UnmapStatus
;
256 BlockSize
= Dev
->BlockIoMedia
.BlockSize
;
259 // Set BufferMapping and BufferDeviceAddress to suppress incorrect
260 // compiler/analyzer warnings.
262 BufferMapping
= NULL
;
263 BufferDeviceAddress
= 0;
266 // ensured by VirtioBlkInit()
268 ASSERT (BlockSize
> 0);
269 ASSERT (BlockSize
% 512 == 0);
272 // ensured by contract above, plus VerifyReadWriteRequest()
274 ASSERT (BufferSize
% BlockSize
== 0);
277 // Prepare virtio-blk request header, setting zero size for flush.
278 // IO Priority is homogeneously 0.
280 Request
.Type
= RequestIsWrite
?
281 (BufferSize
== 0 ? VIRTIO_BLK_T_FLUSH
: VIRTIO_BLK_T_OUT
) :
284 Request
.Sector
= MultU64x32 (Lba
, BlockSize
/ 512);
287 // Host status is bi-directional (we preset with a value and expect the
288 // device to update it). Allocate a host status buffer which can be mapped
289 // to access equally by both processor and the device.
291 Status
= Dev
->VirtIo
->AllocateSharedPages (
293 EFI_SIZE_TO_PAGES (sizeof *HostStatus
),
296 if (EFI_ERROR (Status
)) {
297 return EFI_DEVICE_ERROR
;
300 HostStatus
= HostStatusBuffer
;
303 // Map virtio-blk request header (must be done after request header is
306 Status
= VirtioMapAllBytesInSharedBuffer (
308 VirtioOperationBusMasterRead
,
311 &RequestDeviceAddress
,
314 if (EFI_ERROR (Status
)) {
315 Status
= EFI_DEVICE_ERROR
;
316 goto FreeHostStatusBuffer
;
322 if (BufferSize
> 0) {
323 Status
= VirtioMapAllBytesInSharedBuffer (
326 VirtioOperationBusMasterRead
:
327 VirtioOperationBusMasterWrite
),
330 &BufferDeviceAddress
,
333 if (EFI_ERROR (Status
)) {
334 Status
= EFI_DEVICE_ERROR
;
335 goto UnmapRequestBuffer
;
340 // preset a host status for ourselves that we do not accept as success
342 *HostStatus
= VIRTIO_BLK_S_IOERR
;
345 // Map the Status Buffer with VirtioOperationBusMasterCommonBuffer so that
346 // both processor and device can access it.
348 Status
= VirtioMapAllBytesInSharedBuffer (
350 VirtioOperationBusMasterCommonBuffer
,
353 &HostStatusDeviceAddress
,
356 if (EFI_ERROR (Status
)) {
357 Status
= EFI_DEVICE_ERROR
;
358 goto UnmapDataBuffer
;
361 VirtioPrepare (&Dev
->Ring
, &Indices
);
364 // ensured by VirtioBlkInit() -- this predicate, in combination with the
365 // lock-step progress, ensures we don't have to track free descriptors.
367 ASSERT (Dev
->Ring
.QueueSize
>= 3);
370 // virtio-blk header in first desc
374 RequestDeviceAddress
,
381 // data buffer for read/write in second desc
383 if (BufferSize
> 0) {
385 // From virtio-0.9.5, 2.3.2 Descriptor Table:
386 // "no descriptor chain may be more than 2^32 bytes long in total".
388 // The predicate is ensured by the call contract above (for flush), or
389 // VerifyReadWriteRequest() (for read/write). It also implies that
390 // converting BufferSize to UINT32 will not truncate it.
392 ASSERT (BufferSize
<= SIZE_1GB
);
395 // VRING_DESC_F_WRITE is interpreted from the host's point of view.
401 VRING_DESC_F_NEXT
| (RequestIsWrite
? 0 : VRING_DESC_F_WRITE
),
407 // host status in last (second or third) desc
411 HostStatusDeviceAddress
,
418 // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
427 (*HostStatus
== VIRTIO_BLK_S_OK
))
429 Status
= EFI_SUCCESS
;
431 Status
= EFI_DEVICE_ERROR
;
434 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, StatusMapping
);
437 if (BufferSize
> 0) {
438 UnmapStatus
= Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, BufferMapping
);
439 if (EFI_ERROR (UnmapStatus
) && !RequestIsWrite
&& !EFI_ERROR (Status
)) {
441 // Data from the bus master may not reach the caller; fail the request.
443 Status
= EFI_DEVICE_ERROR
;
448 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, RequestMapping
);
450 FreeHostStatusBuffer
:
451 Dev
->VirtIo
->FreeSharedPages (
453 EFI_SIZE_TO_PAGES (sizeof *HostStatus
),
462 ReadBlocks() operation for virtio-blk.
465 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
466 Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
467 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
468 ReadBlocksEx() Implementation.
470 Parameter checks and conformant return values are implemented in
471 VerifyReadWriteRequest() and SynchronousRequest().
473 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
479 VirtioBlkReadBlocks (
480 IN EFI_BLOCK_IO_PROTOCOL
*This
,
490 if (BufferSize
== 0) {
494 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
495 Status
= VerifyReadWriteRequest (
499 FALSE
// RequestIsWrite
501 if (EFI_ERROR (Status
)) {
505 return SynchronousRequest (
510 FALSE
// RequestIsWrite
516 WriteBlocks() operation for virtio-blk.
519 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
520 Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
521 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
522 WriteBlockEx() Implementation.
524 Parameter checks and conformant return values are implemented in
525 VerifyReadWriteRequest() and SynchronousRequest().
527 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
570 FlushBlocks() operation for virtio-blk.
573 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
574 Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
575 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
576 FlushBlocksEx() Implementation.
578 If the underlying virtio-blk device doesn't support flushing (ie.
579 write-caching), then this function should not be called by higher layers,
580 according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
581 Should they do nonetheless, we do nothing, successfully.
586 VirtioBlkFlushBlocks (
587 IN EFI_BLOCK_IO_PROTOCOL
*This
592 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
593 return Dev
->BlockIoMedia
.WriteCaching
?
599 TRUE
// RequestIsWrite
606 Device probe function for this driver.
608 The DXE core calls this function for any given device in order to see if the
609 driver can drive the device.
611 Specs relevant in the general sense:
613 - UEFI Spec 2.3.1 + Errata C:
614 - 6.3 Protocol Handler Services -- for accessing the underlying device
615 - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
617 - Driver Writer's Guide for UEFI 2.3.1 v1.01:
618 - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
620 - 9 Driver Binding Protocol -- for exporting ourselves
622 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
623 incorporating this driver (independently of
626 @param[in] DeviceHandle The device to probe.
628 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
631 @retval EFI_SUCCESS The driver supports the device being probed.
633 @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
636 @return Error codes from the OpenProtocol() boot service or
642 VirtioBlkDriverBindingSupported (
643 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
644 IN EFI_HANDLE DeviceHandle
,
645 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
649 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
652 // Attempt to open the device with the VirtIo set of interfaces. On success,
653 // the protocol is "instantiated" for the VirtIo device. Covers duplicate
654 // open attempts (EFI_ALREADY_STARTED).
656 Status
= gBS
->OpenProtocol (
657 DeviceHandle
, // candidate device
658 &gVirtioDeviceProtocolGuid
, // for generic VirtIo access
659 (VOID
**)&VirtIo
, // handle to instantiate
660 This
->DriverBindingHandle
, // requestor driver identity
661 DeviceHandle
, // ControllerHandle, according to
662 // the UEFI Driver Model
663 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive VirtIo access to
664 // the device; to be released
666 if (EFI_ERROR (Status
)) {
670 if (VirtIo
->SubSystemDeviceId
!= VIRTIO_SUBSYSTEM_BLOCK_DEVICE
) {
671 Status
= EFI_UNSUPPORTED
;
675 // We needed VirtIo access only transitorily, to see whether we support the
680 &gVirtioDeviceProtocolGuid
,
681 This
->DriverBindingHandle
,
689 Set up all BlockIo and virtio-blk aspects of this driver for the specified
692 @param[in out] Dev The driver instance to configure. The caller is
693 responsible for Dev->VirtIo's validity (ie. working IO
694 access to the underlying virtio-blk device).
696 @retval EFI_SUCCESS Setup complete.
698 @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
699 virtio-blk attributes the host provides.
701 @return Error codes from VirtioRingInit() or
702 VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE or
719 UINT8 PhysicalBlockExp
;
720 UINT8 AlignmentOffset
;
723 UINT64 RingBaseShift
;
725 PhysicalBlockExp
= 0;
730 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
732 NextDevStat
= 0; // step 1 -- reset device
733 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
734 if (EFI_ERROR (Status
)) {
738 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
739 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
740 if (EFI_ERROR (Status
)) {
744 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
745 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
746 if (EFI_ERROR (Status
)) {
751 // Set Page Size - MMIO VirtIo Specific
753 Status
= Dev
->VirtIo
->SetPageSize (Dev
->VirtIo
, EFI_PAGE_SIZE
);
754 if (EFI_ERROR (Status
)) {
759 // step 4a -- retrieve and validate features
761 Status
= Dev
->VirtIo
->GetDeviceFeatures (Dev
->VirtIo
, &Features
);
762 if (EFI_ERROR (Status
)) {
766 Status
= VIRTIO_CFG_READ (Dev
, Capacity
, &NumSectors
);
767 if (EFI_ERROR (Status
)) {
771 if (NumSectors
== 0) {
772 Status
= EFI_UNSUPPORTED
;
776 if (Features
& VIRTIO_BLK_F_BLK_SIZE
) {
777 Status
= VIRTIO_CFG_READ (Dev
, BlkSize
, &BlockSize
);
778 if (EFI_ERROR (Status
)) {
782 if ((BlockSize
== 0) || (BlockSize
% 512 != 0) ||
783 (ModU64x32 (NumSectors
, BlockSize
/ 512) != 0))
786 // We can only handle a logical block consisting of whole sectors,
787 // and only a disk composed of whole logical blocks.
789 Status
= EFI_UNSUPPORTED
;
796 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
797 Status
= VIRTIO_CFG_READ (
799 Topology
.PhysicalBlockExp
,
802 if (EFI_ERROR (Status
)) {
806 if (PhysicalBlockExp
>= 32) {
807 Status
= EFI_UNSUPPORTED
;
811 Status
= VIRTIO_CFG_READ (Dev
, Topology
.AlignmentOffset
, &AlignmentOffset
);
812 if (EFI_ERROR (Status
)) {
816 Status
= VIRTIO_CFG_READ (Dev
, Topology
.OptIoSize
, &OptIoSize
);
817 if (EFI_ERROR (Status
)) {
822 Features
&= VIRTIO_BLK_F_BLK_SIZE
| VIRTIO_BLK_F_TOPOLOGY
| VIRTIO_BLK_F_RO
|
823 VIRTIO_BLK_F_FLUSH
| VIRTIO_F_VERSION_1
|
824 VIRTIO_F_IOMMU_PLATFORM
;
827 // In virtio-1.0, feature negotiation is expected to complete before queue
828 // discovery, and the device can also reject the selected set of features.
830 if (Dev
->VirtIo
->Revision
>= VIRTIO_SPEC_REVISION (1, 0, 0)) {
831 Status
= Virtio10WriteFeatures (Dev
->VirtIo
, Features
, &NextDevStat
);
832 if (EFI_ERROR (Status
)) {
838 // step 4b -- allocate virtqueue
840 Status
= Dev
->VirtIo
->SetQueueSel (Dev
->VirtIo
, 0);
841 if (EFI_ERROR (Status
)) {
845 Status
= Dev
->VirtIo
->GetQueueNumMax (Dev
->VirtIo
, &QueueSize
);
846 if (EFI_ERROR (Status
)) {
851 // SynchronousRequest() uses at most three descriptors
852 Status
= EFI_UNSUPPORTED
;
856 Status
= VirtioRingInit (Dev
->VirtIo
, QueueSize
, &Dev
->Ring
);
857 if (EFI_ERROR (Status
)) {
862 // If anything fails from here on, we must release the ring resources
864 Status
= VirtioRingMap (
870 if (EFI_ERROR (Status
)) {
875 // Additional steps for MMIO: align the queue appropriately, and set the
876 // size. If anything fails from here on, we must unmap the ring resources.
878 Status
= Dev
->VirtIo
->SetQueueNum (Dev
->VirtIo
, QueueSize
);
879 if (EFI_ERROR (Status
)) {
883 Status
= Dev
->VirtIo
->SetQueueAlign (Dev
->VirtIo
, EFI_PAGE_SIZE
);
884 if (EFI_ERROR (Status
)) {
889 // step 4c -- Report GPFN (guest-physical frame number) of queue.
891 Status
= Dev
->VirtIo
->SetQueueAddress (
896 if (EFI_ERROR (Status
)) {
901 // step 5 -- Report understood features.
903 if (Dev
->VirtIo
->Revision
< VIRTIO_SPEC_REVISION (1, 0, 0)) {
904 Features
&= ~(UINT64
)(VIRTIO_F_VERSION_1
| VIRTIO_F_IOMMU_PLATFORM
);
905 Status
= Dev
->VirtIo
->SetGuestFeatures (Dev
->VirtIo
, Features
);
906 if (EFI_ERROR (Status
)) {
912 // step 6 -- initialization complete
914 NextDevStat
|= VSTAT_DRIVER_OK
;
915 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
916 if (EFI_ERROR (Status
)) {
921 // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI
922 // Block I/O Protocol.
924 Dev
->BlockIo
.Revision
= 0;
925 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
926 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
927 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
928 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
929 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
930 Dev
->BlockIoMedia
.MediaId
= 0;
931 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
932 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
933 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
934 Dev
->BlockIoMedia
.ReadOnly
= (BOOLEAN
)((Features
& VIRTIO_BLK_F_RO
) != 0);
935 Dev
->BlockIoMedia
.WriteCaching
= (BOOLEAN
)((Features
& VIRTIO_BLK_F_FLUSH
) != 0);
936 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
937 Dev
->BlockIoMedia
.IoAlign
= 0;
938 Dev
->BlockIoMedia
.LastBlock
= DivU64x32 (
945 "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",
947 Dev
->BlockIoMedia
.BlockSize
,
948 Dev
->BlockIoMedia
.LastBlock
+ 1
951 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
952 Dev
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
954 Dev
->BlockIoMedia
.LowestAlignedLba
= AlignmentOffset
;
955 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
= 1u << PhysicalBlockExp
;
956 Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
= OptIoSize
;
960 "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",
962 Dev
->BlockIoMedia
.LowestAlignedLba
,
963 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
967 "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",
969 Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
976 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
979 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
983 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
984 // Status. VirtIo access failure here should not mask the original error.
986 NextDevStat
|= VSTAT_FAILED
;
987 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
989 return Status
; // reached only via Failed above
994 Uninitialize the internals of a virtio-blk device that has been successfully
995 set up with VirtioBlkInit().
997 @param[in out] Dev The device to clean up.
1004 IN OUT VBLK_DEV
*Dev
1008 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
1009 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
1010 // the old comms area.
1012 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
1014 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
1015 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
1017 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
1018 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
1023 Event notification function enqueued by ExitBootServices().
1025 @param[in] Event Event whose notification function is being invoked.
1027 @param[in] Context Pointer to the VBLK_DEV structure.
1040 DEBUG ((DEBUG_VERBOSE
, "%a: Context=0x%p\n", __FUNCTION__
, Context
));
1042 // Reset the device. This causes the hypervisor to forget about the virtio
1045 // We allocated said ring in EfiBootServicesData type memory, and code
1046 // executing after ExitBootServices() is permitted to overwrite it.
1049 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
1054 After we've pronounced support for a specific device in
1055 DriverBindingSupported(), we start managing said device (passed in by the
1056 Driver Execution Environment) with the following service.
1058 See DriverBindingSupported() for specification references.
1060 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1061 incorporating this driver (independently of
1064 @param[in] DeviceHandle The supported device to drive.
1066 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
1069 @retval EFI_SUCCESS Driver instance has been created and
1070 initialized for the virtio-blk device, it
1071 is now accessible via EFI_BLOCK_IO_PROTOCOL.
1073 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1075 @return Error codes from the OpenProtocol() boot
1076 service, the VirtIo protocol, VirtioBlkInit(),
1077 or the InstallProtocolInterface() boot service.
1082 VirtioBlkDriverBindingStart (
1083 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1084 IN EFI_HANDLE DeviceHandle
,
1085 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1091 Dev
= (VBLK_DEV
*)AllocateZeroPool (sizeof *Dev
);
1093 return EFI_OUT_OF_RESOURCES
;
1096 Status
= gBS
->OpenProtocol (
1098 &gVirtioDeviceProtocolGuid
,
1099 (VOID
**)&Dev
->VirtIo
,
1100 This
->DriverBindingHandle
,
1102 EFI_OPEN_PROTOCOL_BY_DRIVER
1104 if (EFI_ERROR (Status
)) {
1109 // VirtIo access granted, configure virtio-blk device.
1111 Status
= VirtioBlkInit (Dev
);
1112 if (EFI_ERROR (Status
)) {
1116 Status
= gBS
->CreateEvent (
1117 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
1123 if (EFI_ERROR (Status
)) {
1128 // Setup complete, attempt to export the driver instance's BlockIo interface.
1130 Dev
->Signature
= VBLK_SIG
;
1131 Status
= gBS
->InstallProtocolInterface (
1133 &gEfiBlockIoProtocolGuid
,
1134 EFI_NATIVE_INTERFACE
,
1137 if (EFI_ERROR (Status
)) {
1144 gBS
->CloseEvent (Dev
->ExitBoot
);
1147 VirtioBlkUninit (Dev
);
1150 gBS
->CloseProtocol (
1152 &gVirtioDeviceProtocolGuid
,
1153 This
->DriverBindingHandle
,
1165 Stop driving a virtio-blk device and remove its BlockIo interface.
1167 This function replays the success path of DriverBindingStart() in reverse.
1168 The host side virtio-blk device is reset, so that the OS boot loader or the
1169 OS may reinitialize it.
1171 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1172 incorporating this driver (independently of any
1175 @param[in] DeviceHandle Stop driving this device.
1177 @param[in] NumberOfChildren Since this function belongs to a device driver
1178 only (as opposed to a bus driver), the caller
1179 environment sets NumberOfChildren to zero, and
1182 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
1187 VirtioBlkDriverBindingStop (
1188 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1189 IN EFI_HANDLE DeviceHandle
,
1190 IN UINTN NumberOfChildren
,
1191 IN EFI_HANDLE
*ChildHandleBuffer
1195 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
1198 Status
= gBS
->OpenProtocol (
1199 DeviceHandle
, // candidate device
1200 &gEfiBlockIoProtocolGuid
, // retrieve the BlockIo iface
1201 (VOID
**)&BlockIo
, // target pointer
1202 This
->DriverBindingHandle
, // requestor driver identity
1203 DeviceHandle
, // requesting lookup for dev.
1204 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
1206 if (EFI_ERROR (Status
)) {
1210 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (BlockIo
);
1213 // Handle Stop() requests for in-use driver instances gracefully.
1215 Status
= gBS
->UninstallProtocolInterface (
1217 &gEfiBlockIoProtocolGuid
,
1220 if (EFI_ERROR (Status
)) {
1224 gBS
->CloseEvent (Dev
->ExitBoot
);
1226 VirtioBlkUninit (Dev
);
1228 gBS
->CloseProtocol (
1230 &gVirtioDeviceProtocolGuid
,
1231 This
->DriverBindingHandle
,
1241 // The static object that groups the Supported() (ie. probe), Start() and
1242 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1243 // C, 10.1 EFI Driver Binding Protocol.
1245 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
1246 &VirtioBlkDriverBindingSupported
,
1247 &VirtioBlkDriverBindingStart
,
1248 &VirtioBlkDriverBindingStop
,
1249 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1250 NULL
, // ImageHandle, to be overwritten by
1251 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
1252 NULL
// DriverBindingHandle, ditto
1256 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1257 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1258 // in English, for display on standard console devices. This is recommended for
1259 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1260 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1262 // Device type names ("Virtio Block Device") are not formatted because the
1263 // driver supports only that device type. Therefore the driver name suffices
1264 // for unambiguous identification.
1268 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1269 { "eng;en", L
"Virtio Block Driver" },
1274 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1278 VirtioBlkGetDriverName (
1279 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1281 OUT CHAR16
**DriverName
1284 return LookupUnicodeString2 (
1286 This
->SupportedLanguages
,
1289 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1295 VirtioBlkGetDeviceName (
1296 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1297 IN EFI_HANDLE DeviceHandle
,
1298 IN EFI_HANDLE ChildHandle
,
1300 OUT CHAR16
**ControllerName
1303 return EFI_UNSUPPORTED
;
1307 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1308 &VirtioBlkGetDriverName
,
1309 &VirtioBlkGetDeviceName
,
1310 "eng" // SupportedLanguages, ISO 639-2 language codes
1314 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1315 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
)&VirtioBlkGetDriverName
,
1316 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
)&VirtioBlkGetDeviceName
,
1317 "en" // SupportedLanguages, RFC 4646 language codes
1321 // Entry point of this driver.
1325 VirtioBlkEntryPoint (
1326 IN EFI_HANDLE ImageHandle
,
1327 IN EFI_SYSTEM_TABLE
*SystemTable
1330 return EfiLibInstallDriverBindingComponentName2 (