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