- excute -> execute - Pacakges -> Packages - successfull -> successfully - outputed -> outputted - triggerred -> triggered - specifiecd -> specified - hexidecimal -> hexadecimal - Arrary -> Array - Pointion -> Position - paramter -> parameter - stardard -> standard - perodically -> periodically - dependecy -> dependency - evauated -> evaluated - availible -> available - boundry -> boundary - discontiguous -> discontinuous Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gary Lin <glin@suse.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			994 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			994 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation for S3 Boot Script Save thunk driver.
 | 
						|
  This thunk driver consumes PI S3SaveState protocol to produce framework S3BootScriptSave Protocol 
 | 
						|
  
 | 
						|
  Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
#include "ScriptSave.h"
 | 
						|
 | 
						|
EFI_HANDLE                    mHandle;
 | 
						|
EFI_BOOT_SCRIPT_SAVE_PROTOCOL mS3ScriptSave = {
 | 
						|
                                  BootScriptWrite,
 | 
						|
                                  BootScriptCloseTable
 | 
						|
                                 };
 | 
						|
EFI_S3_SAVE_STATE_PROTOCOL    *mS3SaveState;
 | 
						|
 | 
						|
/**
 | 
						|
  Wrapper for a thunk  to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
 | 
						|
  long mode.
 | 
						|
  
 | 
						|
  @param  Function     The 32bit code entry to be executed.
 | 
						|
  @param  Param1       The first parameter to pass to 32bit code
 | 
						|
  @param  Param2       The second parameter to pass to 32bit code
 | 
						|
  @retval EFI_SUCCESS  Execute 32bit code successfully.
 | 
						|
  @retval other        Something wrong when execute the 32bit code 
 | 
						|
              
 | 
						|
**/  
 | 
						|
EFI_STATUS
 | 
						|
Execute32BitCode (
 | 
						|
  IN UINT64      Function,
 | 
						|
  IN UINT64      Param1,
 | 
						|
  IN UINT64      Param2
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  A stub to convert framework boot script dispatch to PI boot script dispatch.
 | 
						|
  
 | 
						|
  @param  ImageHandle  It should be is NULL.
 | 
						|
  @param  Context      The first parameter to pass to 32bit code
 | 
						|
 | 
						|
  @return dispatch value.
 | 
						|
              
 | 
						|
**/  
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FrameworkBootScriptDispatchStub (
 | 
						|
  IN EFI_HANDLE ImageHandle,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  DISPATCH_ENTRYPOINT_FUNC  EntryFunc;
 | 
						|
  VOID                      *PeiServices;
 | 
						|
  IA32_DESCRIPTOR           Idtr;
 | 
						|
 | 
						|
  DEBUG ((EFI_D_ERROR, "FrameworkBootScriptDispatchStub - 0x%08x\n", (UINTN)Context));
 | 
						|
 | 
						|
  EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (Context);
 | 
						|
  AsmReadIdtr (&Idtr);
 | 
						|
  PeiServices = (VOID *)(UINTN)(*(UINT32 *)(Idtr.Base - sizeof (UINT32)));
 | 
						|
 | 
						|
  //
 | 
						|
  // ECP assumes first parameter is NULL, and second parameter is PeiServices.
 | 
						|
  //
 | 
						|
  Status = Execute32BitCode ((UINT64)(UINTN)EntryFunc, 0, (UINT64)(UINTN)PeiServices);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add IO write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptIoWrite (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINTN                 Count;
 | 
						|
  UINT8                 *Buffer;
 | 
						|
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Count       = VA_ARG (Marker, UINTN);
 | 
						|
  Buffer      = VA_ARG (Marker, UINT8 *);
 | 
						|
  
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                        mS3SaveState,
 | 
						|
                        EFI_BOOT_SCRIPT_IO_WRITE_OPCODE,
 | 
						|
                        Width, 
 | 
						|
                        Address, 
 | 
						|
                        Count, 
 | 
						|
                        Buffer
 | 
						|
                        );
 | 
						|
}
 | 
						|
/**
 | 
						|
  Internal function to add IO read/write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptIoReadWrite (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINT8                 *Data;
 | 
						|
  UINT8                 *DataMask;
 | 
						|
 
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Data        = VA_ARG (Marker, UINT8 *);
 | 
						|
  DataMask    = VA_ARG (Marker, UINT8 *);
 | 
						|
  
 | 
						|
   return mS3SaveState->Write (
 | 
						|
                         mS3SaveState,
 | 
						|
                         EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE,
 | 
						|
                         Width, 
 | 
						|
                         Address, 
 | 
						|
                         Data, 
 | 
						|
                         DataMask
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add memory write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptMemWrite (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINTN                 Count;
 | 
						|
  UINT8                 *Buffer;
 | 
						|
 
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Count       = VA_ARG (Marker, UINTN);
 | 
						|
  Buffer      = VA_ARG (Marker, UINT8 *);
 | 
						|
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                        mS3SaveState,
 | 
						|
                        EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE,
 | 
						|
                        Width, 
 | 
						|
                        Address, 
 | 
						|
                        Count, 
 | 
						|
                        Buffer
 | 
						|
                        );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add memory read/write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptMemReadWrite (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINT8                 *Data;
 | 
						|
  UINT8                 *DataMask;
 | 
						|
  
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Data        = VA_ARG (Marker, UINT8 *);
 | 
						|
  DataMask    = VA_ARG (Marker, UINT8 *);
 | 
						|
 | 
						|
 return mS3SaveState->Write (
 | 
						|
                        mS3SaveState,
 | 
						|
                        EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE,
 | 
						|
                        Width, 
 | 
						|
                        Address, 
 | 
						|
                        Data, 
 | 
						|
                        DataMask
 | 
						|
                        );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add PciCfg write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptPciCfgWrite (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINTN                 Count;
 | 
						|
  UINT8                 *Buffer;
 | 
						|
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Count       = VA_ARG (Marker, UINTN);
 | 
						|
  Buffer      = VA_ARG (Marker, UINT8 *);
 | 
						|
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                        mS3SaveState,
 | 
						|
                        EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE,
 | 
						|
                        Width, 
 | 
						|
                        Address, 
 | 
						|
                        Count, 
 | 
						|
                        Buffer
 | 
						|
                        );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to PciCfg read/write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptPciCfgReadWrite (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINT8                 *Data;
 | 
						|
  UINT8                 *DataMask;
 | 
						|
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Data        = VA_ARG (Marker, UINT8 *);
 | 
						|
  DataMask    = VA_ARG (Marker, UINT8 *);
 | 
						|
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE,
 | 
						|
                          Width,
 | 
						|
                          Address,
 | 
						|
                          Data,
 | 
						|
                          DataMask
 | 
						|
                         );
 | 
						|
}
 | 
						|
/**
 | 
						|
  Internal function to add PciCfg2 write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptPciCfg2Write (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINTN                 Count;
 | 
						|
  UINT8                 *Buffer;
 | 
						|
  UINT16                Segment;
 | 
						|
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Count       = VA_ARG (Marker, UINTN);
 | 
						|
  Buffer      = VA_ARG (Marker, UINT8 *);
 | 
						|
  Segment     = VA_ARG (Marker, UINT16);
 | 
						|
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE,
 | 
						|
                          Width, 
 | 
						|
                          Segment, 
 | 
						|
                          Address, 
 | 
						|
                          Count, 
 | 
						|
                          Buffer
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to PciCfg2 read/write opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptPciCfg2ReadWrite (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT16                Segment;
 | 
						|
  UINT64                Address;
 | 
						|
  UINT8                 *Data;
 | 
						|
  UINT8                 *DataMask;
 | 
						|
 
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  Segment     = VA_ARG (Marker, UINT16);
 | 
						|
  Data        = VA_ARG (Marker, UINT8 *);
 | 
						|
  DataMask    = VA_ARG (Marker, UINT8 *);
 | 
						|
 
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE,
 | 
						|
                          Width, 
 | 
						|
                          Segment,
 | 
						|
                          Address,
 | 
						|
                          Data,
 | 
						|
                          DataMask
 | 
						|
                          );
 | 
						|
}
 | 
						|
/**
 | 
						|
  Internal function to add smbus execute opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptSmbusExecute (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress;
 | 
						|
  EFI_SMBUS_DEVICE_COMMAND  Command;
 | 
						|
  EFI_SMBUS_OPERATION       Operation;
 | 
						|
  BOOLEAN                   PecCheck;
 | 
						|
  VOID                     *Buffer;
 | 
						|
  UINTN                    *DataSize;
 | 
						|
  
 | 
						|
  SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN);
 | 
						|
  Command                         = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND);
 | 
						|
  Operation                       = VA_ARG (Marker, EFI_SMBUS_OPERATION);
 | 
						|
  PecCheck                        = VA_ARG (Marker, BOOLEAN);
 | 
						|
  DataSize                        = VA_ARG (Marker, UINTN *);    
 | 
						|
  Buffer                          = VA_ARG (Marker, VOID *);
 | 
						|
 
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE,
 | 
						|
                          SlaveAddress,
 | 
						|
                          Command, 
 | 
						|
                          Operation, 
 | 
						|
                          PecCheck,
 | 
						|
                          DataSize, 
 | 
						|
                          Buffer
 | 
						|
                         );
 | 
						|
}
 | 
						|
/**
 | 
						|
  Internal function to add stall opcode to the table.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptStall (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32                Duration;
 | 
						|
 | 
						|
  Duration    = VA_ARG (Marker, UINT32);
 | 
						|
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_STALL_OPCODE,
 | 
						|
                          Duration
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add Save jmp address according to DISPATCH_OPCODE. 
 | 
						|
  We ignore "Context" parameter
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptDispatch (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID        *EntryPoint;
 | 
						|
 | 
						|
  EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_DISPATCH_OPCODE,
 | 
						|
                          EntryPoint
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add Save jmp address according to DISPATCH_OPCODE. 
 | 
						|
  We ignore "Context" parameter.
 | 
						|
  We need create thunk stub to convert PEI entrypoint (used in Framework version)
 | 
						|
  to DXE entrypoint (defined in PI spec).
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FrameworkBootScriptDispatch (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID           *EntryPoint;
 | 
						|
  VOID           *Context;
 | 
						|
 | 
						|
  EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
 | 
						|
 | 
						|
  //
 | 
						|
  // Register callback
 | 
						|
  //
 | 
						|
  Context    = EntryPoint;
 | 
						|
  EntryPoint = (VOID *)(UINTN)FrameworkBootScriptDispatchStub;
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                         mS3SaveState,
 | 
						|
                         EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE,
 | 
						|
                         EntryPoint,
 | 
						|
                         Context
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add memory pool operation to the table. 
 | 
						|
 
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptMemPoll (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_SCRIPT_WIDTH Width;
 | 
						|
  UINT64                Address;
 | 
						|
  UINT8                 *BitMask;
 | 
						|
  UINT8                 *BitValue;
 | 
						|
  UINT64                Duration;
 | 
						|
  UINT64                LoopTimes;
 | 
						|
  UINT64                Delay;
 | 
						|
 | 
						|
  Width       = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
 | 
						|
  Address     = VA_ARG (Marker, UINT64);
 | 
						|
  BitMask     = VA_ARG (Marker, UINT8 *);
 | 
						|
  BitValue    = VA_ARG (Marker, UINT8 *);
 | 
						|
  Duration    = (UINT64)VA_ARG (Marker, UINT64);
 | 
						|
  LoopTimes   = (UINT64)VA_ARG (Marker, UINT64);
 | 
						|
  //
 | 
						|
  // Framework version: Duration is used for Stall(), which is Microseconds.
 | 
						|
  //                    Total time is: Duration(Microseconds) * LoopTimes.
 | 
						|
  // PI version:        Duration is always 100ns. Delay is LoopTimes.
 | 
						|
  //                    Total time is: 100ns * Delay.
 | 
						|
  // So Delay = Duration(Microseconds) * LoopTimes / 100ns
 | 
						|
  //          = Duration * 1000ns * LoopTimes / 100ns
 | 
						|
  //          = Duration * 10 * LoopTimes
 | 
						|
  //
 | 
						|
  Delay       = MultU64x64 (MultU64x32 (Duration, 10), LoopTimes);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Framework version: First BitMask, then BitValue
 | 
						|
  // PI version: First Data, then DataMask
 | 
						|
  // So we revert their order in function call
 | 
						|
  //
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_MEM_POLL_OPCODE,
 | 
						|
                          Width,
 | 
						|
                          Address,
 | 
						|
                          BitValue,
 | 
						|
                          BitMask,
 | 
						|
                          Delay
 | 
						|
                          );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function to add Save jmp address according to DISPATCH_OPCODE2. 
 | 
						|
  The "Context" parameter is not ignored.
 | 
						|
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
 | 
						|
  @retval EFI_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptDispatch2 (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID                  *EntryPoint;
 | 
						|
  VOID                  *Context;  
 | 
						|
 | 
						|
  EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
 | 
						|
  Context    = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
 | 
						|
 | 
						|
 return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE,
 | 
						|
                          EntryPoint, 
 | 
						|
                          Context
 | 
						|
                         );
 | 
						|
}
 | 
						|
/**
 | 
						|
  Internal function to add the opcode link node to the link
 | 
						|
  list.
 | 
						|
  @param  Marker                The variable argument list to get the opcode
 | 
						|
                                and associated attributes.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
 | 
						|
  @retval EFI_SUCCESS           The opcode entry is added to the link list
 | 
						|
                                successfully.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootScriptInformation (
 | 
						|
  IN VA_LIST                       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32                InformationLength;
 | 
						|
  EFI_PHYSICAL_ADDRESS  Information;  
 | 
						|
 | 
						|
  InformationLength = VA_ARG (Marker, UINT32);
 | 
						|
  Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
 | 
						|
  
 | 
						|
  return mS3SaveState->Write (
 | 
						|
                          mS3SaveState,
 | 
						|
                          EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
 | 
						|
                          InformationLength, 
 | 
						|
                          (VOID*)(UINTN)Information
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record into a specified Framework boot script table.
 | 
						|
 | 
						|
  This function is used to store a boot script record into a given boot
 | 
						|
  script table. If the table specified by TableName is nonexistent in the 
 | 
						|
  system, a new table will automatically be created and then the script record 
 | 
						|
  will be added into the new table. A boot script table can add new script records
 | 
						|
  until EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is called. Currently, the only 
 | 
						|
  meaningful table name is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. This function is
 | 
						|
  responsible for allocating necessary memory for the script.
 | 
						|
 | 
						|
  This function has a variable parameter list. The exact parameter list depends on 
 | 
						|
  the OpCode that is passed into the function. If an unsupported OpCode or illegal 
 | 
						|
  parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
 | 
						|
  If there are not enough resources available for storing more scripts, this function returns
 | 
						|
  EFI_OUT_OF_RESOURCES.
 | 
						|
 | 
						|
  @param  This                  A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
 | 
						|
  @param  TableName             Name of the script table. Currently, the only meaningful value is
 | 
						|
                                EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
 | 
						|
  @param  OpCode                The operation code (opcode) number.
 | 
						|
  @param  ...                   Argument list that is specific to each opcode. 
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation succeeded. A record was added into the
 | 
						|
                                specified script table.
 | 
						|
  @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
 | 
						|
                                If the opcode is unknow or not supported because of the PCD 
 | 
						|
                                Feature Flags.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  There is insufficient memory to store the boot script.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BootScriptWrite (
 | 
						|
  IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL    *This,
 | 
						|
  IN UINT16                           TableName,
 | 
						|
  IN UINT16                           OpCode,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  VA_LIST                   Marker;
 | 
						|
  
 | 
						|
  if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) {
 | 
						|
    //
 | 
						|
    // Only S3 boot script is supported for now
 | 
						|
    //
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Build script according to opcode
 | 
						|
  //
 | 
						|
  switch (OpCode) {
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptIoWrite (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptIoReadWrite (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptMemWrite (Marker);
 | 
						|
    VA_END (Marker); 
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptMemReadWrite (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptPciCfgWrite (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptPciCfgReadWrite (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptSmbusExecute (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_STALL_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptStall (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
  
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = FrameworkBootScriptDispatch (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case FRAMEWORK_EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptDispatch2 (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptInformation (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case FRAMEWORK_EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptMemPoll (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptPciCfg2Write (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
 | 
						|
    VA_START (Marker, OpCode);
 | 
						|
    Status = BootScriptPciCfg2ReadWrite (Marker);
 | 
						|
    VA_END (Marker);
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Closes the specified script table.
 | 
						|
 | 
						|
  This function closes the specified boot script table and returns the base address 
 | 
						|
  of the table. It allocates a new pool to duplicate all the boot scripts in the specified 
 | 
						|
  table. Once this function is called, the specified table will be destroyed after it is 
 | 
						|
  copied into the allocated pool. As a result, any attempts to add a script record into a 
 | 
						|
  closed table will cause a new table to be created. The base address of the allocated pool 
 | 
						|
  will be returned in Address. After using the boot script table, the caller is responsible 
 | 
						|
  for freeing the pool that is allocated by this function. If the boot script table,
 | 
						|
  such as EFI_ACPI_S3_RESUME_SCRIPT_TABLE, is required to be stored in a nonperturbed
 | 
						|
  memory region, the caller should copy the table into the nonperturbed memory region by itself.
 | 
						|
 | 
						|
  @param  This                  A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
 | 
						|
  @param  TableName             Name of the script table. Currently, the only meaningful value is
 | 
						|
                                 EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
 | 
						|
  @param  Address               A pointer to the physical address where the table begins. 
 | 
						|
                               
 | 
						|
  @retval EFI_SUCCESS           The table was successfully returned.
 | 
						|
  @retval EFI_NOT_FOUND         The specified table was not created previously.
 | 
						|
  @retval EFI_OUT_OF_RESOURCE   Memory is insufficient to hold the reorganized boot script table.
 | 
						|
  @retval EFI_UNSUPPORTED       the table type is not EFI_ACPI_S3_RESUME_SCRIPT_TABLE
 | 
						|
  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BootScriptCloseTable (
 | 
						|
  IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL    *This,
 | 
						|
  IN UINT16                           TableName,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS            *Address
 | 
						|
  )
 | 
						|
{ 
 | 
						|
  if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) {
 | 
						|
    //
 | 
						|
    // Only S3 boot script is supported for now
 | 
						|
    //
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Here the close table is not implemented. 
 | 
						|
  //  
 | 
						|
 
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Register image to memory profile.
 | 
						|
 | 
						|
  @param FileName       File name of the image.
 | 
						|
  @param ImageBase      Image base address.
 | 
						|
  @param ImageSize      Image size.
 | 
						|
  @param FileType       File type of the image.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RegisterMemoryProfileImage (
 | 
						|
  IN EFI_GUID                       *FileName,
 | 
						|
  IN PHYSICAL_ADDRESS               ImageBase,
 | 
						|
  IN UINT64                         ImageSize,
 | 
						|
  IN EFI_FV_FILETYPE                FileType
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EDKII_MEMORY_PROFILE_PROTOCOL     *ProfileProtocol;
 | 
						|
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
 | 
						|
  UINT8                             TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
 | 
						|
 | 
						|
  if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {
 | 
						|
 | 
						|
    FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
 | 
						|
    Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      EfiInitializeFwVolDevicepathNode (FilePath, FileName);
 | 
						|
      SetDevicePathEndNode (FilePath + 1);
 | 
						|
 | 
						|
      Status = ProfileProtocol->RegisterImage (
 | 
						|
                                  ProfileProtocol,
 | 
						|
                                  (EFI_DEVICE_PATH_PROTOCOL *) FilePath,
 | 
						|
                                  ImageBase,
 | 
						|
                                  ImageSize,
 | 
						|
                                  FileType
 | 
						|
                                  );
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This routine is entry point of ScriptSave driver.
 | 
						|
 | 
						|
  @param  ImageHandle           Handle for this drivers loaded image protocol.
 | 
						|
  @param  SystemTable           EFI system table.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough resource
 | 
						|
  @retval EFI_SUCCESS           Succesfully installed the ScriptSave driver.
 | 
						|
  @retval other                 Errors occured.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
InitializeScriptSaveOnS3SaveState (
 | 
						|
  IN EFI_HANDLE           ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE     *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                                         *Buffer;
 | 
						|
  UINTN                                         BufferSize;
 | 
						|
  PE_COFF_LOADER_IMAGE_CONTEXT                  ImageContext;
 | 
						|
  BOOT_SCRIPT_THUNK_DATA                        *BootScriptThunkData;
 | 
						|
  EFI_STATUS                                    Status;
 | 
						|
  VOID                                          *DevicePath;
 | 
						|
  EFI_PHYSICAL_ADDRESS                          MemoryAddress;
 | 
						|
  UINTN                                         PageNumber;
 | 
						|
  EFI_HANDLE                                    NewImageHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
 | 
						|
  // point is loaded by DXE code which is the first time loaded. or else, it is already
 | 
						|
  // be reloaded be itself.This is a work-around
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // This is the first-time loaded by DXE core. reload itself to RESERVED mem
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // A workaround: Here we install a dummy handle
 | 
						|
    //
 | 
						|
    NewImageHandle = NULL;
 | 
						|
    Status = gBS->InstallProtocolInterface (
 | 
						|
                    &NewImageHandle,
 | 
						|
                    &gEfiCallerIdGuid,
 | 
						|
                    EFI_NATIVE_INTERFACE,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = GetSectionFromAnyFv  (
 | 
						|
               &gEfiCallerIdGuid,
 | 
						|
               EFI_SECTION_PE32,
 | 
						|
               0,
 | 
						|
               (VOID **) &Buffer,
 | 
						|
               &BufferSize
 | 
						|
               );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    ImageContext.Handle    = Buffer;
 | 
						|
    ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
 | 
						|
    //
 | 
						|
    // Get information about the image being loaded
 | 
						|
    //
 | 
						|
    Status = PeCoffLoaderGetImageInfo (&ImageContext);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    MemoryAddress = SIZE_4GB - 1;
 | 
						|
    if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
 | 
						|
      PageNumber = EFI_SIZE_TO_PAGES ((UINTN) (ImageContext.ImageSize + ImageContext.SectionAlignment));
 | 
						|
    } else {
 | 
						|
      PageNumber = EFI_SIZE_TO_PAGES ((UINTN) ImageContext.ImageSize);
 | 
						|
    }
 | 
						|
    Status  = gBS->AllocatePages (
 | 
						|
                     AllocateMaxAddress,
 | 
						|
                     EfiReservedMemoryType,
 | 
						|
                     PageNumber,
 | 
						|
                     &MemoryAddress
 | 
						|
                     );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)MemoryAddress;
 | 
						|
    //
 | 
						|
    // Align buffer on section boundary
 | 
						|
    //
 | 
						|
    ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
 | 
						|
    ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
 | 
						|
    //
 | 
						|
    // Load the image to our new buffer
 | 
						|
    //
 | 
						|
    Status = PeCoffLoaderLoadImage (&ImageContext);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Relocate the image in our new buffer
 | 
						|
    //
 | 
						|
    Status = PeCoffLoaderRelocateImage (&ImageContext);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
 | 
						|
    //
 | 
						|
    gBS->FreePool (Buffer);
 | 
						|
 | 
						|
    //
 | 
						|
    // Flush the instruction cache so the image data is written before we execute it
 | 
						|
    //
 | 
						|
    InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
 | 
						|
 | 
						|
    RegisterMemoryProfileImage (
 | 
						|
      &gEfiCallerIdGuid,
 | 
						|
      ImageContext.ImageAddress,
 | 
						|
      ImageContext.ImageSize,
 | 
						|
      EFI_FV_FILETYPE_DRIVER
 | 
						|
    );
 | 
						|
 | 
						|
    Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Additional step for BootScriptThunk integrity
 | 
						|
    //
 | 
						|
 | 
						|
    //
 | 
						|
    // Allocate BootScriptThunkData
 | 
						|
    //
 | 
						|
    BootScriptThunkData = AllocatePool (sizeof (BOOT_SCRIPT_THUNK_DATA));
 | 
						|
    ASSERT (BootScriptThunkData != NULL);
 | 
						|
 | 
						|
    BootScriptThunkData->BootScriptThunkBase   = ImageContext.ImageAddress;
 | 
						|
    BootScriptThunkData->BootScriptThunkLength = ImageContext.ImageSize;
 | 
						|
    //
 | 
						|
    // Set BootScriptThunkData
 | 
						|
    //
 | 
						|
    PcdSet64 (BootScriptThunkDataPtr, (UINT64)(UINTN)BootScriptThunkData); 
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // the entry point is invoked after reloading. following code only run in RESERVED mem
 | 
						|
    //
 | 
						|
 | 
						|
    //
 | 
						|
    // Locate and cache PI S3 Save State Protocol.
 | 
						|
    //
 | 
						|
    Status = gBS->LocateProtocol (
 | 
						|
                    &gEfiS3SaveStateProtocolGuid, 
 | 
						|
                    NULL, 
 | 
						|
                    (VOID **) &mS3SaveState
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    return gBS->InstallProtocolInterface (
 | 
						|
                  &mHandle,
 | 
						|
                  &gEfiBootScriptSaveProtocolGuid,
 | 
						|
                  EFI_NATIVE_INTERFACE,
 | 
						|
                  &mS3ScriptSave
 | 
						|
                  );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 |