]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Include/Library/PciCapLib.h
OvmfPkg: introduce PciCapLib
[mirror_edk2.git] / OvmfPkg / Include / Library / PciCapLib.h
diff --git a/OvmfPkg/Include/Library/PciCapLib.h b/OvmfPkg/Include/Library/PciCapLib.h
new file mode 100644 (file)
index 0000000..22a1ad6
--- /dev/null
@@ -0,0 +1,429 @@
+/** @file\r
+  Library class to work with PCI capabilities in PCI config space.\r
+\r
+  Provides functions to parse capabilities lists, and to locate, describe, read\r
+  and write capabilities. PCI config space access is abstracted away.\r
+\r
+  Copyright (C) 2018, Red Hat, Inc.\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
+**/\r
+\r
+#ifndef __PCI_CAP_LIB_H__\r
+#define __PCI_CAP_LIB_H__\r
+\r
+#include <Uefi/UefiBaseType.h>\r
+\r
+//\r
+// Base structure for representing a PCI device -- down to the PCI function\r
+// level -- for the purposes of this library class. This is a forward\r
+// declaration that is completed below. Concrete implementations are supposed\r
+// to inherit and extend this type.\r
+//\r
+typedef struct PCI_CAP_DEV PCI_CAP_DEV;\r
+\r
+/**\r
+  Read the config space of a given PCI device (both normal and extended).\r
+\r
+  PCI_CAP_DEV_READ_CONFIG performs as few config space accesses as possible\r
+  (without attempting 64-bit wide accesses).\r
+\r
+  PCI_CAP_DEV_READ_CONFIG returns an unspecified error if accessing Size bytes\r
+  from SourceOffset exceeds the config space limit of the PCI device. Fewer\r
+  than Size bytes may have been read in this case.\r
+\r
+  @param[in] PciDevice           Implementation-specific unique representation\r
+                                 of the PCI device in the PCI hierarchy.\r
+\r
+  @param[in] SourceOffset        Source offset in the config space of the PCI\r
+                                 device to start reading from.\r
+\r
+  @param[out] DestinationBuffer  Buffer to store the read data to.\r
+\r
+  @param[in] Size                The number of bytes to transfer.\r
+\r
+  @retval RETURN_SUCCESS  Size bytes have been transferred from config space to\r
+                          DestinationBuffer.\r
+\r
+  @return                 Unspecified error codes. Fewer than Size bytes may\r
+                          have been read.\r
+**/\r
+typedef\r
+RETURN_STATUS\r
+(EFIAPI *PCI_CAP_DEV_READ_CONFIG) (\r
+  IN  PCI_CAP_DEV *PciDevice,\r
+  IN  UINT16      SourceOffset,\r
+  OUT VOID        *DestinationBuffer,\r
+  IN  UINT16      Size\r
+  );\r
+\r
+/**\r
+  Write the config space of a given PCI device (both normal and extended).\r
+\r
+  PCI_CAP_DEV_WRITE_CONFIG performs as few config space accesses as possible\r
+  (without attempting 64-bit wide accesses).\r
+\r
+  PCI_CAP_DEV_WRITE_CONFIG returns an unspecified error if accessing Size bytes\r
+  at DestinationOffset exceeds the config space limit of the PCI device. Fewer\r
+  than Size bytes may have been written in this case.\r
+\r
+  @param[in] PciDevice          Implementation-specific unique representation\r
+                                of the PCI device in the PCI hierarchy.\r
+\r
+  @param[in] DestinationOffset  Destination offset in the config space of the\r
+                                PCI device to start writing at.\r
+\r
+  @param[in] SourceBuffer       Buffer to read the data to be stored from.\r
+\r
+  @param[in] Size               The number of bytes to transfer.\r
+\r
+  @retval RETURN_SUCCESS  Size bytes have been transferred from SourceBuffer to\r
+                          config space.\r
+\r
+  @return                 Unspecified error codes. Fewer than Size bytes may\r
+                          have been written.\r
+**/\r
+typedef\r
+RETURN_STATUS\r
+(EFIAPI *PCI_CAP_DEV_WRITE_CONFIG) (\r
+  IN PCI_CAP_DEV *PciDevice,\r
+  IN UINT16      DestinationOffset,\r
+  IN VOID        *SourceBuffer,\r
+  IN UINT16      Size\r
+  );\r
+\r
+//\r
+// Complete the PCI_CAP_DEV type here. The base abstraction only requires\r
+// config space accessors.\r
+//\r
+struct PCI_CAP_DEV {\r
+  PCI_CAP_DEV_READ_CONFIG  ReadConfig;\r
+  PCI_CAP_DEV_WRITE_CONFIG WriteConfig;\r
+};\r
+\r
+//\r
+// Opaque data structure representing parsed PCI Capabilities Lists.\r
+//\r
+typedef struct PCI_CAP_LIST PCI_CAP_LIST;\r
+\r
+//\r
+// Opaque data structure representing a PCI Capability in a parsed Capability\r
+// List.\r
+//\r
+typedef struct PCI_CAP PCI_CAP;\r
+\r
+//\r
+// Distinguishes whether a Capability ID is 8-bit wide and interpreted in\r
+// normal config space, or 16-bit wide and interpreted in extended config\r
+// space. Capability ID definitions are relative to domain.\r
+//\r
+typedef enum {\r
+  PciCapNormal,\r
+  PciCapExtended\r
+} PCI_CAP_DOMAIN;\r
+\r
+//\r
+// Public data structure that PciCapGetInfo() fills in about a PCI_CAP object.\r
+//\r
+typedef struct {\r
+  PCI_CAP_DOMAIN Domain;\r
+  UINT16         CapId;\r
+  //\r
+  // The capability identified by Domain and CapId may have multiple instances\r
+  // in config space. NumInstances provides the total count of occurrences of\r
+  // the capability. It is always positive.\r
+  //\r
+  UINT16 NumInstances;\r
+  //\r
+  // Instance is the serial number, in capabilities list traversal order (not\r
+  // necessarily config space offset order), of the one capability instance\r
+  // that PciCapGetInfo() is reporting about. Instance is always smaller than\r
+  // NumInstances.\r
+  //\r
+  UINT16 Instance;\r
+  //\r
+  // The offset in config space at which the capability header of the\r
+  // capability instance starts.\r
+  //\r
+  UINT16 Offset;\r
+  //\r
+  // The deduced maximum size of the capability instance, including the\r
+  // capability header. This hint is an upper bound, calculated -- without\r
+  // regard to the internal structure of the capability -- from (a) the next\r
+  // lowest offset in configuration space that is known to be used by another\r
+  // capability, and (b) from the end of the config space identified by Domain,\r
+  // whichever is lower.\r
+  //\r
+  UINT16 MaxSizeHint;\r
+  //\r
+  // The version number of the capability instance. Always zero when Domain is\r
+  // PciCapNormal.\r
+  //\r
+  UINT8 Version;\r
+} PCI_CAP_INFO;\r
+\r
+\r
+/**\r
+  Parse the capabilities lists (both normal and extended, as applicable) of a\r
+  PCI device.\r
+\r
+  If the PCI device has no capabilities, that per se will not fail\r
+  PciCapListInit(); an empty capabilities list will be represented.\r
+\r
+  If the PCI device is found to be PCI Express, then an attempt will be made to\r
+  parse the extended capabilities list as well. If the first extended config\r
+  space access -- via PciDevice->ReadConfig() with SourceOffset=0x100 and\r
+  Size=4 -- fails, that per se will not fail PciCapListInit(); the device will\r
+  be assumed to have no extended capabilities.\r
+\r
+  @param[in] PciDevice  Implementation-specific unique representation of the\r
+                        PCI device in the PCI hierarchy.\r
+\r
+  @param[out] CapList   Opaque data structure that holds an in-memory\r
+                        representation of the parsed capabilities lists of\r
+                        PciDevice.\r
+\r
+  @retval RETURN_SUCCESS           The capabilities lists have been parsed from\r
+                                   config space.\r
+\r
+  @retval RETURN_OUT_OF_RESOURCES  Memory allocation failed.\r
+\r
+  @retval RETURN_DEVICE_ERROR      A loop or some other kind of invalid pointer\r
+                                   was detected in the capabilities lists of\r
+                                   PciDevice.\r
+\r
+  @return                          Error codes propagated from\r
+                                   PciDevice->ReadConfig().\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+PciCapListInit (\r
+  IN  PCI_CAP_DEV  *PciDevice,\r
+  OUT PCI_CAP_LIST **CapList\r
+  );\r
+\r
+\r
+/**\r
+  Free the resources used by CapList.\r
+\r
+  @param[in] CapList  The PCI_CAP_LIST object to free, originally produced by\r
+                      PciCapListInit().\r
+**/\r
+VOID\r
+EFIAPI\r
+PciCapListUninit (\r
+  IN PCI_CAP_LIST *CapList\r
+  );\r
+\r
+\r
+/**\r
+  Locate a capability instance in the parsed capabilities lists.\r
+\r
+  @param[in] CapList   The PCI_CAP_LIST object produced by PciCapListInit().\r
+\r
+  @param[in] Domain    Distinguishes whether CapId is 8-bit wide and\r
+                       interpreted in normal config space, or 16-bit wide and\r
+                       interpreted in extended config space. Capability ID\r
+                       definitions are relative to domain.\r
+\r
+  @param[in] CapId     Capability identifier to look up.\r
+\r
+  @param[in] Instance  Domain and CapId may identify a multi-instance\r
+                       capability. When Instance is zero, the first instance of\r
+                       the capability is located (in list traversal order --\r
+                       which may not mean increasing config space offset\r
+                       order). Higher Instance values locate subsequent\r
+                       instances of the same capability (in list traversal\r
+                       order).\r
+\r
+  @param[out] Cap      The capability instance that matches the search\r
+                       criteria. Cap is owned by CapList and becomes invalid\r
+                       when CapList is freed with PciCapListUninit().\r
+                       PciCapListFindCap() may be called with Cap set to NULL,\r
+                       in order to test the existence of a specific capability\r
+                       instance.\r
+\r
+  @retval RETURN_SUCCESS    The capability instance identified by (Domain,\r
+                            CapId, Instance) has been found.\r
+\r
+  @retval RETURN_NOT_FOUND  The requested (Domain, CapId, Instance) capability\r
+                            instance does not exist.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+PciCapListFindCap (\r
+  IN  PCI_CAP_LIST   *CapList,\r
+  IN  PCI_CAP_DOMAIN Domain,\r
+  IN  UINT16         CapId,\r
+  IN  UINT16         Instance,\r
+  OUT PCI_CAP        **Cap    OPTIONAL\r
+  );\r
+\r
+\r
+/**\r
+  Locate the first instance of the capability given by (Domain, CapId) such\r
+  that the instance's Version is greater than or equal to MinVersion.\r
+\r
+  This is a convenience function that may save client code calls to\r
+  PciCapListFindCap() and PciCapGetInfo().\r
+\r
+  @param[in] CapList     The PCI_CAP_LIST object produced by PciCapListInit().\r
+\r
+  @param[in] Domain      Distinguishes whether CapId is 8-bit wide and\r
+                         interpreted in normal config space, or 16-bit wide and\r
+                         interpreted in extended config space. Capability ID\r
+                         definitions are relative to domain.\r
+\r
+  @param[in] CapId       Capability identifier to look up.\r
+\r
+  @param[in] MinVersion  The minimum version that the capability instance is\r
+                         required to have. Note that all capability instances\r
+                         in Domain=PciCapNormal have Version=0.\r
+\r
+  @param[out] Cap        The first capability instance that matches the search\r
+                         criteria. Cap is owned by CapList and becomes invalid\r
+                         when CapList is freed with PciCapListUninit().\r
+                         PciCapListFindCapVersion() may be called with Cap set\r
+                         to NULL, in order just to test whether the search\r
+                         criteria are satisfiable.\r
+\r
+  @retval RETURN_SUCCESS    The first capability instance matching (Domain,\r
+                            CapId, MinVersion) has been located.\r
+\r
+  @retval RETURN_NOT_FOUND  No capability instance matches (Domain, CapId,\r
+                            MinVersion).\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+PciCapListFindCapVersion (\r
+  IN  PCI_CAP_LIST   *CapList,\r
+  IN  PCI_CAP_DOMAIN Domain,\r
+  IN  UINT16         CapId,\r
+  IN  UINT8          MinVersion,\r
+  OUT PCI_CAP        **Cap      OPTIONAL\r
+  );\r
+\r
+\r
+/**\r
+  Get information about a PCI Capability instance.\r
+\r
+  @param[in] Cap    The capability instance to get info about, located with\r
+                    PciCapListFindCap*().\r
+\r
+  @param[out] Info  A PCI_CAP_INFO structure that describes the properties of\r
+                    Cap.\r
+\r
+  @retval RETURN_SUCCESS  Fields of Info have been set.\r
+\r
+  @return                 Unspecified error codes, if filling in Info failed\r
+                          for some reason.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+PciCapGetInfo (\r
+  IN  PCI_CAP      *Cap,\r
+  OUT PCI_CAP_INFO *Info\r
+  );\r
+\r
+\r
+/**\r
+  Read a slice of a capability instance.\r
+\r
+  The function performs as few config space accesses as possible (without\r
+  attempting 64-bit wide accesses). PciCapRead() performs bounds checking on\r
+  SourceOffsetInCap and Size, and only invokes PciDevice->ReadConfig() if the\r
+  requested transfer falls within Cap.\r
+\r
+  @param[in] PciDevice           Implementation-specific unique representation\r
+                                 of the PCI device in the PCI hierarchy.\r
+\r
+  @param[in] Cap                 The capability instance to read, located with\r
+                                 PciCapListFindCap*().\r
+\r
+  @param[in] SourceOffsetInCap   Source offset relative to the capability\r
+                                 header to start reading from. A zero value\r
+                                 refers to the first byte of the capability\r
+                                 header.\r
+\r
+  @param[out] DestinationBuffer  Buffer to store the read data to.\r
+\r
+  @param[in] Size                The number of bytes to transfer.\r
+\r
+  @retval RETURN_SUCCESS          Size bytes have been transferred from Cap to\r
+                                  DestinationBuffer.\r
+\r
+  @retval RETURN_BAD_BUFFER_SIZE  Reading Size bytes starting from\r
+                                  SourceOffsetInCap would not (entirely) be\r
+                                  contained within Cap, as suggested by\r
+                                  PCI_CAP_INFO.MaxSizeHint. No bytes have been\r
+                                  read.\r
+\r
+  @return                         Error codes propagated from\r
+                                  PciDevice->ReadConfig(). Fewer than Size\r
+                                  bytes may have been read.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+PciCapRead (\r
+  IN  PCI_CAP_DEV *PciDevice,\r
+  IN  PCI_CAP     *Cap,\r
+  IN  UINT16      SourceOffsetInCap,\r
+  OUT VOID        *DestinationBuffer,\r
+  IN  UINT16      Size\r
+  );\r
+\r
+\r
+/**\r
+  Write a slice of a capability instance.\r
+\r
+  The function performs as few config space accesses as possible (without\r
+  attempting 64-bit wide accesses). PciCapWrite() performs bounds checking on\r
+  DestinationOffsetInCap and Size, and only invokes PciDevice->WriteConfig() if\r
+  the requested transfer falls within Cap.\r
+\r
+  @param[in] PciDevice               Implementation-specific unique\r
+                                     representation of the PCI device in the\r
+                                     PCI hierarchy.\r
+\r
+  @param[in] Cap                     The capability instance to write, located\r
+                                     with PciCapListFindCap*().\r
+\r
+  @param[in] DestinationOffsetInCap  Destination offset relative to the\r
+                                     capability header to start writing at. A\r
+                                     zero value refers to the first byte of the\r
+                                     capability header.\r
+\r
+  @param[in] SourceBuffer            Buffer to read the data to be stored from.\r
+\r
+  @param[in] Size                    The number of bytes to transfer.\r
+\r
+  @retval RETURN_SUCCESS          Size bytes have been transferred from\r
+                                  SourceBuffer to Cap.\r
+\r
+  @retval RETURN_BAD_BUFFER_SIZE  Writing Size bytes starting at\r
+                                  DestinationOffsetInCap would not (entirely)\r
+                                  be contained within Cap, as suggested by\r
+                                  PCI_CAP_INFO.MaxSizeHint. No bytes have been\r
+                                  written.\r
+\r
+  @return                         Error codes propagated from\r
+                                  PciDevice->WriteConfig(). Fewer than Size\r
+                                  bytes may have been written.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+PciCapWrite (\r
+  IN PCI_CAP_DEV *PciDevice,\r
+  IN PCI_CAP     *Cap,\r
+  IN UINT16      DestinationOffsetInCap,\r
+  IN VOID        *SourceBuffer,\r
+  IN UINT16      Size\r
+  );\r
+\r
+#endif // __PCI_CAP_LIB_H__\r