• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
InitPciDeviceInfoStructure(PCI_DEVICE_SETTING * mConfigData)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
SdtGetInteger(IN UINT8 * Data,OUT UINT64 * Integer)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
SdtIsThisTypeObject(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE Handle,IN UINT8 OpCode,IN UINT8 SubOpCode)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
SdtIsNameIntegerValueEqual(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE Handle,IN CHAR8 * Name,IN UINT64 Value)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
SdtCheckNameIntegerValue(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE ParentHandle,IN CHAR8 * Name,IN UINT64 Value)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
SdtConvertToAcpiPciAdress(IN UINT32 PciAddress)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
SdtGetNameStringSize(IN UINT8 * Buffer)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
SdtFindRootBridgeHandle(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE CheckHandle,IN VOID * Context)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
SdtFindPciDeviceHandle(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE CheckHandle,IN VOID * Context)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
SdtGetHandleByScanAllChilds(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE ParentHandle,IN CHECK_HANDLE_INFO CheckHandleInfo,IN VOID * Context)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
SdtCheckINTxPkgIsMatch(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE INTxPkgHandle,IN UINT32 PciAddress,IN UINT8 INTx,IN BOOLEAN * IsAPIC)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
SdtGetINTxPkgHandle(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE ParentPkgHandle,IN UINT32 PciAddress,IN UINT8 INTx,IN EFI_ACPI_HANDLE * INTxPkgHandle,IN BOOLEAN * IsAPIC)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
SdtUpdateINTxPkg(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE INTxPkgHandle,IN UINT8 PirqValue,IN BOOLEAN IsAPIC)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
SdtCheckParentPackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE ParentPkgHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtCheckReturnPackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE MethodHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePrtMethod(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePackageInName(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE INTxPkgHandle,IN UINT8 GPEPin,IN UINT8 SxNum)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
SdtCheckNamePackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PrwPkgHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePrwPackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePciRouting(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciRootHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePowerWake(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciRootHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtGetRootBridgeHandle(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE DsdtHandle)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
SdtCheckPciDeviceInfoChanged(IN PCI_DEVICE_INFO * PciDeviceInfo,IN BOOLEAN * UpdatePRT,IN BOOLEAN * UpdatePRW)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