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