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