]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c
8f5e6a324cd296285b79287dafa55f7216bcca56
[mirror_edk2.git] / QuarkPlatformPkg / Acpi / DxeSmm / SmmPowerManagement / Ppm.c
1 /** @file
2
3 Processor power management initialization code.
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15
16 **/
17
18 #include "SmmPowerManagement.h"
19
20 //
21 // Global variables
22 //
23 extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;
24 extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
25
26 extern EFI_GUID gPowerManagementAcpiTableStorageGuid;
27
28 /**
29 This function is the entry of processor power management initialization code.
30 It initializes the processor's power management features based on the user
31 configurations and hardware capabilities.
32 **/
33 VOID
34 PpmInit (
35 VOID
36 )
37 {
38 //
39 // Processor Power Management Flags
40 //
41 mGlobalNvsAreaPtr->Cfgd = PcdGet32(PcdPpmFlags);
42
43 //
44 // Patch and publish power management related acpi tables
45 //
46 PpmPatchAndPublishAcpiTables();
47 }
48
49 /**
50 This function is to patch and publish power management related acpi tables.
51 **/
52 VOID
53 PpmPatchAndPublishAcpiTables (
54 VOID
55 )
56 {
57 //
58 // Patch FADT table to enable C2,C3
59 //
60 PpmPatchFadtTable();
61
62 //
63 // Load all the power management acpi tables and patch IST table
64 //
65 PpmLoadAndPatchPMTables();
66 }
67
68 /**
69 This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
70 **/
71 VOID
72 PpmPatchFadtTable (
73 VOID
74 )
75 {
76 EFI_STATUS Status;
77 EFI_ACPI_DESCRIPTION_HEADER *Table;
78 EFI_ACPI_SDT_HEADER *CurrentTable;
79 EFI_ACPI_TABLE_VERSION Version;
80 UINTN Index;
81 UINTN Handle;
82 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtPointer;
83
84 //
85 // Scan all the acpi tables to find FADT 2.0
86 //
87 Index = 0;
88 do {
89 Status = mAcpiSdt->GetAcpiTable (
90 Index,
91 &CurrentTable,
92 &Version,
93 &Handle
94 );
95 if (Status == EFI_NOT_FOUND) {
96 break;
97 }
98 ASSERT_EFI_ERROR (Status);
99 Index++;
100 } while (CurrentTable->Signature != EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE || CurrentTable->Revision != 0x03);
101
102 ASSERT (CurrentTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);
103
104 Table = NULL;
105 Status = gBS->AllocatePool (EfiBootServicesData, CurrentTable->Length, (VOID **) &Table);
106 ASSERT (Table != NULL);
107 CopyMem (Table, CurrentTable, CurrentTable->Length);
108
109 FadtPointer = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE*) Table;
110
111 //
112 // Update the ACPI table and recalculate checksum
113 //
114 Status = mAcpiTable->UninstallAcpiTable (mAcpiTable, Handle);
115 if (EFI_ERROR (Status)) {
116 //
117 // Should not get an error here ever, but abort if we do.
118 //
119 return ;
120 }
121
122 //
123 // Update the check sum
124 // It needs to be zeroed before the checksum calculation
125 //
126 ((EFI_ACPI_SDT_HEADER *)Table)->Checksum = 0;
127 ((EFI_ACPI_SDT_HEADER *)Table)->Checksum =
128 CalculateCheckSum8 ((VOID *)Table, Table->Length);
129
130 //
131 // Add the table
132 //
133 Status = mAcpiTable->InstallAcpiTable (
134 mAcpiTable,
135 Table,
136 Table->Length,
137 &Handle
138 );
139 ASSERT_EFI_ERROR (Status);
140 gBS->FreePool (Table);
141 }
142
143 VOID
144 SsdtTableUpdate (
145 IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader
146 )
147 /*++
148
149 Routine Description:
150
151 Update the SSDT table
152
153 Arguments:
154
155 Table - The SSDT table to be patched
156
157 Returns:
158
159 None
160
161 --*/
162 {
163 UINT8 *CurrPtr;
164 UINT8 *SsdtPointer;
165 UINT32 *Signature;
166
167 //
168 // Loop through the ASL looking for values that we must fix up.
169 //
170 CurrPtr = (UINT8 *) TableHeader;
171 for (SsdtPointer = CurrPtr;
172 SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
173 SsdtPointer++
174 )
175 {
176 Signature = (UINT32 *) SsdtPointer;
177 if ((*Signature) == SIGNATURE_32 ('P', 'M', 'B', 'A')) {
178 switch (*(Signature+1)) {
179 case (SIGNATURE_32 ('L', 'V', 'L', '0')):
180 Signature[0] = PcdGet16(PcdPmbaIoBaseAddress);
181 Signature[1] = 0;
182 break;
183 case (SIGNATURE_32 ('L', 'V', 'L', '2')):
184 Signature[0] = PcdGet16(PcdPmbaIoLVL2);
185 Signature[1] = 0;
186 break;
187 }
188 }
189 }
190 }
191
192 EFI_STATUS
193 LocateSupportProtocol (
194 IN EFI_GUID *Protocol,
195 OUT VOID **Instance,
196 IN UINT32 Type
197 )
198 /*++
199
200 Routine Description:
201
202 Locate the first instance of a protocol. If the protocol requested is an
203 FV protocol, then it will return the first FV that contains the ACPI table
204 storage file.
205
206 Arguments:
207
208 Protocol The protocol to find.
209 Instance Return pointer to the first instance of the protocol
210
211 Returns:
212
213 EFI_SUCCESS The function completed successfully.
214 EFI_NOT_FOUND The protocol could not be located.
215 EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
216
217 --*/
218 {
219 EFI_STATUS Status;
220 EFI_HANDLE *HandleBuffer;
221 UINTN NumberOfHandles;
222 EFI_FV_FILETYPE FileType;
223 UINT32 FvStatus;
224 EFI_FV_FILE_ATTRIBUTES Attributes;
225 UINTN Size;
226 UINTN i;
227
228 FvStatus = 0;
229
230 //
231 // Locate protocol.
232 //
233 Status = gBS->LocateHandleBuffer (
234 ByProtocol,
235 Protocol,
236 NULL,
237 &NumberOfHandles,
238 &HandleBuffer
239 );
240 if (EFI_ERROR (Status)) {
241
242 //
243 // Defined errors at this time are not found and out of resources.
244 //
245 return Status;
246 }
247
248
249
250 //
251 // Looking for FV with ACPI storage file
252 //
253
254 for (i = 0; i < NumberOfHandles; i++) {
255 //
256 // Get the protocol on this handle
257 // This should not fail because of LocateHandleBuffer
258 //
259 Status = gBS->HandleProtocol (
260 HandleBuffer[i],
261 Protocol,
262 Instance
263 );
264 ASSERT_EFI_ERROR (Status);
265
266 if (!Type) {
267 //
268 // Not looking for the FV protocol, so find the first instance of the
269 // protocol. There should not be any errors because our handle buffer
270 // should always contain at least one or LocateHandleBuffer would have
271 // returned not found.
272 //
273 break;
274 }
275
276 //
277 // See if it has the ACPI storage file
278 //
279
280 Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
281 &gPowerManagementAcpiTableStorageGuid,
282 NULL,
283 &Size,
284 &FileType,
285 &Attributes,
286 &FvStatus
287 );
288
289 //
290 // If we found it, then we are done
291 //
292 if (Status == EFI_SUCCESS) {
293 break;
294 }
295 }
296
297 //
298 // Our exit status is determined by the success of the previous operations
299 // If the protocol was found, Instance already points to it.
300 //
301
302 //
303 // Free any allocated buffers
304 //
305 gBS->FreePool (HandleBuffer);
306
307 return Status;
308 }
309
310 /**
311 This function is to load all the power management acpi tables and patch IST table.
312 **/
313 VOID
314 PpmLoadAndPatchPMTables (
315 VOID
316 )
317 {
318 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
319 EFI_STATUS Status;
320 INTN Instance;
321 EFI_ACPI_COMMON_HEADER *CurrentTable;
322 UINTN TableHandle;
323 UINT32 FvStatus;
324 UINTN Size;
325 EFI_ACPI_TABLE_VERSION Version;
326
327 Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
328 if (EFI_ERROR (Status)) {
329 return;
330 }
331
332 //
333 // Read tables from the storage file.
334 //
335 Instance = 0;
336 CurrentTable = NULL;
337
338 while (Status == EFI_SUCCESS) {
339
340 Status = FwVol->ReadSection (
341 FwVol,
342 &gPowerManagementAcpiTableStorageGuid,
343 EFI_SECTION_RAW,
344 Instance,
345 (VOID**)&CurrentTable,
346 &Size,
347 &FvStatus
348 );
349
350 if (!EFI_ERROR(Status)) {
351 Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
352
353 if(((EFI_ACPI_DESCRIPTION_HEADER*) CurrentTable)->OemTableId == SIGNATURE_64 ('C', 'p', 'u', '0', 'I', 's', 't', 0)) {
354 Version = EFI_ACPI_TABLE_VERSION_NONE;
355 } else if(((EFI_ACPI_DESCRIPTION_HEADER*) CurrentTable)->OemTableId == SIGNATURE_64 ('C', 'p', 'u', '1', 'I', 's', 't', 0)) {
356 Version = EFI_ACPI_TABLE_VERSION_NONE;
357 }
358
359 SsdtTableUpdate ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable);
360
361 //
362 // Update the check sum
363 // It needs to be zeroed before the checksum calculation
364 //
365 ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
366 ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = (UINT8)
367 CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
368
369 //
370 // Add the table
371 //
372 TableHandle = 0;
373 Status = mAcpiTable->InstallAcpiTable (
374 mAcpiTable,
375 CurrentTable,
376 CurrentTable->Length,
377 &TableHandle
378 );
379
380 ASSERT_EFI_ERROR (Status);
381
382 //
383 // Increment the instance
384 //
385 Instance++;
386 CurrentTable = NULL;
387 }
388 }
389
390 }