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, 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/Pci.h>
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 PCI 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 PCI IO space
47 we're accessing. Dev->PciIo 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 VirtioWrite() / VirtioRead().
64 #define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \
66 OFFSET_OF_VBLK (Field), \
67 SIZE_OF_VBLK (Field), \
71 #define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \
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 PCI 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
->PciIo
, 0, &Dev
->Ring
, &Indices
) == EFI_SUCCESS
&&
328 HostStatus
== VIRTIO_BLK_S_OK
) {
332 return EFI_DEVICE_ERROR
;
338 ReadBlocks() operation for virtio-blk.
341 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
342 Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
343 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
344 ReadBlocksEx() Implementation.
346 Parameter checks and conformant return values are implemented in
347 VerifyReadWriteRequest() and SynchronousRequest().
349 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
356 VirtioBlkReadBlocks (
357 IN EFI_BLOCK_IO_PROTOCOL
*This
,
367 if (BufferSize
== 0) {
371 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
372 Status
= VerifyReadWriteRequest (
376 FALSE
// RequestIsWrite
378 if (EFI_ERROR (Status
)) {
382 return SynchronousRequest (
387 FALSE
// RequestIsWrite
393 WriteBlocks() operation for virtio-blk.
396 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
397 Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
398 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
399 WriteBlockEx() Implementation.
401 Parameter checks and conformant return values are implemented in
402 VerifyReadWriteRequest() and SynchronousRequest().
404 A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
411 VirtioBlkWriteBlocks (
412 IN EFI_BLOCK_IO_PROTOCOL
*This
,
422 if (BufferSize
== 0) {
426 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
427 Status
= VerifyReadWriteRequest (
431 TRUE
// RequestIsWrite
433 if (EFI_ERROR (Status
)) {
437 return SynchronousRequest (
442 TRUE
// RequestIsWrite
449 FlushBlocks() operation for virtio-blk.
452 - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
453 Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
454 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
455 FlushBlocksEx() Implementation.
457 If the underlying virtio-blk device doesn't support flushing (ie.
458 write-caching), then this function should not be called by higher layers,
459 according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
460 Should they do nonetheless, we do nothing, successfully.
466 VirtioBlkFlushBlocks (
467 IN EFI_BLOCK_IO_PROTOCOL
*This
472 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (This
);
473 return Dev
->BlockIoMedia
.WriteCaching
?
479 TRUE
// RequestIsWrite
487 Device probe function for this driver.
489 The DXE core calls this function for any given device in order to see if the
490 driver can drive the device.
492 Specs relevant in the general sense:
494 - UEFI Spec 2.3.1 + Errata C:
495 - 6.3 Protocol Handler Services -- for accessing the underlying device
496 - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
498 - Driver Writer's Guide for UEFI 2.3.1 v1.01:
499 - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
501 - 9 Driver Binding Protocol -- for exporting ourselves
503 Specs relevant in the specific sense:
504 - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
505 - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
506 Guidelines, 18.3 PCI drivers.
508 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
509 incorporating this driver (independently of
512 @param[in] DeviceHandle The device to probe.
514 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
517 @retval EFI_SUCCESS The driver supports the device being probed.
519 @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
522 @return Error codes from the OpenProtocol() boot service or
529 VirtioBlkDriverBindingSupported (
530 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
531 IN EFI_HANDLE DeviceHandle
,
532 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
536 EFI_PCI_IO_PROTOCOL
*PciIo
;
540 // Attempt to open the device with the PciIo set of interfaces. On success,
541 // the protocol is "instantiated" for the PCI device. Covers duplicate open
542 // attempts (EFI_ALREADY_STARTED).
544 Status
= gBS
->OpenProtocol (
545 DeviceHandle
, // candidate device
546 &gEfiPciIoProtocolGuid
, // for generic PCI access
547 (VOID
**)&PciIo
, // handle to instantiate
548 This
->DriverBindingHandle
, // requestor driver identity
549 DeviceHandle
, // ControllerHandle, according to
550 // the UEFI Driver Model
551 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive PciIo access to
552 // the device; to be released
554 if (EFI_ERROR (Status
)) {
559 // Read entire PCI configuration header for more extensive check ahead.
561 Status
= PciIo
->Pci
.Read (
562 PciIo
, // (protocol, device)
564 EfiPciIoWidthUint32
, // access width & copy
567 sizeof Pci
/ sizeof (UINT32
), // Count
568 &Pci
// target buffer
571 if (Status
== EFI_SUCCESS
) {
573 // virtio-0.9.5, 2.1 PCI Discovery
575 Status
= (Pci
.Hdr
.VendorId
== 0x1AF4 &&
576 Pci
.Hdr
.DeviceId
>= 0x1000 && Pci
.Hdr
.DeviceId
<= 0x103F &&
577 Pci
.Hdr
.RevisionID
== 0x00 &&
578 Pci
.Device
.SubsystemID
== VIRTIO_SUBSYSTEM_BLOCK_DEVICE
) ? EFI_SUCCESS
: EFI_UNSUPPORTED
;
582 // We needed PCI IO access only transitorily, to see whether we support the
585 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
586 This
->DriverBindingHandle
, DeviceHandle
);
593 Set up all BlockIo and virtio-blk aspects of this driver for the specified
596 @param[in out] Dev The driver instance to configure. The caller is
597 responsible for Dev->PciIo's validity (ie. working IO
598 access to the underlying virtio-blk PCI device).
600 @retval EFI_SUCCESS Setup complete.
602 @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
603 virtio-blk attributes the host provides.
605 @return Error codes from VirtioRingInit() or
606 VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE().
626 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
628 NextDevStat
= 0; // step 1 -- reset device
629 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
630 if (EFI_ERROR (Status
)) {
634 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
635 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
636 if (EFI_ERROR (Status
)) {
640 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
641 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
642 if (EFI_ERROR (Status
)) {
647 // step 4a -- retrieve and validate features
649 Status
= VIRTIO_CFG_READ (Dev
, Generic
.VhdrDeviceFeatureBits
, &Features
);
650 if (EFI_ERROR (Status
)) {
653 Status
= VIRTIO_CFG_READ (Dev
, VhdrCapacity
, &NumSectors
);
654 if (EFI_ERROR (Status
)) {
657 if (NumSectors
== 0) {
658 Status
= EFI_UNSUPPORTED
;
662 if (Features
& VIRTIO_BLK_F_BLK_SIZE
) {
663 Status
= VIRTIO_CFG_READ (Dev
, VhdrBlkSize
, &BlockSize
);
664 if (EFI_ERROR (Status
)) {
667 if (BlockSize
== 0 || BlockSize
% 512 != 0 ||
668 ModU64x32 (NumSectors
, BlockSize
/ 512) != 0) {
670 // We can only handle a logical block consisting of whole sectors,
671 // and only a disk composed of whole logical blocks.
673 Status
= EFI_UNSUPPORTED
;
682 // step 4b -- allocate virtqueue
684 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrQueueSelect
, 0);
685 if (EFI_ERROR (Status
)) {
688 Status
= VIRTIO_CFG_READ (Dev
, Generic
.VhdrQueueSize
, &QueueSize
);
689 if (EFI_ERROR (Status
)) {
692 if (QueueSize
< 3) { // SynchronousRequest() uses at most three descriptors
693 Status
= EFI_UNSUPPORTED
;
697 Status
= VirtioRingInit (QueueSize
, &Dev
->Ring
);
698 if (EFI_ERROR (Status
)) {
703 // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything
704 // fails from here on, we must release the ring resources.
706 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrQueueAddress
,
707 (UINTN
) Dev
->Ring
.Base
>> EFI_PAGE_SHIFT
);
708 if (EFI_ERROR (Status
)) {
713 // step 5 -- Report understood features. There are no virtio-blk specific
714 // features to negotiate in virtio-0.9.5, plus we do not want any of the
715 // device-independent (known or unknown) VIRTIO_F_* capabilities (see
718 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrGuestFeatureBits
, 0);
719 if (EFI_ERROR (Status
)) {
724 // step 6 -- initialization complete
726 NextDevStat
|= VSTAT_DRIVER_OK
;
727 Status
= VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
728 if (EFI_ERROR (Status
)) {
733 // Populate the exported interface's attributes; see UEFI spec v2.3.1 +
734 // Errata C, 12.8 EFI Block I/O Protocol. We stick to the lowest possible
735 // EFI_BLOCK_IO_PROTOCOL revision for now.
737 Dev
->BlockIo
.Revision
= 0;
738 Dev
->BlockIo
.Media
= &Dev
->BlockIoMedia
;
739 Dev
->BlockIo
.Reset
= &VirtioBlkReset
;
740 Dev
->BlockIo
.ReadBlocks
= &VirtioBlkReadBlocks
;
741 Dev
->BlockIo
.WriteBlocks
= &VirtioBlkWriteBlocks
;
742 Dev
->BlockIo
.FlushBlocks
= &VirtioBlkFlushBlocks
;
743 Dev
->BlockIoMedia
.MediaId
= 0;
744 Dev
->BlockIoMedia
.RemovableMedia
= FALSE
;
745 Dev
->BlockIoMedia
.MediaPresent
= TRUE
;
746 Dev
->BlockIoMedia
.LogicalPartition
= FALSE
;
747 Dev
->BlockIoMedia
.ReadOnly
= !!(Features
& VIRTIO_BLK_F_RO
);
748 Dev
->BlockIoMedia
.WriteCaching
= !!(Features
& VIRTIO_BLK_F_FLUSH
);
749 Dev
->BlockIoMedia
.BlockSize
= BlockSize
;
750 Dev
->BlockIoMedia
.IoAlign
= 0;
751 Dev
->BlockIoMedia
.LastBlock
= DivU64x32 (NumSectors
,
752 BlockSize
/ 512) - 1;
756 VirtioRingUninit (&Dev
->Ring
);
760 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
761 // Status. PCI IO access failure here should not mask the original error.
763 NextDevStat
|= VSTAT_FAILED
;
764 VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, NextDevStat
);
766 return Status
; // reached only via Failed above
772 Uninitialize the internals of a virtio-blk device that has been successfully
773 set up with VirtioBlkInit().
775 @param[in out] Dev The device to clean up.
787 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
788 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
789 // the old comms area.
791 VIRTIO_CFG_WRITE (Dev
, Generic
.VhdrDeviceStatus
, 0);
793 VirtioRingUninit (&Dev
->Ring
);
795 SetMem (&Dev
->BlockIo
, sizeof Dev
->BlockIo
, 0x00);
796 SetMem (&Dev
->BlockIoMedia
, sizeof Dev
->BlockIoMedia
, 0x00);
802 After we've pronounced support for a specific device in
803 DriverBindingSupported(), we start managing said device (passed in by the
804 Driver Exeuction Environment) with the following service.
806 See DriverBindingSupported() for specification references.
808 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
809 incorporating this driver (independently of
812 @param[in] DeviceHandle The supported device to drive.
814 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
817 @retval EFI_SUCCESS Driver instance has been created and
818 initialized for the virtio-blk PCI device, it
819 is now accessibla via EFI_BLOCK_IO_PROTOCOL.
821 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
823 @return Error codes from the OpenProtocol() boot
824 service, the PciIo protocol, VirtioBlkInit(),
825 or the InstallProtocolInterface() boot service.
831 VirtioBlkDriverBindingStart (
832 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
833 IN EFI_HANDLE DeviceHandle
,
834 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
840 Dev
= (VBLK_DEV
*) AllocateZeroPool (sizeof *Dev
);
842 return EFI_OUT_OF_RESOURCES
;
845 Status
= gBS
->OpenProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
846 (VOID
**)&Dev
->PciIo
, This
->DriverBindingHandle
,
847 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
848 if (EFI_ERROR (Status
)) {
853 // We must retain and ultimately restore the original PCI attributes of the
854 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
855 // 18.3.2 Start() and Stop().
857 // The third parameter ("Attributes", input) is ignored by the Get operation.
858 // The fourth parameter ("Result", output) is ignored by the Enable and Set
861 // For virtio-blk we only need IO space access.
863 Status
= Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationGet
,
864 0, &Dev
->OriginalPciAttributes
);
865 if (EFI_ERROR (Status
)) {
869 Status
= Dev
->PciIo
->Attributes (Dev
->PciIo
,
870 EfiPciIoAttributeOperationEnable
,
871 EFI_PCI_IO_ATTRIBUTE_IO
, NULL
);
872 if (EFI_ERROR (Status
)) {
877 // PCI IO access granted, configure virtio-blk device.
879 Status
= VirtioBlkInit (Dev
);
880 if (EFI_ERROR (Status
)) {
881 goto RestorePciAttributes
;
885 // Setup complete, attempt to export the driver instance's BlockIo interface.
887 Dev
->Signature
= VBLK_SIG
;
888 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
889 &gEfiBlockIoProtocolGuid
, EFI_NATIVE_INTERFACE
,
891 if (EFI_ERROR (Status
)) {
898 VirtioBlkUninit (Dev
);
900 RestorePciAttributes
:
901 Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationSet
,
902 Dev
->OriginalPciAttributes
, NULL
);
905 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
906 This
->DriverBindingHandle
, DeviceHandle
);
917 Stop driving a virtio-blk device and remove its BlockIo interface.
919 This function replays the success path of DriverBindingStart() in reverse.
920 The host side virtio-blk device is reset, so that the OS boot loader or the
921 OS may reinitialize it.
923 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
924 incorporating this driver (independently of any
927 @param[in] DeviceHandle Stop driving this device.
929 @param[in] NumberOfChildren Since this function belongs to a device driver
930 only (as opposed to a bus driver), the caller
931 environment sets NumberOfChildren to zero, and
934 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
940 VirtioBlkDriverBindingStop (
941 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
942 IN EFI_HANDLE DeviceHandle
,
943 IN UINTN NumberOfChildren
,
944 IN EFI_HANDLE
*ChildHandleBuffer
948 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
951 Status
= gBS
->OpenProtocol (
952 DeviceHandle
, // candidate device
953 &gEfiBlockIoProtocolGuid
, // retrieve the BlockIo iface
954 (VOID
**)&BlockIo
, // target pointer
955 This
->DriverBindingHandle
, // requestor driver identity
956 DeviceHandle
, // requesting lookup for dev.
957 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no ref. added
959 if (EFI_ERROR (Status
)) {
963 Dev
= VIRTIO_BLK_FROM_BLOCK_IO (BlockIo
);
966 // Handle Stop() requests for in-use driver instances gracefully.
968 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
969 &gEfiBlockIoProtocolGuid
, &Dev
->BlockIo
);
970 if (EFI_ERROR (Status
)) {
974 VirtioBlkUninit (Dev
);
976 Dev
->PciIo
->Attributes (Dev
->PciIo
, EfiPciIoAttributeOperationSet
,
977 Dev
->OriginalPciAttributes
, NULL
);
979 gBS
->CloseProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
,
980 This
->DriverBindingHandle
, DeviceHandle
);
989 // The static object that groups the Supported() (ie. probe), Start() and
990 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
991 // C, 10.1 EFI Driver Binding Protocol.
993 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
994 &VirtioBlkDriverBindingSupported
,
995 &VirtioBlkDriverBindingStart
,
996 &VirtioBlkDriverBindingStop
,
997 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
998 NULL
, // ImageHandle, to be overwritten by
999 // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
1000 NULL
// DriverBindingHandle, ditto
1005 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1006 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1007 // in English, for display on standard console devices. This is recommended for
1008 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1009 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1011 // Device type names ("Virtio Block Device") are not formatted because the
1012 // driver supports only that device type. Therefore the driver name suffices
1013 // for unambiguous identification.
1017 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
1018 { "eng;en", L
"Virtio Block Driver" },
1023 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
1027 VirtioBlkGetDriverName (
1028 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1030 OUT CHAR16
**DriverName
1033 return LookupUnicodeString2 (
1035 This
->SupportedLanguages
,
1038 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
1044 VirtioBlkGetDeviceName (
1045 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
1046 IN EFI_HANDLE DeviceHandle
,
1047 IN EFI_HANDLE ChildHandle
,
1049 OUT CHAR16
**ControllerName
1052 return EFI_UNSUPPORTED
;
1056 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
1057 &VirtioBlkGetDriverName
,
1058 &VirtioBlkGetDeviceName
,
1059 "eng" // SupportedLanguages, ISO 639-2 language codes
1063 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
1064 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioBlkGetDriverName
,
1065 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioBlkGetDeviceName
,
1066 "en" // SupportedLanguages, RFC 4646 language codes
1071 // Entry point of this driver.
1075 VirtioBlkEntryPoint (
1076 IN EFI_HANDLE ImageHandle
,
1077 IN EFI_SYSTEM_TABLE
*SystemTable
1080 return EfiLibInstallDriverBindingComponentName2 (