]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c
Add missing braces around initializer.
[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
f4a25e81 5Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
13d4af68 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
c56b6566 23#include <Library/HobLib.h>\r
13d4af68 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
31#include <IndustryStandard/Acpi.h>\r
32\r
33#include "AcpiS3Save.h"\r
34\r
35/**\r
36 Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.\r
37**/\r
38VOID\r
39InstallAcpiS3SaveThunk (\r
40 VOID\r
41 );\r
42\r
43/**\r
44 Hook point for AcpiVariableThunkPlatform for S3Ready.\r
45\r
46 @param AcpiS3Context ACPI s3 context\r
47**/\r
48VOID\r
49S3ReadyThunkPlatform (\r
50 IN ACPI_S3_CONTEXT *AcpiS3Context\r
51 );\r
52\r
53UINTN mLegacyRegionSize;\r
54\r
55EFI_ACPI_S3_SAVE_PROTOCOL mS3Save = {\r
56 LegacyGetS3MemorySize,\r
57 S3Ready,\r
58};\r
59\r
60EFI_GUID mAcpiS3IdtrProfileGuid = {\r
ce68d3bc 61 0xdea652b0, 0xd587, 0x4c54, { 0xb5, 0xb4, 0xc6, 0x82, 0xe7, 0xa0, 0xaa, 0x3d }\r
13d4af68 62};\r
63\r
64/**\r
65 Allocate EfiACPIMemoryNVS below 4G memory address.\r
66\r
67 This function allocates EfiACPIMemoryNVS below 4G memory address.\r
68\r
69 @param Size Size of memory to allocate.\r
70 \r
71 @return Allocated address for output.\r
72\r
73**/\r
74VOID*\r
75AllocateAcpiNvsMemoryBelow4G (\r
76 IN UINTN Size\r
77 )\r
78{\r
79 UINTN Pages;\r
80 EFI_PHYSICAL_ADDRESS Address;\r
81 EFI_STATUS Status;\r
82 VOID* Buffer;\r
83\r
84 Pages = EFI_SIZE_TO_PAGES (Size);\r
85 Address = 0xffffffff;\r
86\r
87 Status = gBS->AllocatePages (\r
88 AllocateMaxAddress,\r
89 EfiACPIMemoryNVS,\r
90 Pages,\r
91 &Address\r
92 );\r
93 ASSERT_EFI_ERROR (Status);\r
94\r
95 Buffer = (VOID *) (UINTN) Address;\r
96 ZeroMem (Buffer, Size);\r
97\r
98 return Buffer;\r
99}\r
100\r
101/**\r
102 To find Facs in Acpi tables.\r
103 \r
104 To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored \r
105 in the table.\r
106\r
107 @param AcpiTableGuid The guid used to find ACPI table in UEFI ConfigurationTable.\r
108 \r
109 @return Facs table pointer.\r
110**/\r
111EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *\r
112FindAcpiFacsTableByAcpiGuid (\r
113 IN EFI_GUID *AcpiTableGuid\r
114 )\r
115{\r
116 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
117 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
118 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;\r
119 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;\r
120 UINTN Index;\r
121 UINT32 Data32;\r
122 Rsdp = NULL;\r
123 Rsdt = NULL;\r
124 Fadt = NULL;\r
125 //\r
126 // found ACPI table RSD_PTR from system table\r
127 //\r
128 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
129 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) {\r
130 //\r
131 // A match was found.\r
132 //\r
133 Rsdp = gST->ConfigurationTable[Index].VendorTable;\r
134 break;\r
135 }\r
136 }\r
137\r
138 if (Rsdp == NULL) {\r
139 return NULL;\r
140 }\r
141\r
142 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress;\r
143 if (Rsdt == NULL || Rsdt->Signature != EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {\r
144 return NULL;\r
145 }\r
146\r
147 for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Rsdt->Length; Index = Index + sizeof (UINT32)) {\r
148\r
149 Data32 = *(UINT32 *) ((UINT8 *) Rsdt + Index);\r
150 Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) (UINT32 *) (UINTN) Data32;\r
151 if (Fadt->Header.Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {\r
152 break;\r
153 }\r
154 }\r
155\r
156 if (Fadt == NULL || Fadt->Header.Signature != EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {\r
157 return NULL;\r
158 }\r
159\r
160 Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl;\r
161\r
162 return Facs;\r
163}\r
164\r
165/**\r
166 To find Facs in Acpi tables.\r
167 \r
168 To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored \r
169 in the table.\r
170 \r
171 @return Facs table pointer.\r
172**/\r
173EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *\r
174FindAcpiFacsTable (\r
175 VOID\r
176 )\r
177{\r
178 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;\r
179\r
180 Facs = FindAcpiFacsTableByAcpiGuid (&gEfiAcpi20TableGuid);\r
181 if (Facs != NULL) {\r
182 return Facs;\r
183 }\r
184\r
185 return FindAcpiFacsTableByAcpiGuid (&gEfiAcpi10TableGuid);\r
186}\r
187\r
188/**\r
189 Allocates and fills in the Page Directory and Page Table Entries to\r
190 establish a 1:1 Virtual to Physical mapping.\r
191 If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1 \r
192 virtual to physical mapping page table.\r
193 If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. \r
194 \r
195 @return the 1:1 Virtual to Physical identity mapping page table base address. \r
196\r
197**/\r
198EFI_PHYSICAL_ADDRESS\r
199S3CreateIdentityMappingPageTables (\r
200 VOID\r
201 )\r
202{ \r
203 if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
204 UINT32 RegEax;\r
c56b6566 205 UINT32 RegEdx;\r
13d4af68 206 UINT8 PhysicalAddressBits;\r
207 EFI_PHYSICAL_ADDRESS PageAddress;\r
208 UINTN IndexOfPml4Entries;\r
209 UINTN IndexOfPdpEntries;\r
210 UINTN IndexOfPageDirectoryEntries;\r
c56b6566
JY
211 UINT32 NumberOfPml4EntriesNeeded;\r
212 UINT32 NumberOfPdpEntriesNeeded;\r
13d4af68 213 PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;\r
214 PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;\r
215 PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;\r
216 PAGE_TABLE_ENTRY *PageDirectoryEntry;\r
217 EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;\r
218 UINTN TotalPageTableSize;\r
c56b6566
JY
219 VOID *Hob;\r
220 BOOLEAN Page1GSupport;\r
221 PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;\r
222\r
223 Page1GSupport = FALSE;\r
378175d2
JY
224 if (PcdGetBool(PcdUse1GPageTable)) {\r
225 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
226 if (RegEax >= 0x80000001) {\r
227 AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
228 if ((RegEdx & BIT26) != 0) {\r
229 Page1GSupport = TRUE;\r
230 }\r
c56b6566
JY
231 }\r
232 }\r
13d4af68 233\r
234 //\r
235 // Get physical address bits supported.\r
236 //\r
c56b6566
JY
237 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
238 if (Hob != NULL) {\r
239 PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
13d4af68 240 } else {\r
c56b6566
JY
241 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
242 if (RegEax >= 0x80000008) {\r
243 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
244 PhysicalAddressBits = (UINT8) RegEax;\r
245 } else {\r
246 PhysicalAddressBits = 36;\r
247 }\r
13d4af68 248 }\r
249 \r
c56b6566
JY
250 //\r
251 // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
252 //\r
253 ASSERT (PhysicalAddressBits <= 52);\r
254 if (PhysicalAddressBits > 48) {\r
255 PhysicalAddressBits = 48;\r
256 }\r
257\r
13d4af68 258 //\r
259 // Calculate the table entries needed.\r
260 //\r
261 if (PhysicalAddressBits <= 39 ) {\r
262 NumberOfPml4EntriesNeeded = 1;\r
c56b6566 263 NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));\r
13d4af68 264 } else {\r
c56b6566 265 NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));\r
13d4af68 266 NumberOfPdpEntriesNeeded = 512;\r
267 }\r
268\r
269 //\r
270 // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs.\r
271 //\r
c56b6566
JY
272 if (!Page1GSupport) {\r
273 TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded);\r
274 } else {\r
275 TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded);\r
276 }\r
13d4af68 277 DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize));\r
278\r
279 //\r
280 // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.\r
281 //\r
282 S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (EFI_PAGES_TO_SIZE(TotalPageTableSize));\r
283 ASSERT (S3NvsPageTableAddress != 0);\r
284 PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)(UINTN)S3NvsPageTableAddress;\r
285 S3NvsPageTableAddress += SIZE_4KB;\r
286\r
287 PageMapLevel4Entry = PageMap;\r
288 PageAddress = 0;\r
289 for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {\r
290 //\r
291 // Each PML4 entry points to a page of Page Directory Pointer entires.\r
292 // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.\r
293 //\r
294 PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER *)(UINTN)S3NvsPageTableAddress;\r
295 S3NvsPageTableAddress += SIZE_4KB;\r
296 //\r
297 // Make a PML4 Entry\r
298 //\r
299 PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;\r
300 PageMapLevel4Entry->Bits.ReadWrite = 1;\r
301 PageMapLevel4Entry->Bits.Present = 1;\r
302 \r
c56b6566 303 if (Page1GSupport) {\r
54d3b84e 304 PageDirectory1GEntry = (PAGE_TABLE_1G_ENTRY *)(UINTN)PageDirectoryPointerEntry;\r
13d4af68 305 \r
c56b6566 306 for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {\r
13d4af68 307 //\r
308 // Fill in the Page Directory entries\r
309 //\r
c56b6566
JY
310 PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;\r
311 PageDirectory1GEntry->Bits.ReadWrite = 1;\r
312 PageDirectory1GEntry->Bits.Present = 1;\r
313 PageDirectory1GEntry->Bits.MustBe1 = 1;\r
314 }\r
315 } else {\r
316 for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
317 //\r
318 // Each Directory Pointer entries points to a page of Page Directory entires.\r
319 // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
320 // \r
321 PageDirectoryEntry = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress;\r
322 S3NvsPageTableAddress += SIZE_4KB;\r
323 \r
324 //\r
325 // Fill in a Page Directory Pointer Entries\r
326 //\r
327 PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
328 PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
329 PageDirectoryPointerEntry->Bits.Present = 1;\r
330 \r
331 for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {\r
332 //\r
333 // Fill in the Page Directory entries\r
334 //\r
335 PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
336 PageDirectoryEntry->Bits.ReadWrite = 1;\r
337 PageDirectoryEntry->Bits.Present = 1;\r
338 PageDirectoryEntry->Bits.MustBe1 = 1;\r
339 }\r
13d4af68 340 }\r
341 }\r
342 }\r
343 return (EFI_PHYSICAL_ADDRESS) (UINTN) PageMap;\r
344 } else {\r
345 //\r
346 // If DXE is running 32-bit mode, no need to establish page table.\r
347 //\r
348 return (EFI_PHYSICAL_ADDRESS) 0; \r
349 }\r
350}\r
351\r
352/**\r
353 Gets the buffer of legacy memory below 1 MB \r
354 This function is to get the buffer in legacy memory below 1MB that is required during S3 resume.\r
355\r
356 @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.\r
357 @param Size The returned size of legacy memory below 1 MB.\r
358\r
359 @retval EFI_SUCCESS Size is successfully returned.\r
360 @retval EFI_INVALID_PARAMETER The pointer Size is NULL.\r
361\r
362**/\r
363EFI_STATUS\r
364EFIAPI\r
365LegacyGetS3MemorySize (\r
366 IN EFI_ACPI_S3_SAVE_PROTOCOL *This,\r
367 OUT UINTN *Size\r
368 )\r
369{\r
370 if (Size == NULL) {\r
371 return EFI_INVALID_PARAMETER;\r
372 }\r
373\r
374 *Size = mLegacyRegionSize;\r
375 return EFI_SUCCESS;\r
376}\r
377\r
378/**\r
379 Prepares all information that is needed in the S3 resume boot path.\r
380 \r
381 Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path \r
382 \r
383 @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.\r
384 @param LegacyMemoryAddress The base address of legacy memory.\r
385\r
386 @retval EFI_NOT_FOUND Some necessary information cannot be found.\r
387 @retval EFI_SUCCESS All information was saved successfully.\r
388 @retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information.\r
389 @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB.\r
390\r
391**/\r
392EFI_STATUS\r
393EFIAPI\r
394S3Ready (\r
395 IN EFI_ACPI_S3_SAVE_PROTOCOL *This,\r
396 IN VOID *LegacyMemoryAddress\r
397 )\r
398{\r
399 EFI_STATUS Status;\r
400 EFI_PHYSICAL_ADDRESS AcpiS3ContextBuffer;\r
401 ACPI_S3_CONTEXT *AcpiS3Context;\r
402 STATIC BOOLEAN AlreadyEntered;\r
403 IA32_DESCRIPTOR *Idtr;\r
404 IA32_IDT_GATE_DESCRIPTOR *IdtGate;\r
405\r
406 DEBUG ((EFI_D_INFO, "S3Ready!\n"));\r
407\r
408 //\r
409 // Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again.\r
410 // So if 2nd S3Save() is triggered later, we need ignore it.\r
411 //\r
412 if (AlreadyEntered) {\r
413 return EFI_SUCCESS;\r
414 }\r
415 AlreadyEntered = TRUE;\r
416\r
417 AcpiS3Context = AllocateAcpiNvsMemoryBelow4G (sizeof(*AcpiS3Context));\r
418 ASSERT (AcpiS3Context != NULL);\r
419 AcpiS3ContextBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;\r
420\r
421 //\r
422 // Get ACPI Table because we will save its position to variable\r
423 //\r
424 AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiFacsTable ();\r
425 ASSERT (AcpiS3Context->AcpiFacsTable != 0);\r
426\r
427 IdtGate = AllocateAcpiNvsMemoryBelow4G (sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR));\r
428 Idtr = (IA32_DESCRIPTOR *)(IdtGate + 0x100);\r
429 Idtr->Base = (UINTN)IdtGate;\r
430 Idtr->Limit = (UINT16)(sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 - 1);\r
431 AcpiS3Context->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)Idtr;\r
432\r
433 Status = SaveLockBox (\r
434 &mAcpiS3IdtrProfileGuid,\r
435 (VOID *)(UINTN)Idtr,\r
436 (UINTN)sizeof(IA32_DESCRIPTOR)\r
437 );\r
438 ASSERT_EFI_ERROR (Status);\r
439\r
440 Status = SetLockBoxAttributes (&mAcpiS3IdtrProfileGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
441 ASSERT_EFI_ERROR (Status);\r
442\r
443 //\r
444 // Allocate page table\r
445 //\r
446 AcpiS3Context->S3NvsPageTableAddress = S3CreateIdentityMappingPageTables ();\r
447\r
448 //\r
449 // Allocate stack\r
450 //\r
451 AcpiS3Context->BootScriptStackSize = PcdGet32 (PcdS3BootScriptStackSize);\r
452 AcpiS3Context->BootScriptStackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3BootScriptStackSize));\r
453 ASSERT (AcpiS3Context->BootScriptStackBase != 0);\r
454\r
455 //\r
f4a25e81 456 // Allocate a code buffer < 4G for S3 debug to load external code, set invalid code instructions in it.\r
13d4af68 457 //\r
458 AcpiS3Context->S3DebugBufferAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (EFI_PAGE_SIZE);\r
f4a25e81 459 SetMem ((VOID *)(UINTN)AcpiS3Context->S3DebugBufferAddress, EFI_PAGE_SIZE, 0xff);\r
13d4af68 460\r
461 DEBUG((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8x\n", AcpiS3Context->AcpiFacsTable));\r
462 DEBUG((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8x\n", AcpiS3Context->IdtrProfile));\r
463 DEBUG((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8x\n", AcpiS3Context->S3NvsPageTableAddress));\r
464 DEBUG((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8x\n", AcpiS3Context->S3DebugBufferAddress));\r
465\r
466 Status = SaveLockBox (\r
467 &gEfiAcpiVariableGuid,\r
468 &AcpiS3ContextBuffer,\r
469 sizeof(AcpiS3ContextBuffer)\r
470 );\r
471 ASSERT_EFI_ERROR (Status);\r
472\r
473 Status = SaveLockBox (\r
474 &gEfiAcpiS3ContextGuid,\r
475 (VOID *)(UINTN)AcpiS3Context,\r
476 (UINTN)sizeof(*AcpiS3Context)\r
477 );\r
478 ASSERT_EFI_ERROR (Status);\r
479\r
480 Status = SetLockBoxAttributes (&gEfiAcpiS3ContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
481 ASSERT_EFI_ERROR (Status);\r
482\r
483 if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {\r
484 S3ReadyThunkPlatform (AcpiS3Context);\r
485 }\r
486\r
487 return EFI_SUCCESS;\r
488}\r
489\r
490/**\r
491 The Driver Entry Point.\r
492 \r
493 The function is the driver Entry point which will produce AcpiS3SaveProtocol.\r
494 \r
495 @param ImageHandle A handle for the image that is initializing this driver\r
496 @param SystemTable A pointer to the EFI system table\r
497\r
498 @retval EFI_SUCCESS: Driver initialized successfully\r
499 @retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded\r
500 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources\r
501\r
502**/\r
503EFI_STATUS\r
504EFIAPI\r
505InstallAcpiS3Save (\r
506 IN EFI_HANDLE ImageHandle,\r
507 IN EFI_SYSTEM_TABLE *SystemTable\r
508 )\r
509{\r
510 EFI_STATUS Status;\r
511\r
512 if (!FeaturePcdGet(PcdPlatformCsmSupport)) {\r
513 //\r
514 // More memory for no CSM tip, because GDT need relocation\r
515 //\r
516 mLegacyRegionSize = 0x250;\r
517 } else {\r
518 mLegacyRegionSize = 0x100;\r
519 }\r
520\r
521 if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {\r
522 InstallAcpiS3SaveThunk ();\r
523 }\r
524\r
525 Status = gBS->InstallProtocolInterface (\r
526 &ImageHandle,\r
527 &gEfiAcpiS3SaveProtocolGuid,\r
528 EFI_NATIVE_INTERFACE,\r
529 &mS3Save\r
530 );\r
531 ASSERT_EFI_ERROR (Status);\r
532 return Status;\r
533}\r