diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 5815cdf375..55184faab2 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -595,8 +595,15 @@ VirtioBlkInit ( UINT32 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. // @@ -662,6 +669,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 // @@ -728,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; @@ -748,6 +776,14 @@ VirtioBlkInit ( Dev->BlockIoMedia.IoAlign = 0; Dev->BlockIoMedia.LastBlock = DivU64x32 (NumSectors, BlockSize / 512) - 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; + } return EFI_SUCCESS; ReleaseQueue: