ping

On 05/04/18 23:36, Laszlo Ersek wrote:
> Repo:   https://github.com/lersek/edk2.git
> Branch: pci_cap
> 
> In message [1], Jordan suggested a general "capabilities helper lib that
> could iterate & read the PCI capability structs". Patch #1 introduces
> that library (class and central BASE instance) to MdePkg; the library
> class is called PciCapLib.
> 
> [1] 
> http://mid.mail-archive.com/150696619010.2454.9266470245604846575@jljusten-skl
> 
> PciCapLib offers APIs to parse capabilities lists, and to locate,
> describe, read and write capabilities.
> 
> The library class targets a wide range of client module types; for
> example, platform PEIMs, platform DXE drivers, and UEFI drivers that
> follow the UEFI Driver Model. For this reason, the library class is
> designed with PCI config access abstracted away, even beyond the PPI /
> Protocol level, since those cannot cross the PEI / DXE boundary.
> 
> This (minimal) config space access method abstraction is called
> PCI_CAP_DEV. It is *conceptually* a protocol. Client modules plug
> PCI_CAP_DEV instances into PciCapLib for config space access, similarly
> to how DiskIo and BlockIo instances are plugged into filesystem drivers.
> Similarly to the filesystem driver example, PciCapLib is an example for
> the "strategy pattern".
> 
> Patches #2 and #3 introduce small "factory" libraries that help client
> modules produce PCI_CAP_DEV instances:
> 
> - PciCapPciSegmentLib -- incl. class and central BASE instance -- from
>   patch #2 produces PCI_CAP_DEV instances on top of PciSegmentLib, using
>   the "Segment:Bus:Device.Function" notation. This is meant for platform
>   modules (PEIMs and DXE drivers), which generally have a working
>   PciSegmentLib instance available.
> 
> - PciCapPciIoLib -- incl. class and central UEFI instance -- from patch
>   #3 lets client modules produce PCI_CAP_DEV instances on top of
>   EFI_PCI_IO_PROTOCOL instances. This is meant for UEFI drivers.
> 
> Patches #4 and #5 resolve the three new lib classes to their respective
> central instances in the OvmfPkg and ArmVirtPkg DSC files.
> 
> Patch #6 converts OvmfPkg/PciHotPlugInitDxe to the new APIs, from manual
> capability list parsing. Because PciHotPlugInitDxe is a platform DXE
> driver, this conversion uses PciCapPciSegmentLib and PciCapLib.
> 
> Patch #7 converts OvmfPkg/Virtio10Dxe to the new APIs, from manual
> capability list parsing. Because Virtio10Dxe is a UEFI driver, this
> conversion uses PciCapPciIoLib and PciCapLib.
> 
> ----[ jump to the patches now, and return if you have questions: I
>       have answers, but you might find them too verbose in advance ]----
> 
> Q1: If PCI config access needs to be abstracted from PciCapLib, then why
>     don't we provide multiple instances of PciCapLib? In other words,
>     why the PCI_CAP_DEV "protocol" rather than multiple instances of
>     PciCapLib?
> 
> A1: The point of lib classes and instances is that the class provides a
>     common interface, and the instances provide different
>     implementations. We have the opposite use case here (hence the
>     "strategy pattern"): the implementation of the higher level
>     algorithm is common, and the objects that plug into it differ at the
>     *interface* level ("Segment:Bus:Device.Function" notation versus
>     PciIo protocol).
> 
>     None of those notations are suitable for inclusion in the PciCapLib
>     *class*; a more abstract interface is needed for identifying the PCI
>     device to the library, for parsing of capabilities lists.
> 
> Q2: OK, let's say we can't (and shouldn't) include both notations in the
>     PciCapLib class; can we settle on one of them, rather than
>     PCI_CAP_DEV?
> 
> A2: No, we can't. PciIo is obviously unusable in PEIMs (and in quite a
>     few platform DXE drivers too).
> 
>     It takes a bit longer to explain why the other choice, i.e. adopting
>     the "Segment:Bus:Device.Function" notation for the PciCapLib
>     interface, is not good either. It has to do with the portability of
>     UEFI drivers that bind PciIo protocol instances:
> 
>     It is indeed easy enough to call PciIo->GetLocation() and plug the
>     output values into a theoretical "Segment:Bus:Device.Function"
>     interface. However, about the only two things that could consume
>     such location identifiers and actually *implement* config space
>     access would be:
> 
>     (a) the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Read/Write member
>         functions, where the member functions themselves take the
>         "Bus:Device.Function" part, and the "Segment" part must be used
>         for selecting the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance
>         itself, through the SegmentNumber member;
> 
>     (b) the PciSegmentLib interfaces.
> 
>     Building a PciCapLib instance that uses (a) into a UEFI driver is a
>     bad idea, because there are platforms that provide PciIo instances
>     -- hence the driver can generally run on them -- but don't provide
>     PciRootBridgeIo instances.
> 
>     Building a PciCapLib instance that uses (b) into a UEFI driver is
>     worse. The PciSegmentLib interfaces are not capable of returning
>     errors. For example, if a device appears as PCI Express (implying
>     its extended config space exists, potentially containing extended
>     capabilities), but the underlying platform does not support extended
>     config space access (for example because it only supports
>     0xCF8/0xCFC, and not ECAM), then peeking at the extended config
>     space of the device may invoke undefined behavior within
>     PciSegmentLib, and the PciCapLib instance will be none the wiser.
> 
>     (In fact, for the same reason, even PciCapPciSegmentLib has to
>     extend the "Segment:Bus:Device.Function" notation slightly; so that
>     such issues are caught *before* the call is made to PciSegmentLib.)
> 
> Q3: Wait, I thought it wasn't possible for a PCI Express device to
>     appear on a platform that lacked ECAM.
> 
> A3: Is that a question? :) Yes, it is plenty possible [2]. Same way as
>     garbage / looped config spaces are [3].
> 
> [2] https://github.com/tianocore/edk2/commit/014b472053ae3
> [3] 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=02d578e5edd9
> 
> Cc: Ard Biesheuvel <[email protected]>
> Cc: Jordan Justen <[email protected]>
> Cc: Liming Gao <[email protected]>
> Cc: Michael D Kinney <[email protected]>
> 
> Thanks,
> Laszlo
> 
> Laszlo Ersek (7):
>   MdePkg: introduce PciCapLib
>   MdePkg: introduce PciCapPciSegmentLib
>   MdePkg: introduce PciCapPciIoLib
>   OvmfPkg: resolve PciCapLib, PciCapPciSegmentLib, PciCapPciIoLib
>   ArmVirtPkg: resolve PciCapLib, PciCapPciSegmentLib, PciCapPciIoLib
>   OvmfPkg/PciHotPlugInitDxe: convert to PciCapLib
>   OvmfPkg/Virtio10Dxe: convert to PciCapLib
> 
>  ArmVirtPkg/ArmVirt.dsc.inc                                         |    3 +
>  MdePkg/Include/Library/PciCapLib.h                                 |  429 
> +++++++++
>  MdePkg/Include/Library/PciCapPciIoLib.h                            |   58 ++
>  MdePkg/Include/Library/PciCapPciSegmentLib.h                       |   82 ++
>  MdePkg/Library/BasePciCapLib/BasePciCapLib.c                       | 1007 
> ++++++++++++++++++++
>  MdePkg/Library/BasePciCapLib/BasePciCapLib.h                       |   60 ++
>  MdePkg/Library/BasePciCapLib/BasePciCapLib.inf                     |   37 +
>  MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.c   |  226 
> +++++
>  MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.h   |   47 +
>  MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf |   34 +
>  MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.c             |  243 
> +++++
>  MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.h             |   44 +
>  MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf           |   35 +
>  MdePkg/MdePkg.dec                                                  |   14 +
>  MdePkg/MdePkg.dsc                                                  |    3 +
>  OvmfPkg/Include/IndustryStandard/Virtio10.h                        |    7 +-
>  OvmfPkg/OvmfPkgIa32.dsc                                            |    3 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                                         |    3 +
>  OvmfPkg/OvmfPkgX64.dsc                                             |    3 +
>  OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.c                         |  267 
> ++----
>  OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf                       |    5 +
>  OvmfPkg/Virtio10Dxe/Virtio10.c                                     |  135 +--
>  OvmfPkg/Virtio10Dxe/Virtio10.inf                                   |    2 +
>  23 files changed, 2485 insertions(+), 262 deletions(-)
>  create mode 100644 MdePkg/Include/Library/PciCapLib.h
>  create mode 100644 MdePkg/Include/Library/PciCapPciIoLib.h
>  create mode 100644 MdePkg/Include/Library/PciCapPciSegmentLib.h
>  create mode 100644 MdePkg/Library/BasePciCapLib/BasePciCapLib.c
>  create mode 100644 MdePkg/Library/BasePciCapLib/BasePciCapLib.h
>  create mode 100644 MdePkg/Library/BasePciCapLib/BasePciCapLib.inf
>  create mode 100644 
> MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.c
>  create mode 100644 
> MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.h
>  create mode 100644 
> MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf
>  create mode 100644 MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.c
>  create mode 100644 MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.h
>  create mode 100644 MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf
> 

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to