]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c
IntelFrameworkModulePkg: AcpiS3SaveDxe: call S3Ready() at End-of-Dxe
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / Acpi / AcpiS3SaveDxe / AcpiS3Save.c
CommitLineData
13d4af68 1/** @file\r
2 This is an implementation of the ACPI S3 Save protocol. This is defined in\r
3 S3 boot path specification 0.9.\r
4\r
dbaeca27 5Copyright (c) 2015, Red Hat, Inc.<BR>\r
b34039b2 6Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
13d4af68 7\r
8This program and the accompanying materials\r
9are licensed and made available under the terms and conditions\r
10of the BSD License which accompanies this distribution. The\r
11full text of the license may be found at\r
12http://opensource.org/licenses/bsd-license.php\r
13\r
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19#include <PiDxe.h>\r
20#include <Library/BaseLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/UefiRuntimeServicesTableLib.h>\r
c56b6566 24#include <Library/HobLib.h>\r
13d4af68 25#include <Library/LockBoxLib.h>\r
26#include <Library/PcdLib.h>\r
27#include <Library/DebugLib.h>\r
28#include <Guid/AcpiVariableCompatibility.h>\r
29#include <Guid/AcpiS3Context.h>\r
30#include <Guid/Acpi.h>\r
e50c79f7 31#include <Guid/EventGroup.h>\r
13d4af68 32#include <Protocol/AcpiS3Save.h>\r
33#include <IndustryStandard/Acpi.h>\r
34\r
35#include "AcpiS3Save.h"\r
36\r
37/**\r
38 Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.\r
39**/\r
40VOID\r
41InstallAcpiS3SaveThunk (\r
42 VOID\r
43 );\r
44\r
45/**\r
46 Hook point for AcpiVariableThunkPlatform for S3Ready.\r
47\r
48 @param AcpiS3Context ACPI s3 context\r
49**/\r
50VOID\r
51S3ReadyThunkPlatform (\r
52 IN ACPI_S3_CONTEXT *AcpiS3Context\r
53 );\r
54\r
55UINTN mLegacyRegionSize;\r
56\r
57EFI_ACPI_S3_SAVE_PROTOCOL mS3Save = {\r
58 LegacyGetS3MemorySize,\r
59 S3Ready,\r
60};\r
61\r
62EFI_GUID mAcpiS3IdtrProfileGuid = {\r
ce68d3bc 63 0xdea652b0, 0xd587, 0x4c54, { 0xb5, 0xb4, 0xc6, 0x82, 0xe7, 0xa0, 0xaa, 0x3d }\r
13d4af68 64};\r
65\r
66/**\r
091249f4 67 Allocate memory below 4G memory address.\r
13d4af68 68\r
091249f4 69 This function allocates memory below 4G memory address.\r
13d4af68 70\r
091249f4 71 @param MemoryType Memory type of memory to allocate.\r
13d4af68 72 @param Size Size of memory to allocate.\r
73 \r
74 @return Allocated address for output.\r
75\r
76**/\r
77VOID*\r
091249f4 78AllocateMemoryBelow4G (\r
73f0127f
SZ
79 IN EFI_MEMORY_TYPE MemoryType,\r
80 IN UINTN Size\r
13d4af68 81 )\r
82{\r
83 UINTN Pages;\r
84 EFI_PHYSICAL_ADDRESS Address;\r
85 EFI_STATUS Status;\r
86 VOID* Buffer;\r
87\r
88 Pages = EFI_SIZE_TO_PAGES (Size);\r
89 Address = 0xffffffff;\r
90\r
91 Status = gBS->AllocatePages (\r
92 AllocateMaxAddress,\r
091249f4 93 MemoryType,\r
13d4af68 94 Pages,\r
95 &Address\r
96 );\r
97 ASSERT_EFI_ERROR (Status);\r
98\r
99 Buffer = (VOID *) (UINTN) Address;\r
100 ZeroMem (Buffer, Size);\r
101\r
102 return Buffer;\r
103}\r
104\r
c93776c2
JY
105/**\r
106\r
107 This function scan ACPI table in RSDT.\r
108\r
109 @param Rsdt ACPI RSDT\r
110 @param Signature ACPI table signature\r
111\r
112 @return ACPI table\r
113\r
114**/\r
115VOID *\r
116ScanTableInRSDT (\r
117 IN EFI_ACPI_DESCRIPTION_HEADER *Rsdt,\r
118 IN UINT32 Signature\r
119 )\r
120{\r
121 UINTN Index;\r
122 UINT32 EntryCount;\r
123 UINT32 *EntryPtr;\r
124 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
125\r
126 if (Rsdt == NULL) {\r
127 return NULL;\r
128 }\r
129\r
130 EntryCount = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);\r
131 \r
132 EntryPtr = (UINT32 *)(Rsdt + 1);\r
133 for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) {\r
134 Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(*EntryPtr));\r
135 if (Table->Signature == Signature) {\r
136 return Table;\r
137 }\r
138 }\r
139 \r
140 return NULL;\r
141}\r
142\r
143/**\r
144\r
145 This function scan ACPI table in XSDT.\r
146\r
147 @param Xsdt ACPI XSDT\r
148 @param Signature ACPI table signature\r
149\r
150 @return ACPI table\r
151\r
152**/\r
153VOID *\r
154ScanTableInXSDT (\r
155 IN EFI_ACPI_DESCRIPTION_HEADER *Xsdt,\r
156 IN UINT32 Signature\r
157 )\r
158{\r
159 UINTN Index;\r
160 UINT32 EntryCount;\r
161 UINT64 EntryPtr;\r
162 UINTN BasePtr;\r
163 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
164\r
165 if (Xsdt == NULL) {\r
166 return NULL;\r
167 }\r
168\r
169 EntryCount = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);\r
170 \r
171 BasePtr = (UINTN)(Xsdt + 1);\r
172 for (Index = 0; Index < EntryCount; Index ++) {\r
173 CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64));\r
174 Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(EntryPtr));\r
175 if (Table->Signature == Signature) {\r
176 return Table;\r
177 }\r
178 }\r
179 \r
180 return NULL;\r
181}\r
182\r
183/**\r
184 To find Facs in FADT.\r
185\r
186 @param Fadt FADT table pointer\r
187 \r
188 @return Facs table pointer.\r
189**/\r
190EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *\r
191FindAcpiFacsFromFadt (\r
192 IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt\r
193 )\r
194{\r
195 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;\r
196 UINT64 Data64;\r
197\r
198 if (Fadt == NULL) {\r
199 return NULL;\r
200 }\r
201\r
202 if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {\r
203 Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl;\r
204 } else {\r
205 if (Fadt->FirmwareCtrl != 0) {\r
206 Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl;\r
207 } else {\r
208 CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64));\r
209 Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Data64;\r
210 }\r
211 }\r
212 return Facs;\r
213}\r
214\r
13d4af68 215/**\r
216 To find Facs in Acpi tables.\r
217 \r
218 To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored \r
219 in the table.\r
220\r
221 @param AcpiTableGuid The guid used to find ACPI table in UEFI ConfigurationTable.\r
222 \r
223 @return Facs table pointer.\r
224**/\r
225EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *\r
226FindAcpiFacsTableByAcpiGuid (\r
227 IN EFI_GUID *AcpiTableGuid\r
228 )\r
229{\r
230 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
231 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
c93776c2 232 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;\r
13d4af68 233 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;\r
234 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;\r
235 UINTN Index;\r
c93776c2 236\r
13d4af68 237 Rsdp = NULL;\r
13d4af68 238 //\r
239 // found ACPI table RSD_PTR from system table\r
240 //\r
241 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
242 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) {\r
243 //\r
244 // A match was found.\r
245 //\r
246 Rsdp = gST->ConfigurationTable[Index].VendorTable;\r
247 break;\r
248 }\r
249 }\r
250\r
251 if (Rsdp == NULL) {\r
252 return NULL;\r
253 }\r
254\r
c93776c2
JY
255 //\r
256 // Search XSDT\r
257 //\r
258 if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {\r
259 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress;\r
260 Fadt = ScanTableInXSDT (Xsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);\r
261 if (Fadt != NULL) {\r
262 Facs = FindAcpiFacsFromFadt (Fadt);\r
263 if (Facs != NULL) {\r
264 return Facs;\r
265 }\r
13d4af68 266 }\r
267 }\r
268\r
c93776c2
JY
269 //\r
270 // Search RSDT\r
271 //\r
272 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress;\r
273 Fadt = ScanTableInRSDT (Rsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);\r
274 if (Fadt != NULL) {\r
275 Facs = FindAcpiFacsFromFadt (Fadt);\r
276 if (Facs != NULL) {\r
277 return Facs;\r
278 }\r
13d4af68 279 }\r
280\r
c93776c2 281 return NULL;\r
13d4af68 282}\r
283\r
284/**\r
285 To find Facs in Acpi tables.\r
286 \r
287 To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored \r
288 in the table.\r
289 \r
290 @return Facs table pointer.\r
291**/\r
292EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *\r
293FindAcpiFacsTable (\r
294 VOID\r
295 )\r
296{\r
297 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;\r
298\r
299 Facs = FindAcpiFacsTableByAcpiGuid (&gEfiAcpi20TableGuid);\r
300 if (Facs != NULL) {\r
301 return Facs;\r
302 }\r
303\r
304 return FindAcpiFacsTableByAcpiGuid (&gEfiAcpi10TableGuid);\r
305}\r
306\r
307/**\r
308 Allocates and fills in the Page Directory and Page Table Entries to\r
309 establish a 1:1 Virtual to Physical mapping.\r
310 If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1 \r
311 virtual to physical mapping page table.\r
312 If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. \r
313 \r
314 @return the 1:1 Virtual to Physical identity mapping page table base address. \r
315\r
316**/\r
317EFI_PHYSICAL_ADDRESS\r
318S3CreateIdentityMappingPageTables (\r
319 VOID\r
320 )\r
321{ \r
322 if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
323 UINT32 RegEax;\r
c56b6566 324 UINT32 RegEdx;\r
13d4af68 325 UINT8 PhysicalAddressBits;\r
c56b6566
JY
326 UINT32 NumberOfPml4EntriesNeeded;\r
327 UINT32 NumberOfPdpEntriesNeeded;\r
13d4af68 328 EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;\r
329 UINTN TotalPageTableSize;\r
c56b6566
JY
330 VOID *Hob;\r
331 BOOLEAN Page1GSupport;\r
c56b6566 332\r
ac790db9
EL
333 S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdIdentifyMappingPageTablePtr);\r
334 if (S3NvsPageTableAddress != 0x0) {\r
335 return S3NvsPageTableAddress;\r
336 } else {\r
337 Page1GSupport = FALSE;\r
338 if (PcdGetBool(PcdUse1GPageTable)) {\r
339 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
340 if (RegEax >= 0x80000001) {\r
341 AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
342 if ((RegEdx & BIT26) != 0) {\r
343 Page1GSupport = TRUE;\r
344 }\r
378175d2 345 }\r
c56b6566 346 }\r
ac790db9
EL
347 \r
348 //\r
349 // Get physical address bits supported.\r
350 //\r
351 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
352 if (Hob != NULL) {\r
353 PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
c56b6566 354 } else {\r
ac790db9
EL
355 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
356 if (RegEax >= 0x80000008) {\r
357 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
358 PhysicalAddressBits = (UINT8) RegEax;\r
359 } else {\r
360 PhysicalAddressBits = 36;\r
361 }\r
c56b6566 362 }\r
ac790db9
EL
363 \r
364 //\r
365 // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
366 //\r
367 ASSERT (PhysicalAddressBits <= 52);\r
368 if (PhysicalAddressBits > 48) {\r
369 PhysicalAddressBits = 48;\r
370 }\r
371 \r
372 //\r
373 // Calculate the table entries needed.\r
374 //\r
375 if (PhysicalAddressBits <= 39 ) {\r
376 NumberOfPml4EntriesNeeded = 1;\r
377 NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));\r
378 } else {\r
379 NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));\r
380 NumberOfPdpEntriesNeeded = 512;\r
381 }\r
382 \r
383 //\r
384 // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs.\r
385 //\r
386 if (!Page1GSupport) {\r
387 TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded);\r
388 } else {\r
389 TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded);\r
390 }\r
391 DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize));\r
392 \r
393 //\r
394 // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.\r
395 //\r
396 S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGES_TO_SIZE(TotalPageTableSize));\r
397 ASSERT (S3NvsPageTableAddress != 0);\r
398 PcdSet64 (PcdIdentifyMappingPageTablePtr, S3NvsPageTableAddress); \r
399 return S3NvsPageTableAddress;\r
13d4af68 400 }\r
13d4af68 401 } else {\r
402 //\r
403 // If DXE is running 32-bit mode, no need to establish page table.\r
404 //\r
405 return (EFI_PHYSICAL_ADDRESS) 0; \r
406 }\r
407}\r
408\r
409/**\r
410 Gets the buffer of legacy memory below 1 MB \r
411 This function is to get the buffer in legacy memory below 1MB that is required during S3 resume.\r
412\r
413 @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.\r
414 @param Size The returned size of legacy memory below 1 MB.\r
415\r
416 @retval EFI_SUCCESS Size is successfully returned.\r
417 @retval EFI_INVALID_PARAMETER The pointer Size is NULL.\r
418\r
419**/\r
420EFI_STATUS\r
421EFIAPI\r
422LegacyGetS3MemorySize (\r
423 IN EFI_ACPI_S3_SAVE_PROTOCOL *This,\r
424 OUT UINTN *Size\r
425 )\r
426{\r
dbaeca27
LE
427 ASSERT (FALSE);\r
428\r
13d4af68 429 if (Size == NULL) {\r
430 return EFI_INVALID_PARAMETER;\r
431 }\r
432\r
433 *Size = mLegacyRegionSize;\r
434 return EFI_SUCCESS;\r
435}\r
436\r
437/**\r
438 Prepares all information that is needed in the S3 resume boot path.\r
439 \r
440 Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path \r
441 \r
442 @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.\r
443 @param LegacyMemoryAddress The base address of legacy memory.\r
444\r
445 @retval EFI_NOT_FOUND Some necessary information cannot be found.\r
446 @retval EFI_SUCCESS All information was saved successfully.\r
447 @retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information.\r
448 @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB.\r
449\r
450**/\r
451EFI_STATUS\r
452EFIAPI\r
453S3Ready (\r
454 IN EFI_ACPI_S3_SAVE_PROTOCOL *This,\r
455 IN VOID *LegacyMemoryAddress\r
456 )\r
457{\r
458 EFI_STATUS Status;\r
459 EFI_PHYSICAL_ADDRESS AcpiS3ContextBuffer;\r
460 ACPI_S3_CONTEXT *AcpiS3Context;\r
461 STATIC BOOLEAN AlreadyEntered;\r
462 IA32_DESCRIPTOR *Idtr;\r
463 IA32_IDT_GATE_DESCRIPTOR *IdtGate;\r
464\r
465 DEBUG ((EFI_D_INFO, "S3Ready!\n"));\r
466\r
467 //\r
468 // Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again.\r
469 // So if 2nd S3Save() is triggered later, we need ignore it.\r
470 //\r
471 if (AlreadyEntered) {\r
472 return EFI_SUCCESS;\r
473 }\r
474 AlreadyEntered = TRUE;\r
475\r
dbaeca27
LE
476 ASSERT (LegacyMemoryAddress == NULL);\r
477\r
091249f4 478 AcpiS3Context = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(*AcpiS3Context));\r
13d4af68 479 ASSERT (AcpiS3Context != NULL);\r
480 AcpiS3ContextBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;\r
481\r
482 //\r
483 // Get ACPI Table because we will save its position to variable\r
484 //\r
485 AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiFacsTable ();\r
486 ASSERT (AcpiS3Context->AcpiFacsTable != 0);\r
487\r
091249f4 488 IdtGate = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR));\r
13d4af68 489 Idtr = (IA32_DESCRIPTOR *)(IdtGate + 0x100);\r
490 Idtr->Base = (UINTN)IdtGate;\r
491 Idtr->Limit = (UINT16)(sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 - 1);\r
492 AcpiS3Context->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)Idtr;\r
493\r
494 Status = SaveLockBox (\r
495 &mAcpiS3IdtrProfileGuid,\r
496 (VOID *)(UINTN)Idtr,\r
497 (UINTN)sizeof(IA32_DESCRIPTOR)\r
498 );\r
499 ASSERT_EFI_ERROR (Status);\r
500\r
501 Status = SetLockBoxAttributes (&mAcpiS3IdtrProfileGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
502 ASSERT_EFI_ERROR (Status);\r
503\r
504 //\r
505 // Allocate page table\r
506 //\r
507 AcpiS3Context->S3NvsPageTableAddress = S3CreateIdentityMappingPageTables ();\r
508\r
509 //\r
510 // Allocate stack\r
511 //\r
512 AcpiS3Context->BootScriptStackSize = PcdGet32 (PcdS3BootScriptStackSize);\r
091249f4 513 AcpiS3Context->BootScriptStackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3BootScriptStackSize));\r
13d4af68 514 ASSERT (AcpiS3Context->BootScriptStackBase != 0);\r
515\r
516 //\r
f4a25e81 517 // Allocate a code buffer < 4G for S3 debug to load external code, set invalid code instructions in it.\r
13d4af68 518 //\r
091249f4 519 AcpiS3Context->S3DebugBufferAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGE_SIZE);\r
f4a25e81 520 SetMem ((VOID *)(UINTN)AcpiS3Context->S3DebugBufferAddress, EFI_PAGE_SIZE, 0xff);\r
13d4af68 521\r
522 DEBUG((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8x\n", AcpiS3Context->AcpiFacsTable));\r
523 DEBUG((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8x\n", AcpiS3Context->IdtrProfile));\r
524 DEBUG((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8x\n", AcpiS3Context->S3NvsPageTableAddress));\r
525 DEBUG((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8x\n", AcpiS3Context->S3DebugBufferAddress));\r
b34039b2
LG
526 DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackBase is 0x%8x\n", AcpiS3Context->BootScriptStackBase));\r
527 DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackSize is 0x%8x\n", AcpiS3Context->BootScriptStackSize));\r
13d4af68 528\r
529 Status = SaveLockBox (\r
530 &gEfiAcpiVariableGuid,\r
531 &AcpiS3ContextBuffer,\r
532 sizeof(AcpiS3ContextBuffer)\r
533 );\r
534 ASSERT_EFI_ERROR (Status);\r
535\r
536 Status = SaveLockBox (\r
537 &gEfiAcpiS3ContextGuid,\r
538 (VOID *)(UINTN)AcpiS3Context,\r
539 (UINTN)sizeof(*AcpiS3Context)\r
540 );\r
541 ASSERT_EFI_ERROR (Status);\r
542\r
543 Status = SetLockBoxAttributes (&gEfiAcpiS3ContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
544 ASSERT_EFI_ERROR (Status);\r
545\r
546 if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {\r
547 S3ReadyThunkPlatform (AcpiS3Context);\r
548 }\r
549\r
550 return EFI_SUCCESS;\r
551}\r
552\r
e50c79f7
LE
553/**\r
554 Callback function executed when the EndOfDxe event group is signaled.\r
555\r
556 @param[in] Event Event whose notification function is being invoked.\r
557 @param[in] Context The pointer to the notification function's context, which\r
558 is implementation-dependent.\r
559**/\r
560VOID\r
561EFIAPI\r
562OnEndOfDxe (\r
563 IN EFI_EVENT Event,\r
564 IN VOID *Context\r
565 )\r
566{\r
567 EFI_STATUS Status;\r
568\r
569 //\r
570 // Our S3Ready() function ignores both of its parameters, and always\r
571 // succeeds.\r
572 //\r
573 Status = S3Ready (\r
574 NULL, // This\r
575 NULL // LegacyMemoryAddress\r
576 );\r
577 ASSERT_EFI_ERROR (Status);\r
578\r
579 //\r
580 // Close the event, deregistering the callback and freeing resources.\r
581 //\r
582 Status = gBS->CloseEvent (Event);\r
583 ASSERT_EFI_ERROR (Status);\r
584}\r
585\r
586\r
13d4af68 587/**\r
588 The Driver Entry Point.\r
589 \r
590 The function is the driver Entry point which will produce AcpiS3SaveProtocol.\r
591 \r
592 @param ImageHandle A handle for the image that is initializing this driver\r
593 @param SystemTable A pointer to the EFI system table\r
594\r
595 @retval EFI_SUCCESS: Driver initialized successfully\r
596 @retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded\r
597 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources\r
598\r
599**/\r
600EFI_STATUS\r
601EFIAPI\r
602InstallAcpiS3Save (\r
603 IN EFI_HANDLE ImageHandle,\r
604 IN EFI_SYSTEM_TABLE *SystemTable\r
605 )\r
606{\r
607 EFI_STATUS Status;\r
e50c79f7 608 EFI_EVENT EndOfDxeEvent;\r
13d4af68 609\r
610 if (!FeaturePcdGet(PcdPlatformCsmSupport)) {\r
611 //\r
612 // More memory for no CSM tip, because GDT need relocation\r
613 //\r
614 mLegacyRegionSize = 0x250;\r
615 } else {\r
616 mLegacyRegionSize = 0x100;\r
617 }\r
618\r
619 if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {\r
620 InstallAcpiS3SaveThunk ();\r
621 }\r
622\r
623 Status = gBS->InstallProtocolInterface (\r
624 &ImageHandle,\r
625 &gEfiAcpiS3SaveProtocolGuid,\r
626 EFI_NATIVE_INTERFACE,\r
627 &mS3Save\r
628 );\r
629 ASSERT_EFI_ERROR (Status);\r
e50c79f7
LE
630\r
631 Status = gBS->CreateEventEx (\r
632 EVT_NOTIFY_SIGNAL,\r
633 TPL_CALLBACK,\r
634 OnEndOfDxe,\r
635 NULL, /* NotifyContext */\r
636 &gEfiEndOfDxeEventGroupGuid,\r
637 &EndOfDxeEvent\r
638 );\r
639 ASSERT_EFI_ERROR (Status);\r
13d4af68 640 return Status;\r
641}\r