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