• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 
3   Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
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 //
AppendCpuMapTableEntry(IN EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE * AcpiLocalApic)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;
ProcessorId2ApicId(UINT32 AcpiProcessorId)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++) {
GetProcNumberInPackage(IN UINT8 Package)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++) {
LocateCpuEistProtocol(IN UINT32 CpuIndex,OUT ENHANCED_SPEEDSTEP_PROTOCOL ** EistProtocol)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)) {
PlatformHookInit(VOID)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
AcpiPlatformHooksIsActiveTable(IN OUT EFI_ACPI_COMMON_HEADER * Table)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 
PatchGv3SsdtTable(IN OUT EFI_ACPI_DESCRIPTION_HEADER * TableHeader)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 
PatchDsdtTable(IN OUT EFI_ACPI_DESCRIPTION_HEADER * TableHeader)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