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