AcpiPciUpdate.c 36 KB

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