X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FVirtioBlkDxe%2FVirtioBlk.c;h=daccc7a5d06b48ebcbe8cb4ed28ceaba647c9344;hb=07af4eee931210bad04b98d37a35bd0f61ba6bd3;hp=55283cb3ba66b866a0cdd7c0517a83b81841ce7d;hpb=ece77e4047c36ddd177949e81d548bda244ea8a7;p=mirror_edk2.git
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 55283cb3ba..daccc7a5d0 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -11,7 +11,7 @@
synchronous requests and EFI_BLOCK_IO_PROTOCOL for now.
Copyright (C) 2012, Red Hat, Inc.
- Copyright (c) 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
@@ -56,7 +56,8 @@
one of UINT8, UINT16, UINT32, UINT64.
- @return Status code returned by Virtio->WriteDevice() / Virtio->ReadDevice().
+ @return Status code returned by Virtio->WriteDevice() /
+ Virtio->ReadDevice().
**/
@@ -323,7 +324,8 @@ SynchronousRequest (
//
// virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
//
- if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&
+ if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,
+ NULL) == EFI_SUCCESS &&
HostStatus == VIRTIO_BLK_S_OK) {
return EFI_SUCCESS;
}
@@ -531,8 +533,8 @@ VirtioBlkDriverBindingSupported (
//
// Attempt to open the device with the VirtIo set of interfaces. On success,
- // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
- // attempts (EFI_ALREADY_STARTED).
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate
+ // open attempts (EFI_ALREADY_STARTED).
//
Status = gBS->OpenProtocol (
DeviceHandle, // candidate device
@@ -591,11 +593,18 @@ VirtioBlkInit (
UINT8 NextDevStat;
EFI_STATUS Status;
- UINT32 Features;
+ UINT64 Features;
UINT64 NumSectors;
UINT32 BlockSize;
+ UINT8 PhysicalBlockExp;
+ UINT8 AlignmentOffset;
+ UINT32 OptIoSize;
UINT16 QueueSize;
+ PhysicalBlockExp = 0;
+ AlignmentOffset = 0;
+ OptIoSize = 0;
+
//
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
//
@@ -661,6 +670,28 @@ VirtioBlkInit (
BlockSize = 512;
}
+ if (Features & VIRTIO_BLK_F_TOPOLOGY) {
+ Status = VIRTIO_CFG_READ (Dev, Topology.PhysicalBlockExp,
+ &PhysicalBlockExp);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if (PhysicalBlockExp >= 32) {
+ Status = EFI_UNSUPPORTED;
+ goto Failed;
+ }
+
+ Status = VIRTIO_CFG_READ (Dev, Topology.AlignmentOffset, &AlignmentOffset);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ Status = VIRTIO_CFG_READ (Dev, Topology.OptIoSize, &OptIoSize);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ }
+
//
// step 4b -- allocate virtqueue
//
@@ -699,8 +730,7 @@ VirtioBlkInit (
//
// step 4c -- Report GPFN (guest-physical frame number) of queue.
//
- Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
- (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -727,9 +757,8 @@ VirtioBlkInit (
}
//
- // Populate the exported interface's attributes; see UEFI spec v2.3.1 +
- // Errata C, 12.8 EFI Block I/O Protocol. We stick to the lowest possible
- // EFI_BLOCK_IO_PROTOCOL revision for now.
+ // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI
+ // Block I/O Protocol.
//
Dev->BlockIo.Revision = 0;
Dev->BlockIo.Media = &Dev->BlockIoMedia;
@@ -741,12 +770,30 @@ VirtioBlkInit (
Dev->BlockIoMedia.RemovableMedia = FALSE;
Dev->BlockIoMedia.MediaPresent = TRUE;
Dev->BlockIoMedia.LogicalPartition = FALSE;
- Dev->BlockIoMedia.ReadOnly = !!(Features & VIRTIO_BLK_F_RO);
- Dev->BlockIoMedia.WriteCaching = !!(Features & VIRTIO_BLK_F_FLUSH);
+ Dev->BlockIoMedia.ReadOnly = (BOOLEAN) ((Features & VIRTIO_BLK_F_RO) != 0);
+ Dev->BlockIoMedia.WriteCaching = (BOOLEAN) ((Features & VIRTIO_BLK_F_FLUSH) != 0);
Dev->BlockIoMedia.BlockSize = BlockSize;
Dev->BlockIoMedia.IoAlign = 0;
Dev->BlockIoMedia.LastBlock = DivU64x32 (NumSectors,
BlockSize / 512) - 1;
+
+ DEBUG ((DEBUG_INFO, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",
+ __FUNCTION__, Dev->BlockIoMedia.BlockSize,
+ Dev->BlockIoMedia.LastBlock + 1));
+
+ if (Features & VIRTIO_BLK_F_TOPOLOGY) {
+ Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+
+ Dev->BlockIoMedia.LowestAlignedLba = AlignmentOffset;
+ Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock = 1u << PhysicalBlockExp;
+ Dev->BlockIoMedia.OptimalTransferLengthGranularity = OptIoSize;
+
+ DEBUG ((DEBUG_INFO, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",
+ __FUNCTION__, Dev->BlockIoMedia.LowestAlignedLba,
+ Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock));
+ DEBUG ((DEBUG_INFO, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",
+ __FUNCTION__, Dev->BlockIoMedia.OptimalTransferLengthGranularity));
+ }
return EFI_SUCCESS;
ReleaseQueue:
@@ -794,6 +841,37 @@ VirtioBlkUninit (
}
+/**
+
+ Event notification function enqueued by ExitBootServices().
+
+ @param[in] Event Event whose notification function is being invoked.
+
+ @param[in] Context Pointer to the VBLK_DEV structure.
+
+**/
+
+STATIC
+VOID
+EFIAPI
+VirtioBlkExitBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ VBLK_DEV *Dev;
+
+ //
+ // Reset the device. This causes the hypervisor to forget about the virtio
+ // ring.
+ //
+ // We allocated said ring in EfiBootServicesData type memory, and code
+ // executing after ExitBootServices() is permitted to overwrite it.
+ //
+ Dev = Context;
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+}
+
/**
After we've pronounced support for a specific device in
@@ -854,6 +932,12 @@ VirtioBlkDriverBindingStart (
goto CloseVirtIo;
}
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
+ &VirtioBlkExitBoot, Dev, &Dev->ExitBoot);
+ if (EFI_ERROR (Status)) {
+ goto UninitDev;
+ }
+
//
// Setup complete, attempt to export the driver instance's BlockIo interface.
//
@@ -862,11 +946,14 @@ VirtioBlkDriverBindingStart (
&gEfiBlockIoProtocolGuid, EFI_NATIVE_INTERFACE,
&Dev->BlockIo);
if (EFI_ERROR (Status)) {
- goto UninitDev;
+ goto CloseExitBoot;
}
return EFI_SUCCESS;
+CloseExitBoot:
+ gBS->CloseEvent (Dev->ExitBoot);
+
UninitDev:
VirtioBlkUninit (Dev);
@@ -940,6 +1027,8 @@ VirtioBlkDriverBindingStop (
return Status;
}
+ gBS->CloseEvent (Dev->ExitBoot);
+
VirtioBlkUninit (Dev);
gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,