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.
15 This program and the accompanying materials are licensed and made available
16 under the terms and conditions of the BSD License which accompanies this
17 distribution. The full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
21 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 #include <IndustryStandard/Pci.h>
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 PCI 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 PCI IO space
46 we're accessing. Dev->PciIo 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 VirtioWrite() / VirtioRead().
63 #define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \
65 OFFSET_OF_VBLK (Field), \
66 SIZE_OF_VBLK (Field), \
70 #define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \
72 OFFSET_OF_VBLK (Field), \
73 SIZE_OF_VBLK (Field), \
80 // UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
81 // Driver Writer's Guide for UEFI 2.3.1 v1.01,
82 // 24.2 Block I/O Protocol Implementations
87 IN EFI_BLOCK_IO_PROTOCOL
*This
,
88 IN BOOLEAN ExtendedVerification
92 // If we managed to initialize and install the driver, then the device is
100 Verify correctness of the read/write (not flush) request submitted to the
101 EFI_BLOCK_IO_PROTOCOL instance.
103 This function provides most verification steps described in:
105 UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
107 - EFI_BLOCK_IO_PROTOCOL.ReadBlocks()
108 - EFI_BLOCK_IO_PROTOCOL.WriteBlocks()
110 Driver Writer's Guide for UEFI 2.3.1 v1.01,
111 - 24.2.2. ReadBlocks() and ReadBlocksEx() Implementation
112 - 24.2.3 WriteBlocks() and WriteBlockEx() Implementation
114 Request sizes are limited to 1 GB (checked). This is not a practical
115 limitation, just conformance to virtio-0.9.5, 2.3.2 Descriptor Table: "no
116 descriptor chain may be more than 2^32 bytes long in total".
118 Some Media characteristics are hardcoded in VirtioBlkInit() below (like
119 non-removable media, no restriction on buffer alignment etc); we rely on
120 those here without explicit mention.
122 @param[in] Media The EFI_BLOCK_IO_MEDIA characteristics for
123 this driver instance, extracted from the
124 underlying virtio-blk device at initialization
125 time. We validate the request against this set
129 @param[in] Lba Logical Block Address: number of logical
130 blocks to skip from the beginning of the
133 @param[in] PositiveBufferSize Size of buffer to transfer, in bytes. The
134 caller is responsible to ensure this parameter
137 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
141 @@return Validation result to be forwarded outwards by
142 ReadBlocks() and WriteBlocks, as required by
149 VerifyReadWriteRequest (
150 IN EFI_BLOCK_IO_MEDIA
*Media
,
152 IN UINTN PositiveBufferSize
,
153 IN BOOLEAN RequestIsWrite
158 ASSERT (PositiveBufferSize
> 0);
160 if (PositiveBufferSize
> SIZE_1GB
||
161 PositiveBufferSize
% Media
->BlockSize
> 0) {
162 return EFI_BAD_BUFFER_SIZE
;
164 BlockCount
= PositiveBufferSize
/ Media
->BlockSize
;
167 // Avoid unsigned wraparound on either side in the second comparison.
169 if (Lba
> Media
->LastBlock
|| BlockCount
- 1 > Media
->LastBlock
- Lba
) {
170 return EFI_INVALID_PARAMETER
;
173 if (RequestIsWrite
&& Media
->ReadOnly
) {
174 return EFI_WRITE_PROTECTED
;
185 Format a read / write / flush request as three consecutive virtio
186 descriptors, push them to the host, and poll for the response.
188 This is the main workhorse function. Two use cases are supported, read/write
189 and flush. The function may only be called after the request parameters have
191 - specific checks in ReadBlocks() / WriteBlocks() / FlushBlocks(), and
192 - VerifyReadWriteRequest() (for read/write only).
194 Parameters handled commonly:
196 @param[in] Dev The virtio-blk device the request is targeted
201 @param[in] Lba Must be zero.
203 @param[in] BufferSize Must be zero.
205 @param[in out] Buffer Ignored by the function.
207 @param[in] RequestIsWrite Must be TRUE.
211 @param[in] Lba Logical Block Address: number of logical blocks
212 to skip from the beginning of the device.
214 @param[in] BufferSize Size of buffer to transfer, in bytes. The caller
215 is responsible to ensure this parameter is
218 @param[in out] Buffer The guest side area to read data from the device
219 into, or write data to the device from.
221 @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
224 Return values are common to both use cases, and are appropriate to be
225 forwarded by the EFI_BLOCK_IO_PROTOCOL functions (ReadBlocks(),
226 WriteBlocks(), FlushBlocks()).
229 @retval EFI_SUCCESS Transfer complete.
231 @retval EFI_DEVICE_ERROR Failed to notify host side via PCI write, or
232 unable to parse host response, or host response
233 is not VIRTIO_BLK_S_OK.
244 IN OUT
volatile VOID
*Buffer
,
245 IN BOOLEAN RequestIsWrite
249 volatile VIRTIO_BLK_REQ Request
;
250 volatile UINT8 HostStatus
;
251 UINT16 FirstAvailIdx
;
253 UINTN PollPeriodUsecs
;
255 BlockSize
= Dev
->BlockIoMedia
.BlockSize
;
258 // ensured by VirtioBlkInit()
260 ASSERT (BlockSize
> 0);
261 ASSERT (BlockSize
% 512 == 0);
264 // ensured by contract above, plus VerifyReadWriteRequest()
266 ASSERT (BufferSize
% BlockSize
== 0);
269 // Prepare virtio-blk request header, setting zero size for flush.
270 // IO Priority is homogeneously 0.
272 Request
.Type
= RequestIsWrite
?
273 (BufferSize
== 0 ? VIRTIO_BLK_T_FLUSH
: VIRTIO_BLK_T_OUT
) :
276 Request
.Sector
= Lba
* (BlockSize
/ 512);
279 // Prepare for virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device.
280 // We're going to poll the answer, the host should not send an interrupt.
282 *Dev
->Ring
.Avail
.Flags
= (UINT16
) VRING_AVAIL_F_NO_INTERRUPT
;
285 // preset a host status for ourselves that we do not accept as success
287 HostStatus
= VIRTIO_BLK_S_IOERR
;
290 // ensured by VirtioBlkInit() -- this predicate, in combination with the
291 // lock-step progress, ensures we don't have to track free descriptors.
293 ASSERT (Dev
->Ring
.QueueSize
>= 3);
296 // Implement virtio-0.9.5, 2.4.1 Supplying Buffers to the Device.
298 FirstAvailIdx
= *Dev
->Ring
.Avail
.Idx
;
299 NextAvailIdx
= FirstAvailIdx
;
302 // virtio-blk header in first desc
304 AppendDesc (&Dev
->Ring
, (UINTN
) &Request
, sizeof Request
, VRING_DESC_F_NEXT
,
305 FirstAvailIdx
, &NextAvailIdx
);
308 // data buffer for read/write in second desc
310 if (BufferSize
> 0) {
312 // From virtio-0.9.5, 2.3.2 Descriptor Table:
313 // "no descriptor chain may be more than 2^32 bytes long in total".
315 // The predicate is ensured by the call contract above (for flush), or
316 // VerifyReadWriteRequest() (for read/write). It also implies that
317 // converting BufferSize to UINT32 will not truncate it.
319 ASSERT (BufferSize
<= SIZE_1GB
);
322 // VRING_DESC_F_WRITE is interpreted from the host's point of view.
324 AppendDesc (&Dev
->Ring
, (UINTN
) Buffer
, (UINT32
) BufferSize
,
325 VRING_DESC_F_NEXT
| (RequestIsWrite
? 0 : VRING_DESC_F_WRITE
),
326 FirstAvailIdx
, &NextAvailIdx
);
330 // host status in last (second or third) desc
332 AppendDesc (&Dev
->Ring
, (UINTN
) &HostStatus
, sizeof HostStatus
,
333 VRING_DESC_F_WRITE
, FirstAvailIdx
, &NextAvailIdx
);
336 // virtio-0.9.5, 2.4.1.3 Updating the Index Field
339 *Dev
->Ring
.Avail
.Idx
= NextAvailIdx
;
342 // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are
343 // OK. virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
346 if (EFI_ERROR (VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrQueueNotify
, 0))) {
347 return EFI_DEVICE_ERROR
;
351 // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
352 // Wait until the host processes and acknowledges our 3-part descriptor
353 // chain. The condition we use for polling is greatly simplified and relies
354 // on synchronous, the lock-step progress.
356 // Keep slowing down until we reach a poll period of slightly above 1 ms.
360 while (*Dev
->Ring
.Used
.Idx
!= NextAvailIdx
) {
361 gBS
->Stall (PollPeriodUsecs
); // calls AcpiTimerLib::MicroSecondDelay
363 if (PollPeriodUsecs
< 1024) {
364 PollPeriodUsecs
*= 2;
369 if (HostStatus
== VIRTIO_BLK_S_OK
) {
373 return EFI_DEVICE_ERROR
;
379 ReadBlocks() operation for virtio-blk.
382 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
383 Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
384 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
385 ReadBlocksEx() Implementation.
387 Parameter checks and conformant return values are implemented in
388 VerifyReadWriteRequest() and SynchronousRequest().
390 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
397 VirtioBlkReadBlocks (
398 IN EFI_BLOCK_IO_PROTOCOL
*This
,
408 if (BufferSize
== 0) {
412 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
413 Status
= VerifyReadWriteRequest (
417 FALSE
// RequestIsWrite
419 if (EFI_ERROR (Status
)) {
423 return SynchronousRequest (
428 FALSE
// RequestIsWrite
434 WriteBlocks() operation for virtio-blk.
437 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
438 Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
439 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
440 WriteBlockEx() Implementation.
442 Parameter checks and conformant return values are implemented in
443 VerifyReadWriteRequest() and SynchronousRequest().
445 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
452 VirtioBlkWriteBlocks (
453 IN EFI_BLOCK_IO_PROTOCOL
*This
,
463 if (BufferSize
== 0) {
467 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
468 Status
= VerifyReadWriteRequest (
472 TRUE
// RequestIsWrite
474 if (EFI_ERROR (Status
)) {
478 return SynchronousRequest (
483 TRUE
// RequestIsWrite
490 FlushBlocks() operation for virtio-blk.
493 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
494 Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
495 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
496 FlushBlocksEx() Implementation.
498 If the underlying virtio-blk device doesn't support flushing (ie.
499 write-caching), then this function should not be called by higher layers,
500 according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
501 Should they do nonetheless, we do nothing, successfully.
507 VirtioBlkFlushBlocks (
508 IN EFI_BLOCK_IO_PROTOCOL
*This
513 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
514 return Dev
->BlockIoMedia
.WriteCaching
?
520 TRUE
// RequestIsWrite
528 Device probe function for this driver.
530 The DXE core calls this function for any given device in order to see if the
531 driver can drive the device.
533 Specs relevant in the general sense:
535 - UEFI Spec 2.3.1 + Errata C:
536 - 6.3 Protocol Handler Services -- for accessing the underlying device
537 - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
539 - Driver Writer's Guide for UEFI 2.3.1 v1.01:
540 - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
542 - 9 Driver Binding Protocol -- for exporting ourselves
544 Specs relevant in the specific sense:
545 - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
546 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
547 Guidelines, 18.3 PCI drivers.
549 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
550 incorporating this driver (independently of
553 @param[in] DeviceHandle The device to probe.
555 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
558 @retval EFI_SUCCESS The driver supports the device being probed.
560 @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
563 @return Error codes from the OpenProtocol() boot service or
570 VirtioBlkDriverBindingSupported (
571 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
572 IN EFI_HANDLE DeviceHandle
,
573 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
577 EFI_PCI_IO_PROTOCOL
*PciIo
;
581 // Attempt to open the device with the PciIo set of interfaces. On success,
582 // the protocol is "instantiated" for the PCI device. Covers duplicate open
583 // attempts (EFI_ALREADY_STARTED).
585 Status
= gBS
->OpenProtocol (
586 DeviceHandle
, // candidate device
587 &gEfiPciIoProtocolGuid
, // for generic PCI access
588 (VOID
**)&PciIo
, // handle to instantiate
589 This
->DriverBindingHandle
, // requestor driver identity
590 DeviceHandle
, // ControllerHandle, according to
591 // the UEFI Driver Model
592 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive PciIo access to
593 // the device; to be released
595 if (EFI_ERROR (Status
)) {
600 // Read entire PCI configuration header for more extensive check ahead.
602 Status
= PciIo
->Pci
.Read (
603 PciIo
, // (protocol, device)
605 EfiPciIoWidthUint32
, // access width & copy
608 sizeof Pci
/ sizeof (UINT32
), // Count
609 &Pci
// target buffer
612 if (Status
== EFI_SUCCESS
) {
614 // virtio-0.9.5, 2.1 PCI Discovery
616 Status
= (Pci
.Hdr
.VendorId
== 0x1AF4 &&
617 Pci
.Hdr
.DeviceId
>= 0x1000 && Pci
.Hdr
.DeviceId
<= 0x103F &&
618 Pci
.Hdr
.RevisionID
== 0x00 &&
619 Pci
.Device
.SubsystemID
== 0x02) ? EFI_SUCCESS
: EFI_UNSUPPORTED
;
623 // We needed PCI IO access only transitorily, to see whether we support the
626 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
627 This
->DriverBindingHandle
, DeviceHandle
);
634 Set up all BlockIo and virtio-blk aspects of this driver for the specified
637 @param[in out] Dev The driver instance to configure. The caller is
638 responsible for Dev->PciIo's validity (ie. working IO
639 access to the underlying virtio-blk PCI device).
641 @retval EFI_SUCCESS Setup complete.
643 @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
644 virtio-blk attributes the host provides.
646 @return Error codes from VirtioRingInit() or
647 VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE().
667 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
669 NextDevStat
= 0; // step 1 -- reset device
670 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
671 if (EFI_ERROR (Status
)) {
675 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
676 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
677 if (EFI_ERROR (Status
)) {
681 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
682 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
683 if (EFI_ERROR (Status
)) {
688 // step 4a -- retrieve and validate features
690 Status
= VIRTIO_CFG_READ (Dev
, Generic
.VhdrDeviceFeatureBits
, &Features
);
691 if (EFI_ERROR (Status
)) {
694 Status
= VIRTIO_CFG_READ (Dev
, VhdrCapacity
, &NumSectors
);
695 if (EFI_ERROR (Status
)) {
698 if (NumSectors
== 0) {
699 Status
= EFI_UNSUPPORTED
;
703 if (Features
& VIRTIO_BLK_F_BLK_SIZE
) {
704 Status
= VIRTIO_CFG_READ (Dev
, VhdrBlkSize
, &BlockSize
);
705 if (EFI_ERROR (Status
)) {
708 if (BlockSize
== 0 || BlockSize
% 512 != 0 ||
709 NumSectors
% (BlockSize
/ 512) != 0) {
711 // We can only handle a logical block consisting of whole sectors,
712 // and only a disk composed of whole logical blocks.
714 Status
= EFI_UNSUPPORTED
;
723 // step 4b -- allocate virtqueue
725 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrQueueSelect
, 0);
726 if (EFI_ERROR (Status
)) {
729 Status
= VIRTIO_CFG_READ (Dev
, Generic
.VhdrQueueSize
, &QueueSize
);
730 if (EFI_ERROR (Status
)) {
733 if (QueueSize
< 3) { // SynchronousRequest() uses at most three descriptors
734 Status
= EFI_UNSUPPORTED
;
738 Status
= VirtioRingInit (QueueSize
, &Dev
->Ring
);
739 if (EFI_ERROR (Status
)) {
744 // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything
745 // fails from here on, we must release the ring resources.
747 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrQueueAddress
,
748 (UINTN
) Dev
->Ring
.Base
>> EFI_PAGE_SHIFT
);
749 if (EFI_ERROR (Status
)) {
754 // step 5 -- Report understood features. There are no virtio-blk specific
755 // features to negotiate in virtio-0.9.5, plus we do not want any of the
756 // device-independent (known or unknown) VIRTIO_F_* capabilities (see
759 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrGuestFeatureBits
, 0);
760 if (EFI_ERROR (Status
)) {
765 // step 6 -- initialization complete
767 NextDevStat
|= VSTAT_DRIVER_OK
;
768 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
769 if (EFI_ERROR (Status
)) {
774 // Populate the exported interface's attributes; see UEFI spec v2.3.1 +
775 // Errata C, 12.8 EFI Block I/O Protocol. We stick to the lowest possible
776 // EFI_BLOCK_IO_PROTOCOL revision for now.
778 Dev
->BlockIo
.Revision
= 0;
779 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
780 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
781 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
782 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
783 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
784 Dev
->BlockIoMedia
.MediaId
= 0;
785 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
786 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
787 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
788 Dev
->BlockIoMedia
.ReadOnly
= !!(Features
& VIRTIO_BLK_F_RO
);
789 Dev
->BlockIoMedia
.WriteCaching
= !!(Features
& VIRTIO_BLK_F_FLUSH
);
790 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
791 Dev
->BlockIoMedia
.IoAlign
= 0;
792 Dev
->BlockIoMedia
.LastBlock
= NumSectors
/ (BlockSize
/ 512) - 1;
796 VirtioRingUninit (&Dev
->Ring
);
800 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
801 // Status. PCI IO access failure here should not mask the original error.
803 NextDevStat
|= VSTAT_FAILED
;
804 VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
806 return Status
; // reached only via Failed above
812 Uninitialize the internals of a virtio-blk device that has been successfully
813 set up with VirtioBlkInit().
815 @param[in out] Dev The device to clean up.
827 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
828 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
829 // the old comms area.
831 VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, 0);
833 VirtioRingUninit (&Dev
->Ring
);
835 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
836 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
842 After we've pronounced support for a specific device in
843 DriverBindingSupported(), we start managing said device (passed in by the
844 Driver Exeuction Environment) with the following service.
846 See DriverBindingSupported() for specification references.
848 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
849 incorporating this driver (independently of
852 @param[in] DeviceHandle The supported device to drive.
854 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
857 @retval EFI_SUCCESS Driver instance has been created and
858 initialized for the virtio-blk PCI device, it
859 is now accessibla via EFI_BLOCK_IO_PROTOCOL.
861 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
863 @return Error codes from the OpenProtocol() boot
864 service, the PciIo protocol, VirtioBlkInit(),
865 or the InstallProtocolInterface() boot service.
871 VirtioBlkDriverBindingStart (
872 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
873 IN EFI_HANDLE DeviceHandle
,
874 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
880 Dev
= (VBLK_DEV
*) AllocateZeroPool (sizeof *Dev
);
882 return EFI_OUT_OF_RESOURCES
;
885 Status
= gBS
->OpenProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
886 (VOID
**)&Dev
->PciIo
, This
->DriverBindingHandle
,
887 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
888 if (EFI_ERROR (Status
)) {
893 // We must retain and ultimately restore the original PCI attributes of the
894 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
895 // 18.3.2 Start() and Stop().
897 // The third parameter ("Attributes", input) is ignored by the Get operation.
898 // The fourth parameter ("Result", output) is ignored by the Enable and Set
901 // For virtio-blk we only need IO space access.
903 Status
= Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationGet
,
904 0, &Dev
->OriginalPciAttributes
);
905 if (EFI_ERROR (Status
)) {
909 Status
= Dev
->PciIo
->Attributes (Dev
->PciIo
,
910 EfiPciIoAttributeOperationEnable
,
911 EFI_PCI_IO_ATTRIBUTE_IO
, NULL
);
912 if (EFI_ERROR (Status
)) {
917 // PCI IO access granted, configure virtio-blk device.
919 Status
= VirtioBlkInit (Dev
);
920 if (EFI_ERROR (Status
)) {
921 goto RestorePciAttributes
;
925 // Setup complete, attempt to export the driver instance's BlockIo interface.
927 Dev
->Signature
= VBLK_SIG
;
928 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
929 &gEfiBlockIoProtocolGuid
, EFI_NATIVE_INTERFACE
,
931 if (EFI_ERROR (Status
)) {
938 VirtioBlkUninit (Dev
);
940 RestorePciAttributes
:
941 Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationSet
,
942 Dev
->OriginalPciAttributes
, NULL
);
945 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
946 This
->DriverBindingHandle
, DeviceHandle
);
957 Stop driving a virtio-blk device and remove its BlockIo interface.
959 This function replays the success path of DriverBindingStart() in reverse.
960 The host side virtio-blk device is reset, so that the OS boot loader or the
961 OS may reinitialize it.
963 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
964 incorporating this driver (independently of any
967 @param[in] DeviceHandle Stop driving this device.
969 @param[in] NumberOfChildren Since this function belongs to a device driver
970 only (as opposed to a bus driver), the caller
971 environment sets NumberOfChildren to zero, and
974 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
980 VirtioBlkDriverBindingStop (
981 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
982 IN EFI_HANDLE DeviceHandle
,
983 IN UINTN NumberOfChildren
,
984 IN EFI_HANDLE
*ChildHandleBuffer
990 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
993 // If DriverBindingStop() is called with the driver instance still in use,
994 // or any of the parameters are invalid, we've caught a bug.
996 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
997 &gEfiBlockIoProtocolGuid
, &Dev
->BlockIo
);
998 ASSERT (Status
== EFI_SUCCESS
);
1000 VirtioBlkUninit (Dev
);
1002 Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationSet
,
1003 Dev
->OriginalPciAttributes
, NULL
);
1005 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
1006 This
->DriverBindingHandle
, DeviceHandle
);
1015 // The static object that groups the Supported() (ie. probe), Start() and
1016 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1017 // C, 10.1 EFI Driver Binding Protocol.
1019 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
1020 &VirtioBlkDriverBindingSupported
,
1021 &VirtioBlkDriverBindingStart
,
1022 &VirtioBlkDriverBindingStop
,
1023 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1024 NULL
, // ImageHandle, to be overwritten by
1025 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
1026 NULL
// DriverBindingHandle, ditto
1031 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1032 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1033 // in English, for display on standard console devices. This is recommended for
1034 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1035 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1037 // Device type names ("Virtio Block Device") are not formatted because the
1038 // driver supports only that device type. Therefore the driver name suffices
1039 // for unambiguous identification.
1042 STATIC GLOBAL_REMOVE_IF_UNREFERENCED
1043 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1044 { "eng;en", L
"Virtio Block Driver" },
1048 STATIC GLOBAL_REMOVE_IF_UNREFERENCED
1049 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1053 VirtioBlkGetDriverName (
1054 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1056 OUT CHAR16
**DriverName
1059 return LookupUnicodeString2 (
1061 This
->SupportedLanguages
,
1064 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1070 VirtioBlkGetDeviceName (
1071 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1072 IN EFI_HANDLE DeviceHandle
,
1073 IN EFI_HANDLE ChildHandle
,
1075 OUT CHAR16
**ControllerName
1078 return EFI_UNSUPPORTED
;
1081 STATIC GLOBAL_REMOVE_IF_UNREFERENCED
1082 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1083 &VirtioBlkGetDriverName
,
1084 &VirtioBlkGetDeviceName
,
1085 "eng" // SupportedLanguages, ISO 639-2 language codes
1088 STATIC GLOBAL_REMOVE_IF_UNREFERENCED
1089 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1090 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioBlkGetDriverName
,
1091 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioBlkGetDeviceName
,
1092 "en" // SupportedLanguages, RFC 4646 language codes
1097 // Entry point of this driver.
1101 VirtioBlkEntryPoint (
1102 IN EFI_HANDLE ImageHandle
,
1103 IN EFI_SYSTEM_TABLE
*SystemTable
1106 return EfiLibInstallDriverBindingComponentName2 (