Copyright (C) 2016, Red Hat, Inc.\r
Copyright (C) 2017, AMD Inc, All rights reserved.<BR>\r
\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
**/\r
\r
#include <IndustryStandard/Pci.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PciCapLib.h>\r
+#include <Library/PciCapPciIoLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiLib.h>\r
\r
}\r
\r
\r
-/**\r
- Read a slice from PCI config space at the given offset, then advance the\r
- offset.\r
-\r
- @param [in] PciIo The EFI_PCI_IO_PROTOCOL instance that represents the\r
- device.\r
-\r
- @param [in,out] Offset On input, the offset in PCI config space to start\r
- reading from. On output, the offset of the first byte\r
- that was not read. On error, Offset is not modified.\r
-\r
- @param [in] Size The number of bytes to read.\r
-\r
- @param [out] Buffer On output, the bytes read from PCI config space are\r
- stored in this object.\r
-\r
- @retval EFI_SUCCESS Size bytes have been transferred from PCI config space\r
- (from Offset) to Buffer, and Offset has been incremented\r
- by Size.\r
-\r
- @return Error codes from PciIo->Pci.Read().\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-ReadConfigSpace (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN OUT UINT32 *Offset,\r
- IN UINTN Size,\r
- OUT VOID *Buffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, *Offset, Size, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- *Offset += (UINT32)Size;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
/*\r
Traverse the PCI capabilities list of a virtio-1.0 device, and capture the\r
locations of the interesting virtio-1.0 register blocks.\r
will have been updated from the PCI\r
capabilities found.\r
\r
- @param[in] CapabilityPtr The offset of the first capability in PCI\r
- config space, taken from the standard PCI\r
- device header.\r
-\r
@retval EFI_SUCCESS Traversal successful.\r
\r
- @return Error codes from the ReadConfigSpace() and GetBarType()\r
- helper functions.\r
+ @return Error codes from PciCapPciIoLib, PciCapLib, and the\r
+ GetBarType() helper function.\r
*/\r
STATIC\r
EFI_STATUS\r
ParseCapabilities (\r
- IN OUT VIRTIO_1_0_DEV *Device,\r
- IN UINT8 CapabilityPtr\r
+ IN OUT VIRTIO_1_0_DEV *Device\r
)\r
{\r
- UINT32 Offset;\r
- VIRTIO_PCI_CAP_LINK CapLink;\r
-\r
- for (Offset = CapabilityPtr & 0xFC;\r
- Offset > 0;\r
- Offset = CapLink.CapNext & 0xFC\r
- ) {\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ PCI_CAP_DEV *PciDevice;\r
+ PCI_CAP_LIST *CapList;\r
+ UINT16 VendorInstance;\r
+ PCI_CAP *VendorCap;\r
+\r
+ Status = PciCapPciIoDeviceInit (Device->PciIo, &PciDevice);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = PciCapListInit (PciDevice, &CapList);\r
+ if (EFI_ERROR (Status)) {\r
+ goto UninitPciDevice;\r
+ }\r
+\r
+ for (VendorInstance = 0;\r
+ !EFI_ERROR (PciCapListFindCap (CapList, PciCapNormal,\r
+ EFI_PCI_CAPABILITY_ID_VENDOR, VendorInstance,\r
+ &VendorCap));\r
+ VendorInstance++) {\r
UINT8 CapLen;\r
VIRTIO_PCI_CAP VirtIoCap;\r
VIRTIO_1_0_CONFIG *ParsedConfig;\r
\r
- //\r
- // Read capability identifier and link to next capability.\r
- //\r
- Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof CapLink,\r
- &CapLink);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- if (CapLink.CapId != 0x09) {\r
- //\r
- // Not a vendor-specific capability, move to the next one.\r
- //\r
- continue;\r
- }\r
-\r
//\r
// Big enough to accommodate a VIRTIO_PCI_CAP structure?\r
//\r
- Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof CapLen, &CapLen);\r
+ Status = PciCapRead (PciDevice, VendorCap,\r
+ OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length), &CapLen,\r
+ sizeof CapLen);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto UninitCapList;\r
}\r
- if (CapLen < sizeof CapLink + sizeof CapLen + sizeof VirtIoCap) {\r
+ if (CapLen < sizeof VirtIoCap) {\r
//\r
// Too small, move to next.\r
//\r
//\r
// Read interesting part of capability.\r
//\r
- Status = ReadConfigSpace (Device->PciIo, &Offset, sizeof VirtIoCap,\r
- &VirtIoCap);\r
+ Status = PciCapRead (PciDevice, VendorCap, 0, &VirtIoCap, sizeof VirtIoCap);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto UninitCapList;\r
}\r
+\r
switch (VirtIoCap.ConfigType) {\r
case VIRTIO_PCI_CAP_COMMON_CFG:\r
ParsedConfig = &Device->CommonConfig;\r
//\r
Status = GetBarType (Device->PciIo, VirtIoCap.Bar, &ParsedConfig->BarType);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto UninitCapList;\r
}\r
ParsedConfig->Bar = VirtIoCap.Bar;\r
ParsedConfig->Offset = VirtIoCap.Offset;\r
// This capability has an additional field called NotifyOffsetMultiplier;\r
// parse it too.\r
//\r
- if (CapLen < sizeof CapLink + sizeof CapLen + sizeof VirtIoCap +\r
- sizeof Device->NotifyOffsetMultiplier) {\r
+ if (CapLen < sizeof VirtIoCap + sizeof Device->NotifyOffsetMultiplier) {\r
//\r
// Too small, move to next.\r
//\r
continue;\r
}\r
\r
- Status = ReadConfigSpace (Device->PciIo, &Offset,\r
- sizeof Device->NotifyOffsetMultiplier,\r
- &Device->NotifyOffsetMultiplier);\r
+ Status = PciCapRead (PciDevice, VendorCap, sizeof VirtIoCap,\r
+ &Device->NotifyOffsetMultiplier,\r
+ sizeof Device->NotifyOffsetMultiplier);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto UninitCapList;\r
}\r
}\r
\r
ParsedConfig->Exists = TRUE;\r
}\r
\r
- return EFI_SUCCESS;\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+UninitCapList:\r
+ PciCapListUninit (CapList);\r
+\r
+UninitPciDevice:\r
+ PciCapPciIoDeviceUninit (PciDevice);\r
+\r
+ return Status;\r
}\r
\r
\r
\r
Device->VirtIo.SubSystemDeviceId = Pci.Hdr.DeviceId - 0x1040;\r
\r
- Status = ParseCapabilities (Device, Pci.Device.CapabilityPtr);\r
+ Status = ParseCapabilities (Device);\r
if (EFI_ERROR (Status)) {\r
goto ClosePciIo;\r
}\r