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