Home | History | Annotate | Download | only in AcpiS3SaveDxe
      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 - 2016, 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/BaseMemoryLib.h>
     20 #include <Library/UefiBootServicesTableLib.h>
     21 #include <Library/PcdLib.h>
     22 #include <Library/DebugLib.h>
     23 #include <Protocol/AcpiS3Save.h>
     24 
     25 #include "AcpiS3Save.h"
     26 
     27 /**
     28   Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.
     29 **/
     30 VOID
     31 InstallAcpiS3SaveThunk (
     32   VOID
     33   );
     34 
     35 /**
     36   Hook point for AcpiVariableThunkPlatform for S3Ready.
     37 
     38 **/
     39 VOID
     40 S3ReadyThunkPlatform (
     41   VOID
     42   );
     43 
     44 UINTN     mLegacyRegionSize;
     45 
     46 EFI_ACPI_S3_SAVE_PROTOCOL mS3Save = {
     47   LegacyGetS3MemorySize,
     48   S3Ready,
     49 };
     50 
     51 /**
     52   Allocate memory below 4G memory address.
     53 
     54   This function allocates memory below 4G memory address.
     55 
     56   @param  MemoryType   Memory type of memory to allocate.
     57   @param  Size         Size of memory to allocate.
     58 
     59   @return Allocated address for output.
     60 
     61 **/
     62 VOID*
     63 AllocateMemoryBelow4G (
     64   IN EFI_MEMORY_TYPE    MemoryType,
     65   IN UINTN              Size
     66   )
     67 {
     68   UINTN                 Pages;
     69   EFI_PHYSICAL_ADDRESS  Address;
     70   EFI_STATUS            Status;
     71   VOID*                 Buffer;
     72 
     73   Pages = EFI_SIZE_TO_PAGES (Size);
     74   Address = 0xffffffff;
     75 
     76   Status  = gBS->AllocatePages (
     77                    AllocateMaxAddress,
     78                    MemoryType,
     79                    Pages,
     80                    &Address
     81                    );
     82   ASSERT_EFI_ERROR (Status);
     83 
     84   Buffer = (VOID *) (UINTN) Address;
     85   ZeroMem (Buffer, Size);
     86 
     87   return Buffer;
     88 }
     89 
     90 /**
     91   Gets the buffer of legacy memory below 1 MB
     92   This function is to get the buffer in legacy memory below 1MB that is required during S3 resume.
     93 
     94   @param This           A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.
     95   @param Size           The returned size of legacy memory below 1 MB.
     96 
     97   @retval EFI_SUCCESS           Size is successfully returned.
     98   @retval EFI_INVALID_PARAMETER The pointer Size is NULL.
     99 
    100 **/
    101 EFI_STATUS
    102 EFIAPI
    103 LegacyGetS3MemorySize (
    104   IN  EFI_ACPI_S3_SAVE_PROTOCOL   *This,
    105   OUT UINTN                       *Size
    106   )
    107 {
    108   if (Size == NULL) {
    109     return EFI_INVALID_PARAMETER;
    110   }
    111 
    112   *Size = mLegacyRegionSize;
    113   return EFI_SUCCESS;
    114 }
    115 
    116 /**
    117   Prepares all information that is needed in the S3 resume boot path.
    118 
    119   Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path
    120 
    121   @param This                 A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.
    122   @param LegacyMemoryAddress  The base address of legacy memory.
    123 
    124   @retval EFI_NOT_FOUND         Some necessary information cannot be found.
    125   @retval EFI_SUCCESS           All information was saved successfully.
    126   @retval EFI_OUT_OF_RESOURCES  Resources were insufficient to save all the information.
    127   @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB.
    128 
    129 **/
    130 EFI_STATUS
    131 EFIAPI
    132 S3Ready (
    133   IN EFI_ACPI_S3_SAVE_PROTOCOL    *This,
    134   IN VOID                         *LegacyMemoryAddress
    135   )
    136 {
    137   STATIC BOOLEAN                  AlreadyEntered;
    138 
    139   DEBUG ((EFI_D_INFO, "S3Ready!\n"));
    140 
    141   //
    142   // Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again.
    143   // So if 2nd S3Save() is triggered later, we need ignore it.
    144   //
    145   if (AlreadyEntered) {
    146     return EFI_SUCCESS;
    147   }
    148   AlreadyEntered = TRUE;
    149 
    150   if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
    151     S3ReadyThunkPlatform ();
    152   }
    153 
    154   return EFI_SUCCESS;
    155 }
    156 
    157 /**
    158   The Driver Entry Point.
    159 
    160   The function is the driver Entry point which will produce AcpiS3SaveProtocol.
    161 
    162   @param ImageHandle   A handle for the image that is initializing this driver
    163   @param SystemTable   A pointer to the EFI system table
    164 
    165   @retval EFI_SUCCESS               Driver initialized successfully
    166   @retval EFI_UNSUPPORTED           Do not support ACPI S3
    167   @retval EFI_OUT_OF_RESOURCES      Could not allocate needed resources
    168 
    169 **/
    170 EFI_STATUS
    171 EFIAPI
    172 InstallAcpiS3Save (
    173   IN EFI_HANDLE           ImageHandle,
    174   IN EFI_SYSTEM_TABLE     *SystemTable
    175   )
    176 {
    177   EFI_STATUS        Status;
    178 
    179   if (!PcdGetBool (PcdAcpiS3Enable)) {
    180     return EFI_UNSUPPORTED;
    181   }
    182 
    183   if (!FeaturePcdGet(PcdPlatformCsmSupport)) {
    184     //
    185     // More memory for no CSM tip, because GDT need relocation
    186     //
    187     mLegacyRegionSize = 0x250;
    188   } else {
    189     mLegacyRegionSize = 0x100;
    190   }
    191 
    192   if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
    193     InstallAcpiS3SaveThunk ();
    194   }
    195 
    196   Status = gBS->InstallProtocolInterface (
    197                   &ImageHandle,
    198                   &gEfiAcpiS3SaveProtocolGuid,
    199                   EFI_NATIVE_INTERFACE,
    200                   &mS3Save
    201                   );
    202   ASSERT_EFI_ERROR (Status);
    203   return Status;
    204 }
    205