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
;
814 // In virtio-1.0, feature negotiation is expected to complete before queue
815 // discovery, and the device can also reject the selected set of features.
817 if (Dev
->VirtIo
->Revision
>= VIRTIO_SPEC_REVISION (1, 0, 0)) {
818 Status
= Virtio10WriteFeatures (Dev
->VirtIo
, Features
, &NextDevStat
);
819 if (EFI_ERROR (Status
)) {
825 // step 4b -- allocate virtqueue
827 Status
= Dev
->VirtIo
->SetQueueSel (Dev
->VirtIo
, 0);
828 if (EFI_ERROR (Status
)) {
831 Status
= Dev
->VirtIo
->GetQueueNumMax (Dev
->VirtIo
, &QueueSize
);
832 if (EFI_ERROR (Status
)) {
835 if (QueueSize
< 3) { // SynchronousRequest() uses at most three descriptors
836 Status
= EFI_UNSUPPORTED
;
840 Status
= VirtioRingInit (Dev
->VirtIo
, QueueSize
, &Dev
->Ring
);
841 if (EFI_ERROR (Status
)) {
846 // If anything fails from here on, we must release the ring resources
848 Status
= VirtioRingMap (
854 if (EFI_ERROR (Status
)) {
859 // Additional steps for MMIO: align the queue appropriately, and set the
860 // size. If anything fails from here on, we must unmap the ring resources.
862 Status
= Dev
->VirtIo
->SetQueueNum (Dev
->VirtIo
, QueueSize
);
863 if (EFI_ERROR (Status
)) {
867 Status
= Dev
->VirtIo
->SetQueueAlign (Dev
->VirtIo
, EFI_PAGE_SIZE
);
868 if (EFI_ERROR (Status
)) {
873 // step 4c -- Report GPFN (guest-physical frame number) of queue.
875 Status
= Dev
->VirtIo
->SetQueueAddress (
880 if (EFI_ERROR (Status
)) {
886 // step 5 -- Report understood features.
888 if (Dev
->VirtIo
->Revision
< VIRTIO_SPEC_REVISION (1, 0, 0)) {
889 Features
&= ~(UINT64
)VIRTIO_F_VERSION_1
;
890 Status
= Dev
->VirtIo
->SetGuestFeatures (Dev
->VirtIo
, Features
);
891 if (EFI_ERROR (Status
)) {
897 // step 6 -- initialization complete
899 NextDevStat
|= VSTAT_DRIVER_OK
;
900 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
901 if (EFI_ERROR (Status
)) {
906 // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI
907 // Block I/O Protocol.
909 Dev
->BlockIo
.Revision
= 0;
910 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
911 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
912 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
913 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
914 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
915 Dev
->BlockIoMedia
.MediaId
= 0;
916 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
917 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
918 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
919 Dev
->BlockIoMedia
.ReadOnly
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_RO
) != 0);
920 Dev
->BlockIoMedia
.WriteCaching
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_FLUSH
) != 0);
921 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
922 Dev
->BlockIoMedia
.IoAlign
= 0;
923 Dev
->BlockIoMedia
.LastBlock
= DivU64x32 (NumSectors
,
924 BlockSize
/ 512) - 1;
926 DEBUG ((DEBUG_INFO
, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",
927 __FUNCTION__
, Dev
->BlockIoMedia
.BlockSize
,
928 Dev
->BlockIoMedia
.LastBlock
+ 1));
930 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
931 Dev
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
933 Dev
->BlockIoMedia
.LowestAlignedLba
= AlignmentOffset
;
934 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
= 1u << PhysicalBlockExp
;
935 Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
= OptIoSize
;
937 DEBUG ((DEBUG_INFO
, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",
938 __FUNCTION__
, Dev
->BlockIoMedia
.LowestAlignedLba
,
939 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
));
940 DEBUG ((DEBUG_INFO
, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",
941 __FUNCTION__
, Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
));
946 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
949 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
953 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
954 // Status. VirtIo access failure here should not mask the original error.
956 NextDevStat
|= VSTAT_FAILED
;
957 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
959 return Status
; // reached only via Failed above
965 Uninitialize the internals of a virtio-blk device that has been successfully
966 set up with VirtioBlkInit().
968 @param[in out] Dev The device to clean up.
980 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
981 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
982 // the old comms area.
984 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
986 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
987 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
989 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
990 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
996 Event notification function enqueued by ExitBootServices().
998 @param[in] Event Event whose notification function is being invoked.
1000 @param[in] Context Pointer to the VBLK_DEV structure.
1015 // Reset the device. This causes the hypervisor to forget about the virtio
1018 // We allocated said ring in EfiBootServicesData type memory, and code
1019 // executing after ExitBootServices() is permitted to overwrite it.
1022 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
1025 // Unmap the ring buffer so that hypervisor will not be able to get
1026 // readable data after device is reset.
1028 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
1033 After we've pronounced support for a specific device in
1034 DriverBindingSupported(), we start managing said device (passed in by the
1035 Driver Execution Environment) with the following service.
1037 See DriverBindingSupported() for specification references.
1039 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1040 incorporating this driver (independently of
1043 @param[in] DeviceHandle The supported device to drive.
1045 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
1048 @retval EFI_SUCCESS Driver instance has been created and
1049 initialized for the virtio-blk device, it
1050 is now accessible via EFI_BLOCK_IO_PROTOCOL.
1052 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1054 @return Error codes from the OpenProtocol() boot
1055 service, the VirtIo protocol, VirtioBlkInit(),
1056 or the InstallProtocolInterface() boot service.
1062 VirtioBlkDriverBindingStart (
1063 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1064 IN EFI_HANDLE DeviceHandle
,
1065 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1071 Dev
= (VBLK_DEV
*) AllocateZeroPool (sizeof *Dev
);
1073 return EFI_OUT_OF_RESOURCES
;
1076 Status
= gBS
->OpenProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1077 (VOID
**)&Dev
->VirtIo
, This
->DriverBindingHandle
,
1078 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
1079 if (EFI_ERROR (Status
)) {
1084 // VirtIo access granted, configure virtio-blk device.
1086 Status
= VirtioBlkInit (Dev
);
1087 if (EFI_ERROR (Status
)) {
1091 Status
= gBS
->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_CALLBACK
,
1092 &VirtioBlkExitBoot
, Dev
, &Dev
->ExitBoot
);
1093 if (EFI_ERROR (Status
)) {
1098 // Setup complete, attempt to export the driver instance's BlockIo interface.
1100 Dev
->Signature
= VBLK_SIG
;
1101 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
1102 &gEfiBlockIoProtocolGuid
, EFI_NATIVE_INTERFACE
,
1104 if (EFI_ERROR (Status
)) {
1111 gBS
->CloseEvent (Dev
->ExitBoot
);
1114 VirtioBlkUninit (Dev
);
1117 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1118 This
->DriverBindingHandle
, DeviceHandle
);
1129 Stop driving a virtio-blk device and remove its BlockIo interface.
1131 This function replays the success path of DriverBindingStart() in reverse.
1132 The host side virtio-blk device is reset, so that the OS boot loader or the
1133 OS may reinitialize it.
1135 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
1136 incorporating this driver (independently of any
1139 @param[in] DeviceHandle Stop driving this device.
1141 @param[in] NumberOfChildren Since this function belongs to a device driver
1142 only (as opposed to a bus driver), the caller
1143 environment sets NumberOfChildren to zero, and
1146 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
1152 VirtioBlkDriverBindingStop (
1153 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1154 IN EFI_HANDLE DeviceHandle
,
1155 IN UINTN NumberOfChildren
,
1156 IN EFI_HANDLE
*ChildHandleBuffer
1160 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
1163 Status
= gBS
->OpenProtocol (
1164 DeviceHandle
, // candidate device
1165 &gEfiBlockIoProtocolGuid
, // retrieve the BlockIo iface
1166 (VOID
**)&BlockIo
, // target pointer
1167 This
->DriverBindingHandle
, // requestor driver identity
1168 DeviceHandle
, // requesting lookup for dev.
1169 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
1171 if (EFI_ERROR (Status
)) {
1175 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (BlockIo
);
1178 // Handle Stop() requests for in-use driver instances gracefully.
1180 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
1181 &gEfiBlockIoProtocolGuid
, &Dev
->BlockIo
);
1182 if (EFI_ERROR (Status
)) {
1186 gBS
->CloseEvent (Dev
->ExitBoot
);
1188 VirtioBlkUninit (Dev
);
1190 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1191 This
->DriverBindingHandle
, DeviceHandle
);
1200 // The static object that groups the Supported() (ie. probe), Start() and
1201 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1202 // C, 10.1 EFI Driver Binding Protocol.
1204 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
1205 &VirtioBlkDriverBindingSupported
,
1206 &VirtioBlkDriverBindingStart
,
1207 &VirtioBlkDriverBindingStop
,
1208 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1209 NULL
, // ImageHandle, to be overwritten by
1210 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
1211 NULL
// DriverBindingHandle, ditto
1216 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1217 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1218 // in English, for display on standard console devices. This is recommended for
1219 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1220 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1222 // Device type names ("Virtio Block Device") are not formatted because the
1223 // driver supports only that device type. Therefore the driver name suffices
1224 // for unambiguous identification.
1228 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1229 { "eng;en", L
"Virtio Block Driver" },
1234 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1238 VirtioBlkGetDriverName (
1239 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1241 OUT CHAR16
**DriverName
1244 return LookupUnicodeString2 (
1246 This
->SupportedLanguages
,
1249 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1255 VirtioBlkGetDeviceName (
1256 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1257 IN EFI_HANDLE DeviceHandle
,
1258 IN EFI_HANDLE ChildHandle
,
1260 OUT CHAR16
**ControllerName
1263 return EFI_UNSUPPORTED
;
1267 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1268 &VirtioBlkGetDriverName
,
1269 &VirtioBlkGetDeviceName
,
1270 "eng" // SupportedLanguages, ISO 639-2 language codes
1274 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1275 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioBlkGetDriverName
,
1276 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioBlkGetDeviceName
,
1277 "en" // SupportedLanguages, RFC 4646 language codes
1282 // Entry point of this driver.
1286 VirtioBlkEntryPoint (
1287 IN EFI_HANDLE ImageHandle
,
1288 IN EFI_SYSTEM_TABLE
*SystemTable
1291 return EfiLibInstallDriverBindingComponentName2 (