OvmfPkg: introduce virtio-blk driver

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13798 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten 2012-10-08 07:32:59 +00:00
parent 04cabbc0a1
commit fd51d75991
10 changed files with 1947 additions and 0 deletions

View File

@ -407,6 +407,7 @@
}
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
<LibraryClasses>
PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf

View File

@ -180,6 +180,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf

View File

@ -414,6 +414,7 @@
}
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
<LibraryClasses>
PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf

View File

@ -180,6 +180,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf

View File

@ -412,6 +412,7 @@
}
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
<LibraryClasses>
PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf

View File

@ -180,6 +180,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf

View File

@ -0,0 +1,176 @@
/** @file
Type and macro definitions corresponding to the virtio-0.9.5 specification.
Copyright (C) 2012, Red Hat, Inc.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Base.h>
//
// Data in the communication area is defined as packed and accessed as
// volatile.
//
// Some structures contain arrays with dynamically determined size. In such
// cases the array and its sibling fields are replaced with pointers.
//
// All indices (variables and fields named *Idx) are free-running and wrap
// around after 0xFFFF. The queue size reported by the host is always an
// integral power of 2, not greater than 32768. Actual array indices are
// consistently calculated by taking the remainder of a given Idx object modulo
// QueueSize. Since 0x10000 is an integral multiple of the QueueSize, UINT16
// wraparound is a correct wraparound modulo QueueSize too (it doesn't offset
// the remainder class).
//
// virtio-0.9.5, 2.3.4 Available Ring
//
#define VRING_AVAIL_F_NO_INTERRUPT BIT0
typedef struct {
volatile UINT16 *Flags;
volatile UINT16 *Idx;
volatile UINT16 *Ring; // QueueSize elements
volatile UINT16 *UsedEvent; // unused as per negotiation
} VRING_AVAIL;
//
// virtio-0.9.5, 2.3.5 Used Ring
//
#define VRING_USED_F_NO_NOTIFY BIT0
#pragma pack(1)
typedef struct {
UINT32 Id;
UINT32 Len;
} VRING_USED_ELEM;
#pragma pack()
typedef struct {
volatile UINT16 *Flags;
volatile UINT16 *Idx;
volatile VRING_USED_ELEM *UsedElem; // QueueSize elements
volatile UINT16 *AvailEvent; // unused as per negotiation
} VRING_USED;
//
// virtio-0.9.5, 2.3.2 Descriptor Table
//
#define VRING_DESC_F_NEXT BIT0 // more descriptors in this request
#define VRING_DESC_F_WRITE BIT1 // buffer to be written *by the host*
#define VRING_DESC_F_INDIRECT BIT2 // unused
#pragma pack(1)
typedef struct {
UINT64 Addr;
UINT32 Len;
UINT16 Flags;
UINT16 Next;
} VRING_DESC;
#pragma pack()
typedef struct {
UINTN NumPages;
VOID *Base; // deallocate only this field
volatile VRING_DESC *Desc; // QueueSize elements
VRING_AVAIL Avail;
VRING_USED Used;
UINT16 QueueSize;
} VRING;
//
// virtio-0.9.5, 2.2.2 Virtio Header -- no MSI-X
// virtio-0.9.5, Appendix D
//
#pragma pack(1)
typedef struct {
UINT32 VhdrDeviceFeatureBits;
UINT32 VhdrGuestFeatureBits;
UINT32 VhdrQueueAddress;
UINT16 VhdrQueueSize;
UINT16 VhdrQueueSelect;
UINT16 VhdrQueueNotify;
UINT8 VhdrDeviceStatus;
UINT8 VhdrISR;
UINT64 VhdrCapacity;
UINT32 VhdrSizeMax;
UINT32 VhdrSegMax;
UINT16 VhdrCylinders;
UINT8 VhdrHeads;
UINT8 VhdrSectors;
UINT32 VhdrBlkSize;
} VBLK_HDR;
#pragma pack()
#define OFFSET_OF_VHDR(Field) ((UINTN)(UINT8 *)&((VBLK_HDR *) 0)->Field)
#define SIZE_OF_VHDR(Field) (sizeof ((VBLK_HDR *) 0)->Field)
//
// virtio-0.9.5, 2.2.2.1 Device Status
//
#define VSTAT_ACK BIT0
#define VSTAT_DRIVER BIT1
#define VSTAT_DRIVER_OK BIT2
#define VSTAT_FAILED BIT7
//
// virtio-0.9.5, Appendix B: Reserved (Device-Independent) Feature Bits
//
#define VIRTIO_F_NOTIFY_ON_EMPTY BIT24
#define VIRTIO_F_RING_INDIRECT_DESC BIT28
#define VIRTIO_F_RING_EVENT_IDX BIT29
//
// virtio-0.9.5, Appendix D: Block Device
//
#define VIRTIO_BLK_F_BARRIER BIT0
#define VIRTIO_BLK_F_SIZE_MAX BIT1
#define VIRTIO_BLK_F_SEG_MAX BIT2
#define VIRTIO_BLK_F_GEOMETRY BIT4
#define VIRTIO_BLK_F_RO BIT5
#define VIRTIO_BLK_F_BLK_SIZE BIT6 // treated as "logical block size" in
// practice; actual host side implementation
// negotiates "optimal" block size
// separately
#define VIRTIO_BLK_F_SCSI BIT7
#define VIRTIO_BLK_F_FLUSH BIT9 // identical to "write cache enabled"
//
// We keep the status byte separate from the rest of the virtio-blk request
// header. See description of historical scattering at the end of Appendix D:
// we're going to put the status byte in a separate VRING_DESC.
//
#pragma pack(1)
typedef struct {
UINT32 Type;
UINT32 IoPrio;
UINT64 Sector;
} VIRTIO_BLK_REQ;
#pragma pack()
#define VIRTIO_BLK_T_IN 0x00000000
#define VIRTIO_BLK_T_OUT 0x00000001
#define VIRTIO_BLK_T_SCSI_CMD 0x00000002
#define VIRTIO_BLK_T_SCSI_CMD_OUT 0x00000003
#define VIRTIO_BLK_T_FLUSH 0x00000004
#define VIRTIO_BLK_T_FLUSH_OUT 0x00000005
#define VIRTIO_BLK_T_BARRIER BIT31
#define VIRTIO_BLK_S_OK 0x00
#define VIRTIO_BLK_S_IOERR 0x01
#define VIRTIO_BLK_S_UNSUPP 0x02

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,293 @@
/** @file
Internal definitions for the virtio-blk driver, which produces Block I/O
Protocol instances for virtio-blk devices.
Copyright (C) 2012, Red Hat, Inc.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Protocol/BlockIo.h>
#include <Protocol/ComponentName.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/PciIo.h>
#include "Virtio.h"
#define VBLK_SIG SIGNATURE_32 ('V', 'B', 'L', 'K')
typedef struct {
//
// Parts of this structure are initialized / torn down in various functions
// at various call depths. The table to the right should make it easier to
// track them.
//
// field init function init dpth
// ---------------------- ------------------ ---------
UINT32 Signature; // DriverBindingStart 0
EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0
UINT64 OriginalPciAttributes; // DriverBindingStart 0
VRING Ring; // VirtioRingInit 2
EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1
EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1
} VBLK_DEV;
#define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \
CR (BlockIoPointer, VBLK_DEV, BlockIo, VBLK_SIG)
/**
Device probe function for this driver.
The DXE core calls this function for any given device in order to see if the
driver can drive the device.
Specs relevant in the general sense:
- UEFI Spec 2.3.1 + Errata C:
- 6.3 Protocol Handler Services -- for accessing the underlying device
- 10.1 EFI Driver Binding Protocol -- for exporting ourselves
- Driver Writer's Guide for UEFI 2.3.1 v1.01:
- 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
underlying device
- 9 Driver Binding Protocol -- for exporting ourselves
Specs relevant in the specific sense:
- UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
- Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
Guidelines, 18.3 PCI drivers.
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
incorporating this driver (independently of
any device).
@param[in] DeviceHandle The device to probe.
@param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
@retval EFI_SUCCESS The driver supports the device being probed.
@retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
the device.
@return Error codes from the OpenProtocol() boot service or
the PciIo protocol.
**/
EFI_STATUS
EFIAPI
VirtioBlkDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
After we've pronounced support for a specific device in
DriverBindingSupported(), we start managing said device (passed in by the
Driver Exeuction Environment) with the following service.
See DriverBindingSupported() for specification references.
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
incorporating this driver (independently of
any device).
@param[in] DeviceHandle The supported device to drive.
@param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
@retval EFI_SUCCESS Driver instance has been created and
initialized for the virtio-blk PCI device, it
is now accessibla via EFI_BLOCK_IO_PROTOCOL.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@return Error codes from the OpenProtocol() boot
service, the PciIo protocol, VirtioBlkInit(),
or the InstallProtocolInterface() boot service.
**/
EFI_STATUS
EFIAPI
VirtioBlkDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
Stop driving a virtio-blk device and remove its BlockIo interface.
This function replays the success path of DriverBindingStart() in reverse.
The host side virtio-blk device is reset, so that the OS boot loader or the
OS may reinitialize it.
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
incorporating this driver (independently of any
device).
@param[in] DeviceHandle Stop driving this device.
@param[in] NumberOfChildren Since this function belongs to a device driver
only (as opposed to a bus driver), the caller
environment sets NumberOfChildren to zero, and
we ignore it.
@param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
**/
EFI_STATUS
EFIAPI
VirtioBlkDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
// Driver Writer's Guide for UEFI 2.3.1 v1.01,
// 24.2 Block I/O Protocol Implementations
//
EFI_STATUS
EFIAPI
VirtioBlkReset (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
/**
ReadBlocks() operation for virtio-blk.
See
- UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
- Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
ReadBlocksEx() Implementation.
Parameter checks and conformant return values are implemented in
VerifyReadWriteRequest() and SynchronousRequest().
A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
successfully.
**/
EFI_STATUS
EFIAPI
VirtioBlkReadBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
);
/**
WriteBlocks() operation for virtio-blk.
See
- UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
- Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
WriteBlockEx() Implementation.
Parameter checks and conformant return values are implemented in
VerifyReadWriteRequest() and SynchronousRequest().
A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
successfully.
**/
EFI_STATUS
EFIAPI
VirtioBlkWriteBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
);
/**
FlushBlocks() operation for virtio-blk.
See
- UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
- Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
FlushBlocksEx() Implementation.
If the underlying virtio-blk device doesn't support flushing (ie.
write-caching), then this function should not be called by higher layers,
according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
Should they do nonetheless, we do nothing, successfully.
**/
EFI_STATUS
EFIAPI
VirtioBlkFlushBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This
);
//
// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
// in English, for display on standard console devices. This is recommended for
// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
//
// Device type names ("Virtio Block Device") are not formatted because the
// driver supports only that device type. Therefore the driver name suffices
// for unambiguous identification.
//
EFI_STATUS
EFIAPI
VirtioBlkGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
VirtioBlkGetDeviceName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
IN EFI_HANDLE ChildHandle,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);

View File

@ -0,0 +1,40 @@
## @file
# This driver produces Block I/O Protocol instances for virtio-blk devices.
#
# Copyright (C) 2012, Red Hat, Inc.
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = VirtioBlkDxe
FILE_GUID = 11D92DFB-3CA9-4F93-BA2E-4780ED3E03B5
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = VirtioBlkEntryPoint
[Sources]
VirtioBlk.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
MemoryAllocationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
[Protocols]
gEfiBlockIoProtocolGuid ## BY_START
gEfiPciIoProtocolGuid ## TO_START