• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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 TURE  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 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
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 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
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   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
SdtFindRootBridgeHandle(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE CheckHandle,IN VOID * Context)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
SdtFindPciDeviceHandle(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE CheckHandle,IN VOID * Context)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
SdtGetHandleByScanAllChilds(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE ParentHandle,IN CHECK_HANDLE_INFO CheckHandleInfo,IN VOID * Context)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
SdtCheckINTxPkgIsMatch(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE INTxPkgHandle,IN UINT32 PciAddress,IN UINT8 INTx,IN BOOLEAN * IsAPIC)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
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)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
SdtUpdateINTxPkg(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE INTxPkgHandle,IN UINT8 PirqValue,IN BOOLEAN IsAPIC)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
SdtCheckParentPackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE ParentPkgHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtCheckReturnPackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE MethodHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePrtMethod(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePackageInName(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE INTxPkgHandle,IN UINT8 GPEPin,IN UINT8 SxNum)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
SdtCheckNamePackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PrwPkgHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePrwPackage(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePciRouting(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciRootHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtUpdatePowerWake(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE PciRootHandle,IN PCI_DEVICE_INFO * PciDeviceInfo)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
SdtGetRootBridgeHandle(IN EFI_ACPI_SDT_PROTOCOL * AcpiSdt,IN EFI_ACPI_HANDLE DsdtHandle)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
SdtCheckPciDeviceInfoChanged(IN PCI_DEVICE_INFO * PciDeviceInfo,IN BOOLEAN * UpdatePRT,IN BOOLEAN * UpdatePRW)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