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