--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ \r\r
+ This program and the accompanying materials are licensed and made available under\r\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r\r
+ The full text of the license may be found at \r\r
+ http://opensource.org/licenses/bsd-license.php. \r\r
+ \r\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
+ \r\r
+\r
+Module Name:\r
+\r
+ AcpiPlatformHooks.c\r
+\r
+Abstract:\r
+\r
+ ACPI Platform Driver Hooks\r
+\r
+--*/\r
+\r
+//\r
+// Statements that include other files.\r
+//\r
+#include "AcpiPlatform.h"\r
+#include "AcpiPlatformHooks.h"\r
+#include "Platform.h"\r
+\r
+//\r
+// Prototypes of the various hook functions.\r
+//\r
+#include "AcpiPlatformHooksLib.h"\r
+\r
+extern EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea;\r
+extern SYSTEM_CONFIGURATION mSystemConfiguration;\r
+\r
+ENHANCED_SPEEDSTEP_PROTOCOL *mEistProtocol = NULL;\r
+\r
+EFI_CPU_ID_MAP mCpuApicIdAcpiIdMapTable[MAX_CPU_NUM];\r
+\r
+EFI_STATUS\r
+AppendCpuMapTableEntry (\r
+ IN EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *AcpiLocalApic\r
+ )\r
+{\r
+ BOOLEAN Added;\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {\r
+ if ((mCpuApicIdAcpiIdMapTable[Index].ApicId == AcpiLocalApic->ApicId) && mCpuApicIdAcpiIdMapTable[Index].Flags) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ Added = FALSE;\r
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {\r
+ if (!mCpuApicIdAcpiIdMapTable[Index].Flags) {\r
+ mCpuApicIdAcpiIdMapTable[Index].Flags = 1;\r
+ mCpuApicIdAcpiIdMapTable[Index].ApicId = AcpiLocalApic->ApicId;\r
+ mCpuApicIdAcpiIdMapTable[Index].AcpiProcessorId = AcpiLocalApic->AcpiProcessorId;\r
+ Added = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ ASSERT (Added);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINT32\r
+ProcessorId2ApicId (\r
+ UINT32 AcpiProcessorId\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ ASSERT (AcpiProcessorId < MAX_CPU_NUM);\r
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {\r
+ if (mCpuApicIdAcpiIdMapTable[Index].Flags && (mCpuApicIdAcpiIdMapTable[Index].AcpiProcessorId == AcpiProcessorId)) {\r
+ return mCpuApicIdAcpiIdMapTable[Index].ApicId;\r
+ }\r
+ }\r
+\r
+ return (UINT32) -1;\r
+}\r
+\r
+UINT8\r
+GetProcNumberInPackage (\r
+ IN UINT8 Package\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 Number;\r
+\r
+ Number = 0;\r
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {\r
+ if (mCpuApicIdAcpiIdMapTable[Index].Flags && (((mCpuApicIdAcpiIdMapTable[Index].ApicId >> 0x04) & 0x01) == Package)) {\r
+ Number++;\r
+ }\r
+ }\r
+\r
+ return Number;\r
+}\r
+\r
+EFI_STATUS\r
+LocateCpuEistProtocol (\r
+ IN UINT32 CpuIndex,\r
+ OUT ENHANCED_SPEEDSTEP_PROTOCOL **EistProtocol\r
+ )\r
+{\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ ENHANCED_SPEEDSTEP_PROTOCOL *EistProt;\r
+ UINTN Index;\r
+ UINT32 ApicId;\r
+ EFI_STATUS Status;\r
+\r
+ HandleCount = 0;\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEnhancedSpeedstepProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ Index = 0;\r
+ EistProt = NULL;\r
+ Status = EFI_NOT_FOUND;\r
+ while (Index < HandleCount) {\r
+ gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEnhancedSpeedstepProtocolGuid,\r
+ (VOID **) &EistProt\r
+ );\r
+ //\r
+ // Adjust the CpuIndex by +1 due to the AcpiProcessorId is 1 based.\r
+ //\r
+ ApicId = ProcessorId2ApicId (CpuIndex+1);\r
+ if (ApicId == (UINT32) -1) {\r
+ break;\r
+ }\r
+\r
+ if (EistProt->ProcApicId == ApicId) {\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ gBS->FreePool (HandleBuffer);\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ *EistProtocol = EistProt;\r
+ } else {\r
+ *EistProtocol = NULL;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+PlatformHookInit (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEnhancedSpeedstepProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mEistProtocol\r
+ );\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Called for every ACPI table found in the BIOS flash.\r
+ Returns whether a table is active or not. Inactive tables\r
+ are not published in the ACPI table list.\r
+\r
+ This hook can be used to implement optional SSDT tables or\r
+ enabling/disabling specific functionality (e.g. SPCR table)\r
+ based on a setup switch or platform preference. In case of\r
+ optional SSDT tables,the platform flash will include all the\r
+ SSDT tables but will return EFI_SUCCESS only for those tables\r
+ that need to be published.\r
+\r
+ @param[in] *Table Pointer to the active table.\r
+\r
+ @retval EFI_SUCCESS if the table is active.\r
+ @retval EFI_UNSUPPORTED if the table is not active.\r
+\r
+**/\r
+EFI_STATUS\r
+AcpiPlatformHooksIsActiveTable (\r
+ IN OUT EFI_ACPI_COMMON_HEADER *Table\r
+ )\r
+{\r
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;\r
+\r
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;\r
+\r
+ if (TableHeader->Signature == EFI_ACPI_2_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE) {\r
+\r
+ }\r
+\r
+ if ((mSystemConfiguration.ENDBG2 == 0) && (CompareMem (&TableHeader->OemTableId, "INTLDBG2", 8) == 0)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update the GV3 SSDT table.\r
+\r
+ @param[in][out] *TableHeader The table to be set.\r
+\r
+ @retval EFI_SUCCESS Returns Success.\r
+\r
+**/\r
+EFI_STATUS\r
+PatchGv3SsdtTable (\r
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *CurrPtr;\r
+ UINT8 *SsdtPointer;\r
+ UINT32 Signature;\r
+ UINT32 CpuFixes;\r
+ UINT32 NpssFixes;\r
+ UINT32 SpssFixes;\r
+ UINT32 CpuIndex;\r
+ UINT32 PackageSize;\r
+ UINT32 NewPackageSize;\r
+ UINT32 AdjustSize;\r
+ UINTN EntryIndex;\r
+ UINTN TableIndex;\r
+ EFI_ACPI_NAME_COMMAND *PssTable;\r
+ EFI_PSS_PACKAGE *PssTableItemPtr;\r
+ ENHANCED_SPEEDSTEP_PROTOCOL *EistProt;\r
+ EIST_INFORMATION *EistInfo;\r
+ EFI_ACPI_CPU_PSS_STATE *PssState;\r
+ EFI_ACPI_NAMEPACK_DWORD *NamePtr;\r
+ //\r
+ // Loop through the ASL looking for values that we must fix up.\r
+ //\r
+ NpssFixes = 0;\r
+ SpssFixes = 0;\r
+ CpuFixes = 0;\r
+ CpuIndex = 0;\r
+ CurrPtr = (UINT8 *) TableHeader;\r
+\r
+ EistProt = NULL;\r
+ for (SsdtPointer = CurrPtr; SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); SsdtPointer++) {\r
+ Signature = *(UINT32 *) SsdtPointer;\r
+ switch (Signature) {\r
+\r
+ case SIGNATURE_32 ('_', 'P', 'R', '_'):\r
+ //\r
+ // _CPUX ('0' to '0xF')\r
+ //\r
+ CpuIndex = *(SsdtPointer + 7);\r
+ if (CpuIndex >= '0' && CpuIndex <= '9') {\r
+ CpuIndex -= '0';\r
+ } else {\r
+ if (CpuIndex > '9') {\r
+ CpuIndex -= '7';\r
+ }\r
+ }\r
+\r
+ CpuFixes++;\r
+ LocateCpuEistProtocol (CpuIndex, &EistProt);\r
+ break;\r
+\r
+ case SIGNATURE_32 ('D', 'O', 'M', 'N'):\r
+\r
+ NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);\r
+ if (NamePtr->StartByte != AML_NAME_OP) {\r
+ continue;\r
+ }\r
+\r
+ if (NamePtr->Size != AML_NAME_DWORD_SIZE) {\r
+ continue;\r
+ }\r
+\r
+ NamePtr->Value = 0;\r
+\r
+ if (mCpuApicIdAcpiIdMapTable[CpuIndex].Flags) {\r
+ NamePtr->Value = (mCpuApicIdAcpiIdMapTable[CpuIndex].ApicId >> 0x04) & 0x01;\r
+ }\r
+ break;\r
+\r
+ case SIGNATURE_32 ('N', 'C', 'P', 'U'):\r
+\r
+ NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);\r
+ if (NamePtr->StartByte != AML_NAME_OP) {\r
+ continue;\r
+ }\r
+\r
+ if (NamePtr->Size != AML_NAME_DWORD_SIZE) {\r
+ continue;\r
+ }\r
+\r
+ NamePtr->Value = 0;\r
+ if (mCpuApicIdAcpiIdMapTable[CpuIndex].Flags) {\r
+ NamePtr->Value = GetProcNumberInPackage ((mCpuApicIdAcpiIdMapTable[CpuIndex].ApicId >> 0x04) & 0x01);\r
+ }\r
+ break;\r
+\r
+ case SIGNATURE_32 ('N', 'P', 'S', 'S'):\r
+ case SIGNATURE_32 ('S', 'P', 'S', 'S'):\r
+ if (EistProt == NULL) {\r
+ continue;\r
+ }\r
+\r
+ PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);\r
+ if (PssTable->StartByte != AML_NAME_OP) {\r
+ continue;\r
+ }\r
+\r
+ Status = EistProt->GetEistTable (EistProt, &EistInfo, (VOID **) &PssState);\r
+\r
+ AdjustSize = PssTable->NumEntries * sizeof (EFI_PSS_PACKAGE);\r
+ AdjustSize -= EistInfo->NumStates * sizeof (EFI_PSS_PACKAGE);\r
+ PackageSize = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4);\r
+ NewPackageSize = PackageSize - AdjustSize;\r
+ PssTable->Size = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4));\r
+\r
+ //\r
+ // Set most significant two bits of byte zero to 01, meaning two bytes used.\r
+ //\r
+ PssTable->Size |= 0x40;\r
+\r
+ //\r
+ // Set unused table to Noop Code.\r
+ //\r
+ SetMem( (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE, AdjustSize, AML_NOOP_OP);\r
+ PssTable->NumEntries = (UINT8) EistInfo->NumStates;\r
+ PssTableItemPtr = (EFI_PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (EFI_ACPI_NAME_COMMAND));\r
+\r
+ //\r
+ // Update the size.\r
+ //\r
+ for (TableIndex = 0; TableIndex < EistInfo->NumStates; TableIndex++) {\r
+ EntryIndex = EistInfo->NumStates - TableIndex - 1;\r
+ PssTableItemPtr->CoreFreq = PssState[EntryIndex].CoreFrequency * PssState[EntryIndex].Control;\r
+ PssTableItemPtr->Power = PssState[EntryIndex].Power * 1000;\r
+ if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {\r
+ PssTableItemPtr->BMLatency = PssState[EntryIndex].BusMasterLatency;\r
+ PssTableItemPtr->TransLatency = PssState[EntryIndex].TransitionLatency;\r
+ } else {\r
+ //\r
+ // This method should be supported by SMM PPM Handler.\r
+ //\r
+ PssTableItemPtr->BMLatency = PssState[EntryIndex].BusMasterLatency * 2;\r
+ PssTableItemPtr->TransLatency = PssState[EntryIndex].TransitionLatency * 10;\r
+ }\r
+\r
+ PssTableItemPtr->Control = PssState[EntryIndex].Control;\r
+ PssTableItemPtr->Status = PssState[EntryIndex].Status;\r
+ PssTableItemPtr++;\r
+ }\r
+\r
+ if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {\r
+ NpssFixes++;\r
+ } else {\r
+ SpssFixes++;\r
+ }\r
+\r
+ SsdtPointer = (UINT8 *) PssTable + PackageSize;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // N fixes together currently.\r
+ //\r
+ ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);\r
+ ASSERT (SpssFixes == NpssFixes);\r
+ ASSERT (CpuFixes >= SpssFixes);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update the DSDT table.\r
+\r
+ @param[in][out] *TableHeader The table to be set.\r
+\r
+ @retval EFI_SUCCESS Returns EFI_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+PatchDsdtTable (\r
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader\r
+ )\r
+{\r
+\r
+ UINT8 *CurrPtr;\r
+ UINT8 *DsdtPointer;\r
+ UINT32 *Signature;\r
+ UINT8 *EndPtr;\r
+ UINT8 *Operation;\r
+ UINT32 *Address;\r
+ UINT16 *Size;\r
+\r
+ //\r
+ // Fix PCI32 resource "FIX0" -- PSYS system status area\r
+ //\r
+ CurrPtr = (UINT8*) &((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)[0];\r
+ EndPtr = (UINT8*) TableHeader;\r
+ EndPtr = EndPtr + TableHeader->Length;\r
+ while (CurrPtr < (EndPtr-2)) {\r
+ //\r
+ // Removed the _S3 tag to indicate that we do not support S3. The 4th byte is blank space\r
+ // since there are only 3 char "_S3".\r
+ //\r
+ if (mSystemConfiguration.AcpiSuspendState == 0) {\r
+ //\r
+ // For iasl compiler version 20061109.\r
+ //\r
+ if ((CurrPtr[0] == '_') && (CurrPtr[1] == 'S') && (CurrPtr[2] == '3') && (CurrPtr[3] == '_')) {\r
+ break;\r
+ }\r
+ //\r
+ // For iasl compiler version 20040527.\r
+ //\r
+ if ((CurrPtr[0] == '\\') && (CurrPtr[1] == '_') && (CurrPtr[2] == 'S') && (CurrPtr[3] == '3')) {\r
+ break;\r
+ }\r
+ }\r
+ CurrPtr++;\r
+ }\r
+ CurrPtr = (UINT8*) &((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)[0];\r
+ EndPtr = (UINT8*) TableHeader;\r
+ EndPtr = EndPtr + TableHeader->Length;\r
+ while (CurrPtr < (EndPtr-2)) {\r
+ //\r
+ // For mipi dsi port select _DEP.\r
+ //\r
+ if (mSystemConfiguration.MipiDsi== 1) {\r
+ //\r
+ // For iasl compiler version 20061109.\r
+ //\r
+ if ((CurrPtr[0] == 'N') && (CurrPtr[1] == 'D') && (CurrPtr[2] == 'E') && (CurrPtr[3] == 'P')) {\r
+ CurrPtr[0] = '_';\r
+ break;\r
+ }\r
+\r
+ } else {\r
+ if ((CurrPtr[0] == 'P') && (CurrPtr[1] == 'D') && (CurrPtr[2] == 'E') && (CurrPtr[3] == 'P')) {\r
+ CurrPtr[0] = '_';\r
+ break;\r
+ }\r
+\r
+ }\r
+ CurrPtr++;\r
+ }\r
+ //\r
+ // Loop through the ASL looking for values that we must fix up.\r
+ //\r
+ CurrPtr = (UINT8 *) TableHeader;\r
+ for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {\r
+ Signature = (UINT32 *) DsdtPointer;\r
+\r
+ switch (*Signature) {\r
+ //\r
+ // GNVS operation region.\r
+ //\r
+ case (SIGNATURE_32 ('G', 'N', 'V', 'S')):\r
+ //\r
+ // Conditional match. For Region Objects, the Operator will always be the\r
+ // byte immediately before the specific name. Therefore, subtract 1 to check\r
+ // the Operator.\r
+ //\r
+ Operation = DsdtPointer - 1;\r
+ if (*Operation == AML_OPREGION_OP) {\r
+ Address = (UINT32 *) (DsdtPointer + 6);\r
+ *Address = (UINT32) (UINTN) mGlobalNvsArea.Area;\r
+ Size = (UINT16 *) (DsdtPointer + 11);\r
+ *Size = sizeof (EFI_GLOBAL_NVS_AREA);\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r