2 Update the _PRT and _PRW method for pci devices
4 Copyright (c) 2013-2015 Intel Corporation.
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
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.
16 #include "AcpiPlatform.h"
18 PCI_DEVICE_INFO
*mQNCPciInfo
= NULL
;
21 Init Pci Device Structure
22 @param mConfigData - Pointer of Pci Device information Structure
26 InitPciDeviceInfoStructure (
27 PCI_DEVICE_SETTING
*mConfigData
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.
35 mConfigData
->PciDeviceInfoNumber
= 0;
41 @param Data - AML data buffer
42 @param Integer - integer value.
44 @return Data size processed.
63 CopyMem (Integer
, Data
+ 1, sizeof(UINT8
));
64 return 1 + sizeof(UINT8
);
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
);
83 Check if this handle has expected opcode.
85 @param AcpiSdt Pointer to Acpi SDT protocol
86 @param Handle ACPI handle
87 @param OpCode Expected OpCode
88 @param SubOpCode Expected SubOpCode
90 @retval TURE This handle has expected opcode
91 @retval FALSE This handle does not have expected opcode
95 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
96 IN EFI_ACPI_HANDLE Handle
,
102 EFI_ACPI_DATA_TYPE DataType
;
106 Status
= AcpiSdt
->GetOption (Handle
, 0, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
107 ASSERT_EFI_ERROR (Status
);
108 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
110 if (OpCode
== AML_EXT_OP
) {
111 if (Data
[1] == SubOpCode
) {
115 if (Data
[0] == OpCode
) {
123 Check if this handle has expected name and name value.
125 @param AcpiSdt Pointer to Acpi SDT protocol
126 @param Handle ACPI handle
127 @param Name Expected name
128 @param Value Expected name value
130 @retval TURE This handle has expected name and name value.
131 @retval FALSE This handle does not have expected name and name value.
134 SdtIsNameIntegerValueEqual (
135 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
136 IN EFI_ACPI_HANDLE Handle
,
142 EFI_ACPI_DATA_TYPE DataType
;
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
);
151 if (CompareMem (Data
, Name
, 4) != 0) {
156 // Name match check object
158 Status
= AcpiSdt
->GetOption (Handle
, 2, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
159 ASSERT_EFI_ERROR (Status
);
162 SdtGetInteger (Data
, &Integer
);
163 if (Integer
!= Value
) {
172 Check if this handle's children has expected name and name value.
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
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.
183 SdtCheckNameIntegerValue (
184 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
185 IN EFI_ACPI_HANDLE ParentHandle
,
190 EFI_ACPI_HANDLE PreviousHandle
;
191 EFI_ACPI_HANDLE Handle
;
196 PreviousHandle
= Handle
;
197 Status
= AcpiSdt
->GetChild (ParentHandle
, &Handle
);
198 ASSERT_EFI_ERROR (Status
);
200 if (PreviousHandle
!= NULL
) {
201 Status
= AcpiSdt
->Close (PreviousHandle
);
202 ASSERT_EFI_ERROR (Status
);
208 if (Handle
== NULL
) {
215 if (SdtIsThisTypeObject (AcpiSdt
, Handle
, AML_NAME_OP
, 0)) {
216 if (SdtIsNameIntegerValueEqual (AcpiSdt
, Handle
, Name
, Value
)) {
223 // Should not run here
228 Convert the pci address from VPD (bus,dev,fun) into the address that acpi table
231 @param PciAddress Pci address from VPD
233 @retval return the address that acpi table can recognize
236 SdtConvertToAcpiPciAdress (
240 UINT32 ReturnAddress
;
242 ReturnAddress
= ((PciAddress
& 0x0000FF00) << 8) | (PciAddress
& 0x000000FF);
244 if ((PciAddress
& 0x000000FF) == 0x000000FF)
245 ReturnAddress
|= 0x0000FFFF;
247 return ReturnAddress
;
251 return AML NameString size.
253 @param Buffer - AML name string
255 @return AML name string size
258 SdtGetNameStringSize (
270 // Parse root or prefix
272 if (*Buffer
== AML_ROOT_CHAR
) {
278 } else if (*Buffer
== AML_PARENT_PREFIX_CHAR
) {
284 while (*Buffer
== AML_PARENT_PREFIX_CHAR
) {
291 // Parse name segment
293 if (*Buffer
== AML_DUAL_NAME_PREFIX
) {
300 } else if (*Buffer
== AML_MULTI_NAME_PREFIX
) {
309 } else if (*Buffer
== 0) {
322 Buffer
+= 4 * SegCount
;
323 Length
+= 4 * SegCount
;
329 The routine to check if this device is PCI root bridge.
331 @param AcpiSdt Pointer to Acpi SDT protocol
332 @param DeviceHandle ACPI device handle
333 @param Context Context info - not used here
335 @retval TRUE This is PCI root bridge
336 @retval FALSE This is not PCI root bridge
339 SdtFindRootBridgeHandle (
340 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
341 IN EFI_ACPI_HANDLE CheckHandle
,
346 EFI_ACPI_DATA_TYPE DataType
;
351 if (!SdtIsThisTypeObject (AcpiSdt
, CheckHandle
, AML_EXT_OP
, AML_EXT_DEVICE_OP
))
354 Result
= SdtCheckNameIntegerValue (AcpiSdt
,CheckHandle
, "_HID", (UINT64
)0x080AD041); // PNP0A08
356 Result
= SdtCheckNameIntegerValue (AcpiSdt
, CheckHandle
, "_CID", (UINT64
)0x030AD041); // PNP0A03
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
);
374 The routine to check if this device is wanted.
376 @param AcpiSdt Pointer to Acpi SDT protocol
377 @param DeviceHandle ACPI device handle
378 @param Context Context info - not used here
380 @retval TRUE This is PCI device wanted
381 @retval FALSE This is not PCI device wanted
384 SdtFindPciDeviceHandle (
385 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
386 IN EFI_ACPI_HANDLE CheckHandle
,
391 EFI_ACPI_DATA_TYPE DataType
;
396 if (!SdtIsThisTypeObject (AcpiSdt
, CheckHandle
, AML_EXT_OP
, AML_EXT_DEVICE_OP
))
399 Result
= SdtCheckNameIntegerValue (AcpiSdt
,CheckHandle
, "_ADR", (UINT64
)*(UINT32
*)Context
);
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
);
415 Go through the parent handle and find the handle which pass CheckHandleInfo.
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
422 @return the handle which is first one can pass CheckHandleInfo.
425 SdtGetHandleByScanAllChilds (
426 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
427 IN EFI_ACPI_HANDLE ParentHandle
,
428 IN CHECK_HANDLE_INFO CheckHandleInfo
,
432 EFI_ACPI_HANDLE PreviousHandle
;
433 EFI_ACPI_HANDLE Handle
;
435 EFI_ACPI_HANDLE ReturnHandle
;
438 // Use deep first algo to enumerate all ACPI object
442 PreviousHandle
= Handle
;
443 Status
= AcpiSdt
->GetChild (ParentHandle
, &Handle
);
444 ASSERT_EFI_ERROR (Status
);
446 if (PreviousHandle
!= NULL
) {
447 Status
= AcpiSdt
->Close (PreviousHandle
);
448 ASSERT_EFI_ERROR (Status
);
454 if (Handle
== NULL
) {
461 if (CheckHandleInfo (AcpiSdt
, Handle
, Context
)) {
468 ReturnHandle
= SdtGetHandleByScanAllChilds (AcpiSdt
, Handle
, CheckHandleInfo
, Context
);
469 if (ReturnHandle
!= NULL
) {
475 // Should not run here
481 Check whether the INTx package is matched
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
489 @retval TRUE the INTx package is matched
490 @retval FALSE the INTx package is not matched
494 SdtCheckINTxPkgIsMatch (
495 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
496 IN EFI_ACPI_HANDLE INTxPkgHandle
,
497 IN UINT32 PciAddress
,
502 EFI_ACPI_HANDLE PreviousHandle
;
504 EFI_ACPI_HANDLE MemberHandle
;
505 EFI_ACPI_DATA_TYPE DataType
;
508 UINT64 CurrentPciAddress
;
514 // Check the pci address
517 Status
= AcpiSdt
->GetChild (INTxPkgHandle
, &MemberHandle
);
518 ASSERT_EFI_ERROR (Status
);
519 ASSERT (MemberHandle
!= NULL
);
521 Status
= AcpiSdt
->GetOption (MemberHandle
, 0, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
522 ASSERT_EFI_ERROR (Status
);
523 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
525 CurrentPciAddress
= 0;
526 SdtGetInteger (Data
, &CurrentPciAddress
);
528 if (CurrentPciAddress
!= PciAddress
) {
530 Status
= AcpiSdt
->Close (MemberHandle
);
531 ASSERT_EFI_ERROR (Status
);
536 // Check the pci interrupt pin
538 PreviousHandle
= MemberHandle
;
539 Status
= AcpiSdt
->GetChild (INTxPkgHandle
, &MemberHandle
);
540 ASSERT_EFI_ERROR (Status
);
541 ASSERT (MemberHandle
!= NULL
);
543 if (PreviousHandle
!= NULL
) {
544 Status
= AcpiSdt
->Close (PreviousHandle
);
545 ASSERT_EFI_ERROR (Status
);
548 Status
= AcpiSdt
->GetOption (MemberHandle
, 0, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
549 ASSERT_EFI_ERROR (Status
);
550 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
553 ChildSize
= SdtGetInteger (Data
, &CurrentINTx
);
555 Status
= AcpiSdt
->Close (MemberHandle
);
556 ASSERT_EFI_ERROR (Status
);
558 if (CurrentINTx
!= INTx
)
563 if (*Data
== AML_BYTE_PREFIX
)
567 // Check the pci interrupt source
581 Get the wanted INTx package inside the parent package
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
592 SdtGetINTxPkgHandle (
593 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
594 IN EFI_ACPI_HANDLE ParentPkgHandle
,
595 IN UINT32 PciAddress
,
597 IN EFI_ACPI_HANDLE
*INTxPkgHandle
,
601 EFI_ACPI_HANDLE PreviousHandle
;
603 EFI_ACPI_HANDLE ChildPkgHandle
;
605 ChildPkgHandle
= NULL
;
607 PreviousHandle
= ChildPkgHandle
;
608 Status
= AcpiSdt
->GetChild (ParentPkgHandle
, &ChildPkgHandle
);
609 ASSERT_EFI_ERROR (Status
);
611 if (PreviousHandle
!= NULL
) {
612 Status
= AcpiSdt
->Close (PreviousHandle
);
613 ASSERT_EFI_ERROR (Status
);
616 if (ChildPkgHandle
== NULL
) {
620 if (SdtCheckINTxPkgIsMatch(AcpiSdt
, ChildPkgHandle
, PciAddress
, INTx
, IsAPIC
)) {
621 *INTxPkgHandle
= ChildPkgHandle
;
630 Update the INTx package with the correct pirq value
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
640 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
641 IN EFI_ACPI_HANDLE INTxPkgHandle
,
646 EFI_ACPI_HANDLE PreviousHandle
;
648 EFI_ACPI_HANDLE MemberHandle
;
649 EFI_ACPI_DATA_TYPE DataType
;
657 // Check the pci address
660 Status
= AcpiSdt
->GetChild (INTxPkgHandle
, &MemberHandle
);
661 ASSERT_EFI_ERROR (Status
);
662 ASSERT (MemberHandle
!= NULL
);
665 // Check the pci interrupt pin
667 PreviousHandle
= MemberHandle
;
668 Status
= AcpiSdt
->GetChild (INTxPkgHandle
, &MemberHandle
);
669 ASSERT_EFI_ERROR (Status
);
670 ASSERT (MemberHandle
!= NULL
);
672 if (PreviousHandle
!= NULL
) {
673 Status
= AcpiSdt
->Close (PreviousHandle
);
674 ASSERT_EFI_ERROR (Status
);
677 Status
= AcpiSdt
->GetOption (MemberHandle
, 0, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
678 ASSERT_EFI_ERROR (Status
);
679 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
681 ChildSize
= SdtGetInteger (Data
, &TempValue
);
683 Status
= AcpiSdt
->Close (MemberHandle
);
684 ASSERT_EFI_ERROR (Status
);
689 // update the pci interrupt source or source index
692 ChildSize
= SdtGetNameStringSize (Data
);
693 Data
+= (ChildSize
- 1);
695 PirqValue
+= 0x40; // change to ascii char
696 if (*Data
!= PirqValue
)
700 ChildSize
= SdtGetInteger (Data
, &TempValue
);
705 if (*Data
!= PirqValue
)
711 Check every child package inside this interested parent package for update PRT
713 @param AcpiSdt Pointer to Acpi SDT protocol
714 @param ParentPkgHandle ACPI parent package handle
715 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
719 SdtCheckParentPackage (
720 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
721 IN EFI_ACPI_HANDLE ParentPkgHandle
,
722 IN PCI_DEVICE_INFO
*PciDeviceInfo
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
;
734 INTAPkgHandle
= INTBPkgHandle
= INTCPkgHandle
= INTDPkgHandle
= NULL
;
736 PciAddress
= SdtConvertToAcpiPciAdress(PciDeviceInfo
->DeviceAddress
);
738 if ((PciAddress
& 0xFFFF) == 0xFFFF) {
739 IsAllFunctions
= TRUE
;
741 IsAllFunctions
= FALSE
;
742 PciAddress
= (PciAddress
| 0xFFFF);
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
);
753 if ((PciDeviceInfo
->INTA
[IsAPIC
] != 0xFF) && (INTAPkgHandle
!= NULL
)) {
755 // Find INTA package and there is valid INTA update item, update it
757 SdtUpdateINTxPkg (AcpiSdt
, INTAPkgHandle
, (PciDeviceInfo
->INTA
[IsAPIC
]), IsAPIC
);
758 } else if ((PciDeviceInfo
->INTA
[IsAPIC
] != 0xFF) && (INTAPkgHandle
== NULL
)) {
760 // There is valid INTA update item, but no INA package exist, should add it
762 DEBUG ((EFI_D_ERROR
, "\n\nShould add INTA item for this device(0x%x)\n\n", PciAddress
));
764 } else if ((PciDeviceInfo
->INTA
[IsAPIC
] == 0xFF) && (INTAPkgHandle
!= NULL
) && IsAllFunctions
) {
766 // For all functions senario, if there is invalid INTA update item, but INTA package does exist, should delete it
768 DEBUG ((EFI_D_ERROR
, "\n\nShould remove INTA item for this device(0x%x)\n\n", PciAddress
));
775 if ((PciDeviceInfo
->INTB
[IsAPIC
] != 0xFF) && (INTBPkgHandle
!= NULL
)) {
777 // Find INTB package and there is valid INTB update item, update it
779 SdtUpdateINTxPkg (AcpiSdt
, INTBPkgHandle
, (PciDeviceInfo
->INTB
[IsAPIC
]), IsAPIC
);
780 } else if ((PciDeviceInfo
->INTB
[IsAPIC
] != 0xFF) && (INTBPkgHandle
== NULL
)) {
782 // There is valid INTB update item, but no INTB package exist, should add it
784 DEBUG ((EFI_D_ERROR
, "\n\nShould add INTB item for this device(0x%x)\n\n", PciAddress
));
786 } else if ((PciDeviceInfo
->INTB
[IsAPIC
] == 0xFF) && (INTBPkgHandle
!= NULL
) && IsAllFunctions
) {
788 // For all functions senario, if there is invalid INTB update item, but INTB package does exist, should delete it
790 DEBUG ((EFI_D_ERROR
, "\n\nShould remove INTB item for this device(0x%x)\n\n", PciAddress
));
797 if ((PciDeviceInfo
->INTC
[IsAPIC
] != 0xFF) && (INTCPkgHandle
!= NULL
)) {
799 // Find INTC package and there is valid INTC update item, update it
801 SdtUpdateINTxPkg (AcpiSdt
, INTCPkgHandle
, (PciDeviceInfo
->INTC
[IsAPIC
]), IsAPIC
);
802 } else if ((PciDeviceInfo
->INTC
[IsAPIC
] != 0xFF) && (INTCPkgHandle
== NULL
)) {
804 // There is valid INTC update item, but no INTC package exist, should add it
806 DEBUG ((EFI_D_ERROR
, "\n\nShould add INTC item for this device(0x%x)\n\n", PciAddress
));
808 } else if ((PciDeviceInfo
->INTC
[IsAPIC
] == 0xFF) && (INTCPkgHandle
!= NULL
) && IsAllFunctions
) {
810 // For all functions senario, if there is invalid INTC update item, but INTC package does exist, should delete it
812 DEBUG ((EFI_D_ERROR
, "\n\nShould remove INTC item for this device(0x%x)\n\n", PciAddress
));
818 if ((PciDeviceInfo
->INTD
[IsAPIC
] != 0xFF) && (INTDPkgHandle
!= NULL
)) {
820 // Find INTD package and there is valid INTD update item, update it
822 SdtUpdateINTxPkg (AcpiSdt
, INTDPkgHandle
, (PciDeviceInfo
->INTD
[IsAPIC
]), IsAPIC
);
823 } else if ((PciDeviceInfo
->INTD
[IsAPIC
] != 0xFF) && (INTDPkgHandle
== NULL
)) {
825 // There is valid INTD update item, but no INTD package exist, should add it
827 DEBUG ((EFI_D_ERROR
, "\n\nShould add INTD item for this device(0x%x)\n\n", PciAddress
));
829 } else if ((PciDeviceInfo
->INTD
[IsAPIC
] == 0xFF) && (INTDPkgHandle
!= NULL
) && IsAllFunctions
) {
831 // For all functions senario, if there is invalid INTD update item, but INTD package does exist, should delete it
833 DEBUG ((EFI_D_ERROR
, "\n\nShould remove INTD item for this device(0x%x)\n\n", PciAddress
));
837 if (INTAPkgHandle
!= NULL
) {
838 Status
= AcpiSdt
->Close (INTAPkgHandle
);
839 ASSERT_EFI_ERROR (Status
);
842 if (INTBPkgHandle
!= NULL
) {
843 Status
= AcpiSdt
->Close (INTBPkgHandle
);
844 ASSERT_EFI_ERROR (Status
);
847 if (INTCPkgHandle
!= NULL
) {
848 Status
= AcpiSdt
->Close (INTCPkgHandle
);
849 ASSERT_EFI_ERROR (Status
);
852 if (INTDPkgHandle
!= NULL
) {
853 Status
= AcpiSdt
->Close (INTDPkgHandle
);
854 ASSERT_EFI_ERROR (Status
);
861 Check every return package for update PRT
863 @param AcpiSdt Pointer to Acpi SDT protocol
864 @param ParentHandle ACPI pci device handle
865 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
869 SdtCheckReturnPackage (
870 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
871 IN EFI_ACPI_HANDLE MethodHandle
,
872 IN PCI_DEVICE_INFO
*PciDeviceInfo
875 EFI_ACPI_HANDLE PreviousHandle
;
876 EFI_ACPI_HANDLE ReturnHandle
;
877 EFI_ACPI_HANDLE PackageHandle
;
878 EFI_ACPI_HANDLE NamePkgHandle
;
880 EFI_ACPI_DATA_TYPE DataType
;
887 PreviousHandle
= ReturnHandle
;
888 Status
= AcpiSdt
->GetChild (MethodHandle
, &ReturnHandle
);
889 ASSERT_EFI_ERROR (Status
);
891 if (PreviousHandle
!= NULL
) {
892 Status
= AcpiSdt
->Close (PreviousHandle
);
893 ASSERT_EFI_ERROR (Status
);
896 if (ReturnHandle
== NULL
) {
900 Status
= AcpiSdt
->GetOption (ReturnHandle
, 0, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
901 ASSERT_EFI_ERROR (Status
);
902 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
904 if (*Data
== AML_RETURN_OP
) {
906 // Find the return method handle, then look for the returned package data
908 Status
= AcpiSdt
->GetOption (ReturnHandle
, 1, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
909 ASSERT_EFI_ERROR (Status
);
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
);
918 NamePkgHandle
= NULL
;
919 Status
= AcpiSdt
->FindPath (mDsdtHandle
, NameStr
, &NamePkgHandle
);
920 ASSERT_EFI_ERROR (Status
);
921 ASSERT (NamePkgHandle
!= NULL
);
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
);
928 Status
= AcpiSdt
->GetOption (NamePkgHandle
, 2, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
929 ASSERT_EFI_ERROR (Status
);
930 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_CHILD
);
933 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_CHILD
);
936 // Get the parent package handle
938 PackageHandle
= NULL
;
939 Status
= AcpiSdt
->Open (Data
, &PackageHandle
);
940 ASSERT_EFI_ERROR (Status
);
943 // Check the parent package for update pci routing
945 SdtCheckParentPackage (AcpiSdt
, PackageHandle
, PciDeviceInfo
);
947 Status
= AcpiSdt
->Close (PackageHandle
);
948 ASSERT_EFI_ERROR (Status
);
950 Status
= AcpiSdt
->Close (ReturnHandle
);
951 ASSERT_EFI_ERROR (Status
);
957 // Not ReturnOp, search it as parent
959 SdtCheckReturnPackage (AcpiSdt
, ReturnHandle
, PciDeviceInfo
);
970 update interrupt info inside the PRT method for the given pci device handle
972 @param AcpiSdt Pointer to Acpi SDT protocol
973 @param PciHandle ACPI pci device handle
974 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
979 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
980 IN EFI_ACPI_HANDLE PciHandle
,
981 IN PCI_DEVICE_INFO
*PciDeviceInfo
985 EFI_ACPI_HANDLE PrtMethodHandle
;
988 // Find the PRT method under this pci device
990 PrtMethodHandle
= NULL
;
991 Status
= AcpiSdt
->FindPath (PciHandle
, "_PRT", &PrtMethodHandle
);
993 if (EFI_ERROR (Status
)) {
994 return EFI_INVALID_PARAMETER
;
997 if (PrtMethodHandle
== NULL
) {
998 return EFI_INVALID_PARAMETER
;
1001 SdtCheckReturnPackage(AcpiSdt
, PrtMethodHandle
, PciDeviceInfo
);
1003 Status
= AcpiSdt
->Close (PrtMethodHandle
);
1004 ASSERT_EFI_ERROR (Status
);
1011 Update the package inside name op with correct wakeup resources
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
1020 SdtUpdatePackageInName (
1021 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
1022 IN EFI_ACPI_HANDLE INTxPkgHandle
,
1027 EFI_ACPI_HANDLE PreviousHandle
;
1029 EFI_ACPI_HANDLE MemberHandle
;
1030 EFI_ACPI_DATA_TYPE DataType
;
1035 // Check the gpe pin
1037 MemberHandle
= NULL
;
1038 Status
= AcpiSdt
->GetChild (INTxPkgHandle
, &MemberHandle
);
1039 ASSERT_EFI_ERROR (Status
);
1040 ASSERT (MemberHandle
!= NULL
);
1042 Status
= AcpiSdt
->GetOption (MemberHandle
, 0, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
1043 ASSERT_EFI_ERROR (Status
);
1044 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
1051 if (*Data
!= GPEPin
) {
1057 // Check the sx number
1059 PreviousHandle
= MemberHandle
;
1060 Status
= AcpiSdt
->GetChild (INTxPkgHandle
, &MemberHandle
);
1061 ASSERT_EFI_ERROR (Status
);
1062 ASSERT (MemberHandle
!= NULL
);
1064 if (PreviousHandle
!= NULL
) {
1065 Status
= AcpiSdt
->Close (PreviousHandle
);
1066 ASSERT_EFI_ERROR (Status
);
1069 Status
= AcpiSdt
->GetOption (MemberHandle
, 0, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
1070 ASSERT_EFI_ERROR (Status
);
1071 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
1078 if (*Data
!= SxNum
) {
1083 Status
= AcpiSdt
->Close (MemberHandle
);
1084 ASSERT_EFI_ERROR (Status
);
1089 Check the name package belonged to PRW
1091 @param AcpiSdt Pointer to Acpi SDT protocol
1092 @param PrwPkgHandle ACPI PRW package handle
1093 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
1097 SdtCheckNamePackage (
1098 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
1099 IN EFI_ACPI_HANDLE PrwPkgHandle
,
1100 IN PCI_DEVICE_INFO
*PciDeviceInfo
1103 EFI_ACPI_HANDLE InPkgHandle
;
1105 EFI_ACPI_DATA_TYPE DataType
;
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
);
1114 Status
= AcpiSdt
->GetOption (PrwPkgHandle
, 2, &DataType
, (CONST VOID
**)&Data
, &DataSize
);
1115 ASSERT_EFI_ERROR (Status
);
1116 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_CHILD
);
1119 // Get the inside package handle
1122 Status
= AcpiSdt
->Open (Data
, &InPkgHandle
);
1123 ASSERT_EFI_ERROR (Status
);
1126 // update the package in name op for wakeup info
1128 if ((PciDeviceInfo
->GPEPin
!= 0xFF) && (PciDeviceInfo
->SxNum
!= 0xFF))
1129 SdtUpdatePackageInName (AcpiSdt
, InPkgHandle
, PciDeviceInfo
->GPEPin
, PciDeviceInfo
->SxNum
);
1131 Status
= AcpiSdt
->Close (InPkgHandle
);
1132 ASSERT_EFI_ERROR (Status
);
1139 update wakeup info inside the PRW method for the given pci device handle
1141 @param AcpiSdt Pointer to Acpi SDT protocol
1142 @param PciHandle ACPI pci device handle
1143 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
1147 SdtUpdatePrwPackage (
1148 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
1149 IN EFI_ACPI_HANDLE PciHandle
,
1150 IN PCI_DEVICE_INFO
*PciDeviceInfo
1154 EFI_ACPI_HANDLE PrwPkgHandle
;
1157 // Find the PRT method under this pci device
1159 PrwPkgHandle
= NULL
;
1160 Status
= AcpiSdt
->FindPath (PciHandle
, "_PRW", &PrwPkgHandle
);
1162 if (EFI_ERROR (Status
)) {
1163 return EFI_INVALID_PARAMETER
;
1166 if (PrwPkgHandle
== NULL
) {
1167 return EFI_INVALID_PARAMETER
;
1170 SdtCheckNamePackage(AcpiSdt
, PrwPkgHandle
, PciDeviceInfo
);
1172 Status
= AcpiSdt
->Close (PrwPkgHandle
);
1173 ASSERT_EFI_ERROR (Status
);
1179 update pci routing information in acpi table based on pcd settings
1181 @param AcpiSdt Pointer to Acpi SDT protocol
1182 @param PciRootHandle ACPI root bridge handle
1183 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
1187 SdtUpdatePciRouting (
1188 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
1189 IN EFI_ACPI_HANDLE PciRootHandle
,
1190 IN PCI_DEVICE_INFO
*PciDeviceInfo
1194 EFI_ACPI_HANDLE PciBridgeHandle
;
1198 PciBridgeHandle
= NULL
;
1199 if (PciDeviceInfo
->BridgeAddress
== 0x00000000) {
1201 // Its bridge is the host root bridge
1203 PciBridgeHandle
= PciRootHandle
;
1208 // Its bridge is just a pci device under the host bridge
1212 // Conver the bridge address into one that acpi table can recognize
1214 PciAddress
= SdtConvertToAcpiPciAdress (PciDeviceInfo
->BridgeAddress
);
1217 // Scan the whole table to find the pci device
1219 PciBridgeHandle
= SdtGetHandleByScanAllChilds(AcpiSdt
, PciRootHandle
, SdtFindPciDeviceHandle
, &PciAddress
);
1220 if (PciBridgeHandle
== NULL
) {
1222 return EFI_INVALID_PARAMETER
;
1226 Status
= SdtUpdatePrtMethod(AcpiSdt
, PciBridgeHandle
, PciDeviceInfo
);
1228 if (PciDeviceInfo
->BridgeAddress
!= 0x00000000) {
1229 Status
= AcpiSdt
->Close (PciBridgeHandle
);
1230 ASSERT_EFI_ERROR (Status
);
1238 update power resource wake up information in acpi table based on pcd settings
1240 @param AcpiSdt Pointer to Acpi SDT protocol
1241 @param PciRootHandle ACPI root bridge handle
1242 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
1246 SdtUpdatePowerWake (
1247 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
1248 IN EFI_ACPI_HANDLE PciRootHandle
,
1249 IN PCI_DEVICE_INFO
*PciDeviceInfo
1253 EFI_ACPI_HANDLE PciBridgeHandle
;
1254 EFI_ACPI_HANDLE PciDeviceHandle
;
1257 PciBridgeHandle
= NULL
;
1258 if (PciDeviceInfo
->BridgeAddress
== 0x00000000) {
1260 // Its bridge is the host root bridge
1262 PciBridgeHandle
= PciRootHandle
;
1267 // Its bridge is just a pci device under the host bridge
1271 // Conver the bridge address into one that acpi table can recognize
1273 PciAddress
= SdtConvertToAcpiPciAdress (PciDeviceInfo
->BridgeAddress
);
1276 // Scan the whole table to find the pci device
1278 PciBridgeHandle
= SdtGetHandleByScanAllChilds(AcpiSdt
, PciRootHandle
, SdtFindPciDeviceHandle
, &PciAddress
);
1280 if (PciBridgeHandle
== NULL
) {
1282 Status
= AcpiSdt
->Close (PciRootHandle
);
1283 ASSERT_EFI_ERROR (Status
);
1285 return EFI_INVALID_PARAMETER
;
1289 PciDeviceHandle
= NULL
;
1292 // Conver the device address into one that acpi table can recognize
1294 PciAddress
= SdtConvertToAcpiPciAdress (PciDeviceInfo
->DeviceAddress
);
1297 // Scan the whole table to find the pci device
1299 PciDeviceHandle
= SdtGetHandleByScanAllChilds(AcpiSdt
, PciBridgeHandle
, SdtFindPciDeviceHandle
, &PciAddress
);
1301 if (PciDeviceHandle
== NULL
) {
1302 if (PciDeviceInfo
->BridgeAddress
!= 0x00000000) {
1303 Status
= AcpiSdt
->Close (PciBridgeHandle
);
1304 ASSERT_EFI_ERROR (Status
);
1307 return EFI_INVALID_PARAMETER
;
1310 Status
= SdtUpdatePrwPackage(AcpiSdt
, PciDeviceHandle
, PciDeviceInfo
);
1312 Status
= AcpiSdt
->Close (PciDeviceHandle
);
1313 ASSERT_EFI_ERROR (Status
);
1315 if (PciDeviceInfo
->BridgeAddress
!= 0x00000000) {
1316 Status
= AcpiSdt
->Close (PciBridgeHandle
);
1317 ASSERT_EFI_ERROR (Status
);
1325 Get the root bridge handle by scanning the acpi table
1327 @param AcpiSdt Pointer to Acpi SDT protocol
1328 @param DsdtHandle ACPI root handle
1330 @retval EFI_ACPI_HANDLE the handle of the root bridge
1333 SdtGetRootBridgeHandle (
1334 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdt
,
1335 IN EFI_ACPI_HANDLE DsdtHandle
1338 EFI_ACPI_HANDLE PciRootHandle
;
1341 // Scan the whole table to find the root bridge
1343 PciRootHandle
= NULL
;
1344 PciRootHandle
= SdtGetHandleByScanAllChilds(AcpiSdt
, DsdtHandle
, SdtFindRootBridgeHandle
, NULL
);
1345 ASSERT (PciRootHandle
!= NULL
);
1347 return PciRootHandle
;
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
1359 SdtCheckPciDeviceInfoChanged (
1360 IN PCI_DEVICE_INFO
*PciDeviceInfo
,
1361 IN BOOLEAN
*UpdatePRT
,
1362 IN BOOLEAN
*UpdatePRW
1367 if (mQNCPciInfo
== NULL
) {
1376 for (Index
= 0;Index
< CURRENT_PCI_DEVICE_NUM
; Index
++) {
1377 if ((mQNCPciInfo
[Index
].BridgeAddress
== PciDeviceInfo
->BridgeAddress
)
1378 && (mQNCPciInfo
[Index
].DeviceAddress
== PciDeviceInfo
->DeviceAddress
)) {
1380 // Find one matched entry
1382 if (CompareMem (&(mQNCPciInfo
[Index
].INTA
[0]), &PciDeviceInfo
->INTA
[0], 10) == 0) {
1385 //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and no change\n", Index));
1387 if (CompareMem (&(mQNCPciInfo
[Index
].INTA
[0]), &PciDeviceInfo
->INTA
[0], 8) == 0)
1390 if (CompareMem (&(mQNCPciInfo
[Index
].GPEPin
), &PciDeviceInfo
->GPEPin
, 2) == 0)
1393 if (*(UINT64
*)(&PciDeviceInfo
->INTA
[0]) == 0xFFFFFFFFFFFFFFFFULL
)
1396 if (*(UINT16
*)(&PciDeviceInfo
->GPEPin
) == 0xFFFF)
1399 //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and but need update PRT:0x%x PRW:0x%x\n", Index, *UpdatePRT, *UpdatePRW));
1405 //if (Index == 42) {
1406 // DEBUG ((EFI_D_ERROR, "Find No matched entry\n"));