Replace the manual capability list parsing in OvmfPkg/Virtio10Dxe with
PciCapLib and PciCapPciIoLib API calls.
The VIRTIO_PCI_CAP_LINK structure type is now superfluous. (Well, it
always has been; we should have used EFI_PCI_CAPABILITY_HDR.)
Also, EFI_PCI_CAPABILITY_VENDOR_HDR is now included at the front of
VIRTIO_PCI_CAP. No driver other than Virtio10Dxe relies on VIRTIO_PCI_CAP.
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
Notes:
v2:
- no changes
OvmfPkg/Virtio10Dxe/Virtio10.inf | 2 +
OvmfPkg/Include/IndustryStandard/Virtio10.h | 7 +-
OvmfPkg/Virtio10Dxe/Virtio10.c | 135 +++++++-------------
3 files changed, 52 insertions(+), 92 deletions(-)
diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.inf b/OvmfPkg/Virtio10Dxe/Virtio10.inf
index c4ef15d94bfc..db0cb1189a29 100644
--- a/OvmfPkg/Virtio10Dxe/Virtio10.inf
+++ b/OvmfPkg/Virtio10Dxe/Virtio10.inf
@@ -32,6 +32,8 @@ [LibraryClasses]
BaseMemoryLib
DebugLib
MemoryAllocationLib
+ PciCapLib
+ PciCapPciIoLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
diff --git a/OvmfPkg/Include/IndustryStandard/Virtio10.h b/OvmfPkg/Include/IndustryStandard/Virtio10.h
index c5efb5cfcb8a..7d51aa36b326 100644
--- a/OvmfPkg/Include/IndustryStandard/Virtio10.h
+++ b/OvmfPkg/Include/IndustryStandard/Virtio10.h
@@ -16,6 +16,7 @@
#ifndef _VIRTIO_1_0_H_
#define _VIRTIO_1_0_H_
+#include <IndustryStandard/Pci23.h>
#include <IndustryStandard/Virtio095.h>
//
@@ -29,11 +30,7 @@
//
#pragma pack (1)
typedef struct {
- UINT8 CapId; // Capability identifier (generic)
- UINT8 CapNext; // Link to next capability (generic)
-} VIRTIO_PCI_CAP_LINK;
-
-typedef struct {
+ EFI_PCI_CAPABILITY_VENDOR_HDR VendorHdr;
UINT8 ConfigType; // Identifies the specific VirtIo 1.0 config structure
UINT8 Bar; // The BAR that contains the structure
UINT8 Padding[3];
diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
index e9b50b6e437b..9ebb72c76bfd 100644
--- a/OvmfPkg/Virtio10Dxe/Virtio10.c
+++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
@@ -21,6 +21,8 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/PciCapLib.h>
+#include <Library/PciCapPciIoLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
@@ -184,48 +186,6 @@ GetBarType (
}
-/**
- Read a slice from PCI config space at the given offset, then advance the
- offset.
-
- @param [in] PciIo The EFI_PCI_IO_PROTOCOL instance that represents the
- device.
-
- @param [in,out] Offset On input, the offset in PCI config space to start
- reading from. On output, the offset of the first byte
- that was not read. On error, Offset is not modified.
-
- @param [in] Size The number of bytes to read.
-
- @param [out] Buffer On output, the bytes read from PCI config space are
- stored in this object.
-
- @retval EFI_SUCCESS Size bytes have been transferred from PCI config space
- (from Offset) to Buffer, and Offset has been incremented
- by Size.
-
- @return Error codes from PciIo->Pci.Read().
-**/
-STATIC
-EFI_STATUS
-ReadConfigSpace (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN OUT UINT32 *Offset,
- IN UINTN Size,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
-
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, *Offset, Size, Buffer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- *Offset += (UINT32)Size;
- return EFI_SUCCESS;
-}
-
-
/*
Traverse the PCI capabilities list of a virtio-1.0 device, and capture the
locations of the interesting virtio-1.0 register blocks.
@@ -239,57 +199,51 @@ ReadConfigSpace (
will have been updated from the PCI
capabilities found.
- @param[in] CapabilityPtr The offset of the first capability in PCI
- config space, taken from the standard PCI
- device header.
-
@retval EFI_SUCCESS Traversal successful.
- @return Error codes from the ReadConfigSpace() and GetBarType()
- helper functions.
+ @return Error codes from PciCapPciIoLib, PciCapLib, and the
+ GetBarType() helper function.
*/
STATIC
EFI_STATUS
ParseCapabilities (
- IN OUT VIRTIO_1_0_DEV *Device,
- IN UINT8 CapabilityPtr
+ IN OUT VIRTIO_1_0_DEV *Device
)
{
- UINT32 Offset;
- VIRTIO_PCI_CAP_LINK CapLink;
+ EFI_STATUS Status;
+ PCI_CAP_DEV *PciDevice;
+ PCI_CAP_LIST *CapList;
+ UINT16 VendorInstance;
+ PCI_CAP *VendorCap;
- for (Offset = CapabilityPtr & 0xFC;
- Offset > 0;
- Offset = CapLink.CapNext & 0xFC
- ) {
- EFI_STATUS Status;
+ Status = PciCapPciIoDeviceInit (Device->PciIo, &PciDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = PciCapListInit (PciDevice, &CapList);
+ if (EFI_ERROR (Status)) {
+ goto UninitPciDevice;
+ }
+
+ for (VendorInstance = 0;
+ !EFI_ERROR (PciCapListFindCap (CapList, PciCapNormal,
+ EFI_PCI_CAPABILITY_ID_VENDOR, VendorInstance,
+ &VendorCap));
+ VendorInstance++) {
UINT8 CapLen;
VIRTIO_PCI_CAP VirtIoCap;
VIRTIO_1_0_CONFIG *ParsedConfig;
- //
- // Read capability identifier and link to next capability.
- //
- Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof CapLink,
- &CapLink);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (CapLink.CapId != 0x09) {
- //
- // Not a vendor-specific capability, move to the next one.
- //
- continue;
- }
-
//
// Big enough to accommodate a VIRTIO_PCI_CAP structure?
//
- Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof CapLen, &CapLen);
+ Status = PciCapRead (PciDevice, VendorCap,
+ OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length), &CapLen,
+ sizeof CapLen);
if (EFI_ERROR (Status)) {
- return Status;
+ goto UninitCapList;
}
- if (CapLen < sizeof CapLink + sizeof CapLen + sizeof VirtIoCap) {
+ if (CapLen < sizeof VirtIoCap) {
//
// Too small, move to next.
//
@@ -299,11 +253,11 @@ ParseCapabilities (
//
// Read interesting part of capability.
//
- Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof VirtIoCap,
- &VirtIoCap);
+ Status = PciCapRead (PciDevice, VendorCap, 0, &VirtIoCap, sizeof VirtIoCap);
if (EFI_ERROR (Status)) {
- return Status;
+ goto UninitCapList;
}
+
switch (VirtIoCap.ConfigType) {
case VIRTIO_PCI_CAP_COMMON_CFG:
ParsedConfig = &Device->CommonConfig;
@@ -326,7 +280,7 @@ ParseCapabilities (
//
Status = GetBarType (Device->PciIo, VirtIoCap.Bar, &ParsedConfig->BarType);
if (EFI_ERROR (Status)) {
- return Status;
+ goto UninitCapList;
}
ParsedConfig->Bar = VirtIoCap.Bar;
ParsedConfig->Offset = VirtIoCap.Offset;
@@ -337,19 +291,18 @@ ParseCapabilities (
// This capability has an additional field called NotifyOffsetMultiplier;
// parse it too.
//
- if (CapLen < sizeof CapLink + sizeof CapLen + sizeof VirtIoCap +
- sizeof Device->NotifyOffsetMultiplier) {
+ if (CapLen < sizeof VirtIoCap + sizeof Device->NotifyOffsetMultiplier) {
//
// Too small, move to next.
//
continue;
}
- Status = ReadConfigSpace (Device->PciIo, &Offset,
- sizeof Device->NotifyOffsetMultiplier,
- &Device->NotifyOffsetMultiplier);
+ Status = PciCapRead (PciDevice, VendorCap, sizeof VirtIoCap,
+ &Device->NotifyOffsetMultiplier,
+ sizeof Device->NotifyOffsetMultiplier);
if (EFI_ERROR (Status)) {
- return Status;
+ goto UninitCapList;
}
}
@@ -359,7 +312,15 @@ ParseCapabilities (
ParsedConfig->Exists = TRUE;
}
- return EFI_SUCCESS;
+ ASSERT_EFI_ERROR (Status);
+
+UninitCapList:
+ PciCapListUninit (CapList);
+
+UninitPciDevice:
+ PciCapPciIoDeviceUninit (PciDevice);
+
+ return Status;
}
@@ -1015,7 +976,7 @@ Virtio10BindingStart (
Device->VirtIo.SubSystemDeviceId = Pci.Hdr.DeviceId - 0x1040;
- Status = ParseCapabilities (Device, Pci.Device.CapabilityPtr);
+ Status = ParseCapabilities (Device);
if (EFI_ERROR (Status)) {
goto ClosePciIo;
}
--
2.14.1.3.gb7cf6e02401b
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
On 23 May 2018 at 22:21, Laszlo Ersek <lersek@redhat.com> wrote:
> Replace the manual capability list parsing in OvmfPkg/Virtio10Dxe with
> PciCapLib and PciCapPciIoLib API calls.
>
> The VIRTIO_PCI_CAP_LINK structure type is now superfluous. (Well, it
> always has been; we should have used EFI_PCI_CAPABILITY_HDR.)
>
> Also, EFI_PCI_CAPABILITY_VENDOR_HDR is now included at the front of
> VIRTIO_PCI_CAP. No driver other than Virtio10Dxe relies on VIRTIO_PCI_CAP.
>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>
> Notes:
> v2:
> - no changes
>
> OvmfPkg/Virtio10Dxe/Virtio10.inf | 2 +
> OvmfPkg/Include/IndustryStandard/Virtio10.h | 7 +-
> OvmfPkg/Virtio10Dxe/Virtio10.c | 135 +++++++-------------
> 3 files changed, 52 insertions(+), 92 deletions(-)
>
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.inf b/OvmfPkg/Virtio10Dxe/Virtio10.inf
> index c4ef15d94bfc..db0cb1189a29 100644
> --- a/OvmfPkg/Virtio10Dxe/Virtio10.inf
> +++ b/OvmfPkg/Virtio10Dxe/Virtio10.inf
> @@ -32,6 +32,8 @@ [LibraryClasses]
> BaseMemoryLib
> DebugLib
> MemoryAllocationLib
> + PciCapLib
> + PciCapPciIoLib
> UefiBootServicesTableLib
> UefiDriverEntryPoint
> UefiLib
> diff --git a/OvmfPkg/Include/IndustryStandard/Virtio10.h b/OvmfPkg/Include/IndustryStandard/Virtio10.h
> index c5efb5cfcb8a..7d51aa36b326 100644
> --- a/OvmfPkg/Include/IndustryStandard/Virtio10.h
> +++ b/OvmfPkg/Include/IndustryStandard/Virtio10.h
> @@ -16,6 +16,7 @@
> #ifndef _VIRTIO_1_0_H_
> #define _VIRTIO_1_0_H_
>
> +#include <IndustryStandard/Pci23.h>
> #include <IndustryStandard/Virtio095.h>
>
> //
> @@ -29,11 +30,7 @@
> //
> #pragma pack (1)
> typedef struct {
> - UINT8 CapId; // Capability identifier (generic)
> - UINT8 CapNext; // Link to next capability (generic)
> -} VIRTIO_PCI_CAP_LINK;
> -
> -typedef struct {
> + EFI_PCI_CAPABILITY_VENDOR_HDR VendorHdr;
> UINT8 ConfigType; // Identifies the specific VirtIo 1.0 config structure
> UINT8 Bar; // The BAR that contains the structure
> UINT8 Padding[3];
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
> index e9b50b6e437b..9ebb72c76bfd 100644
> --- a/OvmfPkg/Virtio10Dxe/Virtio10.c
> +++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
> @@ -21,6 +21,8 @@
> #include <Library/BaseMemoryLib.h>
> #include <Library/DebugLib.h>
> #include <Library/MemoryAllocationLib.h>
> +#include <Library/PciCapLib.h>
> +#include <Library/PciCapPciIoLib.h>
> #include <Library/UefiBootServicesTableLib.h>
> #include <Library/UefiLib.h>
>
> @@ -184,48 +186,6 @@ GetBarType (
> }
>
>
> -/**
> - Read a slice from PCI config space at the given offset, then advance the
> - offset.
> -
> - @param [in] PciIo The EFI_PCI_IO_PROTOCOL instance that represents the
> - device.
> -
> - @param [in,out] Offset On input, the offset in PCI config space to start
> - reading from. On output, the offset of the first byte
> - that was not read. On error, Offset is not modified.
> -
> - @param [in] Size The number of bytes to read.
> -
> - @param [out] Buffer On output, the bytes read from PCI config space are
> - stored in this object.
> -
> - @retval EFI_SUCCESS Size bytes have been transferred from PCI config space
> - (from Offset) to Buffer, and Offset has been incremented
> - by Size.
> -
> - @return Error codes from PciIo->Pci.Read().
> -**/
> -STATIC
> -EFI_STATUS
> -ReadConfigSpace (
> - IN EFI_PCI_IO_PROTOCOL *PciIo,
> - IN OUT UINT32 *Offset,
> - IN UINTN Size,
> - OUT VOID *Buffer
> - )
> -{
> - EFI_STATUS Status;
> -
> - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, *Offset, Size, Buffer);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> - *Offset += (UINT32)Size;
> - return EFI_SUCCESS;
> -}
> -
> -
> /*
> Traverse the PCI capabilities list of a virtio-1.0 device, and capture the
> locations of the interesting virtio-1.0 register blocks.
> @@ -239,57 +199,51 @@ ReadConfigSpace (
> will have been updated from the PCI
> capabilities found.
>
> - @param[in] CapabilityPtr The offset of the first capability in PCI
> - config space, taken from the standard PCI
> - device header.
> -
> @retval EFI_SUCCESS Traversal successful.
>
> - @return Error codes from the ReadConfigSpace() and GetBarType()
> - helper functions.
> + @return Error codes from PciCapPciIoLib, PciCapLib, and the
> + GetBarType() helper function.
> */
> STATIC
> EFI_STATUS
> ParseCapabilities (
> - IN OUT VIRTIO_1_0_DEV *Device,
> - IN UINT8 CapabilityPtr
> + IN OUT VIRTIO_1_0_DEV *Device
> )
> {
> - UINT32 Offset;
> - VIRTIO_PCI_CAP_LINK CapLink;
> + EFI_STATUS Status;
> + PCI_CAP_DEV *PciDevice;
> + PCI_CAP_LIST *CapList;
> + UINT16 VendorInstance;
> + PCI_CAP *VendorCap;
>
> - for (Offset = CapabilityPtr & 0xFC;
> - Offset > 0;
> - Offset = CapLink.CapNext & 0xFC
> - ) {
> - EFI_STATUS Status;
> + Status = PciCapPciIoDeviceInit (Device->PciIo, &PciDevice);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Status = PciCapListInit (PciDevice, &CapList);
> + if (EFI_ERROR (Status)) {
> + goto UninitPciDevice;
> + }
> +
> + for (VendorInstance = 0;
> + !EFI_ERROR (PciCapListFindCap (CapList, PciCapNormal,
> + EFI_PCI_CAPABILITY_ID_VENDOR, VendorInstance,
> + &VendorCap));
> + VendorInstance++) {
> UINT8 CapLen;
> VIRTIO_PCI_CAP VirtIoCap;
> VIRTIO_1_0_CONFIG *ParsedConfig;
>
> - //
> - // Read capability identifier and link to next capability.
> - //
> - Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof CapLink,
> - &CapLink);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> - if (CapLink.CapId != 0x09) {
> - //
> - // Not a vendor-specific capability, move to the next one.
> - //
> - continue;
> - }
> -
> //
> // Big enough to accommodate a VIRTIO_PCI_CAP structure?
> //
> - Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof CapLen, &CapLen);
> + Status = PciCapRead (PciDevice, VendorCap,
> + OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length), &CapLen,
> + sizeof CapLen);
> if (EFI_ERROR (Status)) {
> - return Status;
> + goto UninitCapList;
> }
> - if (CapLen < sizeof CapLink + sizeof CapLen + sizeof VirtIoCap) {
> + if (CapLen < sizeof VirtIoCap) {
> //
> // Too small, move to next.
> //
> @@ -299,11 +253,11 @@ ParseCapabilities (
> //
> // Read interesting part of capability.
> //
> - Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof VirtIoCap,
> - &VirtIoCap);
> + Status = PciCapRead (PciDevice, VendorCap, 0, &VirtIoCap, sizeof VirtIoCap);
> if (EFI_ERROR (Status)) {
> - return Status;
> + goto UninitCapList;
> }
> +
> switch (VirtIoCap.ConfigType) {
> case VIRTIO_PCI_CAP_COMMON_CFG:
> ParsedConfig = &Device->CommonConfig;
> @@ -326,7 +280,7 @@ ParseCapabilities (
> //
> Status = GetBarType (Device->PciIo, VirtIoCap.Bar, &ParsedConfig->BarType);
> if (EFI_ERROR (Status)) {
> - return Status;
> + goto UninitCapList;
> }
> ParsedConfig->Bar = VirtIoCap.Bar;
> ParsedConfig->Offset = VirtIoCap.Offset;
> @@ -337,19 +291,18 @@ ParseCapabilities (
> // This capability has an additional field called NotifyOffsetMultiplier;
> // parse it too.
> //
> - if (CapLen < sizeof CapLink + sizeof CapLen + sizeof VirtIoCap +
> - sizeof Device->NotifyOffsetMultiplier) {
> + if (CapLen < sizeof VirtIoCap + sizeof Device->NotifyOffsetMultiplier) {
> //
> // Too small, move to next.
> //
> continue;
> }
>
> - Status = ReadConfigSpace (Device->PciIo, &Offset,
> - sizeof Device->NotifyOffsetMultiplier,
> - &Device->NotifyOffsetMultiplier);
> + Status = PciCapRead (PciDevice, VendorCap, sizeof VirtIoCap,
> + &Device->NotifyOffsetMultiplier,
> + sizeof Device->NotifyOffsetMultiplier);
> if (EFI_ERROR (Status)) {
> - return Status;
> + goto UninitCapList;
> }
> }
>
> @@ -359,7 +312,15 @@ ParseCapabilities (
> ParsedConfig->Exists = TRUE;
> }
>
> - return EFI_SUCCESS;
> + ASSERT_EFI_ERROR (Status);
> +
> +UninitCapList:
> + PciCapListUninit (CapList);
> +
> +UninitPciDevice:
> + PciCapPciIoDeviceUninit (PciDevice);
> +
> + return Status;
> }
>
>
> @@ -1015,7 +976,7 @@ Virtio10BindingStart (
>
> Device->VirtIo.SubSystemDeviceId = Pci.Hdr.DeviceId - 0x1040;
>
> - Status = ParseCapabilities (Device, Pci.Device.CapabilityPtr);
> + Status = ParseCapabilities (Device);
> if (EFI_ERROR (Status)) {
> goto ClosePciIo;
> }
> --
> 2.14.1.3.gb7cf6e02401b
>
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
On 05/24/18 10:16, Ard Biesheuvel wrote: > On 23 May 2018 at 22:21, Laszlo Ersek <lersek@redhat.com> wrote: >> Replace the manual capability list parsing in OvmfPkg/Virtio10Dxe with >> PciCapLib and PciCapPciIoLib API calls. >> >> The VIRTIO_PCI_CAP_LINK structure type is now superfluous. (Well, it >> always has been; we should have used EFI_PCI_CAPABILITY_HDR.) >> >> Also, EFI_PCI_CAPABILITY_VENDOR_HDR is now included at the front of >> VIRTIO_PCI_CAP. No driver other than Virtio10Dxe relies on VIRTIO_PCI_CAP. >> >> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> >> Cc: Jordan Justen <jordan.l.justen@intel.com> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Laszlo Ersek <lersek@redhat.com> > > Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Thanks for the super quick review! Can you please clarify your review of 2/7? You agreed with the commit msg (thanks!) but didn't comment on the code in either direction. Thanks! Laszlo _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2026 Red Hat, Inc.