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