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