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