AcpiPlatformHooks.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /** @file
  2. Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. Module Name:
  5. AcpiPlatformHooks.c
  6. Abstract:
  7. ACPI Platform Driver Hooks
  8. --*/
  9. //
  10. // Statements that include other files.
  11. //
  12. #include "AcpiPlatform.h"
  13. #include "AcpiPlatformHooks.h"
  14. #include "Platform.h"
  15. //
  16. // Prototypes of the various hook functions.
  17. //
  18. #include "AcpiPlatformHooksLib.h"
  19. extern SYSTEM_CONFIGURATION mSystemConfiguration;
  20. ENHANCED_SPEEDSTEP_PROTOCOL *mEistProtocol = NULL;
  21. EFI_CPU_ID_MAP mCpuApicIdAcpiIdMapTable[MAX_CPU_NUM];
  22. EFI_STATUS
  23. AppendCpuMapTableEntry (
  24. IN EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *AcpiLocalApic
  25. )
  26. {
  27. BOOLEAN Added;
  28. UINTN Index;
  29. for (Index = 0; Index < MAX_CPU_NUM; Index++) {
  30. if ((mCpuApicIdAcpiIdMapTable[Index].ApicId == AcpiLocalApic->ApicId) && mCpuApicIdAcpiIdMapTable[Index].Flags) {
  31. return EFI_SUCCESS;
  32. }
  33. }
  34. Added = FALSE;
  35. for (Index = 0; Index < MAX_CPU_NUM; Index++) {
  36. if (!mCpuApicIdAcpiIdMapTable[Index].Flags) {
  37. mCpuApicIdAcpiIdMapTable[Index].Flags = 1;
  38. mCpuApicIdAcpiIdMapTable[Index].ApicId = AcpiLocalApic->ApicId;
  39. mCpuApicIdAcpiIdMapTable[Index].AcpiProcessorId = AcpiLocalApic->AcpiProcessorId;
  40. Added = TRUE;
  41. break;
  42. }
  43. }
  44. ASSERT (Added);
  45. return EFI_SUCCESS;
  46. }
  47. UINT32
  48. ProcessorId2ApicId (
  49. UINT32 AcpiProcessorId
  50. )
  51. {
  52. UINTN Index;
  53. ASSERT (AcpiProcessorId < MAX_CPU_NUM);
  54. for (Index = 0; Index < MAX_CPU_NUM; Index++) {
  55. if (mCpuApicIdAcpiIdMapTable[Index].Flags && (mCpuApicIdAcpiIdMapTable[Index].AcpiProcessorId == AcpiProcessorId)) {
  56. return mCpuApicIdAcpiIdMapTable[Index].ApicId;
  57. }
  58. }
  59. return (UINT32) -1;
  60. }
  61. UINT8
  62. GetProcNumberInPackage (
  63. IN UINT8 Package
  64. )
  65. {
  66. UINTN Index;
  67. UINT8 Number;
  68. Number = 0;
  69. for (Index = 0; Index < MAX_CPU_NUM; Index++) {
  70. if (mCpuApicIdAcpiIdMapTable[Index].Flags && (((mCpuApicIdAcpiIdMapTable[Index].ApicId >> 0x04) & 0x01) == Package)) {
  71. Number++;
  72. }
  73. }
  74. return Number;
  75. }
  76. EFI_STATUS
  77. LocateCpuEistProtocol (
  78. IN UINT32 CpuIndex,
  79. OUT ENHANCED_SPEEDSTEP_PROTOCOL **EistProtocol
  80. )
  81. {
  82. UINTN HandleCount;
  83. EFI_HANDLE *HandleBuffer;
  84. ENHANCED_SPEEDSTEP_PROTOCOL *EistProt;
  85. UINTN Index;
  86. UINT32 ApicId;
  87. EFI_STATUS Status;
  88. HandleCount = 0;
  89. gBS->LocateHandleBuffer (
  90. ByProtocol,
  91. &gEnhancedSpeedstepProtocolGuid,
  92. NULL,
  93. &HandleCount,
  94. &HandleBuffer
  95. );
  96. Index = 0;
  97. EistProt = NULL;
  98. Status = EFI_NOT_FOUND;
  99. while (Index < HandleCount) {
  100. gBS->HandleProtocol (
  101. HandleBuffer[Index],
  102. &gEnhancedSpeedstepProtocolGuid,
  103. (VOID **) &EistProt
  104. );
  105. //
  106. // Adjust the CpuIndex by +1 due to the AcpiProcessorId is 1 based.
  107. //
  108. ApicId = ProcessorId2ApicId (CpuIndex+1);
  109. if (ApicId == (UINT32) -1) {
  110. break;
  111. }
  112. if (EistProt->ProcApicId == ApicId) {
  113. Status = EFI_SUCCESS;
  114. break;
  115. }
  116. Index++;
  117. }
  118. if (HandleBuffer != NULL) {
  119. gBS->FreePool (HandleBuffer);
  120. }
  121. if (!EFI_ERROR (Status)) {
  122. *EistProtocol = EistProt;
  123. } else {
  124. *EistProtocol = NULL;
  125. }
  126. return Status;
  127. }
  128. EFI_STATUS
  129. PlatformHookInit (
  130. VOID
  131. )
  132. {
  133. EFI_STATUS Status;
  134. Status = gBS->LocateProtocol (
  135. &gEnhancedSpeedstepProtocolGuid,
  136. NULL,
  137. (VOID **) &mEistProtocol
  138. );
  139. ASSERT_EFI_ERROR (Status);
  140. return Status;
  141. }
  142. /**
  143. Called for every ACPI table found in the BIOS flash.
  144. Returns whether a table is active or not. Inactive tables
  145. are not published in the ACPI table list.
  146. This hook can be used to implement optional SSDT tables or
  147. enabling/disabling specific functionality (e.g. SPCR table)
  148. based on a setup switch or platform preference. In case of
  149. optional SSDT tables,the platform flash will include all the
  150. SSDT tables but will return EFI_SUCCESS only for those tables
  151. that need to be published.
  152. @param[in] *Table Pointer to the active table.
  153. @retval EFI_SUCCESS if the table is active.
  154. @retval EFI_UNSUPPORTED if the table is not active.
  155. **/
  156. EFI_STATUS
  157. AcpiPlatformHooksIsActiveTable (
  158. IN OUT EFI_ACPI_COMMON_HEADER *Table
  159. )
  160. {
  161. EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
  162. TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
  163. if (TableHeader->Signature == EFI_ACPI_2_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE) {
  164. }
  165. if ((mSystemConfiguration.ENDBG2 == 0) && (CompareMem (&TableHeader->OemTableId, "INTLDBG2", 8) == 0)) {
  166. return EFI_UNSUPPORTED;
  167. }
  168. return EFI_SUCCESS;
  169. }
  170. /**
  171. Update the GV3 SSDT table.
  172. @param[in][out] *TableHeader The table to be set.
  173. @retval EFI_SUCCESS Returns Success.
  174. **/
  175. EFI_STATUS
  176. PatchGv3SsdtTable (
  177. IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader
  178. )
  179. {
  180. UINT8 *CurrPtr;
  181. UINT8 *SsdtPointer;
  182. UINT32 Signature;
  183. UINT32 CpuFixes;
  184. UINT32 NpssFixes;
  185. UINT32 SpssFixes;
  186. UINT32 CpuIndex;
  187. UINT32 PackageSize;
  188. UINT32 NewPackageSize;
  189. UINT32 AdjustSize;
  190. UINTN EntryIndex;
  191. UINTN TableIndex;
  192. EFI_ACPI_NAME_COMMAND *PssTable;
  193. EFI_PSS_PACKAGE *PssTableItemPtr;
  194. ENHANCED_SPEEDSTEP_PROTOCOL *EistProt;
  195. EIST_INFORMATION *EistInfo;
  196. EFI_ACPI_CPU_PSS_STATE *PssState;
  197. EFI_ACPI_NAMEPACK_DWORD *NamePtr;
  198. //
  199. // Loop through the ASL looking for values that we must fix up.
  200. //
  201. NpssFixes = 0;
  202. SpssFixes = 0;
  203. CpuFixes = 0;
  204. CpuIndex = 0;
  205. CurrPtr = (UINT8 *) TableHeader;
  206. EistProt = NULL;
  207. for (SsdtPointer = CurrPtr; SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); SsdtPointer++) {
  208. Signature = *(UINT32 *) SsdtPointer;
  209. switch (Signature) {
  210. case SIGNATURE_32 ('_', 'P', 'R', '_'):
  211. //
  212. // _CPUX ('0' to '0xF')
  213. //
  214. CpuIndex = *(SsdtPointer + 7);
  215. if (CpuIndex >= '0' && CpuIndex <= '9') {
  216. CpuIndex -= '0';
  217. } else {
  218. if (CpuIndex > '9') {
  219. CpuIndex -= '7';
  220. }
  221. }
  222. CpuFixes++;
  223. LocateCpuEistProtocol (CpuIndex, &EistProt);
  224. break;
  225. case SIGNATURE_32 ('D', 'O', 'M', 'N'):
  226. NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
  227. if (NamePtr->StartByte != AML_NAME_OP) {
  228. continue;
  229. }
  230. if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
  231. continue;
  232. }
  233. NamePtr->Value = 0;
  234. if (mCpuApicIdAcpiIdMapTable[CpuIndex].Flags) {
  235. NamePtr->Value = (mCpuApicIdAcpiIdMapTable[CpuIndex].ApicId >> 0x04) & 0x01;
  236. }
  237. break;
  238. case SIGNATURE_32 ('N', 'C', 'P', 'U'):
  239. NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
  240. if (NamePtr->StartByte != AML_NAME_OP) {
  241. continue;
  242. }
  243. if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
  244. continue;
  245. }
  246. NamePtr->Value = 0;
  247. if (mCpuApicIdAcpiIdMapTable[CpuIndex].Flags) {
  248. NamePtr->Value = GetProcNumberInPackage ((mCpuApicIdAcpiIdMapTable[CpuIndex].ApicId >> 0x04) & 0x01);
  249. }
  250. break;
  251. case SIGNATURE_32 ('N', 'P', 'S', 'S'):
  252. case SIGNATURE_32 ('S', 'P', 'S', 'S'):
  253. if (EistProt == NULL) {
  254. continue;
  255. }
  256. PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
  257. if (PssTable->StartByte != AML_NAME_OP) {
  258. continue;
  259. }
  260. EistProt->GetEistTable (EistProt, &EistInfo, (VOID **) &PssState);
  261. AdjustSize = PssTable->NumEntries * sizeof (EFI_PSS_PACKAGE);
  262. AdjustSize -= EistInfo->NumStates * sizeof (EFI_PSS_PACKAGE);
  263. PackageSize = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4);
  264. NewPackageSize = PackageSize - AdjustSize;
  265. PssTable->Size = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4));
  266. //
  267. // Set most significant two bits of byte zero to 01, meaning two bytes used.
  268. //
  269. PssTable->Size |= 0x40;
  270. //
  271. // Set unused table to Noop Code.
  272. //
  273. SetMem( (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE, AdjustSize, AML_NOOP_OP);
  274. PssTable->NumEntries = (UINT8) EistInfo->NumStates;
  275. PssTableItemPtr = (EFI_PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (EFI_ACPI_NAME_COMMAND));
  276. //
  277. // Update the size.
  278. //
  279. for (TableIndex = 0; TableIndex < EistInfo->NumStates; TableIndex++) {
  280. EntryIndex = EistInfo->NumStates - TableIndex - 1;
  281. PssTableItemPtr->CoreFreq = PssState[EntryIndex].CoreFrequency * PssState[EntryIndex].Control;
  282. PssTableItemPtr->Power = PssState[EntryIndex].Power * 1000;
  283. if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
  284. PssTableItemPtr->BMLatency = PssState[EntryIndex].BusMasterLatency;
  285. PssTableItemPtr->TransLatency = PssState[EntryIndex].TransitionLatency;
  286. } else {
  287. //
  288. // This method should be supported by SMM PPM Handler.
  289. //
  290. PssTableItemPtr->BMLatency = PssState[EntryIndex].BusMasterLatency * 2;
  291. PssTableItemPtr->TransLatency = PssState[EntryIndex].TransitionLatency * 10;
  292. }
  293. PssTableItemPtr->Control = PssState[EntryIndex].Control;
  294. PssTableItemPtr->Status = PssState[EntryIndex].Status;
  295. PssTableItemPtr++;
  296. }
  297. if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
  298. NpssFixes++;
  299. } else {
  300. SpssFixes++;
  301. }
  302. SsdtPointer = (UINT8 *) PssTable + PackageSize;
  303. break;
  304. }
  305. }
  306. //
  307. // N fixes together currently.
  308. //
  309. ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);
  310. ASSERT (SpssFixes == NpssFixes);
  311. ASSERT (CpuFixes >= SpssFixes);
  312. return EFI_SUCCESS;
  313. }
  314. /**
  315. Update the DSDT table.
  316. @param[in][out] *TableHeader The table to be set.
  317. @retval EFI_SUCCESS Returns EFI_SUCCESS.
  318. **/
  319. EFI_STATUS
  320. PatchDsdtTable (
  321. IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader
  322. )
  323. {
  324. UINT8 *CurrPtr;
  325. UINT8 *DsdtPointer;
  326. UINT32 *Signature;
  327. UINT8 *EndPtr;
  328. UINT8 *Operation;
  329. UINT32 *Address;
  330. UINT16 *Size;
  331. //
  332. // Fix PCI32 resource "FIX0" -- PSYS system status area
  333. //
  334. CurrPtr = (UINT8*) &((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)[0];
  335. EndPtr = (UINT8*) TableHeader;
  336. EndPtr = EndPtr + TableHeader->Length;
  337. while (CurrPtr < (EndPtr-2)) {
  338. //
  339. // Removed the _S3 tag to indicate that we do not support S3. The 4th byte is blank space
  340. // since there are only 3 char "_S3".
  341. //
  342. if (mSystemConfiguration.AcpiSuspendState == 0) {
  343. //
  344. // For iasl compiler version 20061109.
  345. //
  346. if ((CurrPtr[0] == '_') && (CurrPtr[1] == 'S') && (CurrPtr[2] == '3') && (CurrPtr[3] == '_')) {
  347. break;
  348. }
  349. //
  350. // For iasl compiler version 20040527.
  351. //
  352. if ((CurrPtr[0] == '\\') && (CurrPtr[1] == '_') && (CurrPtr[2] == 'S') && (CurrPtr[3] == '3')) {
  353. break;
  354. }
  355. }
  356. CurrPtr++;
  357. }
  358. CurrPtr = (UINT8*) &((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)[0];
  359. EndPtr = (UINT8*) TableHeader;
  360. EndPtr = EndPtr + TableHeader->Length;
  361. while (CurrPtr < (EndPtr-2)) {
  362. //
  363. // For mipi dsi port select _DEP.
  364. //
  365. if (mSystemConfiguration.MipiDsi== 1) {
  366. //
  367. // For iasl compiler version 20061109.
  368. //
  369. if ((CurrPtr[0] == 'N') && (CurrPtr[1] == 'D') && (CurrPtr[2] == 'E') && (CurrPtr[3] == 'P')) {
  370. CurrPtr[0] = '_';
  371. break;
  372. }
  373. } else {
  374. if ((CurrPtr[0] == 'P') && (CurrPtr[1] == 'D') && (CurrPtr[2] == 'E') && (CurrPtr[3] == 'P')) {
  375. CurrPtr[0] = '_';
  376. break;
  377. }
  378. }
  379. CurrPtr++;
  380. }
  381. //
  382. // Loop through the ASL looking for values that we must fix up.
  383. //
  384. CurrPtr = (UINT8 *) TableHeader;
  385. for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {
  386. Signature = (UINT32 *) DsdtPointer;
  387. switch (*Signature) {
  388. //
  389. // GNVS operation region.
  390. //
  391. case (SIGNATURE_32 ('G', 'N', 'V', 'S')):
  392. //
  393. // Conditional match. For Region Objects, the Operator will always be the
  394. // byte immediately before the specific name. Therefore, subtract 1 to check
  395. // the Operator.
  396. //
  397. Operation = DsdtPointer - 1;
  398. if (*Operation == AML_OPREGION_OP) {
  399. Address = (UINT32 *) (DsdtPointer + 6);
  400. *Address = (UINT32) (UINTN) mGlobalNvsArea.Area;
  401. Size = (UINT16 *) (DsdtPointer + 11);
  402. *Size = sizeof (EFI_GLOBAL_NVS_AREA);
  403. }
  404. break;
  405. default:
  406. break;
  407. }
  408. }
  409. return EFI_SUCCESS;
  410. }