Home | History | Annotate | Download | only in AcpiPlatform
      1 /** @file
      2 Update the _PRT and _PRW method for pci devices
      3 
      4 Copyright (c) 2013-2016 Intel Corporation.
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 
     15 **/
     16 #include "AcpiPlatform.h"
     17 
     18 PCI_DEVICE_INFO *mQNCPciInfo = NULL;
     19 
     20 /**
     21   Init Pci Device Structure
     22   @param mConfigData    - Pointer of Pci Device information Structure
     23 
     24 **/
     25 VOID
     26 InitPciDeviceInfoStructure (
     27   PCI_DEVICE_SETTING            *mConfigData
     28   )
     29 {
     30   //
     31   // Return 0 given that function unsupported.
     32   // Would need to parse ACPI tables and build mQNCPciInfo above
     33   // with found _PRT & _PRW methods for PCI devices.
     34   //
     35   mConfigData->PciDeviceInfoNumber = 0;
     36 }
     37 
     38 /**
     39   return Integer value.
     40 
     41   @param Data    - AML data buffer
     42   @param Integer - integer value.
     43 
     44   @return Data size processed.
     45 **/
     46 UINTN
     47 SdtGetInteger (
     48   IN  UINT8  *Data,
     49   OUT UINT64 *Integer
     50   )
     51 {
     52   *Integer = 0;
     53   switch (*Data) {
     54   case AML_ZERO_OP:
     55     return 1;
     56   case AML_ONE_OP:
     57     *Integer = 1;
     58     return 1;
     59   case AML_ONES_OP:
     60     *Integer = (UINTN)-1;
     61     return 1;
     62   case AML_BYTE_PREFIX:
     63     CopyMem (Integer, Data + 1, sizeof(UINT8));
     64     return 1 + sizeof(UINT8);
     65   case AML_WORD_PREFIX:
     66     CopyMem (Integer, Data + 1, sizeof(UINT16));
     67     return 1 + sizeof(UINT16);
     68   case AML_DWORD_PREFIX:
     69     CopyMem (Integer, Data + 1, sizeof(UINT32));
     70     return 1 + sizeof(UINT32);
     71   case AML_QWORD_PREFIX:
     72     CopyMem (Integer, Data + 1, sizeof(UINT64));
     73     return 1 + sizeof(UINT64);
     74   default:
     75     // Something wrong
     76     ASSERT (FALSE);
     77     return 1;
     78   }
     79 }
     80 
     81 
     82 /**
     83   Check if this handle has expected opcode.
     84 
     85   @param AcpiSdt    Pointer to Acpi SDT protocol
     86   @param Handle     ACPI handle
     87   @param OpCode     Expected OpCode
     88   @param SubOpCode  Expected SubOpCode
     89 
     90   @retval TRUE  This handle has expected opcode
     91   @retval FALSE This handle does not have expected opcode
     92 **/
     93 BOOLEAN
     94 SdtIsThisTypeObject (
     95   IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
     96   IN EFI_ACPI_HANDLE Handle,
     97   IN UINT8           OpCode,
     98   IN UINT8           SubOpCode
     99   )
    100 {
    101   EFI_STATUS         Status;
    102   EFI_ACPI_DATA_TYPE DataType;
    103   UINT8              *Data;
    104   UINTN              DataSize;
    105 
    106   Status = AcpiSdt->GetOption (Handle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
    107   ASSERT_EFI_ERROR (Status);
    108   ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
    109 
    110   if (OpCode == AML_EXT_OP) {
    111     if (Data[1] == SubOpCode) {
    112       return TRUE;
    113     }
    114   } else {
    115     if (Data[0] == OpCode) {
    116       return TRUE;
    117     }
    118   }
    119   return FALSE;
    120 }
    121 
    122 /**
    123   Check if this handle has expected name and name value.
    124 
    125   @param AcpiSdt    Pointer to Acpi SDT protocol
    126   @param Handle     ACPI handle
    127   @param Name       Expected name
    128   @param Value      Expected name value
    129 
    130   @retval TRUE  This handle has expected name and name value.
    131   @retval FALSE This handle does not have expected name and name value.
    132 **/
    133 BOOLEAN
    134 SdtIsNameIntegerValueEqual (
    135   IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
    136   IN EFI_ACPI_HANDLE Handle,
    137   IN CHAR8           *Name,
    138   IN UINT64          Value
    139   )
    140 {
    141   EFI_STATUS         Status;
    142   EFI_ACPI_DATA_TYPE DataType;
    143   UINT8              *Data;
    144   UINTN              DataSize;
    145   UINT64             Integer;
    146 
    147   Status = AcpiSdt->GetOption (Handle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
    148   ASSERT_EFI_ERROR (Status);
    149   ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
    150 
    151   if (CompareMem (Data, Name, 4) != 0) {
    152     return FALSE;
    153   }
    154 
    155   //
    156   // Name match check object
    157   //
    158   Status = AcpiSdt->GetOption (Handle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
    159   ASSERT_EFI_ERROR (Status);
    160 
    161   Integer = 0;
    162   SdtGetInteger (Data, &Integer);
    163   if (Integer != Value) {
    164     return FALSE;
    165   }
    166 
    167   // All match
    168   return TRUE;
    169 }
    170 
    171 /**
    172   Check if this handle's children has expected name and name value.
    173 
    174   @param AcpiSdt          Pointer to Acpi SDT protocol
    175   @param ParentHandle     ACPI parent handle
    176   @param Name             Expected name
    177   @param Value            Expected name value
    178 
    179   @retval TRUE  This handle's children has expected name and name value.
    180   @retval FALSE This handle's children does not have expected name and name value.
    181 **/
    182 BOOLEAN
    183 SdtCheckNameIntegerValue (
    184   IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
    185   IN EFI_ACPI_HANDLE ParentHandle,
    186   IN CHAR8           *Name,
    187   IN UINT64          Value
    188   )
    189 {
    190   EFI_ACPI_HANDLE PreviousHandle;
    191   EFI_ACPI_HANDLE Handle;
    192   EFI_STATUS      Status;
    193 
    194   Handle = NULL;
    195   while (TRUE) {
    196     PreviousHandle = Handle;
    197     Status = AcpiSdt->GetChild (ParentHandle, &Handle);
    198     ASSERT_EFI_ERROR (Status);
    199 
    200     if (PreviousHandle != NULL) {
    201       Status = AcpiSdt->Close (PreviousHandle);
    202       ASSERT_EFI_ERROR (Status);
    203     }
    204 
    205     //
    206     // Done
    207     //
    208     if (Handle == NULL) {
    209       return FALSE;
    210     }
    211 
    212     //
    213     // Check this name
    214     //
    215     if (SdtIsThisTypeObject (AcpiSdt, Handle, AML_NAME_OP, 0)) {
    216       if (SdtIsNameIntegerValueEqual (AcpiSdt, Handle, Name, Value)) {
    217         return TRUE;
    218       }
    219     }
    220   }
    221 
    222   //
    223   // Should not run here
    224   //
    225 }
    226 
    227 /**
    228   Convert the pci address from VPD (bus,dev,fun) into the address that acpi table
    229   can recognize.
    230 
    231   @param PciAddress    Pci address from VPD
    232 
    233   @retval return the address that acpi table can recognize
    234 **/
    235 UINT32
    236 SdtConvertToAcpiPciAdress (
    237   IN UINT32 PciAddress
    238   )
    239 {
    240   UINT32 ReturnAddress;
    241 
    242   ReturnAddress = ((PciAddress & 0x0000FF00) << 8) | (PciAddress & 0x000000FF);
    243 
    244   if ((PciAddress & 0x000000FF) == 0x000000FF)
    245     ReturnAddress |= 0x0000FFFF;
    246 
    247   return ReturnAddress;
    248 }
    249 
    250 /**
    251   return AML NameString size.
    252 
    253   @param Buffer - AML name string
    254 
    255   @return AML name string size
    256 **/
    257 UINTN
    258 SdtGetNameStringSize (
    259   IN UINT8              *Buffer
    260   )
    261 {
    262   UINTN                 SegCount;
    263   UINTN                 Length;
    264 
    265   Length = 0;
    266 
    267   //
    268   // Parse root or prefix
    269   //
    270   if (*Buffer == AML_ROOT_CHAR) {
    271     //
    272     // RootChar
    273     //
    274     Buffer ++;
    275     Length ++;
    276   } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
    277     //
    278     // ParentPrefixChar
    279     //
    280     Buffer ++;
    281     Length ++;
    282     while (*Buffer == AML_PARENT_PREFIX_CHAR) {
    283       Buffer ++;
    284       Length ++;
    285     }
    286   }
    287 
    288   //
    289   // Parse name segment
    290   //
    291   if (*Buffer == AML_DUAL_NAME_PREFIX) {
    292     //
    293     // DualName
    294     //
    295     Buffer ++;
    296     Length ++;
    297     SegCount = 2;
    298   } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
    299     //
    300     // MultiName
    301     //
    302     Buffer ++;
    303     Length ++;
    304     SegCount = *Buffer;
    305     Buffer ++;
    306     Length ++;
    307   } else if (*Buffer == 0) {
    308     //
    309     // NULL Name
    310     //
    311     SegCount = 0;
    312     Length ++;
    313   } else {
    314     //
    315     // NameSeg
    316     //
    317     SegCount = 1;
    318   }
    319 
    320   Buffer += 4 * SegCount;
    321   Length += 4 * SegCount;
    322 
    323   return Length;
    324 }
    325 
    326 /**
    327   The routine to check if this device is PCI root bridge.
    328 
    329   @param AcpiSdt       Pointer to Acpi SDT protocol
    330   @param DeviceHandle  ACPI device handle
    331   @param Context       Context info - not used here
    332 
    333   @retval TRUE  This is PCI root bridge
    334   @retval FALSE This is not PCI root bridge
    335 **/
    336 BOOLEAN
    337 SdtFindRootBridgeHandle (
    338   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    339   IN EFI_ACPI_HANDLE        CheckHandle,
    340   IN VOID                   *Context
    341   )
    342 {
    343   BOOLEAN            Result;
    344   EFI_ACPI_DATA_TYPE DataType;
    345   UINT8              *Data;
    346   UINTN              DataSize;
    347   EFI_STATUS         Status;
    348 
    349   if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
    350     return FALSE;
    351 
    352   Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_HID", (UINT64)0x080AD041); // PNP0A08
    353   if (!Result) {
    354     Result = SdtCheckNameIntegerValue (AcpiSdt, CheckHandle, "_CID", (UINT64)0x030AD041); // PNP0A03
    355     if (!Result) {
    356       return Result;
    357     }
    358   }
    359 
    360   //
    361   // Found
    362   //
    363   Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
    364   ASSERT_EFI_ERROR (Status);
    365   ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
    366 
    367   return Result;
    368 }
    369 
    370 
    371 /**
    372   The routine to check if this device is wanted.
    373 
    374   @param AcpiSdt       Pointer to Acpi SDT protocol
    375   @param DeviceHandle  ACPI device handle
    376   @param Context       Context info - not used here
    377 
    378   @retval TRUE  This is PCI device wanted
    379   @retval FALSE This is not PCI device wanted
    380 **/
    381 BOOLEAN
    382 SdtFindPciDeviceHandle (
    383   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    384   IN EFI_ACPI_HANDLE        CheckHandle,
    385   IN VOID                   *Context
    386   )
    387 {
    388   BOOLEAN            Result;
    389   EFI_ACPI_DATA_TYPE DataType;
    390   UINT8              *Data;
    391   UINTN              DataSize;
    392   EFI_STATUS         Status;
    393 
    394   if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
    395     return FALSE;
    396 
    397   Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_ADR", (UINT64)*(UINT32 *)Context);
    398   if (!Result) {
    399     return Result;
    400   }
    401 
    402   //
    403   // Found
    404   //
    405   Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
    406   ASSERT_EFI_ERROR (Status);
    407   ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
    408 
    409   return Result;
    410 }
    411 
    412 /**
    413   Go through the parent handle and find the handle which pass CheckHandleInfo.
    414 
    415   @param AcpiSdt          Pointer to Acpi SDT protocol
    416   @param ParentHandle     ACPI parent handle
    417   @param CheckHandleInfo  The callback routine to check if this handle meet the requirement
    418   @param Context          The context of CheckHandleInfo
    419 
    420   @return the handle which is first one can pass CheckHandleInfo.
    421 **/
    422 EFI_ACPI_HANDLE
    423 SdtGetHandleByScanAllChilds (
    424   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    425   IN EFI_ACPI_HANDLE        ParentHandle,
    426   IN CHECK_HANDLE_INFO      CheckHandleInfo,
    427   IN VOID                   *Context
    428   )
    429 {
    430   EFI_ACPI_HANDLE    PreviousHandle;
    431   EFI_ACPI_HANDLE    Handle;
    432   EFI_STATUS         Status;
    433   EFI_ACPI_HANDLE    ReturnHandle;
    434 
    435   //
    436   // Use deep first algo to enumerate all ACPI object
    437   //
    438   Handle = NULL;
    439   while (TRUE) {
    440     PreviousHandle = Handle;
    441     Status = AcpiSdt->GetChild (ParentHandle, &Handle);
    442     ASSERT_EFI_ERROR (Status);
    443 
    444     if (PreviousHandle != NULL) {
    445       Status = AcpiSdt->Close (PreviousHandle);
    446       ASSERT_EFI_ERROR (Status);
    447     }
    448 
    449     //
    450     // Done
    451     //
    452     if (Handle == NULL) {
    453       return NULL;
    454     }
    455 
    456     //
    457     // Check this handle
    458     //
    459     if (CheckHandleInfo (AcpiSdt, Handle, Context)) {
    460       return Handle;
    461     }
    462 
    463     //
    464     // Enumerate
    465     //
    466     ReturnHandle = SdtGetHandleByScanAllChilds (AcpiSdt, Handle, CheckHandleInfo, Context);
    467     if (ReturnHandle != NULL) {
    468       return ReturnHandle;
    469     }
    470   }
    471 
    472   //
    473   // Should not run here
    474   //
    475 }
    476 
    477 
    478 /**
    479   Check whether the INTx package is matched
    480 
    481   @param AcpiSdt          Pointer to Acpi SDT protocol
    482   @param INTxPkgHandle    ACPI INTx package handle
    483   @param PciAddress       Acpi pci address
    484   @param INTx             Index of INTx pin
    485   @param IsAPIC           Tell whether the returned INTx package is for APIC or not
    486 
    487   @retval       TRUE      the INTx package is matched
    488   @retval       FALSE     the INTx package is not matched
    489 
    490 **/
    491 BOOLEAN
    492 SdtCheckINTxPkgIsMatch (
    493   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    494   IN EFI_ACPI_HANDLE        INTxPkgHandle,
    495   IN UINT32                 PciAddress,
    496   IN UINT8                  INTx,
    497   IN BOOLEAN                *IsAPIC
    498   )
    499 {
    500   EFI_ACPI_HANDLE    PreviousHandle;
    501   EFI_STATUS         Status;
    502   EFI_ACPI_HANDLE    MemberHandle;
    503   EFI_ACPI_DATA_TYPE DataType;
    504   UINT8              *Data;
    505   UINTN              DataSize;
    506   UINT64             CurrentPciAddress;
    507   UINT64             CurrentINTx;
    508   UINTN              ChildSize;
    509 
    510 
    511   //
    512   // Check the pci address
    513   //
    514   MemberHandle = NULL;
    515   Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
    516   ASSERT_EFI_ERROR (Status);
    517   ASSERT (MemberHandle != NULL);
    518 
    519   Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
    520   ASSERT_EFI_ERROR (Status);
    521   ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
    522 
    523   CurrentPciAddress = 0;
    524   SdtGetInteger (Data, &CurrentPciAddress);
    525 
    526   if (CurrentPciAddress != PciAddress) {
    527 
    528     Status = AcpiSdt->Close (MemberHandle);
    529     ASSERT_EFI_ERROR (Status);
    530     return FALSE;
    531   }
    532 
    533   //
    534   // Check the pci interrupt pin
    535   //
    536   PreviousHandle = MemberHandle;
    537   Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
    538   ASSERT_EFI_ERROR (Status);
    539   ASSERT (MemberHandle != NULL);
    540 
    541   if (PreviousHandle != NULL) {
    542     Status = AcpiSdt->Close (PreviousHandle);
    543     ASSERT_EFI_ERROR (Status);
    544   }
    545 
    546   Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
    547   ASSERT_EFI_ERROR (Status);
    548   ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
    549 
    550   CurrentINTx = 0;
    551   ChildSize = SdtGetInteger (Data, &CurrentINTx);
    552 
    553   Status = AcpiSdt->Close (MemberHandle);
    554   ASSERT_EFI_ERROR (Status);
    555 
    556   if (CurrentINTx != INTx)
    557     return FALSE;
    558 
    559   Data += ChildSize;
    560 
    561   if (*Data == AML_BYTE_PREFIX)
    562     Data += 1;
    563 
    564   //
    565   // Check the pci interrupt source
    566   //
    567   if (*Data  != 0)
    568     *IsAPIC = FALSE;
    569   else
    570     *IsAPIC = TRUE;
    571 
    572   return TRUE;
    573 }
    574 
    575 
    576 
    577 
    578 /**
    579   Get the wanted INTx package inside the parent package
    580 
    581   @param AcpiSdt          Pointer to Acpi SDT protocol
    582   @param ParentPkgHandle  ACPI parent package handle
    583   @param PciAddress       Acpi pci address
    584   @param INTx             Index of INTx pin
    585   @param INTxPkgHandle    ACPI INTx package handle
    586   @param IsAPIC           Tell whether the returned INTx package is for APIC or not
    587 
    588 **/
    589 VOID
    590 SdtGetINTxPkgHandle (
    591   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    592   IN EFI_ACPI_HANDLE        ParentPkgHandle,
    593   IN UINT32                 PciAddress,
    594   IN UINT8                  INTx,
    595   IN EFI_ACPI_HANDLE        *INTxPkgHandle,
    596   IN BOOLEAN                *IsAPIC
    597   )
    598 {
    599   EFI_ACPI_HANDLE    PreviousHandle;
    600   EFI_STATUS         Status;
    601   EFI_ACPI_HANDLE    ChildPkgHandle;
    602 
    603   ChildPkgHandle = NULL;
    604   while (TRUE) {
    605     PreviousHandle = ChildPkgHandle;
    606     Status = AcpiSdt->GetChild (ParentPkgHandle, &ChildPkgHandle);
    607     ASSERT_EFI_ERROR (Status);
    608 
    609     if (PreviousHandle != NULL) {
    610       Status = AcpiSdt->Close (PreviousHandle);
    611       ASSERT_EFI_ERROR (Status);
    612     }
    613 
    614     if (ChildPkgHandle == NULL) {
    615       break;
    616     }
    617 
    618     if (SdtCheckINTxPkgIsMatch(AcpiSdt, ChildPkgHandle, PciAddress, INTx, IsAPIC)) {
    619       *INTxPkgHandle = ChildPkgHandle;
    620       return;
    621     }
    622   }
    623 
    624   return;
    625 }
    626 
    627 /**
    628   Update the INTx package with the correct pirq value
    629 
    630   @param AcpiSdt          Pointer to Acpi SDT protocol
    631   @param INTxPkgHandle    ACPI INTx package handle
    632   @param PirqValue        Correct pirq value
    633   @param IsAPIC           Tell whether the INTx package is for APIC or not
    634 
    635 **/
    636 VOID
    637 SdtUpdateINTxPkg (
    638   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    639   IN EFI_ACPI_HANDLE        INTxPkgHandle,
    640   IN UINT8                  PirqValue,
    641   IN BOOLEAN                IsAPIC
    642   )
    643 {
    644   EFI_ACPI_HANDLE    PreviousHandle;
    645   EFI_STATUS         Status;
    646   EFI_ACPI_HANDLE    MemberHandle;
    647   EFI_ACPI_DATA_TYPE DataType;
    648   UINT8              *Data;
    649   UINTN              DataSize;
    650   UINT64             TempValue;
    651   UINTN              ChildSize;
    652 
    653 
    654   //
    655   // Check the pci address
    656   //
    657   MemberHandle = NULL;
    658   Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
    659   ASSERT_EFI_ERROR (Status);
    660   ASSERT (MemberHandle != NULL);
    661 
    662   //
    663   // Check the pci interrupt pin
    664   //
    665   PreviousHandle = MemberHandle;
    666   Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
    667   ASSERT_EFI_ERROR (Status);
    668   ASSERT (MemberHandle != NULL);
    669 
    670   if (PreviousHandle != NULL) {
    671     Status = AcpiSdt->Close (PreviousHandle);
    672     ASSERT_EFI_ERROR (Status);
    673   }
    674 
    675   Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
    676   ASSERT_EFI_ERROR (Status);
    677   ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
    678 
    679   ChildSize = SdtGetInteger (Data, &TempValue);
    680 
    681   Status = AcpiSdt->Close (MemberHandle);
    682   ASSERT_EFI_ERROR (Status);
    683 
    684   Data += ChildSize;
    685 
    686   //
    687   // update the pci interrupt source or source index
    688   //
    689   if (!IsAPIC) {
    690     ChildSize = SdtGetNameStringSize (Data);
    691     Data += (ChildSize - 1);
    692 
    693     PirqValue += 0x40;   // change to ascii char
    694     if (*Data != PirqValue)
    695       *Data = PirqValue;
    696   } else {
    697 
    698     ChildSize = SdtGetInteger (Data, &TempValue);
    699     Data += ChildSize;
    700 
    701     Data += 1;
    702 
    703     if (*Data != PirqValue)
    704       *Data = PirqValue;
    705   }
    706 }
    707 
    708 /**
    709   Check every child package inside this interested parent package for update PRT
    710 
    711   @param AcpiSdt          Pointer to Acpi SDT protocol
    712   @param ParentPkgHandle  ACPI parent package handle
    713   @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
    714 
    715 **/
    716 VOID
    717 SdtCheckParentPackage (
    718   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    719   IN EFI_ACPI_HANDLE        ParentPkgHandle,
    720   IN PCI_DEVICE_INFO        *PciDeviceInfo
    721   )
    722 {
    723   EFI_ACPI_HANDLE    INTAPkgHandle;
    724   EFI_ACPI_HANDLE    INTBPkgHandle;
    725   EFI_ACPI_HANDLE    INTCPkgHandle;
    726   EFI_ACPI_HANDLE    INTDPkgHandle;
    727   UINT32             PciAddress = 0;
    728   BOOLEAN            IsAllFunctions = FALSE;
    729   UINT8              IsAPIC = 0;
    730   EFI_STATUS         Status;
    731 
    732   INTAPkgHandle = INTBPkgHandle = INTCPkgHandle = INTDPkgHandle = NULL;
    733 
    734   PciAddress   = SdtConvertToAcpiPciAdress(PciDeviceInfo->DeviceAddress);
    735 
    736   if ((PciAddress & 0xFFFF) == 0xFFFF) {
    737     IsAllFunctions = TRUE;
    738   } else {
    739     IsAllFunctions = FALSE;
    740     PciAddress = (PciAddress | 0xFFFF);
    741   }
    742 
    743   SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 0, &INTAPkgHandle, (BOOLEAN *)&IsAPIC);
    744   SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 1, &INTBPkgHandle, (BOOLEAN *)&IsAPIC);
    745   SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 2, &INTCPkgHandle, (BOOLEAN *)&IsAPIC);
    746   SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 3, &INTDPkgHandle, (BOOLEAN *)&IsAPIC);
    747 
    748   //
    749   // Check INTA
    750   //
    751   if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle != NULL)) {
    752     //
    753     // Find INTA package and there is valid INTA update item, update it
    754     //
    755     SdtUpdateINTxPkg (AcpiSdt, INTAPkgHandle, (PciDeviceInfo->INTA[IsAPIC]), IsAPIC);
    756   } else if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle == NULL)) {
    757     //
    758     // There is valid INTA update item, but no INA package exist, should add it
    759     //
    760     DEBUG ((EFI_D_ERROR, "\n\nShould add INTA item for this device(0x%x)\n\n", PciAddress));
    761 
    762   } else if ((PciDeviceInfo->INTA[IsAPIC] == 0xFF) && (INTAPkgHandle != NULL) && IsAllFunctions) {
    763     //
    764     // For all functions senario, if there is invalid INTA update item, but INTA package does exist, should delete it
    765     //
    766     DEBUG ((EFI_D_ERROR, "\n\nShould remove INTA item for this device(0x%x)\n\n", PciAddress));
    767 
    768   }
    769 
    770   //
    771   // Check INTB
    772   //
    773   if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle != NULL)) {
    774     //
    775     // Find INTB package and there is valid INTB update item, update it
    776     //
    777     SdtUpdateINTxPkg (AcpiSdt, INTBPkgHandle, (PciDeviceInfo->INTB[IsAPIC]), IsAPIC);
    778   } else if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle == NULL)) {
    779     //
    780     // There is valid INTB update item, but no INTB package exist, should add it
    781     //
    782     DEBUG ((EFI_D_ERROR, "\n\nShould add INTB item for this device(0x%x)\n\n", PciAddress));
    783 
    784   } else if ((PciDeviceInfo->INTB[IsAPIC] == 0xFF) && (INTBPkgHandle != NULL) && IsAllFunctions) {
    785     //
    786     // For all functions senario, if there is invalid INTB update item, but INTB package does exist, should delete it
    787     //
    788     DEBUG ((EFI_D_ERROR, "\n\nShould remove INTB item for this device(0x%x)\n\n", PciAddress));
    789 
    790   }
    791 
    792   //
    793   // Check INTC
    794   //
    795   if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle != NULL)) {
    796     //
    797     // Find INTC package and there is valid INTC update item, update it
    798     //
    799     SdtUpdateINTxPkg (AcpiSdt, INTCPkgHandle, (PciDeviceInfo->INTC[IsAPIC]), IsAPIC);
    800   } else if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle == NULL)) {
    801     //
    802     // There is valid INTC update item, but no INTC package exist, should add it
    803     //
    804     DEBUG ((EFI_D_ERROR, "\n\nShould add INTC item for this device(0x%x)\n\n", PciAddress));
    805 
    806   } else if ((PciDeviceInfo->INTC[IsAPIC] == 0xFF) && (INTCPkgHandle != NULL) && IsAllFunctions) {
    807     //
    808     // For all functions senario, if there is invalid INTC update item, but INTC package does exist, should delete it
    809     //
    810     DEBUG ((EFI_D_ERROR, "\n\nShould remove INTC item for this device(0x%x)\n\n", PciAddress));
    811   }
    812 
    813   //
    814   // Check INTD
    815   //
    816   if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle != NULL)) {
    817     //
    818     // Find INTD package and there is valid INTD update item, update it
    819     //
    820     SdtUpdateINTxPkg (AcpiSdt, INTDPkgHandle, (PciDeviceInfo->INTD[IsAPIC]), IsAPIC);
    821   } else if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle == NULL)) {
    822     //
    823     // There is valid INTD update item, but no INTD package exist, should add it
    824     //
    825     DEBUG ((EFI_D_ERROR, "\n\nShould add INTD item for this device(0x%x)\n\n", PciAddress));
    826 
    827   }  else if ((PciDeviceInfo->INTD[IsAPIC] == 0xFF) && (INTDPkgHandle != NULL) && IsAllFunctions) {
    828     //
    829     // For all functions senario, if there is invalid INTD update item, but INTD package does exist, should delete it
    830     //
    831     DEBUG ((EFI_D_ERROR, "\n\nShould remove INTD item for this device(0x%x)\n\n", PciAddress));
    832   }
    833 
    834 
    835   if (INTAPkgHandle != NULL) {
    836     Status = AcpiSdt->Close (INTAPkgHandle);
    837     ASSERT_EFI_ERROR (Status);
    838   }
    839 
    840   if (INTBPkgHandle != NULL) {
    841     Status = AcpiSdt->Close (INTBPkgHandle);
    842     ASSERT_EFI_ERROR (Status);
    843   }
    844 
    845   if (INTCPkgHandle != NULL) {
    846     Status = AcpiSdt->Close (INTCPkgHandle);
    847     ASSERT_EFI_ERROR (Status);
    848   }
    849 
    850   if (INTDPkgHandle != NULL) {
    851     Status = AcpiSdt->Close (INTDPkgHandle);
    852     ASSERT_EFI_ERROR (Status);
    853   }
    854 
    855   return;
    856 }
    857 
    858 /**
    859   Check every return package for update PRT
    860 
    861   @param AcpiSdt          Pointer to Acpi SDT protocol
    862   @param ParentHandle     ACPI pci device handle
    863   @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
    864 
    865 **/
    866 VOID
    867 SdtCheckReturnPackage (
    868   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    869   IN EFI_ACPI_HANDLE        MethodHandle,
    870   IN PCI_DEVICE_INFO        *PciDeviceInfo
    871   )
    872 {
    873   EFI_ACPI_HANDLE    PreviousHandle;
    874   EFI_ACPI_HANDLE    ReturnHandle;
    875   EFI_ACPI_HANDLE    PackageHandle;
    876   EFI_ACPI_HANDLE    NamePkgHandle;
    877   EFI_STATUS         Status;
    878   EFI_ACPI_DATA_TYPE DataType;
    879   UINT8              *Data;
    880   UINTN              DataSize;
    881   CHAR8              NameStr[128];
    882 
    883   ReturnHandle = NULL;
    884   while (TRUE) {
    885     PreviousHandle = ReturnHandle;
    886     Status = AcpiSdt->GetChild (MethodHandle, &ReturnHandle);
    887     ASSERT_EFI_ERROR (Status);
    888 
    889     if (PreviousHandle != NULL) {
    890       Status = AcpiSdt->Close (PreviousHandle);
    891       ASSERT_EFI_ERROR (Status);
    892     }
    893 
    894     if (ReturnHandle == NULL) {
    895       break;
    896     }
    897 
    898     Status = AcpiSdt->GetOption (ReturnHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
    899     ASSERT_EFI_ERROR (Status);
    900     ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
    901 
    902     if (*Data == AML_RETURN_OP) {
    903       //
    904       // Find the return method handle, then look for the returned package data
    905       //
    906       Status = AcpiSdt->GetOption (ReturnHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
    907       ASSERT_EFI_ERROR (Status);
    908 
    909 
    910       if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) {
    911         ZeroMem (NameStr, 128);
    912         AsciiStrCpy (NameStr, "\\_SB.");
    913         DataSize = SdtGetNameStringSize (Data);
    914         AsciiStrnCat (NameStr, (CHAR8 *)Data, DataSize);
    915 
    916         NamePkgHandle = NULL;
    917         Status = AcpiSdt->FindPath (mDsdtHandle, NameStr, &NamePkgHandle);
    918         ASSERT_EFI_ERROR (Status);
    919         ASSERT (NamePkgHandle != NULL);
    920 
    921         Status = AcpiSdt->GetOption (NamePkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
    922         ASSERT_EFI_ERROR (Status);
    923         ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
    924         ASSERT (*Data == AML_NAME_OP);
    925 
    926         Status = AcpiSdt->GetOption (NamePkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
    927         ASSERT_EFI_ERROR (Status);
    928         ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
    929       }
    930 
    931       ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
    932 
    933       //
    934       // Get the parent package handle
    935       //
    936       PackageHandle = NULL;
    937       Status = AcpiSdt->Open (Data, &PackageHandle);
    938       ASSERT_EFI_ERROR (Status);
    939 
    940       //
    941       // Check the parent package for update pci routing
    942       //
    943       SdtCheckParentPackage (AcpiSdt, PackageHandle, PciDeviceInfo);
    944 
    945       Status = AcpiSdt->Close (PackageHandle);
    946       ASSERT_EFI_ERROR (Status);
    947 
    948       Status = AcpiSdt->Close (ReturnHandle);
    949       ASSERT_EFI_ERROR (Status);
    950 
    951       break;
    952     }
    953 
    954     //
    955     // Not ReturnOp, search it as parent
    956     //
    957     SdtCheckReturnPackage (AcpiSdt, ReturnHandle, PciDeviceInfo);
    958   }
    959 
    960   //
    961   // Done
    962   //
    963   return;
    964 
    965 }
    966 
    967 /**
    968   update interrupt info inside the PRT method for the given pci device handle
    969 
    970   @param AcpiSdt       Pointer to Acpi SDT protocol
    971   @param PciHandle     ACPI pci device handle
    972   @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
    973 
    974 **/
    975 EFI_STATUS
    976 SdtUpdatePrtMethod (
    977   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
    978   IN EFI_ACPI_HANDLE        PciHandle,
    979   IN PCI_DEVICE_INFO        *PciDeviceInfo
    980   )
    981 {
    982   EFI_STATUS         Status;
    983   EFI_ACPI_HANDLE    PrtMethodHandle;
    984 
    985   //
    986   // Find the PRT method under this pci device
    987   //
    988   PrtMethodHandle = NULL;
    989   Status = AcpiSdt->FindPath (PciHandle, "_PRT", &PrtMethodHandle);
    990 
    991   if (EFI_ERROR (Status)) {
    992     return EFI_INVALID_PARAMETER;
    993   }
    994 
    995   if (PrtMethodHandle == NULL) {
    996     return EFI_INVALID_PARAMETER;
    997   }
    998 
    999   SdtCheckReturnPackage(AcpiSdt, PrtMethodHandle, PciDeviceInfo);
   1000 
   1001   Status = AcpiSdt->Close (PrtMethodHandle);
   1002   ASSERT_EFI_ERROR (Status);
   1003 
   1004   return Status;
   1005 }
   1006 
   1007 
   1008 /**
   1009   Update the package inside name op with correct wakeup resources
   1010 
   1011   @param AcpiSdt          Pointer to Acpi SDT protocol
   1012   @param InPkgHandle      ACPI inside package handle
   1013   @param GPEPin           Correct gpe pin
   1014   @param SxNum            Correct system state the device can wake up from
   1015 
   1016 **/
   1017 VOID
   1018 SdtUpdatePackageInName (
   1019   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
   1020   IN EFI_ACPI_HANDLE        INTxPkgHandle,
   1021   IN UINT8                  GPEPin,
   1022   IN UINT8                  SxNum
   1023   )
   1024 {
   1025   EFI_ACPI_HANDLE    PreviousHandle;
   1026   EFI_STATUS         Status;
   1027   EFI_ACPI_HANDLE    MemberHandle;
   1028   EFI_ACPI_DATA_TYPE DataType;
   1029   UINT8              *Data;
   1030   UINTN              DataSize;
   1031 
   1032   //
   1033   // Check the gpe pin
   1034   //
   1035   MemberHandle = NULL;
   1036   Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
   1037   ASSERT_EFI_ERROR (Status);
   1038   ASSERT (MemberHandle != NULL);
   1039 
   1040   Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
   1041   ASSERT_EFI_ERROR (Status);
   1042   ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
   1043 
   1044   //
   1045   // Skip byte prefix
   1046   //
   1047   Data += 1;
   1048 
   1049   if (*Data != GPEPin) {
   1050 
   1051     *Data = GPEPin;
   1052   }
   1053 
   1054   //
   1055   // Check the sx number
   1056   //
   1057   PreviousHandle = MemberHandle;
   1058   Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
   1059   ASSERT_EFI_ERROR (Status);
   1060   ASSERT (MemberHandle != NULL);
   1061 
   1062   if (PreviousHandle != NULL) {
   1063     Status = AcpiSdt->Close (PreviousHandle);
   1064     ASSERT_EFI_ERROR (Status);
   1065   }
   1066 
   1067   Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
   1068   ASSERT_EFI_ERROR (Status);
   1069   ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
   1070 
   1071   //
   1072   // Skip byte prefix
   1073   //
   1074   Data += 1;
   1075 
   1076   if (*Data != SxNum) {
   1077 
   1078     *Data = SxNum;
   1079   }
   1080 
   1081   Status = AcpiSdt->Close (MemberHandle);
   1082   ASSERT_EFI_ERROR (Status);
   1083 
   1084 }
   1085 
   1086 /**
   1087   Check the name package belonged to PRW
   1088 
   1089   @param AcpiSdt          Pointer to Acpi SDT protocol
   1090   @param PrwPkgHandle     ACPI PRW package handle
   1091   @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
   1092 
   1093 **/
   1094 VOID
   1095 SdtCheckNamePackage (
   1096   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
   1097   IN EFI_ACPI_HANDLE        PrwPkgHandle,
   1098   IN PCI_DEVICE_INFO        *PciDeviceInfo
   1099   )
   1100 {
   1101   EFI_ACPI_HANDLE    InPkgHandle;
   1102   EFI_STATUS         Status;
   1103   EFI_ACPI_DATA_TYPE DataType;
   1104   UINT8              *Data;
   1105   UINTN              DataSize;
   1106 
   1107   Status = AcpiSdt->GetOption (PrwPkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
   1108   ASSERT_EFI_ERROR (Status);
   1109   ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
   1110   ASSERT (*Data == AML_NAME_OP);
   1111 
   1112   Status = AcpiSdt->GetOption (PrwPkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
   1113   ASSERT_EFI_ERROR (Status);
   1114   ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
   1115 
   1116   //
   1117   // Get the inside package handle
   1118   //
   1119   InPkgHandle = NULL;
   1120   Status = AcpiSdt->Open (Data, &InPkgHandle);
   1121   ASSERT_EFI_ERROR (Status);
   1122 
   1123   //
   1124   // update the package in name op for wakeup info
   1125   //
   1126   if ((PciDeviceInfo->GPEPin != 0xFF) && (PciDeviceInfo->SxNum != 0xFF))
   1127     SdtUpdatePackageInName (AcpiSdt, InPkgHandle, PciDeviceInfo->GPEPin, PciDeviceInfo->SxNum);
   1128 
   1129   Status = AcpiSdt->Close (InPkgHandle);
   1130   ASSERT_EFI_ERROR (Status);
   1131 
   1132   return;
   1133 
   1134 }
   1135 
   1136 /**
   1137   update wakeup info inside the PRW method for the given pci device handle
   1138 
   1139   @param AcpiSdt       Pointer to Acpi SDT protocol
   1140   @param PciHandle     ACPI pci device handle
   1141   @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
   1142 
   1143 **/
   1144 EFI_STATUS
   1145 SdtUpdatePrwPackage (
   1146   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
   1147   IN EFI_ACPI_HANDLE        PciHandle,
   1148   IN PCI_DEVICE_INFO        *PciDeviceInfo
   1149   )
   1150 {
   1151   EFI_STATUS         Status;
   1152   EFI_ACPI_HANDLE    PrwPkgHandle;
   1153 
   1154   //
   1155   // Find the PRT method under this pci device
   1156   //
   1157   PrwPkgHandle = NULL;
   1158   Status = AcpiSdt->FindPath (PciHandle, "_PRW", &PrwPkgHandle);
   1159 
   1160   if (EFI_ERROR (Status)) {
   1161     return EFI_INVALID_PARAMETER;
   1162   }
   1163 
   1164   if (PrwPkgHandle == NULL) {
   1165     return EFI_INVALID_PARAMETER;
   1166   }
   1167 
   1168   SdtCheckNamePackage(AcpiSdt, PrwPkgHandle, PciDeviceInfo);
   1169 
   1170   Status = AcpiSdt->Close (PrwPkgHandle);
   1171   ASSERT_EFI_ERROR (Status);
   1172 
   1173   return Status;
   1174 }
   1175 
   1176 /**
   1177   update pci routing information in acpi table based on pcd settings
   1178 
   1179   @param AcpiSdt          Pointer to Acpi SDT protocol
   1180   @param PciRootHandle       ACPI root bridge handle
   1181   @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
   1182 
   1183 **/
   1184 EFI_STATUS
   1185 SdtUpdatePciRouting (
   1186   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
   1187   IN EFI_ACPI_HANDLE        PciRootHandle,
   1188   IN PCI_DEVICE_INFO        *PciDeviceInfo
   1189   )
   1190 {
   1191   EFI_STATUS         Status;
   1192   EFI_ACPI_HANDLE    PciBridgeHandle;
   1193   UINT32             PciAddress;
   1194 
   1195 
   1196   PciBridgeHandle = NULL;
   1197   if (PciDeviceInfo->BridgeAddress == 0x00000000) {
   1198     //
   1199     // Its bridge is the host root bridge
   1200     //
   1201     PciBridgeHandle = PciRootHandle;
   1202 
   1203   } else {
   1204 
   1205     //
   1206     // Its bridge is just a pci device under the host bridge
   1207     //
   1208 
   1209     //
   1210     // Conver the bridge address into one that acpi table can recognize
   1211     //
   1212     PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
   1213 
   1214     //
   1215     // Scan the whole table to find the pci device
   1216     //
   1217     PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
   1218     if (PciBridgeHandle == NULL) {
   1219 
   1220       return EFI_INVALID_PARAMETER;
   1221     }
   1222   }
   1223 
   1224   Status = SdtUpdatePrtMethod(AcpiSdt, PciBridgeHandle, PciDeviceInfo);
   1225 
   1226   if (PciDeviceInfo->BridgeAddress != 0x00000000) {
   1227     Status = AcpiSdt->Close (PciBridgeHandle);
   1228     ASSERT_EFI_ERROR (Status);
   1229   }
   1230 
   1231   return Status;
   1232 }
   1233 
   1234 
   1235 /**
   1236   update power resource wake up information in acpi table based on pcd settings
   1237 
   1238   @param AcpiSdt          Pointer to Acpi SDT protocol
   1239   @param PciRootHandle    ACPI root bridge handle
   1240   @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
   1241 
   1242 **/
   1243 EFI_STATUS
   1244 SdtUpdatePowerWake (
   1245   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
   1246   IN EFI_ACPI_HANDLE        PciRootHandle,
   1247   IN PCI_DEVICE_INFO        *PciDeviceInfo
   1248   )
   1249 {
   1250   EFI_STATUS         Status;
   1251   EFI_ACPI_HANDLE    PciBridgeHandle;
   1252   EFI_ACPI_HANDLE    PciDeviceHandle;
   1253   UINT32             PciAddress;
   1254 
   1255   PciBridgeHandle = NULL;
   1256   if (PciDeviceInfo->BridgeAddress == 0x00000000) {
   1257     //
   1258     // Its bridge is the host root bridge
   1259     //
   1260     PciBridgeHandle = PciRootHandle;
   1261 
   1262   } else {
   1263 
   1264     //
   1265     // Its bridge is just a pci device under the host bridge
   1266     //
   1267 
   1268     //
   1269     // Conver the bridge address into one that acpi table can recognize
   1270     //
   1271     PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
   1272 
   1273     //
   1274     // Scan the whole table to find the pci device
   1275     //
   1276     PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
   1277 
   1278     if (PciBridgeHandle == NULL) {
   1279 
   1280       Status = AcpiSdt->Close (PciRootHandle);
   1281       ASSERT_EFI_ERROR (Status);
   1282 
   1283       return EFI_INVALID_PARAMETER;
   1284     }
   1285   }
   1286 
   1287   PciDeviceHandle = NULL;
   1288 
   1289   //
   1290   // Conver the device address into one that acpi table can recognize
   1291   //
   1292   PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->DeviceAddress);
   1293 
   1294   //
   1295   // Scan the whole table to find the pci device
   1296   //
   1297   PciDeviceHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciBridgeHandle, SdtFindPciDeviceHandle, &PciAddress);
   1298 
   1299   if (PciDeviceHandle == NULL) {
   1300     if (PciDeviceInfo->BridgeAddress != 0x00000000) {
   1301       Status = AcpiSdt->Close (PciBridgeHandle);
   1302       ASSERT_EFI_ERROR (Status);
   1303     }
   1304 
   1305     return EFI_INVALID_PARAMETER;
   1306   }
   1307 
   1308   Status = SdtUpdatePrwPackage(AcpiSdt, PciDeviceHandle, PciDeviceInfo);
   1309 
   1310   Status = AcpiSdt->Close (PciDeviceHandle);
   1311   ASSERT_EFI_ERROR (Status);
   1312 
   1313   if (PciDeviceInfo->BridgeAddress != 0x00000000) {
   1314     Status = AcpiSdt->Close (PciBridgeHandle);
   1315     ASSERT_EFI_ERROR (Status);
   1316   }
   1317 
   1318   return Status;
   1319 }
   1320 
   1321 
   1322 /**
   1323   Get the root bridge handle by scanning the acpi table
   1324 
   1325   @param AcpiSdt          Pointer to Acpi SDT protocol
   1326   @param DsdtHandle       ACPI root handle
   1327 
   1328   @retval EFI_ACPI_HANDLE the handle of the root bridge
   1329 **/
   1330 EFI_ACPI_HANDLE
   1331 SdtGetRootBridgeHandle (
   1332   IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
   1333   IN EFI_ACPI_HANDLE        DsdtHandle
   1334   )
   1335 {
   1336   EFI_ACPI_HANDLE    PciRootHandle;
   1337 
   1338   //
   1339   // Scan the whole table to find the root bridge
   1340   //
   1341   PciRootHandle = NULL;
   1342   PciRootHandle = SdtGetHandleByScanAllChilds(AcpiSdt, DsdtHandle, SdtFindRootBridgeHandle, NULL);
   1343   ASSERT (PciRootHandle != NULL);
   1344 
   1345   return PciRootHandle;
   1346 }
   1347 
   1348 
   1349 /**
   1350   Check input Pci device info is changed from the default values
   1351   @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
   1352   @param UpdatePRT        Pointer to BOOLEAN
   1353   @param UpdatePRW        Pointer to BOOLEAN
   1354 
   1355 **/
   1356 VOID
   1357 SdtCheckPciDeviceInfoChanged (
   1358   IN PCI_DEVICE_INFO        *PciDeviceInfo,
   1359   IN BOOLEAN                *UpdatePRT,
   1360   IN BOOLEAN                *UpdatePRW
   1361   )
   1362 {
   1363   UINTN Index = 0;
   1364 
   1365   if (mQNCPciInfo == NULL) {
   1366     *UpdatePRT = FALSE;
   1367     *UpdatePRW = FALSE;
   1368     return;
   1369   }
   1370 
   1371   *UpdatePRT = TRUE;
   1372   *UpdatePRW = TRUE;
   1373 
   1374   for (Index = 0;Index < CURRENT_PCI_DEVICE_NUM; Index++) {
   1375     if ((mQNCPciInfo[Index].BridgeAddress == PciDeviceInfo->BridgeAddress)
   1376       && (mQNCPciInfo[Index].DeviceAddress == PciDeviceInfo->DeviceAddress)) {
   1377       //
   1378       // Find one matched entry
   1379       //
   1380       if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 10) == 0) {
   1381         *UpdatePRT = FALSE;
   1382         *UpdatePRW = FALSE;
   1383         //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and no change\n", Index));
   1384       } else {
   1385         if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 8) == 0)
   1386           *UpdatePRT = FALSE;
   1387 
   1388         if (CompareMem (&(mQNCPciInfo[Index].GPEPin), &PciDeviceInfo->GPEPin, 2) == 0)
   1389           *UpdatePRW = FALSE;
   1390 
   1391         if (*(UINT64 *)(&PciDeviceInfo->INTA[0]) == 0xFFFFFFFFFFFFFFFFULL)
   1392           *UpdatePRT = FALSE;
   1393 
   1394         if (*(UINT16 *)(&PciDeviceInfo->GPEPin) == 0xFFFF)
   1395           *UpdatePRW = FALSE;
   1396 
   1397         //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and but need update PRT:0x%x PRW:0x%x\n", Index, *UpdatePRT, *UpdatePRW));
   1398       }
   1399       break;
   1400     }
   1401   }
   1402 
   1403   //if (Index == 42) {
   1404   //  DEBUG ((EFI_D_ERROR, "Find No matched entry\n"));
   1405   //}
   1406 
   1407   return;
   1408 }
   1409