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