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