mirror of https://github.com/acidanthera/audk.git
1403 lines
36 KiB
C
1403 lines
36 KiB
C
/** @file
|
|
Update the _PRT and _PRW method for pci devices
|
|
|
|
Copyright (c) 2013-2016 Intel Corporation.
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
|
|
**/
|
|
#include "AcpiPlatform.h"
|
|
|
|
PCI_DEVICE_INFO *mQNCPciInfo = NULL;
|
|
|
|
/**
|
|
Init Pci Device Structure
|
|
@param mConfigData - Pointer of Pci Device information Structure
|
|
|
|
**/
|
|
VOID
|
|
InitPciDeviceInfoStructure (
|
|
PCI_DEVICE_SETTING *mConfigData
|
|
)
|
|
{
|
|
//
|
|
// Return 0 given that function unsupported.
|
|
// Would need to parse ACPI tables and build mQNCPciInfo above
|
|
// with found _PRT & _PRW methods for PCI devices.
|
|
//
|
|
mConfigData->PciDeviceInfoNumber = 0;
|
|
}
|
|
|
|
/**
|
|
return Integer value.
|
|
|
|
@param Data - AML data buffer
|
|
@param Integer - integer value.
|
|
|
|
@return Data size processed.
|
|
**/
|
|
UINTN
|
|
SdtGetInteger (
|
|
IN UINT8 *Data,
|
|
OUT UINT64 *Integer
|
|
)
|
|
{
|
|
*Integer = 0;
|
|
switch (*Data) {
|
|
case AML_ZERO_OP:
|
|
return 1;
|
|
case AML_ONE_OP:
|
|
*Integer = 1;
|
|
return 1;
|
|
case AML_ONES_OP:
|
|
*Integer = (UINTN)-1;
|
|
return 1;
|
|
case AML_BYTE_PREFIX:
|
|
CopyMem (Integer, Data + 1, sizeof(UINT8));
|
|
return 1 + sizeof(UINT8);
|
|
case AML_WORD_PREFIX:
|
|
CopyMem (Integer, Data + 1, sizeof(UINT16));
|
|
return 1 + sizeof(UINT16);
|
|
case AML_DWORD_PREFIX:
|
|
CopyMem (Integer, Data + 1, sizeof(UINT32));
|
|
return 1 + sizeof(UINT32);
|
|
case AML_QWORD_PREFIX:
|
|
CopyMem (Integer, Data + 1, sizeof(UINT64));
|
|
return 1 + sizeof(UINT64);
|
|
default:
|
|
// Something wrong
|
|
ASSERT (FALSE);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Check if this handle has expected opcode.
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param Handle ACPI handle
|
|
@param OpCode Expected OpCode
|
|
@param SubOpCode Expected SubOpCode
|
|
|
|
@retval TRUE This handle has expected opcode
|
|
@retval FALSE This handle does not have expected opcode
|
|
**/
|
|
BOOLEAN
|
|
SdtIsThisTypeObject (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE Handle,
|
|
IN UINT8 OpCode,
|
|
IN UINT8 SubOpCode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
|
|
Status = AcpiSdt->GetOption (Handle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
|
|
if (OpCode == AML_EXT_OP) {
|
|
if (Data[1] == SubOpCode) {
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
if (Data[0] == OpCode) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check if this handle has expected name and name value.
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param Handle ACPI handle
|
|
@param Name Expected name
|
|
@param Value Expected name value
|
|
|
|
@retval TRUE This handle has expected name and name value.
|
|
@retval FALSE This handle does not have expected name and name value.
|
|
**/
|
|
BOOLEAN
|
|
SdtIsNameIntegerValueEqual (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE Handle,
|
|
IN CHAR8 *Name,
|
|
IN UINT64 Value
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
UINT64 Integer;
|
|
|
|
Status = AcpiSdt->GetOption (Handle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
|
|
|
|
if (CompareMem (Data, Name, 4) != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Name match check object
|
|
//
|
|
Status = AcpiSdt->GetOption (Handle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Integer = 0;
|
|
SdtGetInteger (Data, &Integer);
|
|
if (Integer != Value) {
|
|
return FALSE;
|
|
}
|
|
|
|
// All match
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Check if this handle's children has expected name and name value.
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param ParentHandle ACPI parent handle
|
|
@param Name Expected name
|
|
@param Value Expected name value
|
|
|
|
@retval TRUE This handle's children has expected name and name value.
|
|
@retval FALSE This handle's children does not have expected name and name value.
|
|
**/
|
|
BOOLEAN
|
|
SdtCheckNameIntegerValue (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE ParentHandle,
|
|
IN CHAR8 *Name,
|
|
IN UINT64 Value
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PreviousHandle;
|
|
EFI_ACPI_HANDLE Handle;
|
|
EFI_STATUS Status;
|
|
|
|
Handle = NULL;
|
|
while (TRUE) {
|
|
PreviousHandle = Handle;
|
|
Status = AcpiSdt->GetChild (ParentHandle, &Handle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (PreviousHandle != NULL) {
|
|
Status = AcpiSdt->Close (PreviousHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
if (Handle == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check this name
|
|
//
|
|
if (SdtIsThisTypeObject (AcpiSdt, Handle, AML_NAME_OP, 0)) {
|
|
if (SdtIsNameIntegerValueEqual (AcpiSdt, Handle, Name, Value)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Should not run here
|
|
//
|
|
}
|
|
|
|
/**
|
|
Convert the pci address from VPD (bus,dev,fun) into the address that acpi table
|
|
can recognize.
|
|
|
|
@param PciAddress Pci address from VPD
|
|
|
|
@retval return the address that acpi table can recognize
|
|
**/
|
|
UINT32
|
|
SdtConvertToAcpiPciAdress (
|
|
IN UINT32 PciAddress
|
|
)
|
|
{
|
|
UINT32 ReturnAddress;
|
|
|
|
ReturnAddress = ((PciAddress & 0x0000FF00) << 8) | (PciAddress & 0x000000FF);
|
|
|
|
if ((PciAddress & 0x000000FF) == 0x000000FF)
|
|
ReturnAddress |= 0x0000FFFF;
|
|
|
|
return ReturnAddress;
|
|
}
|
|
|
|
/**
|
|
return AML NameString size.
|
|
|
|
@param Buffer - AML name string
|
|
|
|
@return AML name string size
|
|
**/
|
|
UINTN
|
|
SdtGetNameStringSize (
|
|
IN UINT8 *Buffer
|
|
)
|
|
{
|
|
UINTN SegCount;
|
|
UINTN Length;
|
|
|
|
Length = 0;
|
|
|
|
//
|
|
// Parse root or prefix
|
|
//
|
|
if (*Buffer == AML_ROOT_CHAR) {
|
|
//
|
|
// RootChar
|
|
//
|
|
Buffer ++;
|
|
Length ++;
|
|
} else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
|
|
//
|
|
// ParentPrefixChar
|
|
//
|
|
Buffer ++;
|
|
Length ++;
|
|
while (*Buffer == AML_PARENT_PREFIX_CHAR) {
|
|
Buffer ++;
|
|
Length ++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Parse name segment
|
|
//
|
|
if (*Buffer == AML_DUAL_NAME_PREFIX) {
|
|
//
|
|
// DualName
|
|
//
|
|
Buffer ++;
|
|
Length ++;
|
|
SegCount = 2;
|
|
} else if (*Buffer == AML_MULTI_NAME_PREFIX) {
|
|
//
|
|
// MultiName
|
|
//
|
|
Buffer ++;
|
|
Length ++;
|
|
SegCount = *Buffer;
|
|
Buffer ++;
|
|
Length ++;
|
|
} else if (*Buffer == 0) {
|
|
//
|
|
// NULL Name
|
|
//
|
|
SegCount = 0;
|
|
Length ++;
|
|
} else {
|
|
//
|
|
// NameSeg
|
|
//
|
|
SegCount = 1;
|
|
}
|
|
|
|
Buffer += 4 * SegCount;
|
|
Length += 4 * SegCount;
|
|
|
|
return Length;
|
|
}
|
|
|
|
/**
|
|
The routine to check if this device is PCI root bridge.
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param DeviceHandle ACPI device handle
|
|
@param Context Context info - not used here
|
|
|
|
@retval TRUE This is PCI root bridge
|
|
@retval FALSE This is not PCI root bridge
|
|
**/
|
|
BOOLEAN
|
|
SdtFindRootBridgeHandle (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE CheckHandle,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
BOOLEAN Result;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
EFI_STATUS Status;
|
|
|
|
if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
|
|
return FALSE;
|
|
|
|
Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_HID", (UINT64)0x080AD041); // PNP0A08
|
|
if (!Result) {
|
|
Result = SdtCheckNameIntegerValue (AcpiSdt, CheckHandle, "_CID", (UINT64)0x030AD041); // PNP0A03
|
|
if (!Result) {
|
|
return Result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Found
|
|
//
|
|
Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
/**
|
|
The routine to check if this device is wanted.
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param DeviceHandle ACPI device handle
|
|
@param Context Context info - not used here
|
|
|
|
@retval TRUE This is PCI device wanted
|
|
@retval FALSE This is not PCI device wanted
|
|
**/
|
|
BOOLEAN
|
|
SdtFindPciDeviceHandle (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE CheckHandle,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
BOOLEAN Result;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
EFI_STATUS Status;
|
|
|
|
if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
|
|
return FALSE;
|
|
|
|
Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_ADR", (UINT64)*(UINT32 *)Context);
|
|
if (!Result) {
|
|
return Result;
|
|
}
|
|
|
|
//
|
|
// Found
|
|
//
|
|
Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
|
|
|
|
return Result;
|
|
}
|
|
|
|
/**
|
|
Go through the parent handle and find the handle which pass CheckHandleInfo.
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param ParentHandle ACPI parent handle
|
|
@param CheckHandleInfo The callback routine to check if this handle meet the requirement
|
|
@param Context The context of CheckHandleInfo
|
|
|
|
@return the handle which is first one can pass CheckHandleInfo.
|
|
**/
|
|
EFI_ACPI_HANDLE
|
|
SdtGetHandleByScanAllChilds (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE ParentHandle,
|
|
IN CHECK_HANDLE_INFO CheckHandleInfo,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PreviousHandle;
|
|
EFI_ACPI_HANDLE Handle;
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE ReturnHandle;
|
|
|
|
//
|
|
// Use deep first algo to enumerate all ACPI object
|
|
//
|
|
Handle = NULL;
|
|
while (TRUE) {
|
|
PreviousHandle = Handle;
|
|
Status = AcpiSdt->GetChild (ParentHandle, &Handle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (PreviousHandle != NULL) {
|
|
Status = AcpiSdt->Close (PreviousHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
if (Handle == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Check this handle
|
|
//
|
|
if (CheckHandleInfo (AcpiSdt, Handle, Context)) {
|
|
return Handle;
|
|
}
|
|
|
|
//
|
|
// Enumerate
|
|
//
|
|
ReturnHandle = SdtGetHandleByScanAllChilds (AcpiSdt, Handle, CheckHandleInfo, Context);
|
|
if (ReturnHandle != NULL) {
|
|
return ReturnHandle;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Should not run here
|
|
//
|
|
}
|
|
|
|
|
|
/**
|
|
Check whether the INTx package is matched
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param INTxPkgHandle ACPI INTx package handle
|
|
@param PciAddress Acpi pci address
|
|
@param INTx Index of INTx pin
|
|
@param IsAPIC Tell whether the returned INTx package is for APIC or not
|
|
|
|
@retval TRUE the INTx package is matched
|
|
@retval FALSE the INTx package is not matched
|
|
|
|
**/
|
|
BOOLEAN
|
|
SdtCheckINTxPkgIsMatch (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE INTxPkgHandle,
|
|
IN UINT32 PciAddress,
|
|
IN UINT8 INTx,
|
|
IN BOOLEAN *IsAPIC
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PreviousHandle;
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE MemberHandle;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
UINT64 CurrentPciAddress;
|
|
UINT64 CurrentINTx;
|
|
UINTN ChildSize;
|
|
|
|
|
|
//
|
|
// Check the pci address
|
|
//
|
|
MemberHandle = NULL;
|
|
Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (MemberHandle != NULL);
|
|
|
|
Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
|
|
CurrentPciAddress = 0;
|
|
SdtGetInteger (Data, &CurrentPciAddress);
|
|
|
|
if (CurrentPciAddress != PciAddress) {
|
|
|
|
Status = AcpiSdt->Close (MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check the pci interrupt pin
|
|
//
|
|
PreviousHandle = MemberHandle;
|
|
Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (MemberHandle != NULL);
|
|
|
|
if (PreviousHandle != NULL) {
|
|
Status = AcpiSdt->Close (PreviousHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
|
|
CurrentINTx = 0;
|
|
ChildSize = SdtGetInteger (Data, &CurrentINTx);
|
|
|
|
Status = AcpiSdt->Close (MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (CurrentINTx != INTx)
|
|
return FALSE;
|
|
|
|
Data += ChildSize;
|
|
|
|
if (*Data == AML_BYTE_PREFIX)
|
|
Data += 1;
|
|
|
|
//
|
|
// Check the pci interrupt source
|
|
//
|
|
if (*Data != 0)
|
|
*IsAPIC = FALSE;
|
|
else
|
|
*IsAPIC = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
Get the wanted INTx package inside the parent package
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param ParentPkgHandle ACPI parent package handle
|
|
@param PciAddress Acpi pci address
|
|
@param INTx Index of INTx pin
|
|
@param INTxPkgHandle ACPI INTx package handle
|
|
@param IsAPIC Tell whether the returned INTx package is for APIC or not
|
|
|
|
**/
|
|
VOID
|
|
SdtGetINTxPkgHandle (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE ParentPkgHandle,
|
|
IN UINT32 PciAddress,
|
|
IN UINT8 INTx,
|
|
IN EFI_ACPI_HANDLE *INTxPkgHandle,
|
|
IN BOOLEAN *IsAPIC
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PreviousHandle;
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE ChildPkgHandle;
|
|
|
|
ChildPkgHandle = NULL;
|
|
while (TRUE) {
|
|
PreviousHandle = ChildPkgHandle;
|
|
Status = AcpiSdt->GetChild (ParentPkgHandle, &ChildPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (PreviousHandle != NULL) {
|
|
Status = AcpiSdt->Close (PreviousHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (ChildPkgHandle == NULL) {
|
|
break;
|
|
}
|
|
|
|
if (SdtCheckINTxPkgIsMatch(AcpiSdt, ChildPkgHandle, PciAddress, INTx, IsAPIC)) {
|
|
*INTxPkgHandle = ChildPkgHandle;
|
|
return;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Update the INTx package with the correct pirq value
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param INTxPkgHandle ACPI INTx package handle
|
|
@param PirqValue Correct pirq value
|
|
@param IsAPIC Tell whether the INTx package is for APIC or not
|
|
|
|
**/
|
|
VOID
|
|
SdtUpdateINTxPkg (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE INTxPkgHandle,
|
|
IN UINT8 PirqValue,
|
|
IN BOOLEAN IsAPIC
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PreviousHandle;
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE MemberHandle;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
UINT64 TempValue;
|
|
UINTN ChildSize;
|
|
|
|
|
|
//
|
|
// Check the pci address
|
|
//
|
|
MemberHandle = NULL;
|
|
Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (MemberHandle != NULL);
|
|
|
|
//
|
|
// Check the pci interrupt pin
|
|
//
|
|
PreviousHandle = MemberHandle;
|
|
Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (MemberHandle != NULL);
|
|
|
|
if (PreviousHandle != NULL) {
|
|
Status = AcpiSdt->Close (PreviousHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
|
|
ChildSize = SdtGetInteger (Data, &TempValue);
|
|
|
|
Status = AcpiSdt->Close (MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Data += ChildSize;
|
|
|
|
//
|
|
// update the pci interrupt source or source index
|
|
//
|
|
if (!IsAPIC) {
|
|
ChildSize = SdtGetNameStringSize (Data);
|
|
Data += (ChildSize - 1);
|
|
|
|
PirqValue += 0x40; // change to ascii char
|
|
if (*Data != PirqValue)
|
|
*Data = PirqValue;
|
|
} else {
|
|
|
|
ChildSize = SdtGetInteger (Data, &TempValue);
|
|
Data += ChildSize;
|
|
|
|
Data += 1;
|
|
|
|
if (*Data != PirqValue)
|
|
*Data = PirqValue;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check every child package inside this interested parent package for update PRT
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param ParentPkgHandle ACPI parent package handle
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
|
|
**/
|
|
VOID
|
|
SdtCheckParentPackage (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE ParentPkgHandle,
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE INTAPkgHandle;
|
|
EFI_ACPI_HANDLE INTBPkgHandle;
|
|
EFI_ACPI_HANDLE INTCPkgHandle;
|
|
EFI_ACPI_HANDLE INTDPkgHandle;
|
|
UINT32 PciAddress = 0;
|
|
BOOLEAN IsAllFunctions = FALSE;
|
|
UINT8 IsAPIC = 0;
|
|
EFI_STATUS Status;
|
|
|
|
INTAPkgHandle = INTBPkgHandle = INTCPkgHandle = INTDPkgHandle = NULL;
|
|
|
|
PciAddress = SdtConvertToAcpiPciAdress(PciDeviceInfo->DeviceAddress);
|
|
|
|
if ((PciAddress & 0xFFFF) == 0xFFFF) {
|
|
IsAllFunctions = TRUE;
|
|
} else {
|
|
IsAllFunctions = FALSE;
|
|
PciAddress = (PciAddress | 0xFFFF);
|
|
}
|
|
|
|
SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 0, &INTAPkgHandle, (BOOLEAN *)&IsAPIC);
|
|
SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 1, &INTBPkgHandle, (BOOLEAN *)&IsAPIC);
|
|
SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 2, &INTCPkgHandle, (BOOLEAN *)&IsAPIC);
|
|
SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 3, &INTDPkgHandle, (BOOLEAN *)&IsAPIC);
|
|
|
|
//
|
|
// Check INTA
|
|
//
|
|
if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle != NULL)) {
|
|
//
|
|
// Find INTA package and there is valid INTA update item, update it
|
|
//
|
|
SdtUpdateINTxPkg (AcpiSdt, INTAPkgHandle, (PciDeviceInfo->INTA[IsAPIC]), IsAPIC);
|
|
} else if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle == NULL)) {
|
|
//
|
|
// There is valid INTA update item, but no INA package exist, should add it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould add INTA item for this device(0x%x)\n\n", PciAddress));
|
|
|
|
} else if ((PciDeviceInfo->INTA[IsAPIC] == 0xFF) && (INTAPkgHandle != NULL) && IsAllFunctions) {
|
|
//
|
|
// For all functions senario, if there is invalid INTA update item, but INTA package does exist, should delete it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould remove INTA item for this device(0x%x)\n\n", PciAddress));
|
|
|
|
}
|
|
|
|
//
|
|
// Check INTB
|
|
//
|
|
if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle != NULL)) {
|
|
//
|
|
// Find INTB package and there is valid INTB update item, update it
|
|
//
|
|
SdtUpdateINTxPkg (AcpiSdt, INTBPkgHandle, (PciDeviceInfo->INTB[IsAPIC]), IsAPIC);
|
|
} else if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle == NULL)) {
|
|
//
|
|
// There is valid INTB update item, but no INTB package exist, should add it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould add INTB item for this device(0x%x)\n\n", PciAddress));
|
|
|
|
} else if ((PciDeviceInfo->INTB[IsAPIC] == 0xFF) && (INTBPkgHandle != NULL) && IsAllFunctions) {
|
|
//
|
|
// For all functions senario, if there is invalid INTB update item, but INTB package does exist, should delete it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould remove INTB item for this device(0x%x)\n\n", PciAddress));
|
|
|
|
}
|
|
|
|
//
|
|
// Check INTC
|
|
//
|
|
if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle != NULL)) {
|
|
//
|
|
// Find INTC package and there is valid INTC update item, update it
|
|
//
|
|
SdtUpdateINTxPkg (AcpiSdt, INTCPkgHandle, (PciDeviceInfo->INTC[IsAPIC]), IsAPIC);
|
|
} else if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle == NULL)) {
|
|
//
|
|
// There is valid INTC update item, but no INTC package exist, should add it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould add INTC item for this device(0x%x)\n\n", PciAddress));
|
|
|
|
} else if ((PciDeviceInfo->INTC[IsAPIC] == 0xFF) && (INTCPkgHandle != NULL) && IsAllFunctions) {
|
|
//
|
|
// For all functions senario, if there is invalid INTC update item, but INTC package does exist, should delete it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould remove INTC item for this device(0x%x)\n\n", PciAddress));
|
|
}
|
|
|
|
//
|
|
// Check INTD
|
|
//
|
|
if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle != NULL)) {
|
|
//
|
|
// Find INTD package and there is valid INTD update item, update it
|
|
//
|
|
SdtUpdateINTxPkg (AcpiSdt, INTDPkgHandle, (PciDeviceInfo->INTD[IsAPIC]), IsAPIC);
|
|
} else if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle == NULL)) {
|
|
//
|
|
// There is valid INTD update item, but no INTD package exist, should add it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould add INTD item for this device(0x%x)\n\n", PciAddress));
|
|
|
|
} else if ((PciDeviceInfo->INTD[IsAPIC] == 0xFF) && (INTDPkgHandle != NULL) && IsAllFunctions) {
|
|
//
|
|
// For all functions senario, if there is invalid INTD update item, but INTD package does exist, should delete it
|
|
//
|
|
DEBUG ((EFI_D_ERROR, "\n\nShould remove INTD item for this device(0x%x)\n\n", PciAddress));
|
|
}
|
|
|
|
|
|
if (INTAPkgHandle != NULL) {
|
|
Status = AcpiSdt->Close (INTAPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (INTBPkgHandle != NULL) {
|
|
Status = AcpiSdt->Close (INTBPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (INTCPkgHandle != NULL) {
|
|
Status = AcpiSdt->Close (INTCPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (INTDPkgHandle != NULL) {
|
|
Status = AcpiSdt->Close (INTDPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Check every return package for update PRT
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param ParentHandle ACPI pci device handle
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
|
|
**/
|
|
VOID
|
|
SdtCheckReturnPackage (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE MethodHandle,
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PreviousHandle;
|
|
EFI_ACPI_HANDLE ReturnHandle;
|
|
EFI_ACPI_HANDLE PackageHandle;
|
|
EFI_ACPI_HANDLE NamePkgHandle;
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
CHAR8 NameStr[128];
|
|
|
|
ReturnHandle = NULL;
|
|
while (TRUE) {
|
|
PreviousHandle = ReturnHandle;
|
|
Status = AcpiSdt->GetChild (MethodHandle, &ReturnHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (PreviousHandle != NULL) {
|
|
Status = AcpiSdt->Close (PreviousHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (ReturnHandle == NULL) {
|
|
break;
|
|
}
|
|
|
|
Status = AcpiSdt->GetOption (ReturnHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
|
|
if (*Data == AML_RETURN_OP) {
|
|
//
|
|
// Find the return method handle, then look for the returned package data
|
|
//
|
|
Status = AcpiSdt->GetOption (ReturnHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) {
|
|
ZeroMem (NameStr, 128);
|
|
AsciiStrCpy (NameStr, "\\_SB.");
|
|
DataSize = SdtGetNameStringSize (Data);
|
|
AsciiStrnCat (NameStr, (CHAR8 *)Data, DataSize);
|
|
|
|
NamePkgHandle = NULL;
|
|
Status = AcpiSdt->FindPath (mDsdtHandle, NameStr, &NamePkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (NamePkgHandle != NULL);
|
|
|
|
Status = AcpiSdt->GetOption (NamePkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
ASSERT (*Data == AML_NAME_OP);
|
|
|
|
Status = AcpiSdt->GetOption (NamePkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
|
|
}
|
|
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
|
|
|
|
//
|
|
// Get the parent package handle
|
|
//
|
|
PackageHandle = NULL;
|
|
Status = AcpiSdt->Open (Data, &PackageHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Check the parent package for update pci routing
|
|
//
|
|
SdtCheckParentPackage (AcpiSdt, PackageHandle, PciDeviceInfo);
|
|
|
|
Status = AcpiSdt->Close (PackageHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = AcpiSdt->Close (ReturnHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Not ReturnOp, search it as parent
|
|
//
|
|
SdtCheckReturnPackage (AcpiSdt, ReturnHandle, PciDeviceInfo);
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
update interrupt info inside the PRT method for the given pci device handle
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param PciHandle ACPI pci device handle
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SdtUpdatePrtMethod (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE PciHandle,
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE PrtMethodHandle;
|
|
|
|
//
|
|
// Find the PRT method under this pci device
|
|
//
|
|
PrtMethodHandle = NULL;
|
|
Status = AcpiSdt->FindPath (PciHandle, "_PRT", &PrtMethodHandle);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (PrtMethodHandle == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
SdtCheckReturnPackage(AcpiSdt, PrtMethodHandle, PciDeviceInfo);
|
|
|
|
Status = AcpiSdt->Close (PrtMethodHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Update the package inside name op with correct wakeup resources
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param InPkgHandle ACPI inside package handle
|
|
@param GPEPin Correct gpe pin
|
|
@param SxNum Correct system state the device can wake up from
|
|
|
|
**/
|
|
VOID
|
|
SdtUpdatePackageInName (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE INTxPkgHandle,
|
|
IN UINT8 GPEPin,
|
|
IN UINT8 SxNum
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PreviousHandle;
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE MemberHandle;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
|
|
//
|
|
// Check the gpe pin
|
|
//
|
|
MemberHandle = NULL;
|
|
Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (MemberHandle != NULL);
|
|
|
|
Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
|
|
//
|
|
// Skip byte prefix
|
|
//
|
|
Data += 1;
|
|
|
|
if (*Data != GPEPin) {
|
|
|
|
*Data = GPEPin;
|
|
}
|
|
|
|
//
|
|
// Check the sx number
|
|
//
|
|
PreviousHandle = MemberHandle;
|
|
Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (MemberHandle != NULL);
|
|
|
|
if (PreviousHandle != NULL) {
|
|
Status = AcpiSdt->Close (PreviousHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
|
|
//
|
|
// Skip byte prefix
|
|
//
|
|
Data += 1;
|
|
|
|
if (*Data != SxNum) {
|
|
|
|
*Data = SxNum;
|
|
}
|
|
|
|
Status = AcpiSdt->Close (MemberHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
}
|
|
|
|
/**
|
|
Check the name package belonged to PRW
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param PrwPkgHandle ACPI PRW package handle
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
|
|
**/
|
|
VOID
|
|
SdtCheckNamePackage (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE PrwPkgHandle,
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE InPkgHandle;
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_DATA_TYPE DataType;
|
|
UINT8 *Data;
|
|
UINTN DataSize;
|
|
|
|
Status = AcpiSdt->GetOption (PrwPkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
|
|
ASSERT (*Data == AML_NAME_OP);
|
|
|
|
Status = AcpiSdt->GetOption (PrwPkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
|
|
|
|
//
|
|
// Get the inside package handle
|
|
//
|
|
InPkgHandle = NULL;
|
|
Status = AcpiSdt->Open (Data, &InPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// update the package in name op for wakeup info
|
|
//
|
|
if ((PciDeviceInfo->GPEPin != 0xFF) && (PciDeviceInfo->SxNum != 0xFF))
|
|
SdtUpdatePackageInName (AcpiSdt, InPkgHandle, PciDeviceInfo->GPEPin, PciDeviceInfo->SxNum);
|
|
|
|
Status = AcpiSdt->Close (InPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
update wakeup info inside the PRW method for the given pci device handle
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param PciHandle ACPI pci device handle
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SdtUpdatePrwPackage (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE PciHandle,
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE PrwPkgHandle;
|
|
|
|
//
|
|
// Find the PRT method under this pci device
|
|
//
|
|
PrwPkgHandle = NULL;
|
|
Status = AcpiSdt->FindPath (PciHandle, "_PRW", &PrwPkgHandle);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (PrwPkgHandle == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
SdtCheckNamePackage(AcpiSdt, PrwPkgHandle, PciDeviceInfo);
|
|
|
|
Status = AcpiSdt->Close (PrwPkgHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
update pci routing information in acpi table based on pcd settings
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param PciRootHandle ACPI root bridge handle
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SdtUpdatePciRouting (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE PciRootHandle,
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE PciBridgeHandle;
|
|
UINT32 PciAddress;
|
|
|
|
|
|
PciBridgeHandle = NULL;
|
|
if (PciDeviceInfo->BridgeAddress == 0x00000000) {
|
|
//
|
|
// Its bridge is the host root bridge
|
|
//
|
|
PciBridgeHandle = PciRootHandle;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Its bridge is just a pci device under the host bridge
|
|
//
|
|
|
|
//
|
|
// Conver the bridge address into one that acpi table can recognize
|
|
//
|
|
PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
|
|
|
|
//
|
|
// Scan the whole table to find the pci device
|
|
//
|
|
PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
|
|
if (PciBridgeHandle == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
Status = SdtUpdatePrtMethod(AcpiSdt, PciBridgeHandle, PciDeviceInfo);
|
|
|
|
if (PciDeviceInfo->BridgeAddress != 0x00000000) {
|
|
Status = AcpiSdt->Close (PciBridgeHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
update power resource wake up information in acpi table based on pcd settings
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param PciRootHandle ACPI root bridge handle
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SdtUpdatePowerWake (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE PciRootHandle,
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_HANDLE PciBridgeHandle;
|
|
EFI_ACPI_HANDLE PciDeviceHandle;
|
|
UINT32 PciAddress;
|
|
|
|
PciBridgeHandle = NULL;
|
|
if (PciDeviceInfo->BridgeAddress == 0x00000000) {
|
|
//
|
|
// Its bridge is the host root bridge
|
|
//
|
|
PciBridgeHandle = PciRootHandle;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Its bridge is just a pci device under the host bridge
|
|
//
|
|
|
|
//
|
|
// Conver the bridge address into one that acpi table can recognize
|
|
//
|
|
PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
|
|
|
|
//
|
|
// Scan the whole table to find the pci device
|
|
//
|
|
PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
|
|
|
|
if (PciBridgeHandle == NULL) {
|
|
|
|
Status = AcpiSdt->Close (PciRootHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
PciDeviceHandle = NULL;
|
|
|
|
//
|
|
// Conver the device address into one that acpi table can recognize
|
|
//
|
|
PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->DeviceAddress);
|
|
|
|
//
|
|
// Scan the whole table to find the pci device
|
|
//
|
|
PciDeviceHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciBridgeHandle, SdtFindPciDeviceHandle, &PciAddress);
|
|
|
|
if (PciDeviceHandle == NULL) {
|
|
if (PciDeviceInfo->BridgeAddress != 0x00000000) {
|
|
Status = AcpiSdt->Close (PciBridgeHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = SdtUpdatePrwPackage(AcpiSdt, PciDeviceHandle, PciDeviceInfo);
|
|
|
|
Status = AcpiSdt->Close (PciDeviceHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (PciDeviceInfo->BridgeAddress != 0x00000000) {
|
|
Status = AcpiSdt->Close (PciBridgeHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Get the root bridge handle by scanning the acpi table
|
|
|
|
@param AcpiSdt Pointer to Acpi SDT protocol
|
|
@param DsdtHandle ACPI root handle
|
|
|
|
@retval EFI_ACPI_HANDLE the handle of the root bridge
|
|
**/
|
|
EFI_ACPI_HANDLE
|
|
SdtGetRootBridgeHandle (
|
|
IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
|
|
IN EFI_ACPI_HANDLE DsdtHandle
|
|
)
|
|
{
|
|
EFI_ACPI_HANDLE PciRootHandle;
|
|
|
|
//
|
|
// Scan the whole table to find the root bridge
|
|
//
|
|
PciRootHandle = NULL;
|
|
PciRootHandle = SdtGetHandleByScanAllChilds(AcpiSdt, DsdtHandle, SdtFindRootBridgeHandle, NULL);
|
|
ASSERT (PciRootHandle != NULL);
|
|
|
|
return PciRootHandle;
|
|
}
|
|
|
|
|
|
/**
|
|
Check input Pci device info is changed from the default values
|
|
@param PciDeviceInfo Pointer to PCI_DEVICE_INFO
|
|
@param UpdatePRT Pointer to BOOLEAN
|
|
@param UpdatePRW Pointer to BOOLEAN
|
|
|
|
**/
|
|
VOID
|
|
SdtCheckPciDeviceInfoChanged (
|
|
IN PCI_DEVICE_INFO *PciDeviceInfo,
|
|
IN BOOLEAN *UpdatePRT,
|
|
IN BOOLEAN *UpdatePRW
|
|
)
|
|
{
|
|
UINTN Index = 0;
|
|
|
|
if (mQNCPciInfo == NULL) {
|
|
*UpdatePRT = FALSE;
|
|
*UpdatePRW = FALSE;
|
|
return;
|
|
}
|
|
|
|
*UpdatePRT = TRUE;
|
|
*UpdatePRW = TRUE;
|
|
|
|
for (Index = 0;Index < CURRENT_PCI_DEVICE_NUM; Index++) {
|
|
if ((mQNCPciInfo[Index].BridgeAddress == PciDeviceInfo->BridgeAddress)
|
|
&& (mQNCPciInfo[Index].DeviceAddress == PciDeviceInfo->DeviceAddress)) {
|
|
//
|
|
// Find one matched entry
|
|
//
|
|
if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 10) == 0) {
|
|
*UpdatePRT = FALSE;
|
|
*UpdatePRW = FALSE;
|
|
//DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and no change\n", Index));
|
|
} else {
|
|
if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 8) == 0)
|
|
*UpdatePRT = FALSE;
|
|
|
|
if (CompareMem (&(mQNCPciInfo[Index].GPEPin), &PciDeviceInfo->GPEPin, 2) == 0)
|
|
*UpdatePRW = FALSE;
|
|
|
|
if (*(UINT64 *)(&PciDeviceInfo->INTA[0]) == 0xFFFFFFFFFFFFFFFFULL)
|
|
*UpdatePRT = FALSE;
|
|
|
|
if (*(UINT16 *)(&PciDeviceInfo->GPEPin) == 0xFFFF)
|
|
*UpdatePRW = FALSE;
|
|
|
|
//DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and but need update PRT:0x%x PRW:0x%x\n", Index, *UpdatePRT, *UpdatePRW));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//if (Index == 42) {
|
|
// DEBUG ((EFI_D_ERROR, "Find No matched entry\n"));
|
|
//}
|
|
|
|
return;
|
|
}
|