mirror of https://github.com/acidanthera/audk.git
OvmfPkg/PciHotPlugInitDxe: convert to PciCapLib
Replace the manual capability list parsing in OvmfPkg/PciHotPlugInitDxe with PciCapLib and PciCapPciSegmentLib API calls. 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>
This commit is contained in:
parent
65cefddcde
commit
3815101ff8
OvmfPkg/PciHotPlugInitDxe
|
@ -14,6 +14,7 @@
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <IndustryStandard/Acpi10.h>
|
#include <IndustryStandard/Acpi10.h>
|
||||||
|
#include <IndustryStandard/Q35MchIch9.h>
|
||||||
#include <IndustryStandard/QemuPciBridgeCapabilities.h>
|
#include <IndustryStandard/QemuPciBridgeCapabilities.h>
|
||||||
|
|
||||||
#include <Library/BaseLib.h>
|
#include <Library/BaseLib.h>
|
||||||
|
@ -21,12 +22,20 @@
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/DevicePathLib.h>
|
#include <Library/DevicePathLib.h>
|
||||||
#include <Library/MemoryAllocationLib.h>
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/PciCapLib.h>
|
||||||
|
#include <Library/PciCapPciSegmentLib.h>
|
||||||
#include <Library/PciLib.h>
|
#include <Library/PciLib.h>
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
|
||||||
#include <Protocol/PciHotPlugInit.h>
|
#include <Protocol/PciHotPlugInit.h>
|
||||||
#include <Protocol/PciRootBridgeIo.h>
|
#include <Protocol/PciRootBridgeIo.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// TRUE if the PCI platform supports extended config space, FALSE otherwise.
|
||||||
|
//
|
||||||
|
STATIC BOOLEAN mPciExtConfSpaceSupported;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// The protocol interface this driver produces.
|
// The protocol interface this driver produces.
|
||||||
//
|
//
|
||||||
|
@ -248,91 +257,11 @@ HighBitSetRoundUp64 (
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Read a slice from conventional PCI config space at the given offset, then
|
|
||||||
advance the offset.
|
|
||||||
|
|
||||||
@param[in] PciAddress The address of the PCI Device -- Bus, Device, Function
|
|
||||||
-- in UEFI (not PciLib) encoding.
|
|
||||||
|
|
||||||
@param[in,out] Offset On input, the offset in conventional PCI config space
|
|
||||||
to start reading from. On output, the offset of the
|
|
||||||
first byte that was not read.
|
|
||||||
|
|
||||||
@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.
|
|
||||||
**/
|
|
||||||
STATIC
|
|
||||||
VOID
|
|
||||||
ReadConfigSpace (
|
|
||||||
IN CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciAddress,
|
|
||||||
IN OUT UINT8 *Offset,
|
|
||||||
IN UINT8 Size,
|
|
||||||
OUT VOID *Buffer
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PciReadBuffer (
|
|
||||||
PCI_LIB_ADDRESS (
|
|
||||||
PciAddress->Bus,
|
|
||||||
PciAddress->Device,
|
|
||||||
PciAddress->Function,
|
|
||||||
*Offset
|
|
||||||
),
|
|
||||||
Size,
|
|
||||||
Buffer
|
|
||||||
);
|
|
||||||
*Offset += Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Convenience wrapper macro for ReadConfigSpace().
|
|
||||||
|
|
||||||
Given the following conditions:
|
|
||||||
|
|
||||||
- HeaderField is the first field in the structure pointed-to by Struct,
|
|
||||||
|
|
||||||
- Struct->HeaderField has been populated from the conventional PCI config
|
|
||||||
space of the PCI device identified by PciAddress,
|
|
||||||
|
|
||||||
- *Offset points one past HeaderField in the conventional PCI config space of
|
|
||||||
the PCI device identified by PciAddress,
|
|
||||||
|
|
||||||
populate the rest of *Struct from conventional PCI config space, starting at
|
|
||||||
*Offset. Finally, increment *Offset so that it point one past *Struct.
|
|
||||||
|
|
||||||
@param[in] PciAddress The address of the PCI Device -- Bus, Device, Function
|
|
||||||
-- in UEFI (not PciLib) encoding. Type: pointer to
|
|
||||||
CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
|
|
||||||
|
|
||||||
@param[in,out] Offset On input, the offset in conventional PCI config space
|
|
||||||
to start reading from; one past Struct->HeaderField.
|
|
||||||
On output, the offset of the first byte that was not
|
|
||||||
read; one past *Struct. Type: pointer to UINT8.
|
|
||||||
|
|
||||||
@param[out] Struct The structure to complete. Type: pointer to structure
|
|
||||||
object.
|
|
||||||
|
|
||||||
@param[in] HeaderField The name of the first field in *Struct, after which
|
|
||||||
*Struct should be populated. Type: structure member
|
|
||||||
identifier.
|
|
||||||
**/
|
|
||||||
#define COMPLETE_CONFIG_SPACE_STRUCT(PciAddress, Offset, Struct, HeaderField) \
|
|
||||||
ReadConfigSpace ( \
|
|
||||||
(PciAddress), \
|
|
||||||
(Offset), \
|
|
||||||
(UINT8)(sizeof *(Struct) - sizeof ((Struct)->HeaderField)), \
|
|
||||||
&((Struct)->HeaderField) + 1 \
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Look up the QEMU-specific Resource Reservation capability in the conventional
|
Look up the QEMU-specific Resource Reservation capability in the conventional
|
||||||
config space of a Hotplug Controller (that is, PCI Bridge).
|
config space of a Hotplug Controller (that is, PCI Bridge).
|
||||||
|
|
||||||
This function performs as few config space reads as possible.
|
On error, the contents of ReservationHint are indeterminate.
|
||||||
|
|
||||||
@param[in] HpcPciAddress The address of the PCI Bridge -- Bus, Device,
|
@param[in] HpcPciAddress The address of the PCI Bridge -- Bus, Device,
|
||||||
Function -- in UEFI (not PciLib) encoding.
|
Function -- in UEFI (not PciLib) encoding.
|
||||||
|
@ -343,8 +272,9 @@ ReadConfigSpace (
|
||||||
@retval EFI_SUCCESS The capability has been found, ReservationHint has
|
@retval EFI_SUCCESS The capability has been found, ReservationHint has
|
||||||
been populated.
|
been populated.
|
||||||
|
|
||||||
@retval EFI_NOT_FOUND The capability is missing. The contents of
|
@retval EFI_NOT_FOUND The capability is missing.
|
||||||
ReservationHint are now indeterminate.
|
|
||||||
|
@return Error codes from PciCapPciSegmentLib and PciCapLib.
|
||||||
**/
|
**/
|
||||||
STATIC
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -353,10 +283,12 @@ QueryReservationHint (
|
||||||
OUT QEMU_PCI_BRIDGE_CAPABILITY_RESOURCE_RESERVATION *ReservationHint
|
OUT QEMU_PCI_BRIDGE_CAPABILITY_RESOURCE_RESERVATION *ReservationHint
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT16 PciVendorId;
|
UINT16 PciVendorId;
|
||||||
UINT16 PciStatus;
|
EFI_STATUS Status;
|
||||||
UINT8 PciCapPtr;
|
PCI_CAP_DEV *PciDevice;
|
||||||
UINT8 Offset;
|
PCI_CAP_LIST *CapList;
|
||||||
|
UINT16 VendorInstance;
|
||||||
|
PCI_CAP *VendorCap;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the vendor identifier.
|
// Check the vendor identifier.
|
||||||
|
@ -374,108 +306,101 @@ QueryReservationHint (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the Capabilities List bit in the PCI Status Register.
|
// Parse the capabilities lists.
|
||||||
//
|
//
|
||||||
PciStatus = PciRead16 (
|
Status = PciCapPciSegmentDeviceInit (
|
||||||
PCI_LIB_ADDRESS (
|
mPciExtConfSpaceSupported ? PciCapExtended : PciCapNormal,
|
||||||
HpcPciAddress->Bus,
|
0, // Segment
|
||||||
HpcPciAddress->Device,
|
HpcPciAddress->Bus,
|
||||||
HpcPciAddress->Function,
|
HpcPciAddress->Device,
|
||||||
PCI_PRIMARY_STATUS_OFFSET
|
HpcPciAddress->Function,
|
||||||
)
|
&PciDevice
|
||||||
);
|
);
|
||||||
if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
|
if (EFI_ERROR (Status)) {
|
||||||
return EFI_NOT_FOUND;
|
return Status;
|
||||||
|
}
|
||||||
|
Status = PciCapListInit (PciDevice, &CapList);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto UninitPciDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fetch the start of the Capabilities List.
|
// Scan the vendor capability instances for the Resource Reservation
|
||||||
|
// capability.
|
||||||
//
|
//
|
||||||
PciCapPtr = PciRead8 (
|
VendorInstance = 0;
|
||||||
PCI_LIB_ADDRESS (
|
for (;;) {
|
||||||
HpcPciAddress->Bus,
|
UINT8 VendorLength;
|
||||||
HpcPciAddress->Device,
|
UINT8 BridgeCapType;
|
||||||
HpcPciAddress->Function,
|
|
||||||
PCI_CAPBILITY_POINTER_OFFSET
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
Status = PciCapListFindCap (
|
||||||
// Scan the Capabilities List until we find the terminator element, or the
|
CapList,
|
||||||
// Resource Reservation capability.
|
PciCapNormal,
|
||||||
//
|
EFI_PCI_CAPABILITY_ID_VENDOR,
|
||||||
for (Offset = PciCapPtr & 0xFC;
|
VendorInstance++,
|
||||||
Offset > 0;
|
&VendorCap
|
||||||
Offset = ReservationHint->BridgeHdr.VendorHdr.Hdr.NextItemPtr & 0xFC) {
|
);
|
||||||
BOOLEAN EnoughRoom;
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto UninitCapList;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the Resource Reservation capability would fit into config space
|
// Check the vendor capability length.
|
||||||
// at this offset.
|
|
||||||
//
|
//
|
||||||
EnoughRoom = (BOOLEAN)(
|
Status = PciCapRead (
|
||||||
Offset <= PCI_MAX_CONFIG_OFFSET - sizeof *ReservationHint
|
PciDevice,
|
||||||
);
|
VendorCap,
|
||||||
|
OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length),
|
||||||
//
|
&VendorLength,
|
||||||
// Read the standard capability header so we can check the capability ID
|
sizeof VendorLength
|
||||||
// (if necessary) and advance to the next capability.
|
);
|
||||||
//
|
if (EFI_ERROR (Status)) {
|
||||||
ReadConfigSpace (
|
goto UninitCapList;
|
||||||
HpcPciAddress,
|
}
|
||||||
&Offset,
|
if (VendorLength != sizeof *ReservationHint) {
|
||||||
(UINT8)sizeof ReservationHint->BridgeHdr.VendorHdr.Hdr,
|
|
||||||
&ReservationHint->BridgeHdr.VendorHdr.Hdr
|
|
||||||
);
|
|
||||||
if (!EnoughRoom ||
|
|
||||||
(ReservationHint->BridgeHdr.VendorHdr.Hdr.CapabilityID !=
|
|
||||||
EFI_PCI_CAPABILITY_ID_VENDOR)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Read the rest of the vendor capability header so we can check the
|
// Check the vendor bridge capability type.
|
||||||
// capability length.
|
|
||||||
//
|
//
|
||||||
COMPLETE_CONFIG_SPACE_STRUCT (
|
Status = PciCapRead (
|
||||||
HpcPciAddress,
|
PciDevice,
|
||||||
&Offset,
|
VendorCap,
|
||||||
&ReservationHint->BridgeHdr.VendorHdr,
|
OFFSET_OF (QEMU_PCI_BRIDGE_CAPABILITY_HDR, Type),
|
||||||
Hdr
|
&BridgeCapType,
|
||||||
);
|
sizeof BridgeCapType
|
||||||
if (ReservationHint->BridgeHdr.VendorHdr.Length !=
|
);
|
||||||
sizeof *ReservationHint) {
|
if (EFI_ERROR (Status)) {
|
||||||
continue;
|
goto UninitCapList;
|
||||||
}
|
}
|
||||||
|
if (BridgeCapType ==
|
||||||
//
|
|
||||||
// Read the rest of the QEMU bridge capability header so we can check the
|
|
||||||
// capability type.
|
|
||||||
//
|
|
||||||
COMPLETE_CONFIG_SPACE_STRUCT (
|
|
||||||
HpcPciAddress,
|
|
||||||
&Offset,
|
|
||||||
&ReservationHint->BridgeHdr,
|
|
||||||
VendorHdr
|
|
||||||
);
|
|
||||||
if (ReservationHint->BridgeHdr.Type !=
|
|
||||||
QEMU_PCI_BRIDGE_CAPABILITY_TYPE_RESOURCE_RESERVATION) {
|
QEMU_PCI_BRIDGE_CAPABILITY_TYPE_RESOURCE_RESERVATION) {
|
||||||
continue;
|
//
|
||||||
|
// We have a match.
|
||||||
|
//
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Read the body of the reservation hint.
|
|
||||||
//
|
|
||||||
COMPLETE_CONFIG_SPACE_STRUCT (
|
|
||||||
HpcPciAddress,
|
|
||||||
&Offset,
|
|
||||||
ReservationHint,
|
|
||||||
BridgeHdr
|
|
||||||
);
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EFI_NOT_FOUND;
|
//
|
||||||
|
// Populate ReservationHint.
|
||||||
|
//
|
||||||
|
Status = PciCapRead (
|
||||||
|
PciDevice,
|
||||||
|
VendorCap,
|
||||||
|
0, // SourceOffsetInCap
|
||||||
|
ReservationHint,
|
||||||
|
sizeof *ReservationHint
|
||||||
|
);
|
||||||
|
|
||||||
|
UninitCapList:
|
||||||
|
PciCapListUninit (CapList);
|
||||||
|
|
||||||
|
UninitPciDevice:
|
||||||
|
PciCapPciSegmentDeviceUninit (PciDevice);
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -870,6 +795,8 @@ DriverInitialize (
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
mPciExtConfSpaceSupported = (PcdGet16 (PcdOvmfHostBridgePciDevId) ==
|
||||||
|
INTEL_Q35_MCH_DEVICE_ID);
|
||||||
mPciHotPlugInit.GetRootHpcList = GetRootHpcList;
|
mPciHotPlugInit.GetRootHpcList = GetRootHpcList;
|
||||||
mPciHotPlugInit.InitializeRootHpc = InitializeRootHpc;
|
mPciHotPlugInit.InitializeRootHpc = InitializeRootHpc;
|
||||||
mPciHotPlugInit.GetResourcePadding = GetResourcePadding;
|
mPciHotPlugInit.GetResourcePadding = GetResourcePadding;
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
DebugLib
|
DebugLib
|
||||||
DevicePathLib
|
DevicePathLib
|
||||||
MemoryAllocationLib
|
MemoryAllocationLib
|
||||||
|
PciCapLib
|
||||||
|
PciCapPciSegmentLib
|
||||||
PciLib
|
PciLib
|
||||||
UefiBootServicesTableLib
|
UefiBootServicesTableLib
|
||||||
UefiDriverEntryPoint
|
UefiDriverEntryPoint
|
||||||
|
@ -42,5 +44,8 @@
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiPciHotPlugInitProtocolGuid ## ALWAYS_PRODUCES
|
gEfiPciHotPlugInitProtocolGuid ## ALWAYS_PRODUCES
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId ## CONSUMES
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
TRUE
|
TRUE
|
||||||
|
|
Loading…
Reference in New Issue