| /** @file | |
| Update the _PRT and _PRW method for pci devices | |
| Copyright (c) 2013-2016 Intel Corporation. | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #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; | |
| } |