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 - 2016, Intel Corporation. All rights reserved.<BR>
15 Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
17 This program and the accompanying materials are licensed and made available
18 under the terms and conditions of the BSD License which accompanies this
19 distribution. The full text of the license may be found at
20 http://opensource.org/licenses/bsd-license.php
22 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
23 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 #include <IndustryStandard/VirtioBlk.h>
28 #include <Library/BaseMemoryLib.h>
29 #include <Library/DebugLib.h>
30 #include <Library/MemoryAllocationLib.h>
31 #include <Library/UefiBootServicesTableLib.h>
32 #include <Library/UefiLib.h>
33 #include <Library/VirtioLib.h>
35 #include "VirtioBlk.h"
39 Convenience macros to read and write region 0 IO space elements of the
40 virtio-blk device, for configuration purposes.
42 The following macros make it possible to specify only the "core parameters"
43 for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
44 returns, the transaction will have been completed.
46 @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space
47 we're accessing. Dev->VirtIo must be valid.
49 @param[in] Field A field name from VBLK_HDR, identifying the virtio-blk
50 configuration item to access.
52 @param[in] Value (VIRTIO_CFG_WRITE() only.) The value to write to the
53 selected configuration item.
55 @param[out] Pointer (VIRTIO_CFG_READ() only.) The object to receive the
56 value read from the configuration item. Its type must be
57 one of UINT8, UINT16, UINT32, UINT64.
60 @return Status code returned by Virtio->WriteDevice() /
65 #define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
67 OFFSET_OF_VBLK (Field), \
68 SIZE_OF_VBLK (Field), \
72 #define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
74 OFFSET_OF_VBLK (Field), \
75 SIZE_OF_VBLK (Field), \
82 // UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
83 // Driver Writer's Guide for UEFI 2.3.1 v1.01,
84 // 24.2 Block I/O Protocol Implementations
89 IN EFI_BLOCK_IO_PROTOCOL
*This
,
90 IN BOOLEAN ExtendedVerification
94 // If we managed to initialize and install the driver, then the device is
102 Verify correctness of the read/write (not flush) request submitted to the
103 EFI_BLOCK_IO_PROTOCOL instance.
105 This function provides most verification steps described in:
107 UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
109 - EFI_BLOCK_IO_PROTOCOL.ReadBlocks()
110 - EFI_BLOCK_IO_PROTOCOL.WriteBlocks()
112 Driver Writer's Guide for UEFI 2.3.1 v1.01,
113 - 24.2.2. ReadBlocks() and ReadBlocksEx() Implementation
114 - 24.2.3 WriteBlocks() and WriteBlockEx() Implementation
116 Request sizes are limited to 1 GB (checked). This is not a practical
117 limitation, just conformance to virtio-0.9.5, 2.3.2 Descriptor Table: "no
118 descriptor chain may be more than 2^32 bytes long in total".
120 Some Media characteristics are hardcoded in VirtioBlkInit() below (like
121 non-removable media, no restriction on buffer alignment etc); we rely on
122 those here without explicit mention.
124 @param[in] Media The EFI_BLOCK_IO_MEDIA characteristics for
125 this driver instance, extracted from the
126 underlying virtio-blk device at initialization
127 time. We validate the request against this set
131 @param[in] Lba Logical Block Address: number of logical
132 blocks to skip from the beginning of the
135 @param[in] PositiveBufferSize Size of buffer to transfer, in bytes. The
136 caller is responsible to ensure this parameter
139 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
143 @@return Validation result to be forwarded outwards by
144 ReadBlocks() and WriteBlocks, as required by
151 VerifyReadWriteRequest (
152 IN EFI_BLOCK_IO_MEDIA
*Media
,
154 IN UINTN PositiveBufferSize
,
155 IN BOOLEAN RequestIsWrite
160 ASSERT (PositiveBufferSize
> 0);
162 if (PositiveBufferSize
> SIZE_1GB
||
163 PositiveBufferSize
% Media
->BlockSize
> 0) {
164 return EFI_BAD_BUFFER_SIZE
;
166 BlockCount
= PositiveBufferSize
/ Media
->BlockSize
;
169 // Avoid unsigned wraparound on either side in the second comparison.
171 if (Lba
> Media
->LastBlock
|| BlockCount
- 1 > Media
->LastBlock
- Lba
) {
172 return EFI_INVALID_PARAMETER
;
175 if (RequestIsWrite
&& Media
->ReadOnly
) {
176 return EFI_WRITE_PROTECTED
;
187 Format a read / write / flush request as three consecutive virtio
188 descriptors, push them to the host, and poll for the response.
190 This is the main workhorse function. Two use cases are supported, read/write
191 and flush. The function may only be called after the request parameters have
193 - specific checks in ReadBlocks() / WriteBlocks() / FlushBlocks(), and
194 - VerifyReadWriteRequest() (for read/write only).
196 Parameters handled commonly:
198 @param[in] Dev The virtio-blk device the request is targeted
203 @param[in] Lba Must be zero.
205 @param[in] BufferSize Must be zero.
207 @param[in out] Buffer Ignored by the function.
209 @param[in] RequestIsWrite Must be TRUE.
213 @param[in] Lba Logical Block Address: number of logical blocks
214 to skip from the beginning of the device.
216 @param[in] BufferSize Size of buffer to transfer, in bytes. The caller
217 is responsible to ensure this parameter is
220 @param[in out] Buffer The guest side area to read data from the device
221 into, or write data to the device from.
223 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
226 Return values are common to both use cases, and are appropriate to be
227 forwarded by the EFI_BLOCK_IO_PROTOCOL functions (ReadBlocks(),
228 WriteBlocks(), FlushBlocks()).
231 @retval EFI_SUCCESS Transfer complete.
233 @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
234 unable to parse host response, or host response
235 is not VIRTIO_BLK_S_OK or failed to map Buffer
236 for a bus master operation.
247 IN OUT
volatile VOID
*Buffer
,
248 IN BOOLEAN RequestIsWrite
252 volatile VIRTIO_BLK_REQ Request
;
253 volatile UINT8
*HostStatus
;
254 VOID
*HostStatusBuffer
;
255 DESC_INDICES Indices
;
256 VOID
*RequestMapping
;
259 EFI_PHYSICAL_ADDRESS BufferDeviceAddress
;
260 EFI_PHYSICAL_ADDRESS HostStatusDeviceAddress
;
261 EFI_PHYSICAL_ADDRESS RequestDeviceAddress
;
264 BlockSize
= Dev
->BlockIoMedia
.BlockSize
;
267 // ensured by VirtioBlkInit()
269 ASSERT (BlockSize
> 0);
270 ASSERT (BlockSize
% 512 == 0);
273 // ensured by contract above, plus VerifyReadWriteRequest()
275 ASSERT (BufferSize
% BlockSize
== 0);
278 // Prepare virtio-blk request header, setting zero size for flush.
279 // IO Priority is homogeneously 0.
281 Request
.Type
= RequestIsWrite
?
282 (BufferSize
== 0 ? VIRTIO_BLK_T_FLUSH
: VIRTIO_BLK_T_OUT
) :
285 Request
.Sector
= MultU64x32(Lba
, BlockSize
/ 512);
288 // Host status is bi-directional (we preset with a value and expect the
289 // device to update it). Allocate a host status buffer which can be mapped
290 // to access equally by both processor and the device.
292 Status
= Dev
->VirtIo
->AllocateSharedPages (
294 EFI_SIZE_TO_PAGES (sizeof *HostStatus
),
297 if (EFI_ERROR (Status
)) {
298 return EFI_DEVICE_ERROR
;
301 HostStatus
= HostStatusBuffer
;
304 // Map virtio-blk request header (must be done after request header is
307 Status
= VirtioMapAllBytesInSharedBuffer (
309 VirtioOperationBusMasterRead
,
312 &RequestDeviceAddress
,
315 if (EFI_ERROR (Status
)) {
316 Status
= EFI_DEVICE_ERROR
;
317 goto FreeHostStatusBuffer
;
323 if (BufferSize
> 0) {
324 Status
= VirtioMapAllBytesInSharedBuffer (
327 VirtioOperationBusMasterRead
:
328 VirtioOperationBusMasterWrite
),
331 &BufferDeviceAddress
,
334 if (EFI_ERROR (Status
)) {
335 Status
= EFI_DEVICE_ERROR
;
336 goto UnmapRequestBuffer
;
341 // preset a host status for ourselves that we do not accept as success
343 *HostStatus
= VIRTIO_BLK_S_IOERR
;
346 // Map the Status Buffer with VirtioOperationBusMasterCommonBuffer so that
347 // both processor and device can access it.
349 Status
= VirtioMapAllBytesInSharedBuffer (
351 VirtioOperationBusMasterCommonBuffer
,
354 &HostStatusDeviceAddress
,
357 if (EFI_ERROR (Status
)) {
358 Status
= EFI_DEVICE_ERROR
;
359 goto UnmapDataBuffer
;
362 VirtioPrepare (&Dev
->Ring
, &Indices
);
365 // ensured by VirtioBlkInit() -- this predicate, in combination with the
366 // lock-step progress, ensures we don't have to track free descriptors.
368 ASSERT (Dev
->Ring
.QueueSize
>= 3);
371 // virtio-blk header in first desc
375 RequestDeviceAddress
,
382 // data buffer for read/write in second desc
384 if (BufferSize
> 0) {
386 // From virtio-0.9.5, 2.3.2 Descriptor Table:
387 // "no descriptor chain may be more than 2^32 bytes long in total".
389 // The predicate is ensured by the call contract above (for flush), or
390 // VerifyReadWriteRequest() (for read/write). It also implies that
391 // converting BufferSize to UINT32 will not truncate it.
393 ASSERT (BufferSize
<= SIZE_1GB
);
396 // VRING_DESC_F_WRITE is interpreted from the host's point of view.
402 VRING_DESC_F_NEXT
| (RequestIsWrite
? 0 : VRING_DESC_F_WRITE
),
408 // host status in last (second or third) desc
412 HostStatusDeviceAddress
,
419 // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
421 if (VirtioFlush (Dev
->VirtIo
, 0, &Dev
->Ring
, &Indices
,
422 NULL
) == EFI_SUCCESS
&&
423 *HostStatus
== VIRTIO_BLK_S_OK
) {
424 Status
= EFI_SUCCESS
;
426 Status
= EFI_DEVICE_ERROR
;
429 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, StatusMapping
);
432 if (BufferSize
> 0) {
433 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, BufferMapping
);
437 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, RequestMapping
);
439 FreeHostStatusBuffer
:
440 Dev
->VirtIo
->FreeSharedPages (
442 EFI_SIZE_TO_PAGES (sizeof *HostStatus
),
452 ReadBlocks() operation for virtio-blk.
455 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
456 Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
457 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
458 ReadBlocksEx() Implementation.
460 Parameter checks and conformant return values are implemented in
461 VerifyReadWriteRequest() and SynchronousRequest().
463 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
470 VirtioBlkReadBlocks (
471 IN EFI_BLOCK_IO_PROTOCOL
*This
,
481 if (BufferSize
== 0) {
485 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
486 Status
= VerifyReadWriteRequest (
490 FALSE
// RequestIsWrite
492 if (EFI_ERROR (Status
)) {
496 return SynchronousRequest (
501 FALSE
// RequestIsWrite
507 WriteBlocks() operation for virtio-blk.
510 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
511 Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
512 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
513 WriteBlockEx() Implementation.
515 Parameter checks and conformant return values are implemented in
516 VerifyReadWriteRequest() and SynchronousRequest().
518 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
525 VirtioBlkWriteBlocks (
526 IN EFI_BLOCK_IO_PROTOCOL
*This
,
536 if (BufferSize
== 0) {
540 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
541 Status
= VerifyReadWriteRequest (
545 TRUE
// RequestIsWrite
547 if (EFI_ERROR (Status
)) {
551 return SynchronousRequest (
556 TRUE
// RequestIsWrite
563 FlushBlocks() operation for virtio-blk.
566 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
567 Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
568 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
569 FlushBlocksEx() Implementation.
571 If the underlying virtio-blk device doesn't support flushing (ie.
572 write-caching), then this function should not be called by higher layers,
573 according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
574 Should they do nonetheless, we do nothing, successfully.
580 VirtioBlkFlushBlocks (
581 IN EFI_BLOCK_IO_PROTOCOL
*This
586 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
587 return Dev
->BlockIoMedia
.WriteCaching
?
593 TRUE
// RequestIsWrite
601 Device probe function for this driver.
603 The DXE core calls this function for any given device in order to see if the
604 driver can drive the device.
606 Specs relevant in the general sense:
608 - UEFI Spec 2.3.1 + Errata C:
609 - 6.3 Protocol Handler Services -- for accessing the underlying device
610 - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
612 - Driver Writer's Guide for UEFI 2.3.1 v1.01:
613 - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
615 - 9 Driver Binding Protocol -- for exporting ourselves
617 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
618 incorporating this driver (independently of
621 @param[in] DeviceHandle The device to probe.
623 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
626 @retval EFI_SUCCESS The driver supports the device being probed.
628 @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
631 @return Error codes from the OpenProtocol() boot service or
638 VirtioBlkDriverBindingSupported (
639 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
640 IN EFI_HANDLE DeviceHandle
,
641 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
645 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
648 // Attempt to open the device with the VirtIo set of interfaces. On success,
649 // the protocol is "instantiated" for the VirtIo device. Covers duplicate
650 // open attempts (EFI_ALREADY_STARTED).
652 Status
= gBS
->OpenProtocol (
653 DeviceHandle
, // candidate device
654 &gVirtioDeviceProtocolGuid
, // for generic VirtIo access
655 (VOID
**)&VirtIo
, // handle to instantiate
656 This
->DriverBindingHandle
, // requestor driver identity
657 DeviceHandle
, // ControllerHandle, according to
658 // the UEFI Driver Model
659 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive VirtIo access to
660 // the device; to be released
662 if (EFI_ERROR (Status
)) {
666 if (VirtIo
->SubSystemDeviceId
!= VIRTIO_SUBSYSTEM_BLOCK_DEVICE
) {
667 Status
= EFI_UNSUPPORTED
;
671 // We needed VirtIo access only transitorily, to see whether we support the
674 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
675 This
->DriverBindingHandle
, DeviceHandle
);
682 Set up all BlockIo and virtio-blk aspects of this driver for the specified
685 @param[in out] Dev The driver instance to configure. The caller is
686 responsible for Dev->VirtIo's validity (ie. working IO
687 access to the underlying virtio-blk device).
689 @retval EFI_SUCCESS Setup complete.
691 @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
692 virtio-blk attributes the host provides.
694 @return Error codes from VirtioRingInit() or
695 VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE or
713 UINT8 PhysicalBlockExp
;
714 UINT8 AlignmentOffset
;
717 UINT64 RingBaseShift
;
719 PhysicalBlockExp
= 0;
724 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
726 NextDevStat
= 0; // step 1 -- reset device
727 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
728 if (EFI_ERROR (Status
)) {
732 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
733 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
734 if (EFI_ERROR (Status
)) {
738 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
739 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
740 if (EFI_ERROR (Status
)) {
745 // Set Page Size - MMIO VirtIo Specific
747 Status
= Dev
->VirtIo
->SetPageSize (Dev
->VirtIo
, EFI_PAGE_SIZE
);
748 if (EFI_ERROR (Status
)) {
753 // step 4a -- retrieve and validate features
755 Status
= Dev
->VirtIo
->GetDeviceFeatures (Dev
->VirtIo
, &Features
);
756 if (EFI_ERROR (Status
)) {
760 Status
= VIRTIO_CFG_READ (Dev
, Capacity
, &NumSectors
);
761 if (EFI_ERROR (Status
)) {
764 if (NumSectors
== 0) {
765 Status
= EFI_UNSUPPORTED
;
769 if (Features
& VIRTIO_BLK_F_BLK_SIZE
) {
770 Status
= VIRTIO_CFG_READ (Dev
, BlkSize
, &BlockSize
);
771 if (EFI_ERROR (Status
)) {
774 if (BlockSize
== 0 || BlockSize
% 512 != 0 ||
775 ModU64x32 (NumSectors
, BlockSize
/ 512) != 0) {
777 // We can only handle a logical block consisting of whole sectors,
778 // and only a disk composed of whole logical blocks.
780 Status
= EFI_UNSUPPORTED
;
788 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
789 Status
= VIRTIO_CFG_READ (Dev
, Topology
.PhysicalBlockExp
,
791 if (EFI_ERROR (Status
)) {
794 if (PhysicalBlockExp
>= 32) {
795 Status
= EFI_UNSUPPORTED
;
799 Status
= VIRTIO_CFG_READ (Dev
, Topology
.AlignmentOffset
, &AlignmentOffset
);
800 if (EFI_ERROR (Status
)) {
804 Status
= VIRTIO_CFG_READ (Dev
, Topology
.OptIoSize
, &OptIoSize
);
805 if (EFI_ERROR (Status
)) {
810 Features
&= VIRTIO_BLK_F_BLK_SIZE
| VIRTIO_BLK_F_TOPOLOGY
| VIRTIO_BLK_F_RO
|
811 VIRTIO_BLK_F_FLUSH
| VIRTIO_F_VERSION_1
|
812 VIRTIO_F_IOMMU_PLATFORM
;
815 // In virtio-1.0, feature negotiation is expected to complete before queue
816 // discovery, and the device can also reject the selected set of features.
818 if (Dev
->VirtIo
->Revision
>= VIRTIO_SPEC_REVISION (1, 0, 0)) {
819 Status
= Virtio10WriteFeatures (Dev
->VirtIo
, Features
, &NextDevStat
);
820 if (EFI_ERROR (Status
)) {
826 // step 4b -- allocate virtqueue
828 Status
= Dev
->VirtIo
->SetQueueSel (Dev
->VirtIo
, 0);
829 if (EFI_ERROR (Status
)) {
832 Status
= Dev
->VirtIo
->GetQueueNumMax (Dev
->VirtIo
, &QueueSize
);
833 if (EFI_ERROR (Status
)) {
836 if (QueueSize
< 3) { // SynchronousRequest() uses at most three descriptors
837 Status
= EFI_UNSUPPORTED
;
841 Status
= VirtioRingInit (Dev
->VirtIo
, QueueSize
, &Dev
->Ring
);
842 if (EFI_ERROR (Status
)) {
847 // If anything fails from here on, we must release the ring resources
849 Status
= VirtioRingMap (
855 if (EFI_ERROR (Status
)) {
860 // Additional steps for MMIO: align the queue appropriately, and set the
861 // size. If anything fails from here on, we must unmap the ring resources.
863 Status
= Dev
->VirtIo
->SetQueueNum (Dev
->VirtIo
, QueueSize
);
864 if (EFI_ERROR (Status
)) {
868 Status
= Dev
->VirtIo
->SetQueueAlign (Dev
->VirtIo
, EFI_PAGE_SIZE
);
869 if (EFI_ERROR (Status
)) {
874 // step 4c -- Report GPFN (guest-physical frame number) of queue.
876 Status
= Dev
->VirtIo
->SetQueueAddress (
881 if (EFI_ERROR (Status
)) {
887 // step 5 -- Report understood features.
889 if (Dev
->VirtIo
->Revision
< VIRTIO_SPEC_REVISION (1, 0, 0)) {
890 Features
&= ~(UINT64
)(VIRTIO_F_VERSION_1
| VIRTIO_F_IOMMU_PLATFORM
);
891 Status
= Dev
->VirtIo
->SetGuestFeatures (Dev
->VirtIo
, Features
);
892 if (EFI_ERROR (Status
)) {
898 // step 6 -- initialization complete
900 NextDevStat
|= VSTAT_DRIVER_OK
;
901 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
902 if (EFI_ERROR (Status
)) {
907 // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI
908 // Block I/O Protocol.
910 Dev
->BlockIo
.Revision
= 0;
911 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
912 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
913 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
914 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
915 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
916 Dev
->BlockIoMedia
.MediaId
= 0;
917 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
918 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
919 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
920 Dev
->BlockIoMedia
.ReadOnly
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_RO
) != 0);
921 Dev
->BlockIoMedia
.WriteCaching
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_FLUSH
) != 0);
922 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
923 Dev
->BlockIoMedia
.IoAlign
= 0;
924 Dev
->BlockIoMedia
.LastBlock
= DivU64x32 (NumSectors
,
925 BlockSize
/ 512) - 1;
927 DEBUG ((DEBUG_INFO
, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",
928 __FUNCTION__
, Dev
->BlockIoMedia
.BlockSize
,
929 Dev
->BlockIoMedia
.LastBlock
+ 1));
931 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
932 Dev
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
934 Dev
->BlockIoMedia
.LowestAlignedLba
= AlignmentOffset
;
935 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
= 1u << PhysicalBlockExp
;
936 Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
= OptIoSize
;
938 DEBUG ((DEBUG_INFO
, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",
939 __FUNCTION__
, Dev
->BlockIoMedia
.LowestAlignedLba
,
940 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
));
941 DEBUG ((DEBUG_INFO
, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",
942 __FUNCTION__
, Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
));
947 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
950 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
954 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
955 // Status. VirtIo access failure here should not mask the original error.
957 NextDevStat
|= VSTAT_FAILED
;
958 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
960 return Status
; // reached only via Failed above
966 Uninitialize the internals of a virtio-blk device that has been successfully
967 set up with VirtioBlkInit().
969 @param[in out] Dev The device to clean up.
981 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
982 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
983 // the old comms area.
985 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
987 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
988 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
990 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
991 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
997 Event notification function enqueued by ExitBootServices().
999 @param[in] Event Event whose notification function is being invoked.
1001 @param[in] Context Pointer to the VBLK_DEV structure.
1016 // Reset the device. This causes the hypervisor to forget about the virtio
1019 // We allocated said ring in EfiBootServicesData type memory, and code
1020 // executing after ExitBootServices() is permitted to overwrite it.
1023 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
1026 // Unmap the ring buffer so that hypervisor will not be able to get
1027 // readable data after device is reset.
1029 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
1034 After we've pronounced support for a specific device in
1035 DriverBindingSupported(), we start managing said device (passed in by the
1036 Driver Execution Environment) with the following service.
1038 See DriverBindingSupported() for specification references.
1040 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1041 incorporating this driver (independently of
1044 @param[in] DeviceHandle The supported device to drive.
1046 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
1049 @retval EFI_SUCCESS Driver instance has been created and
1050 initialized for the virtio-blk device, it
1051 is now accessible via EFI_BLOCK_IO_PROTOCOL.
1053 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1055 @return Error codes from the OpenProtocol() boot
1056 service, the VirtIo protocol, VirtioBlkInit(),
1057 or the InstallProtocolInterface() boot service.
1063 VirtioBlkDriverBindingStart (
1064 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1065 IN EFI_HANDLE DeviceHandle
,
1066 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1072 Dev
= (VBLK_DEV
*) AllocateZeroPool (sizeof *Dev
);
1074 return EFI_OUT_OF_RESOURCES
;
1077 Status
= gBS
->OpenProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1078 (VOID
**)&Dev
->VirtIo
, This
->DriverBindingHandle
,
1079 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
1080 if (EFI_ERROR (Status
)) {
1085 // VirtIo access granted, configure virtio-blk device.
1087 Status
= VirtioBlkInit (Dev
);
1088 if (EFI_ERROR (Status
)) {
1092 Status
= gBS
->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_CALLBACK
,
1093 &VirtioBlkExitBoot
, Dev
, &Dev
->ExitBoot
);
1094 if (EFI_ERROR (Status
)) {
1099 // Setup complete, attempt to export the driver instance's BlockIo interface.
1101 Dev
->Signature
= VBLK_SIG
;
1102 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
1103 &gEfiBlockIoProtocolGuid
, EFI_NATIVE_INTERFACE
,
1105 if (EFI_ERROR (Status
)) {
1112 gBS
->CloseEvent (Dev
->ExitBoot
);
1115 VirtioBlkUninit (Dev
);
1118 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1119 This
->DriverBindingHandle
, DeviceHandle
);
1130 Stop driving a virtio-blk device and remove its BlockIo interface.
1132 This function replays the success path of DriverBindingStart() in reverse.
1133 The host side virtio-blk device is reset, so that the OS boot loader or the
1134 OS may reinitialize it.
1136 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1137 incorporating this driver (independently of any
1140 @param[in] DeviceHandle Stop driving this device.
1142 @param[in] NumberOfChildren Since this function belongs to a device driver
1143 only (as opposed to a bus driver), the caller
1144 environment sets NumberOfChildren to zero, and
1147 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
1153 VirtioBlkDriverBindingStop (
1154 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1155 IN EFI_HANDLE DeviceHandle
,
1156 IN UINTN NumberOfChildren
,
1157 IN EFI_HANDLE
*ChildHandleBuffer
1161 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
1164 Status
= gBS
->OpenProtocol (
1165 DeviceHandle
, // candidate device
1166 &gEfiBlockIoProtocolGuid
, // retrieve the BlockIo iface
1167 (VOID
**)&BlockIo
, // target pointer
1168 This
->DriverBindingHandle
, // requestor driver identity
1169 DeviceHandle
, // requesting lookup for dev.
1170 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
1172 if (EFI_ERROR (Status
)) {
1176 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (BlockIo
);
1179 // Handle Stop() requests for in-use driver instances gracefully.
1181 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
1182 &gEfiBlockIoProtocolGuid
, &Dev
->BlockIo
);
1183 if (EFI_ERROR (Status
)) {
1187 gBS
->CloseEvent (Dev
->ExitBoot
);
1189 VirtioBlkUninit (Dev
);
1191 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1192 This
->DriverBindingHandle
, DeviceHandle
);
1201 // The static object that groups the Supported() (ie. probe), Start() and
1202 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1203 // C, 10.1 EFI Driver Binding Protocol.
1205 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
1206 &VirtioBlkDriverBindingSupported
,
1207 &VirtioBlkDriverBindingStart
,
1208 &VirtioBlkDriverBindingStop
,
1209 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1210 NULL
, // ImageHandle, to be overwritten by
1211 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
1212 NULL
// DriverBindingHandle, ditto
1217 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1218 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1219 // in English, for display on standard console devices. This is recommended for
1220 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1221 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1223 // Device type names ("Virtio Block Device") are not formatted because the
1224 // driver supports only that device type. Therefore the driver name suffices
1225 // for unambiguous identification.
1229 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1230 { "eng;en", L
"Virtio Block Driver" },
1235 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1239 VirtioBlkGetDriverName (
1240 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1242 OUT CHAR16
**DriverName
1245 return LookupUnicodeString2 (
1247 This
->SupportedLanguages
,
1250 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1256 VirtioBlkGetDeviceName (
1257 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1258 IN EFI_HANDLE DeviceHandle
,
1259 IN EFI_HANDLE ChildHandle
,
1261 OUT CHAR16
**ControllerName
1264 return EFI_UNSUPPORTED
;
1268 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1269 &VirtioBlkGetDriverName
,
1270 &VirtioBlkGetDeviceName
,
1271 "eng" // SupportedLanguages, ISO 639-2 language codes
1275 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1276 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioBlkGetDriverName
,
1277 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioBlkGetDeviceName
,
1278 "en" // SupportedLanguages, RFC 4646 language codes
1283 // Entry point of this driver.
1287 VirtioBlkEntryPoint (
1288 IN EFI_HANDLE ImageHandle
,
1289 IN EFI_SYSTEM_TABLE
*SystemTable
1292 return EfiLibInstallDriverBindingComponentName2 (