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