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