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>
16 This program and the accompanying materials are licensed and made available
17 under the terms and conditions of the BSD License which accompanies this
18 distribution. The full text of the license may be found at
19 http://opensource.org/licenses/bsd-license.php
21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
22 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 #include <IndustryStandard/VirtioBlk.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/DebugLib.h>
29 #include <Library/MemoryAllocationLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/UefiLib.h>
32 #include <Library/VirtioLib.h>
34 #include "VirtioBlk.h"
38 Convenience macros to read and write region 0 IO space elements of the
39 virtio-blk device, for configuration purposes.
41 The following macros make it possible to specify only the "core parameters"
42 for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
43 returns, the transaction will have been completed.
45 @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space
46 we're accessing. Dev->VirtIo must be valid.
48 @param[in] Field A field name from VBLK_HDR, identifying the virtio-blk
49 configuration item to access.
51 @param[in] Value (VIRTIO_CFG_WRITE() only.) The value to write to the
52 selected configuration item.
54 @param[out] Pointer (VIRTIO_CFG_READ() only.) The object to receive the
55 value read from the configuration item. Its type must be
56 one of UINT8, UINT16, UINT32, UINT64.
59 @return Status code returned by Virtio->WriteDevice() /
64 #define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
66 OFFSET_OF_VBLK (Field), \
67 SIZE_OF_VBLK (Field), \
71 #define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
73 OFFSET_OF_VBLK (Field), \
74 SIZE_OF_VBLK (Field), \
81 // UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
82 // Driver Writer's Guide for UEFI 2.3.1 v1.01,
83 // 24.2 Block I/O Protocol Implementations
88 IN EFI_BLOCK_IO_PROTOCOL
*This
,
89 IN BOOLEAN ExtendedVerification
93 // If we managed to initialize and install the driver, then the device is
101 Verify correctness of the read/write (not flush) request submitted to the
102 EFI_BLOCK_IO_PROTOCOL instance.
104 This function provides most verification steps described in:
106 UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
108 - EFI_BLOCK_IO_PROTOCOL.ReadBlocks()
109 - EFI_BLOCK_IO_PROTOCOL.WriteBlocks()
111 Driver Writer's Guide for UEFI 2.3.1 v1.01,
112 - 24.2.2. ReadBlocks() and ReadBlocksEx() Implementation
113 - 24.2.3 WriteBlocks() and WriteBlockEx() Implementation
115 Request sizes are limited to 1 GB (checked). This is not a practical
116 limitation, just conformance to virtio-0.9.5, 2.3.2 Descriptor Table: "no
117 descriptor chain may be more than 2^32 bytes long in total".
119 Some Media characteristics are hardcoded in VirtioBlkInit() below (like
120 non-removable media, no restriction on buffer alignment etc); we rely on
121 those here without explicit mention.
123 @param[in] Media The EFI_BLOCK_IO_MEDIA characteristics for
124 this driver instance, extracted from the
125 underlying virtio-blk device at initialization
126 time. We validate the request against this set
130 @param[in] Lba Logical Block Address: number of logical
131 blocks to skip from the beginning of the
134 @param[in] PositiveBufferSize Size of buffer to transfer, in bytes. The
135 caller is responsible to ensure this parameter
138 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
142 @@return Validation result to be forwarded outwards by
143 ReadBlocks() and WriteBlocks, as required by
150 VerifyReadWriteRequest (
151 IN EFI_BLOCK_IO_MEDIA
*Media
,
153 IN UINTN PositiveBufferSize
,
154 IN BOOLEAN RequestIsWrite
159 ASSERT (PositiveBufferSize
> 0);
161 if (PositiveBufferSize
> SIZE_1GB
||
162 PositiveBufferSize
% Media
->BlockSize
> 0) {
163 return EFI_BAD_BUFFER_SIZE
;
165 BlockCount
= PositiveBufferSize
/ Media
->BlockSize
;
168 // Avoid unsigned wraparound on either side in the second comparison.
170 if (Lba
> Media
->LastBlock
|| BlockCount
- 1 > Media
->LastBlock
- Lba
) {
171 return EFI_INVALID_PARAMETER
;
174 if (RequestIsWrite
&& Media
->ReadOnly
) {
175 return EFI_WRITE_PROTECTED
;
186 Format a read / write / flush request as three consecutive virtio
187 descriptors, push them to the host, and poll for the response.
189 This is the main workhorse function. Two use cases are supported, read/write
190 and flush. The function may only be called after the request parameters have
192 - specific checks in ReadBlocks() / WriteBlocks() / FlushBlocks(), and
193 - VerifyReadWriteRequest() (for read/write only).
195 Parameters handled commonly:
197 @param[in] Dev The virtio-blk device the request is targeted
202 @param[in] Lba Must be zero.
204 @param[in] BufferSize Must be zero.
206 @param[in out] Buffer Ignored by the function.
208 @param[in] RequestIsWrite Must be TRUE.
212 @param[in] Lba Logical Block Address: number of logical blocks
213 to skip from the beginning of the device.
215 @param[in] BufferSize Size of buffer to transfer, in bytes. The caller
216 is responsible to ensure this parameter is
219 @param[in out] Buffer The guest side area to read data from the device
220 into, or write data to the device from.
222 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
225 Return values are common to both use cases, and are appropriate to be
226 forwarded by the EFI_BLOCK_IO_PROTOCOL functions (ReadBlocks(),
227 WriteBlocks(), FlushBlocks()).
230 @retval EFI_SUCCESS Transfer complete.
232 @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
233 unable to parse host response, or host response
234 is not VIRTIO_BLK_S_OK.
245 IN OUT
volatile VOID
*Buffer
,
246 IN BOOLEAN RequestIsWrite
250 volatile VIRTIO_BLK_REQ Request
;
251 volatile UINT8 HostStatus
;
252 DESC_INDICES Indices
;
254 BlockSize
= Dev
->BlockIoMedia
.BlockSize
;
257 // ensured by VirtioBlkInit()
259 ASSERT (BlockSize
> 0);
260 ASSERT (BlockSize
% 512 == 0);
263 // ensured by contract above, plus VerifyReadWriteRequest()
265 ASSERT (BufferSize
% BlockSize
== 0);
268 // Prepare virtio-blk request header, setting zero size for flush.
269 // IO Priority is homogeneously 0.
271 Request
.Type
= RequestIsWrite
?
272 (BufferSize
== 0 ? VIRTIO_BLK_T_FLUSH
: VIRTIO_BLK_T_OUT
) :
275 Request
.Sector
= MultU64x32(Lba
, BlockSize
/ 512);
277 VirtioPrepare (&Dev
->Ring
, &Indices
);
280 // preset a host status for ourselves that we do not accept as success
282 HostStatus
= VIRTIO_BLK_S_IOERR
;
285 // ensured by VirtioBlkInit() -- this predicate, in combination with the
286 // lock-step progress, ensures we don't have to track free descriptors.
288 ASSERT (Dev
->Ring
.QueueSize
>= 3);
291 // virtio-blk header in first desc
293 VirtioAppendDesc (&Dev
->Ring
, (UINTN
) &Request
, sizeof Request
,
294 VRING_DESC_F_NEXT
, &Indices
);
297 // data buffer for read/write in second desc
299 if (BufferSize
> 0) {
301 // From virtio-0.9.5, 2.3.2 Descriptor Table:
302 // "no descriptor chain may be more than 2^32 bytes long in total".
304 // The predicate is ensured by the call contract above (for flush), or
305 // VerifyReadWriteRequest() (for read/write). It also implies that
306 // converting BufferSize to UINT32 will not truncate it.
308 ASSERT (BufferSize
<= SIZE_1GB
);
311 // VRING_DESC_F_WRITE is interpreted from the host's point of view.
313 VirtioAppendDesc (&Dev
->Ring
, (UINTN
) Buffer
, (UINT32
) BufferSize
,
314 VRING_DESC_F_NEXT
| (RequestIsWrite
? 0 : VRING_DESC_F_WRITE
),
319 // host status in last (second or third) desc
321 VirtioAppendDesc (&Dev
->Ring
, (UINTN
) &HostStatus
, sizeof HostStatus
,
322 VRING_DESC_F_WRITE
, &Indices
);
325 // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
327 if (VirtioFlush (Dev
->VirtIo
, 0, &Dev
->Ring
, &Indices
,
328 NULL
) == EFI_SUCCESS
&&
329 HostStatus
== VIRTIO_BLK_S_OK
) {
333 return EFI_DEVICE_ERROR
;
339 ReadBlocks() operation for virtio-blk.
342 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
343 Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
344 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
345 ReadBlocksEx() Implementation.
347 Parameter checks and conformant return values are implemented in
348 VerifyReadWriteRequest() and SynchronousRequest().
350 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
357 VirtioBlkReadBlocks (
358 IN EFI_BLOCK_IO_PROTOCOL
*This
,
368 if (BufferSize
== 0) {
372 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
373 Status
= VerifyReadWriteRequest (
377 FALSE
// RequestIsWrite
379 if (EFI_ERROR (Status
)) {
383 return SynchronousRequest (
388 FALSE
// RequestIsWrite
394 WriteBlocks() operation for virtio-blk.
397 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
398 Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
399 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
400 WriteBlockEx() Implementation.
402 Parameter checks and conformant return values are implemented in
403 VerifyReadWriteRequest() and SynchronousRequest().
405 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
412 VirtioBlkWriteBlocks (
413 IN EFI_BLOCK_IO_PROTOCOL
*This
,
423 if (BufferSize
== 0) {
427 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
428 Status
= VerifyReadWriteRequest (
432 TRUE
// RequestIsWrite
434 if (EFI_ERROR (Status
)) {
438 return SynchronousRequest (
443 TRUE
// RequestIsWrite
450 FlushBlocks() operation for virtio-blk.
453 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
454 Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
455 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
456 FlushBlocksEx() Implementation.
458 If the underlying virtio-blk device doesn't support flushing (ie.
459 write-caching), then this function should not be called by higher layers,
460 according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
461 Should they do nonetheless, we do nothing, successfully.
467 VirtioBlkFlushBlocks (
468 IN EFI_BLOCK_IO_PROTOCOL
*This
473 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
474 return Dev
->BlockIoMedia
.WriteCaching
?
480 TRUE
// RequestIsWrite
488 Device probe function for this driver.
490 The DXE core calls this function for any given device in order to see if the
491 driver can drive the device.
493 Specs relevant in the general sense:
495 - UEFI Spec 2.3.1 + Errata C:
496 - 6.3 Protocol Handler Services -- for accessing the underlying device
497 - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
499 - Driver Writer's Guide for UEFI 2.3.1 v1.01:
500 - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
502 - 9 Driver Binding Protocol -- for exporting ourselves
504 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
505 incorporating this driver (independently of
508 @param[in] DeviceHandle The device to probe.
510 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
513 @retval EFI_SUCCESS The driver supports the device being probed.
515 @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
518 @return Error codes from the OpenProtocol() boot service or
525 VirtioBlkDriverBindingSupported (
526 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
527 IN EFI_HANDLE DeviceHandle
,
528 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
532 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
535 // Attempt to open the device with the VirtIo set of interfaces. On success,
536 // the protocol is "instantiated" for the VirtIo device. Covers duplicate
537 // open attempts (EFI_ALREADY_STARTED).
539 Status
= gBS
->OpenProtocol (
540 DeviceHandle
, // candidate device
541 &gVirtioDeviceProtocolGuid
, // for generic VirtIo access
542 (VOID
**)&VirtIo
, // handle to instantiate
543 This
->DriverBindingHandle
, // requestor driver identity
544 DeviceHandle
, // ControllerHandle, according to
545 // the UEFI Driver Model
546 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive VirtIo access to
547 // the device; to be released
549 if (EFI_ERROR (Status
)) {
553 if (VirtIo
->SubSystemDeviceId
!= VIRTIO_SUBSYSTEM_BLOCK_DEVICE
) {
554 Status
= EFI_UNSUPPORTED
;
558 // We needed VirtIo access only transitorily, to see whether we support the
561 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
562 This
->DriverBindingHandle
, DeviceHandle
);
569 Set up all BlockIo and virtio-blk aspects of this driver for the specified
572 @param[in out] Dev The driver instance to configure. The caller is
573 responsible for Dev->VirtIo's validity (ie. working IO
574 access to the underlying virtio-blk device).
576 @retval EFI_SUCCESS Setup complete.
578 @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
579 virtio-blk attributes the host provides.
581 @return Error codes from VirtioRingInit() or
582 VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE().
599 UINT8 PhysicalBlockExp
;
600 UINT8 AlignmentOffset
;
604 PhysicalBlockExp
= 0;
609 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
611 NextDevStat
= 0; // step 1 -- reset device
612 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
613 if (EFI_ERROR (Status
)) {
617 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
618 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
619 if (EFI_ERROR (Status
)) {
623 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
624 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
625 if (EFI_ERROR (Status
)) {
630 // Set Page Size - MMIO VirtIo Specific
632 Status
= Dev
->VirtIo
->SetPageSize (Dev
->VirtIo
, EFI_PAGE_SIZE
);
633 if (EFI_ERROR (Status
)) {
638 // step 4a -- retrieve and validate features
640 Status
= Dev
->VirtIo
->GetDeviceFeatures (Dev
->VirtIo
, &Features
);
641 if (EFI_ERROR (Status
)) {
645 Status
= VIRTIO_CFG_READ (Dev
, Capacity
, &NumSectors
);
646 if (EFI_ERROR (Status
)) {
649 if (NumSectors
== 0) {
650 Status
= EFI_UNSUPPORTED
;
654 if (Features
& VIRTIO_BLK_F_BLK_SIZE
) {
655 Status
= VIRTIO_CFG_READ (Dev
, BlkSize
, &BlockSize
);
656 if (EFI_ERROR (Status
)) {
659 if (BlockSize
== 0 || BlockSize
% 512 != 0 ||
660 ModU64x32 (NumSectors
, BlockSize
/ 512) != 0) {
662 // We can only handle a logical block consisting of whole sectors,
663 // and only a disk composed of whole logical blocks.
665 Status
= EFI_UNSUPPORTED
;
673 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
674 Status
= VIRTIO_CFG_READ (Dev
, Topology
.PhysicalBlockExp
,
676 if (EFI_ERROR (Status
)) {
679 if (PhysicalBlockExp
>= 32) {
680 Status
= EFI_UNSUPPORTED
;
684 Status
= VIRTIO_CFG_READ (Dev
, Topology
.AlignmentOffset
, &AlignmentOffset
);
685 if (EFI_ERROR (Status
)) {
689 Status
= VIRTIO_CFG_READ (Dev
, Topology
.OptIoSize
, &OptIoSize
);
690 if (EFI_ERROR (Status
)) {
695 Features
&= VIRTIO_BLK_F_BLK_SIZE
| VIRTIO_BLK_F_TOPOLOGY
| VIRTIO_BLK_F_RO
|
696 VIRTIO_BLK_F_FLUSH
| VIRTIO_F_VERSION_1
;
699 // In virtio-1.0, feature negotiation is expected to complete before queue
700 // discovery, and the device can also reject the selected set of features.
702 if (Dev
->VirtIo
->Revision
>= VIRTIO_SPEC_REVISION (1, 0, 0)) {
703 Status
= Virtio10WriteFeatures (Dev
->VirtIo
, Features
, &NextDevStat
);
704 if (EFI_ERROR (Status
)) {
710 // step 4b -- allocate virtqueue
712 Status
= Dev
->VirtIo
->SetQueueSel (Dev
->VirtIo
, 0);
713 if (EFI_ERROR (Status
)) {
716 Status
= Dev
->VirtIo
->GetQueueNumMax (Dev
->VirtIo
, &QueueSize
);
717 if (EFI_ERROR (Status
)) {
720 if (QueueSize
< 3) { // SynchronousRequest() uses at most three descriptors
721 Status
= EFI_UNSUPPORTED
;
725 Status
= VirtioRingInit (QueueSize
, &Dev
->Ring
);
726 if (EFI_ERROR (Status
)) {
731 // Additional steps for MMIO: align the queue appropriately, and set the
732 // size. If anything fails from here on, we must release the ring resources.
734 Status
= Dev
->VirtIo
->SetQueueNum (Dev
->VirtIo
, QueueSize
);
735 if (EFI_ERROR (Status
)) {
739 Status
= Dev
->VirtIo
->SetQueueAlign (Dev
->VirtIo
, EFI_PAGE_SIZE
);
740 if (EFI_ERROR (Status
)) {
745 // step 4c -- Report GPFN (guest-physical frame number) of queue.
747 Status
= Dev
->VirtIo
->SetQueueAddress (Dev
->VirtIo
, &Dev
->Ring
);
748 if (EFI_ERROR (Status
)) {
754 // step 5 -- Report understood features.
756 if (Dev
->VirtIo
->Revision
< VIRTIO_SPEC_REVISION (1, 0, 0)) {
757 Features
&= ~(UINT64
)VIRTIO_F_VERSION_1
;
758 Status
= Dev
->VirtIo
->SetGuestFeatures (Dev
->VirtIo
, Features
);
759 if (EFI_ERROR (Status
)) {
765 // step 6 -- initialization complete
767 NextDevStat
|= VSTAT_DRIVER_OK
;
768 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
769 if (EFI_ERROR (Status
)) {
774 // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI
775 // Block I/O Protocol.
777 Dev
->BlockIo
.Revision
= 0;
778 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
779 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
780 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
781 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
782 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
783 Dev
->BlockIoMedia
.MediaId
= 0;
784 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
785 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
786 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
787 Dev
->BlockIoMedia
.ReadOnly
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_RO
) != 0);
788 Dev
->BlockIoMedia
.WriteCaching
= (BOOLEAN
) ((Features
& VIRTIO_BLK_F_FLUSH
) != 0);
789 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
790 Dev
->BlockIoMedia
.IoAlign
= 0;
791 Dev
->BlockIoMedia
.LastBlock
= DivU64x32 (NumSectors
,
792 BlockSize
/ 512) - 1;
794 DEBUG ((DEBUG_INFO
, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",
795 __FUNCTION__
, Dev
->BlockIoMedia
.BlockSize
,
796 Dev
->BlockIoMedia
.LastBlock
+ 1));
798 if (Features
& VIRTIO_BLK_F_TOPOLOGY
) {
799 Dev
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
801 Dev
->BlockIoMedia
.LowestAlignedLba
= AlignmentOffset
;
802 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
= 1u << PhysicalBlockExp
;
803 Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
= OptIoSize
;
805 DEBUG ((DEBUG_INFO
, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",
806 __FUNCTION__
, Dev
->BlockIoMedia
.LowestAlignedLba
,
807 Dev
->BlockIoMedia
.LogicalBlocksPerPhysicalBlock
));
808 DEBUG ((DEBUG_INFO
, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",
809 __FUNCTION__
, Dev
->BlockIoMedia
.OptimalTransferLengthGranularity
));
814 VirtioRingUninit (&Dev
->Ring
);
818 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
819 // Status. VirtIo access failure here should not mask the original error.
821 NextDevStat
|= VSTAT_FAILED
;
822 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
824 return Status
; // reached only via Failed above
830 Uninitialize the internals of a virtio-blk device that has been successfully
831 set up with VirtioBlkInit().
833 @param[in out] Dev The device to clean up.
845 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
846 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
847 // the old comms area.
849 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
851 VirtioRingUninit (&Dev
->Ring
);
853 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
854 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
860 Event notification function enqueued by ExitBootServices().
862 @param[in] Event Event whose notification function is being invoked.
864 @param[in] Context Pointer to the VBLK_DEV structure.
879 // Reset the device. This causes the hypervisor to forget about the virtio
882 // We allocated said ring in EfiBootServicesData type memory, and code
883 // executing after ExitBootServices() is permitted to overwrite it.
886 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
891 After we've pronounced support for a specific device in
892 DriverBindingSupported(), we start managing said device (passed in by the
893 Driver Execution Environment) with the following service.
895 See DriverBindingSupported() for specification references.
897 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
898 incorporating this driver (independently of
901 @param[in] DeviceHandle The supported device to drive.
903 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
906 @retval EFI_SUCCESS Driver instance has been created and
907 initialized for the virtio-blk device, it
908 is now accessible via EFI_BLOCK_IO_PROTOCOL.
910 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
912 @return Error codes from the OpenProtocol() boot
913 service, the VirtIo protocol, VirtioBlkInit(),
914 or the InstallProtocolInterface() boot service.
920 VirtioBlkDriverBindingStart (
921 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
922 IN EFI_HANDLE DeviceHandle
,
923 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
929 Dev
= (VBLK_DEV
*) AllocateZeroPool (sizeof *Dev
);
931 return EFI_OUT_OF_RESOURCES
;
934 Status
= gBS
->OpenProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
935 (VOID
**)&Dev
->VirtIo
, This
->DriverBindingHandle
,
936 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
937 if (EFI_ERROR (Status
)) {
942 // VirtIo access granted, configure virtio-blk device.
944 Status
= VirtioBlkInit (Dev
);
945 if (EFI_ERROR (Status
)) {
949 Status
= gBS
->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_CALLBACK
,
950 &VirtioBlkExitBoot
, Dev
, &Dev
->ExitBoot
);
951 if (EFI_ERROR (Status
)) {
956 // Setup complete, attempt to export the driver instance's BlockIo interface.
958 Dev
->Signature
= VBLK_SIG
;
959 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
960 &gEfiBlockIoProtocolGuid
, EFI_NATIVE_INTERFACE
,
962 if (EFI_ERROR (Status
)) {
969 gBS
->CloseEvent (Dev
->ExitBoot
);
972 VirtioBlkUninit (Dev
);
975 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
976 This
->DriverBindingHandle
, DeviceHandle
);
987 Stop driving a virtio-blk device and remove its BlockIo interface.
989 This function replays the success path of DriverBindingStart() in reverse.
990 The host side virtio-blk device is reset, so that the OS boot loader or the
991 OS may reinitialize it.
993 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
994 incorporating this driver (independently of any
997 @param[in] DeviceHandle Stop driving this device.
999 @param[in] NumberOfChildren Since this function belongs to a device driver
1000 only (as opposed to a bus driver), the caller
1001 environment sets NumberOfChildren to zero, and
1004 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
1010 VirtioBlkDriverBindingStop (
1011 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1012 IN EFI_HANDLE DeviceHandle
,
1013 IN UINTN NumberOfChildren
,
1014 IN EFI_HANDLE
*ChildHandleBuffer
1018 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
1021 Status
= gBS
->OpenProtocol (
1022 DeviceHandle
, // candidate device
1023 &gEfiBlockIoProtocolGuid
, // retrieve the BlockIo iface
1024 (VOID
**)&BlockIo
, // target pointer
1025 This
->DriverBindingHandle
, // requestor driver identity
1026 DeviceHandle
, // requesting lookup for dev.
1027 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
1029 if (EFI_ERROR (Status
)) {
1033 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (BlockIo
);
1036 // Handle Stop() requests for in-use driver instances gracefully.
1038 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
1039 &gEfiBlockIoProtocolGuid
, &Dev
->BlockIo
);
1040 if (EFI_ERROR (Status
)) {
1044 gBS
->CloseEvent (Dev
->ExitBoot
);
1046 VirtioBlkUninit (Dev
);
1048 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
1049 This
->DriverBindingHandle
, DeviceHandle
);
1058 // The static object that groups the Supported() (ie. probe), Start() and
1059 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1060 // C, 10.1 EFI Driver Binding Protocol.
1062 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
1063 &VirtioBlkDriverBindingSupported
,
1064 &VirtioBlkDriverBindingStart
,
1065 &VirtioBlkDriverBindingStop
,
1066 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1067 NULL
, // ImageHandle, to be overwritten by
1068 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
1069 NULL
// DriverBindingHandle, ditto
1074 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1075 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1076 // in English, for display on standard console devices. This is recommended for
1077 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1078 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1080 // Device type names ("Virtio Block Device") are not formatted because the
1081 // driver supports only that device type. Therefore the driver name suffices
1082 // for unambiguous identification.
1086 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1087 { "eng;en", L
"Virtio Block Driver" },
1092 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1096 VirtioBlkGetDriverName (
1097 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1099 OUT CHAR16
**DriverName
1102 return LookupUnicodeString2 (
1104 This
->SupportedLanguages
,
1107 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1113 VirtioBlkGetDeviceName (
1114 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1115 IN EFI_HANDLE DeviceHandle
,
1116 IN EFI_HANDLE ChildHandle
,
1118 OUT CHAR16
**ControllerName
1121 return EFI_UNSUPPORTED
;
1125 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1126 &VirtioBlkGetDriverName
,
1127 &VirtioBlkGetDeviceName
,
1128 "eng" // SupportedLanguages, ISO 639-2 language codes
1132 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1133 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioBlkGetDriverName
,
1134 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioBlkGetDeviceName
,
1135 "en" // SupportedLanguages, RFC 4646 language codes
1140 // Entry point of this driver.
1144 VirtioBlkEntryPoint (
1145 IN EFI_HANDLE ImageHandle
,
1146 IN EFI_SYSTEM_TABLE
*SystemTable
1149 return EfiLibInstallDriverBindingComponentName2 (