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