mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-03 21:17:23 +01:00 
			
		
		
		
	REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			2495 lines
		
	
	
		
			83 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2495 lines
		
	
	
		
			83 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Save the S3 data to S3 boot script.
 | 
						|
 | 
						|
  Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
#include "InternalBootScriptLib.h"
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Data structure usage:
 | 
						|
 | 
						|
  +------------------------------+<------- PcdS3BootScriptTablePrivateDataPtr
 | 
						|
  | SCRIPT_TABLE_PRIVATE_DATA    |          (mS3BootScriptTablePtr, Before SmmReadyToLock)
 | 
						|
  |    TableBase                 |---      PcdS3BootScriptTablePrivateSmmDataPtr
 | 
						|
  |    TableLength               |--|--     (mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr, After SmmReadyToLock InSmm)
 | 
						|
  |    TableMemoryPageNumber     |--|-|----
 | 
						|
  |    AtRuntime                 |  | |   |
 | 
						|
  |    InSmm                     |  | |   |
 | 
						|
  |    BootTimeScriptLength      |--|-|---|---
 | 
						|
  |    SmmLocked                 |  | |   |  |
 | 
						|
  |    BackFromS3                |  | |   |  |
 | 
						|
  +------------------------------+  | |   |  |
 | 
						|
                                    | |   |  |
 | 
						|
  +------------------------------+<-- |   |  |
 | 
						|
  | EFI_BOOT_SCRIPT_TABLE_HEADER |    |   |  |
 | 
						|
  |    TableLength               |----|-- |  |
 | 
						|
  +------------------------------+    | | |  |
 | 
						|
  |     ......                   |    | | |  |
 | 
						|
  +------------------------------+<---- | |  |
 | 
						|
  | EFI_BOOT_SCRIPT_TERMINATE    |      | |  |
 | 
						|
  +------------------------------+<------ |  |
 | 
						|
                                          |  |
 | 
						|
                                          |  |
 | 
						|
  mBootScriptDataBootTimeGuid LockBox:    |  |
 | 
						|
   Used to restore data after back from S3|  |
 | 
						|
   to handle potential INSERT boot script |  |
 | 
						|
   at runtime.                            |  |
 | 
						|
  +------------------------------+        |  |
 | 
						|
  | Boot Time Boot Script        |        |  |
 | 
						|
  | Before SmmReadyToLock        |        |  |
 | 
						|
  |                              |        |  |
 | 
						|
  |                              |        |  |
 | 
						|
  +------------------------------+        |  |
 | 
						|
  | Boot Time Boot Script        |        |  |
 | 
						|
  | After SmmReadyToLock InSmm   |        |  |
 | 
						|
  |                              |        |  |
 | 
						|
  +------------------------------+<-------|--|
 | 
						|
                                          |  |
 | 
						|
                                          |  |
 | 
						|
  mBootScriptDataGuid LockBox: (IN_PLACE) |  |
 | 
						|
   Used to restore data at S3 resume.     |  |
 | 
						|
  +------------------------------+        |  |
 | 
						|
  | Boot Time Boot Script        |        |  |
 | 
						|
  | Before SmmReadyToLock        |        |  |
 | 
						|
  |                              |        |  |
 | 
						|
  |                              |        |  |
 | 
						|
  +------------------------------+        |  |
 | 
						|
  | Boot Time Boot Script        |        |  |
 | 
						|
  | After SmmReadyToLock InSmm   |        |  |
 | 
						|
  |                              |        |  |
 | 
						|
  +------------------------------+<-------|---
 | 
						|
  | Runtime Boot Script          |        |
 | 
						|
  | After SmmReadyToLock InSmm   |        |
 | 
						|
  +------------------------------+        |
 | 
						|
  |     ......                   |        |
 | 
						|
  +------------------------------+<--------
 | 
						|
 | 
						|
 | 
						|
  mBootScriptTableBaseGuid LockBox: (IN_PLACE)
 | 
						|
  +------------------------------+
 | 
						|
  | mS3BootScriptTablePtr->      |
 | 
						|
  |  TableBase                   |
 | 
						|
  +------------------------------+
 | 
						|
 | 
						|
 | 
						|
  mBootScriptSmmPrivateDataGuid LockBox: (IN_PLACE)
 | 
						|
   SMM private data with BackFromS3 = TRUE
 | 
						|
   at runtime. S3 will help restore it to
 | 
						|
   tell the Library the system is back from S3.
 | 
						|
  +------------------------------+
 | 
						|
  | SCRIPT_TABLE_PRIVATE_DATA    |
 | 
						|
  |    TableBase                 |
 | 
						|
  |    TableLength               |
 | 
						|
  |    TableMemoryPageNumber     |
 | 
						|
  |    AtRuntime                 |
 | 
						|
  |    InSmm                     |
 | 
						|
  |    BootTimeScriptLength      |
 | 
						|
  |    SmmLocked                 |
 | 
						|
  |    BackFromS3 = TRUE         |
 | 
						|
  +------------------------------+
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
SCRIPT_TABLE_PRIVATE_DATA  *mS3BootScriptTablePtr;
 | 
						|
 | 
						|
//
 | 
						|
// Allocate SMM copy because we can not use mS3BootScriptTablePtr after SmmReadyToLock in InSmm.
 | 
						|
//
 | 
						|
SCRIPT_TABLE_PRIVATE_DATA  *mS3BootScriptTableSmmPtr;
 | 
						|
 | 
						|
EFI_GUID  mBootScriptDataGuid = {
 | 
						|
  0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }
 | 
						|
};
 | 
						|
 | 
						|
EFI_GUID  mBootScriptDataBootTimeGuid = {
 | 
						|
  0xb5af1d7a, 0xb8cf, 0x4eb3, { 0x89, 0x25, 0xa8, 0x20, 0xe1, 0x6b, 0x68, 0x7d }
 | 
						|
};
 | 
						|
 | 
						|
EFI_GUID  mBootScriptTableBaseGuid = {
 | 
						|
  0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }
 | 
						|
};
 | 
						|
 | 
						|
EFI_GUID  mBootScriptSmmPrivateDataGuid = {
 | 
						|
  0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 }
 | 
						|
};
 | 
						|
 | 
						|
EFI_EVENT              mEventDxeSmmReadyToLock           = NULL;
 | 
						|
VOID                   *mRegistrationSmmExitBootServices = NULL;
 | 
						|
VOID                   *mRegistrationSmmLegacyBoot       = NULL;
 | 
						|
VOID                   *mRegistrationSmmReadyToLock      = NULL;
 | 
						|
BOOLEAN                mS3BootScriptTableAllocated       = FALSE;
 | 
						|
BOOLEAN                mS3BootScriptTableSmmAllocated    = FALSE;
 | 
						|
EFI_SMM_SYSTEM_TABLE2  *mBootScriptSmst                  = NULL;
 | 
						|
BOOLEAN                mS3BootScriptAcpiS3Enable         = TRUE;
 | 
						|
 | 
						|
/**
 | 
						|
  This is an internal function to add a terminate node the entry, recalculate the table
 | 
						|
  length and fill into the table.
 | 
						|
 | 
						|
  @return the base address of the boot script table.
 | 
						|
 **/
 | 
						|
UINT8 *
 | 
						|
S3BootScriptInternalCloseTable (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                         *S3TableBase;
 | 
						|
  EFI_BOOT_SCRIPT_TERMINATE     ScriptTerminate;
 | 
						|
  EFI_BOOT_SCRIPT_TABLE_HEADER  *ScriptTableInfo;
 | 
						|
 | 
						|
  S3TableBase = mS3BootScriptTablePtr->TableBase;
 | 
						|
 | 
						|
  if (S3TableBase == NULL) {
 | 
						|
    //
 | 
						|
    // the table is not exist
 | 
						|
    //
 | 
						|
    return S3TableBase;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Append the termination entry.
 | 
						|
  //
 | 
						|
  ScriptTerminate.OpCode = S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE;
 | 
						|
  ScriptTerminate.Length = (UINT8)sizeof (EFI_BOOT_SCRIPT_TERMINATE);
 | 
						|
  CopyMem (mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength, &ScriptTerminate, sizeof (EFI_BOOT_SCRIPT_TERMINATE));
 | 
						|
  //
 | 
						|
  // fill the table length
 | 
						|
  //
 | 
						|
  ScriptTableInfo              = (EFI_BOOT_SCRIPT_TABLE_HEADER *)(mS3BootScriptTablePtr->TableBase);
 | 
						|
  ScriptTableInfo->TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
 | 
						|
 | 
						|
  return S3TableBase;
 | 
						|
  //
 | 
						|
  // NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to
 | 
						|
  // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).
 | 
						|
  // Because maybe after SmmReadyToLock, we still need add entries into the table,
 | 
						|
  // and the entry should be added start before this TERMINATE node.
 | 
						|
  //
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function save boot script data to LockBox.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SaveBootScriptDataToLockBox (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Save whole memory copy into LockBox.
 | 
						|
  // It will be used to restore data at S3 resume.
 | 
						|
  //
 | 
						|
  Status = SaveLockBox (
 | 
						|
             &mBootScriptDataGuid,
 | 
						|
             (VOID *)mS3BootScriptTablePtr->TableBase,
 | 
						|
             EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr->TableMemoryPageNumber)
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = SetLockBoxAttributes (&mBootScriptDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Just need save TableBase.
 | 
						|
  // Do not update other field because they will NOT be used in S3.
 | 
						|
  //
 | 
						|
  Status = SaveLockBox (
 | 
						|
             &mBootScriptTableBaseGuid,
 | 
						|
             (VOID *)&mS3BootScriptTablePtr->TableBase,
 | 
						|
             sizeof (mS3BootScriptTablePtr->TableBase)
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = SetLockBoxAttributes (&mBootScriptTableBaseGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This is the Event call back function to notify the Library the system is entering
 | 
						|
  SmmLocked phase.
 | 
						|
 | 
						|
  @param  Event   Pointer to this event
 | 
						|
  @param  Context Event handler private data
 | 
						|
 **/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
S3BootScriptEventCallBack (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  VOID        *Interface;
 | 
						|
 | 
						|
  //
 | 
						|
  // Try to locate it because EfiCreateProtocolNotifyEvent will trigger it once when registration.
 | 
						|
  // Just return if it is not found.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiDxeSmmReadyToLockProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &Interface
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Here we should tell the library that we are entering SmmLocked phase.
 | 
						|
  // and the memory page number occupied by the table should not grow anymore.
 | 
						|
  //
 | 
						|
  if (!mS3BootScriptTablePtr->SmmLocked) {
 | 
						|
    //
 | 
						|
    // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table
 | 
						|
    // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate
 | 
						|
    // node on every add to boot script table.
 | 
						|
    //
 | 
						|
    S3BootScriptInternalCloseTable ();
 | 
						|
    mS3BootScriptTablePtr->SmmLocked = TRUE;
 | 
						|
 | 
						|
    //
 | 
						|
    // Save BootScript data to lockbox
 | 
						|
    //
 | 
						|
    SaveBootScriptDataToLockBox ();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This is the Event call back function is triggered in SMM to notify the Library
 | 
						|
  the system is entering SmmLocked phase and set InSmm flag.
 | 
						|
 | 
						|
  @param  Protocol   Points to the protocol's unique identifier
 | 
						|
  @param  Interface  Points to the interface instance
 | 
						|
  @param  Handle     The handle on which the interface was installed
 | 
						|
 | 
						|
  @retval EFI_SUCCESS SmmEventCallback runs successfully
 | 
						|
 **/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSmmEventCallBack (
 | 
						|
  IN CONST EFI_GUID  *Protocol,
 | 
						|
  IN VOID            *Interface,
 | 
						|
  IN EFI_HANDLE      Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Check if it is already done
 | 
						|
  //
 | 
						|
  if (mS3BootScriptTablePtr == mS3BootScriptTableSmmPtr) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Last chance to call-out, just make sure SmmLocked is set.
 | 
						|
  //
 | 
						|
  S3BootScriptEventCallBack (NULL, NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Save a SMM copy. If TableBase is NOT null, it means SMM copy has been ready, skip copy mem.
 | 
						|
  //
 | 
						|
  if (mS3BootScriptTableSmmPtr->TableBase == NULL) {
 | 
						|
    CopyMem (mS3BootScriptTableSmmPtr, mS3BootScriptTablePtr, sizeof (*mS3BootScriptTablePtr));
 | 
						|
 | 
						|
    //
 | 
						|
    // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.
 | 
						|
    // InSmm will only be checked if SmmLocked is TRUE.
 | 
						|
    //
 | 
						|
    mS3BootScriptTableSmmPtr->InSmm = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // We should not use ACPI Reserved copy, because it is not safe.
 | 
						|
  //
 | 
						|
  mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is to save boot time boot script data to LockBox.
 | 
						|
 | 
						|
  Because there may be INSERT boot script at runtime in SMM.
 | 
						|
  The boot time copy will be used to restore data after back from S3.
 | 
						|
  Otherwise the data inserted may cause some boot time boot script data lost
 | 
						|
  if only BootScriptData used.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SaveBootTimeDataToLockBox (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,
 | 
						|
  // and then save the data to BootScriptDataBootTime LockBox.
 | 
						|
  //
 | 
						|
  Status = RestoreLockBox (
 | 
						|
             &mBootScriptDataGuid,
 | 
						|
             NULL,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Save BootScriptDataBootTime
 | 
						|
  // It will be used to restore data after back from S3.
 | 
						|
  //
 | 
						|
  Status = SaveLockBox (
 | 
						|
             &mBootScriptDataBootTimeGuid,
 | 
						|
             (VOID *)mS3BootScriptTablePtr->TableBase,
 | 
						|
             mS3BootScriptTablePtr->BootTimeScriptLength
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.
 | 
						|
  S3 resume will help restore it to tell the Library the system is back from S3.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SaveSmmPriviateDataToLockBoxAtRuntime (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Save boot script SMM private data with BackFromS3 = TRUE.
 | 
						|
  //
 | 
						|
  mS3BootScriptTablePtr->BackFromS3 = TRUE;
 | 
						|
  Status                            = SaveLockBox (
 | 
						|
                                        &mBootScriptSmmPrivateDataGuid,
 | 
						|
                                        (VOID *)mS3BootScriptTablePtr,
 | 
						|
                                        sizeof (SCRIPT_TABLE_PRIVATE_DATA)
 | 
						|
                                        );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.
 | 
						|
  //
 | 
						|
  mS3BootScriptTablePtr->BackFromS3 = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This is the Event call back function is triggered in SMM to notify the Library
 | 
						|
  the system is entering runtime phase.
 | 
						|
 | 
						|
  @param[in] Protocol   Points to the protocol's unique identifier
 | 
						|
  @param[in] Interface  Points to the interface instance
 | 
						|
  @param[in] Handle     The handle on which the interface was installed
 | 
						|
 | 
						|
  @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
 | 
						|
 **/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSmmAtRuntimeCallBack (
 | 
						|
  IN CONST EFI_GUID  *Protocol,
 | 
						|
  IN VOID            *Interface,
 | 
						|
  IN EFI_HANDLE      Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!mS3BootScriptTablePtr->AtRuntime) {
 | 
						|
    mS3BootScriptTablePtr->BootTimeScriptLength = (UINT32)(mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));
 | 
						|
    SaveBootTimeDataToLockBox ();
 | 
						|
 | 
						|
    mS3BootScriptTablePtr->AtRuntime = TRUE;
 | 
						|
    SaveSmmPriviateDataToLockBoxAtRuntime ();
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Library Constructor.
 | 
						|
  this function just identify it is a smm driver or non-smm driver linked against
 | 
						|
  with the library
 | 
						|
 | 
						|
  @param  ImageHandle   The firmware allocated handle for the EFI image.
 | 
						|
  @param  SystemTable   A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval RETURN_SUCCESS    The constructor always returns RETURN_SUCCESS.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptLibInitialize (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                 Status;
 | 
						|
  SCRIPT_TABLE_PRIVATE_DATA  *S3TablePtr;
 | 
						|
  SCRIPT_TABLE_PRIVATE_DATA  *S3TableSmmPtr;
 | 
						|
  VOID                       *Registration;
 | 
						|
  EFI_SMM_BASE2_PROTOCOL     *SmmBase2;
 | 
						|
  BOOLEAN                    InSmm;
 | 
						|
  EFI_PHYSICAL_ADDRESS       Buffer;
 | 
						|
 | 
						|
  if (!PcdGetBool (PcdAcpiS3Enable)) {
 | 
						|
    mS3BootScriptAcpiS3Enable = FALSE;
 | 
						|
    DEBUG ((DEBUG_INFO, "%a: Skip S3BootScript because ACPI S3 disabled.\n", gEfiCallerBaseName));
 | 
						|
    return RETURN_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA *)(UINTN)PcdGet64 (PcdS3BootScriptTablePrivateDataPtr);
 | 
						|
  //
 | 
						|
  // The Boot script private data is not be initialized. create it
 | 
						|
  //
 | 
						|
  if (S3TablePtr == 0) {
 | 
						|
    Buffer = SIZE_4GB - 1;
 | 
						|
    Status = gBS->AllocatePages (
 | 
						|
                    AllocateMaxAddress,
 | 
						|
                    EfiReservedMemoryType,
 | 
						|
                    EFI_SIZE_TO_PAGES (sizeof (SCRIPT_TABLE_PRIVATE_DATA)),
 | 
						|
                    &Buffer
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    mS3BootScriptTableAllocated = TRUE;
 | 
						|
    S3TablePtr                  = (VOID *)(UINTN)Buffer;
 | 
						|
 | 
						|
    Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, (UINT64)(UINTN)S3TablePtr);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    ZeroMem (S3TablePtr, sizeof (SCRIPT_TABLE_PRIVATE_DATA));
 | 
						|
    //
 | 
						|
    // Create event to notify the library system enter the SmmLocked phase.
 | 
						|
    //
 | 
						|
    mEventDxeSmmReadyToLock = EfiCreateProtocolNotifyEvent (
 | 
						|
                                &gEfiDxeSmmReadyToLockProtocolGuid,
 | 
						|
                                TPL_CALLBACK,
 | 
						|
                                S3BootScriptEventCallBack,
 | 
						|
                                NULL,
 | 
						|
                                &Registration
 | 
						|
                                );
 | 
						|
    ASSERT (mEventDxeSmmReadyToLock != NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  mS3BootScriptTablePtr = S3TablePtr;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get InSmm, we need to register SmmReadyToLock if this library is linked to SMM driver.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&SmmBase2);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return RETURN_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = SmmBase2->InSmm (SmmBase2, &InSmm);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return RETURN_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!InSmm) {
 | 
						|
    return RETURN_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Good, we are in SMM
 | 
						|
  //
 | 
						|
  Status = SmmBase2->GetSmstLocation (SmmBase2, &mBootScriptSmst);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return RETURN_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  S3TableSmmPtr = (SCRIPT_TABLE_PRIVATE_DATA *)(UINTN)PcdGet64 (PcdS3BootScriptTablePrivateSmmDataPtr);
 | 
						|
  //
 | 
						|
  // The Boot script private data in SMM is not be initialized. create it
 | 
						|
  //
 | 
						|
  if (S3TableSmmPtr == 0) {
 | 
						|
    Status = mBootScriptSmst->SmmAllocatePool (
 | 
						|
                                EfiRuntimeServicesData,
 | 
						|
                                sizeof (SCRIPT_TABLE_PRIVATE_DATA),
 | 
						|
                                (VOID **)&S3TableSmmPtr
 | 
						|
                                );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    mS3BootScriptTableSmmAllocated = TRUE;
 | 
						|
 | 
						|
    Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64)(UINTN)S3TableSmmPtr);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    ZeroMem (S3TableSmmPtr, sizeof (SCRIPT_TABLE_PRIVATE_DATA));
 | 
						|
 | 
						|
    //
 | 
						|
    // Register SmmExitBootServices and SmmLegacyBoot notification.
 | 
						|
    //
 | 
						|
    Status = mBootScriptSmst->SmmRegisterProtocolNotify (
 | 
						|
                                &gEdkiiSmmExitBootServicesProtocolGuid,
 | 
						|
                                S3BootScriptSmmAtRuntimeCallBack,
 | 
						|
                                &mRegistrationSmmExitBootServices
 | 
						|
                                );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = mBootScriptSmst->SmmRegisterProtocolNotify (
 | 
						|
                                &gEdkiiSmmLegacyBootProtocolGuid,
 | 
						|
                                S3BootScriptSmmAtRuntimeCallBack,
 | 
						|
                                &mRegistrationSmmLegacyBoot
 | 
						|
                                );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  mS3BootScriptTableSmmPtr = S3TableSmmPtr;
 | 
						|
 | 
						|
  //
 | 
						|
  // Register SmmReadyToLock notification.
 | 
						|
  //
 | 
						|
  Status = mBootScriptSmst->SmmRegisterProtocolNotify (
 | 
						|
                              &gEfiSmmReadyToLockProtocolGuid,
 | 
						|
                              S3BootScriptSmmEventCallBack,
 | 
						|
                              &mRegistrationSmmReadyToLock
 | 
						|
                              );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Library Destructor to free the resources allocated by
 | 
						|
  S3BootScriptLibInitialize() and unregister callbacks.
 | 
						|
 | 
						|
  NOTICE: The destructor doesn't support unloading as a separate action, and it
 | 
						|
  only supports unloading if the containing driver's entry point function fails.
 | 
						|
 | 
						|
  @param ImageHandle        The firmware allocated handle for the EFI image.
 | 
						|
  @param SystemTable        A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval RETURN_SUCCESS    The destructor always returns RETURN_SUCCESS.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptLibDeinitialize (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  if (!mS3BootScriptAcpiS3Enable) {
 | 
						|
    return RETURN_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() in %a module\n", __FUNCTION__, gEfiCallerBaseName));
 | 
						|
 | 
						|
  if (mEventDxeSmmReadyToLock != NULL) {
 | 
						|
    //
 | 
						|
    // Close the DxeSmmReadyToLock event.
 | 
						|
    //
 | 
						|
    Status = gBS->CloseEvent (mEventDxeSmmReadyToLock);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  if (mBootScriptSmst != NULL) {
 | 
						|
    if (mRegistrationSmmExitBootServices != NULL) {
 | 
						|
      //
 | 
						|
      // Unregister SmmExitBootServices notification.
 | 
						|
      //
 | 
						|
      Status = mBootScriptSmst->SmmRegisterProtocolNotify (
 | 
						|
                                  &gEdkiiSmmExitBootServicesProtocolGuid,
 | 
						|
                                  NULL,
 | 
						|
                                  &mRegistrationSmmExitBootServices
 | 
						|
                                  );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mRegistrationSmmLegacyBoot != NULL) {
 | 
						|
      //
 | 
						|
      // Unregister SmmLegacyBoot notification.
 | 
						|
      //
 | 
						|
      Status = mBootScriptSmst->SmmRegisterProtocolNotify (
 | 
						|
                                  &gEdkiiSmmLegacyBootProtocolGuid,
 | 
						|
                                  NULL,
 | 
						|
                                  &mRegistrationSmmLegacyBoot
 | 
						|
                                  );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mRegistrationSmmReadyToLock != NULL) {
 | 
						|
      //
 | 
						|
      // Unregister SmmReadyToLock notification.
 | 
						|
      //
 | 
						|
      Status = mBootScriptSmst->SmmRegisterProtocolNotify (
 | 
						|
                                  &gEfiSmmReadyToLockProtocolGuid,
 | 
						|
                                  NULL,
 | 
						|
                                  &mRegistrationSmmReadyToLock
 | 
						|
                                  );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the resources allocated and set PCDs to 0.
 | 
						|
  //
 | 
						|
  if (mS3BootScriptTableAllocated) {
 | 
						|
    Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mS3BootScriptTablePtr, EFI_SIZE_TO_PAGES (sizeof (SCRIPT_TABLE_PRIVATE_DATA)));
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, 0);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((mBootScriptSmst != NULL) && mS3BootScriptTableSmmAllocated) {
 | 
						|
    Status = mBootScriptSmst->SmmFreePool (mS3BootScriptTableSmmPtr);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, 0);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  To get the start address from which a new boot time s3 boot script entry will write into.
 | 
						|
  If the table is not exist, the functio will first allocate a buffer for the table
 | 
						|
  If the table buffer is not enough for the new entry, in non-smm mode, the funtion will
 | 
						|
  invoke reallocate to enlarge buffer.
 | 
						|
 | 
						|
  @param EntryLength      the new entry length.
 | 
						|
 | 
						|
  @retval the address from which the a new s3 boot script entry will write into
 | 
						|
 **/
 | 
						|
UINT8 *
 | 
						|
S3BootScriptGetBootTimeEntryAddAddress (
 | 
						|
  UINT8  EntryLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PHYSICAL_ADDRESS          S3TableBase;
 | 
						|
  EFI_PHYSICAL_ADDRESS          NewS3TableBase;
 | 
						|
  UINT8                         *NewEntryPtr;
 | 
						|
  UINT32                        TableLength;
 | 
						|
  UINT16                        PageNumber;
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_BOOT_SCRIPT_TABLE_HEADER  *ScriptTableInfo;
 | 
						|
 | 
						|
  S3TableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(mS3BootScriptTablePtr->TableBase);
 | 
						|
  if (S3TableBase == 0) {
 | 
						|
    //
 | 
						|
    // The table is not exist. This is the first to add entry.
 | 
						|
    // Allocate ACPI script table space under 4G memory.
 | 
						|
    //
 | 
						|
    S3TableBase = 0xffffffff;
 | 
						|
    Status      = gBS->AllocatePages (
 | 
						|
                         AllocateMaxAddress,
 | 
						|
                         EfiReservedMemoryType,
 | 
						|
                         2 + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber),
 | 
						|
                         (EFI_PHYSICAL_ADDRESS *)&S3TableBase
 | 
						|
                         );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Fill Table Header
 | 
						|
    //
 | 
						|
    ScriptTableInfo                              = (EFI_BOOT_SCRIPT_TABLE_HEADER *)(UINTN)S3TableBase;
 | 
						|
    ScriptTableInfo->OpCode                      = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;
 | 
						|
    ScriptTableInfo->Length                      = (UINT8)sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
 | 
						|
    ScriptTableInfo->Version                     = BOOT_SCRIPT_TABLE_VERSION;
 | 
						|
    ScriptTableInfo->TableLength                 = 0; // will be calculate at CloseTable
 | 
						|
    mS3BootScriptTablePtr->TableLength           = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
 | 
						|
    mS3BootScriptTablePtr->TableBase             = (UINT8 *)(UINTN)S3TableBase;
 | 
						|
    mS3BootScriptTablePtr->TableMemoryPageNumber = (UINT16)(2 + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber));
 | 
						|
  }
 | 
						|
 | 
						|
  // Here we do not count the reserved memory for runtime script table.
 | 
						|
  PageNumber  = (UINT16)(mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber));
 | 
						|
  TableLength =  mS3BootScriptTablePtr->TableLength;
 | 
						|
  if (EFI_PAGES_TO_SIZE ((UINTN)PageNumber) < (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {
 | 
						|
    //
 | 
						|
    // The buffer is too small to hold the table, Reallocate the buffer
 | 
						|
    //
 | 
						|
    NewS3TableBase = 0xffffffff;
 | 
						|
    Status         = gBS->AllocatePages (
 | 
						|
                            AllocateMaxAddress,
 | 
						|
                            EfiReservedMemoryType,
 | 
						|
                            2 + PageNumber + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber),
 | 
						|
                            (EFI_PHYSICAL_ADDRESS *)&NewS3TableBase
 | 
						|
                            );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem ((VOID *)(UINTN)NewS3TableBase, (VOID *)(UINTN)S3TableBase, TableLength);
 | 
						|
    gBS->FreePages (S3TableBase, mS3BootScriptTablePtr->TableMemoryPageNumber);
 | 
						|
 | 
						|
    mS3BootScriptTablePtr->TableBase             = (UINT8 *)(UINTN)NewS3TableBase;
 | 
						|
    mS3BootScriptTablePtr->TableMemoryPageNumber =  (UINT16)(2 + PageNumber + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // calculate the the start address for the new entry.
 | 
						|
  //
 | 
						|
  NewEntryPtr = mS3BootScriptTablePtr->TableBase + TableLength;
 | 
						|
 | 
						|
  //
 | 
						|
  // update the table lenghth
 | 
						|
  //
 | 
						|
  mS3BootScriptTablePtr->TableLength =  TableLength + EntryLength;
 | 
						|
 | 
						|
  //
 | 
						|
  // In the boot time, we will not append the termination entry to the boot script
 | 
						|
  // table until the callers think there is no boot time data that should be added and
 | 
						|
  // it is caller's responsibility to explicit call the CloseTable.
 | 
						|
  //
 | 
						|
  //
 | 
						|
 | 
						|
  return NewEntryPtr;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.
 | 
						|
  In this case, it should be ensured that there is enough buffer to hold the entry.
 | 
						|
 | 
						|
  @param EntryLength      the new entry length.
 | 
						|
 | 
						|
  @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into
 | 
						|
 **/
 | 
						|
UINT8 *
 | 
						|
S3BootScriptGetRuntimeEntryAddAddress (
 | 
						|
  UINT8  EntryLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  *NewEntryPtr;
 | 
						|
 | 
						|
  NewEntryPtr = NULL;
 | 
						|
  //
 | 
						|
  // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node.
 | 
						|
  //
 | 
						|
  if ((mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE)) <= EFI_PAGES_TO_SIZE ((UINTN)(mS3BootScriptTablePtr->TableMemoryPageNumber))) {
 | 
						|
    NewEntryPtr                        = mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength;
 | 
						|
    mS3BootScriptTablePtr->TableLength = mS3BootScriptTablePtr->TableLength + EntryLength;
 | 
						|
    //
 | 
						|
    // Append a terminate node on every insert
 | 
						|
    //
 | 
						|
    S3BootScriptInternalCloseTable ();
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINT8 *)NewEntryPtr;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is to restore boot time boot script data from LockBox.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RestoreBootTimeDataFromLockBox (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       LockBoxLength;
 | 
						|
 | 
						|
  //
 | 
						|
  // Restore boot time boot script data from LockBox.
 | 
						|
  //
 | 
						|
  LockBoxLength = mS3BootScriptTablePtr->BootTimeScriptLength;
 | 
						|
  Status        = RestoreLockBox (
 | 
						|
                    &mBootScriptDataBootTimeGuid,
 | 
						|
                    (VOID *)mS3BootScriptTablePtr->TableBase,
 | 
						|
                    &LockBoxLength
 | 
						|
                    );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Update the data to BootScriptData LockBox.
 | 
						|
  //
 | 
						|
  Status = UpdateLockBox (
 | 
						|
             &mBootScriptDataGuid,
 | 
						|
             0,
 | 
						|
             (VOID *)mS3BootScriptTablePtr->TableBase,
 | 
						|
             LockBoxLength
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Update TableLength.
 | 
						|
  //
 | 
						|
  mS3BootScriptTablePtr->TableLength = (UINT32)(mS3BootScriptTablePtr->BootTimeScriptLength - sizeof (EFI_BOOT_SCRIPT_TERMINATE));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  To get the start address from which a new s3 boot script entry will write into.
 | 
						|
 | 
						|
  @param EntryLength      the new entry length.
 | 
						|
 | 
						|
  @retval the address from which the a new s3 boot script entry will write into
 | 
						|
 **/
 | 
						|
UINT8 *
 | 
						|
S3BootScriptGetEntryAddAddress (
 | 
						|
  UINT8  EntryLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  *NewEntryPtr;
 | 
						|
 | 
						|
  if (!mS3BootScriptAcpiS3Enable) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mS3BootScriptTablePtr->SmmLocked) {
 | 
						|
    //
 | 
						|
    // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
 | 
						|
    //
 | 
						|
    if (!mS3BootScriptTablePtr->InSmm) {
 | 
						|
      //
 | 
						|
      // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.
 | 
						|
      // Do not use ASSERT, because we may have test to invoke this interface.
 | 
						|
      //
 | 
						|
      DEBUG ((DEBUG_ERROR, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mS3BootScriptTablePtr->BackFromS3) {
 | 
						|
      //
 | 
						|
      // Back from S3, restore boot time boot script data from LockBox
 | 
						|
      // and set BackFromS3 flag back to FALSE.
 | 
						|
      //
 | 
						|
      RestoreBootTimeDataFromLockBox ();
 | 
						|
      mS3BootScriptTablePtr->BackFromS3 = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    NewEntryPtr = S3BootScriptGetRuntimeEntryAddAddress (EntryLength);
 | 
						|
  } else {
 | 
						|
    NewEntryPtr = S3BootScriptGetBootTimeEntryAddAddress (EntryLength);
 | 
						|
  }
 | 
						|
 | 
						|
  return NewEntryPtr;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sync BootScript LockBox data.
 | 
						|
 | 
						|
  @param Script           The address from where the boot script has been added or updated.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SyncBootScript (
 | 
						|
  IN UINT8  *Script
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT32      ScriptOffset;
 | 
						|
  UINT32      TotalScriptLength;
 | 
						|
 | 
						|
  if (!mS3BootScriptTablePtr->SmmLocked || !mS3BootScriptTablePtr->InSmm) {
 | 
						|
    //
 | 
						|
    // If it is not after SmmReadyToLock in SMM,
 | 
						|
    // just return.
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  ScriptOffset = (UINT32)(Script - mS3BootScriptTablePtr->TableBase);
 | 
						|
 | 
						|
  TotalScriptLength = (UINT32)(mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));
 | 
						|
 | 
						|
  //
 | 
						|
  // Update BootScriptData
 | 
						|
  // So in S3 resume, the data can be restored correctly.
 | 
						|
  //
 | 
						|
  Status = UpdateLockBox (
 | 
						|
             &mBootScriptDataGuid,
 | 
						|
             ScriptOffset,
 | 
						|
             (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + ScriptOffset),
 | 
						|
             TotalScriptLength - ScriptOffset
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Now the length field is updated, need sync to lockbox.
 | 
						|
  // So at S3 resume, the data can be restored correctly.
 | 
						|
  //
 | 
						|
  Status = UpdateLockBox (
 | 
						|
             &mBootScriptDataGuid,
 | 
						|
             OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),
 | 
						|
             &TotalScriptLength,
 | 
						|
             sizeof (TotalScriptLength)
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This is an function to close the S3 boot script table. The function could only be called in
 | 
						|
  BOOT time phase. To comply with the Framework spec definition on
 | 
						|
  EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable(), this function will fulfill following things:
 | 
						|
  1. Closes the specified boot script table
 | 
						|
  2. It allocates a new memory pool to duplicate all the boot scripts in the specified table.
 | 
						|
     Once this function is called, the table maintained by the library will be destroyed
 | 
						|
     after it is copied into the allocated pool.
 | 
						|
  3. Any attempts to add a script record after calling this function will cause a new table
 | 
						|
     to be created by the library.
 | 
						|
  4. The base address of the allocated pool will be returned in Address. Note that after
 | 
						|
     using the boot script table, the CALLER is responsible for freeing the pool that is allocated
 | 
						|
     by this function.
 | 
						|
 | 
						|
  In Spec PI1.1, this EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is retired. To provides this API for now is
 | 
						|
  for Framework Spec compatibility.
 | 
						|
 | 
						|
  If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out
 | 
						|
  how to get the script to run at S3 resume because the boot script maintained by the lib will be
 | 
						|
  destroyed.
 | 
						|
 | 
						|
  @return the base address of the new copy of the boot script table.
 | 
						|
  @note this function could only called in boot time phase
 | 
						|
 | 
						|
**/
 | 
						|
UINT8 *
 | 
						|
EFIAPI
 | 
						|
S3BootScriptCloseTable (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                         *S3TableBase;
 | 
						|
  UINT32                        TableLength;
 | 
						|
  UINT8                         *Buffer;
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_BOOT_SCRIPT_TABLE_HEADER  *ScriptTableInfo;
 | 
						|
 | 
						|
  S3TableBase =    mS3BootScriptTablePtr->TableBase;
 | 
						|
  if (S3TableBase == 0) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Append the termination record the S3 boot script table
 | 
						|
  //
 | 
						|
  S3BootScriptInternalCloseTable ();
 | 
						|
  TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
 | 
						|
  //
 | 
						|
  // Allocate the buffer and copy the boot script to the buffer.
 | 
						|
  //
 | 
						|
  Status = gBS->AllocatePool (
 | 
						|
                  EfiBootServicesData,
 | 
						|
                  (UINTN)TableLength,
 | 
						|
                  (VOID **)&Buffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (Buffer, S3TableBase, TableLength);
 | 
						|
 | 
						|
  //
 | 
						|
  // Destroy the table maintained by the library so that the next write operation
 | 
						|
  // will write the record to the first entry of the table.
 | 
						|
  //
 | 
						|
  // Fill the table header.
 | 
						|
  ScriptTableInfo              = (EFI_BOOT_SCRIPT_TABLE_HEADER *)S3TableBase;
 | 
						|
  ScriptTableInfo->OpCode      = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;
 | 
						|
  ScriptTableInfo->Length      = (UINT8)sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
 | 
						|
  ScriptTableInfo->TableLength = 0;   // will be calculate at close the table
 | 
						|
 | 
						|
  mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
 | 
						|
  return Buffer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Save I/O write to boot script
 | 
						|
 | 
						|
  @param Width   The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Address The base address of the I/O operations.
 | 
						|
  @param Count   The number of I/O operations to perform.
 | 
						|
  @param Buffer  The source buffer from which to write data.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveIoWrite (
 | 
						|
  IN  S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN  UINT64                    Address,
 | 
						|
  IN  UINTN                     Count,
 | 
						|
  IN  VOID                      *Buffer
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  UINT8                     Length;
 | 
						|
  UINT8                     *Script;
 | 
						|
  UINT8                     WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_IO_WRITE  ScriptIoWrite;
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
 | 
						|
  //
 | 
						|
  // Truncation check
 | 
						|
  //
 | 
						|
  if ((Count > MAX_UINT8) ||
 | 
						|
      (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_IO_WRITE)))
 | 
						|
  {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_WRITE) + (WidthInByte * Count));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // save script data
 | 
						|
  //
 | 
						|
  ScriptIoWrite.OpCode  = EFI_BOOT_SCRIPT_IO_WRITE_OPCODE;
 | 
						|
  ScriptIoWrite.Length  = Length;
 | 
						|
  ScriptIoWrite.Width   = Width;
 | 
						|
  ScriptIoWrite.Address = Address;
 | 
						|
  ScriptIoWrite.Count   = (UINT32)Count;
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptIoWrite, sizeof (EFI_BOOT_SCRIPT_IO_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)), Buffer, WidthInByte * Count);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for an I/O modify operation into a S3 boot script table
 | 
						|
 | 
						|
  @param Width   The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Address The base address of the I/O operations.
 | 
						|
  @param Data    A pointer to the data to be OR-ed.
 | 
						|
  @param DataMask  A pointer to the data mask to be AND-ed with the data read from the register
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveIoReadWrite (
 | 
						|
  IN  S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN  UINT64                    Address,
 | 
						|
  IN  VOID                      *Data,
 | 
						|
  IN  VOID                      *DataMask
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                          Length;
 | 
						|
  UINT8                          *Script;
 | 
						|
  UINT8                          WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_IO_READ_WRITE  ScriptIoReadWrite;
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
  Length      = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptIoReadWrite.OpCode  = EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE;
 | 
						|
  ScriptIoReadWrite.Length  = Length;
 | 
						|
  ScriptIoReadWrite.Width   = Width;
 | 
						|
  ScriptIoReadWrite.Address = Address;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptIoReadWrite, sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE)), Data, WidthInByte);
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for a memory write operation into a specified boot script table.
 | 
						|
 | 
						|
  @param Width   The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Address The base address of the memory operations
 | 
						|
  @param Count   The number of memory operations to perform.
 | 
						|
  @param Buffer  The source buffer from which to write the data.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveMemWrite (
 | 
						|
  IN  S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN  UINT64                    Address,
 | 
						|
  IN  UINTN                     Count,
 | 
						|
  IN  VOID                      *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                      Length;
 | 
						|
  UINT8                      *Script;
 | 
						|
  UINT8                      WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_MEM_WRITE  ScriptMemWrite;
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
 | 
						|
  //
 | 
						|
  // Truncation check
 | 
						|
  //
 | 
						|
  if ((Count > MAX_UINT8) ||
 | 
						|
      (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)))
 | 
						|
  {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_WRITE) + (WidthInByte * Count));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptMemWrite.OpCode  = EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE;
 | 
						|
  ScriptMemWrite.Length  = Length;
 | 
						|
  ScriptMemWrite.Width   = Width;
 | 
						|
  ScriptMemWrite.Address = Address;
 | 
						|
  ScriptMemWrite.Count   = (UINT32)Count;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptMemWrite, sizeof (EFI_BOOT_SCRIPT_MEM_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)), Buffer, WidthInByte * Count);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for a memory modify operation into a specified boot script table.
 | 
						|
 | 
						|
  @param Width     The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Address   The base address of the memory operations. Address needs alignment if required
 | 
						|
  @param Data      A pointer to the data to be OR-ed.
 | 
						|
  @param DataMask  A pointer to the data mask to be AND-ed with the data read from the register.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveMemReadWrite (
 | 
						|
  IN  S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN  UINT64                    Address,
 | 
						|
  IN  VOID                      *Data,
 | 
						|
  IN  VOID                      *DataMask
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                           Length;
 | 
						|
  UINT8                           *Script;
 | 
						|
  UINT8                           WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_MEM_READ_WRITE  ScriptMemReadWrite;
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
  Length      = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptMemReadWrite.OpCode  = EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE;
 | 
						|
  ScriptMemReadWrite.Length  = Length;
 | 
						|
  ScriptMemReadWrite.Width   = Width;
 | 
						|
  ScriptMemReadWrite.Address = Address;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptMemReadWrite, sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE)), Data, WidthInByte);
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for a PCI configuration space write operation into a specified boot script table.
 | 
						|
 | 
						|
  @param Width     The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Address   The address within the PCI configuration space.
 | 
						|
  @param Count     The number of PCI operations to perform.
 | 
						|
  @param Buffer    The source buffer from which to write the data.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
  @note  A known Limitations in the implementation which is 64bits operations are not supported.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSavePciCfgWrite (
 | 
						|
  IN  S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN  UINT64                    Address,
 | 
						|
  IN  UINTN                     Count,
 | 
						|
  IN  VOID                      *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                             Length;
 | 
						|
  UINT8                             *Script;
 | 
						|
  UINT8                             WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE  ScriptPciWrite;
 | 
						|
 | 
						|
  if ((Width == S3BootScriptWidthUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFifoUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFillUint64))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
 | 
						|
  //
 | 
						|
  // Truncation check
 | 
						|
  //
 | 
						|
  if ((Count > MAX_UINT8) ||
 | 
						|
      (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)))
 | 
						|
  {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptPciWrite.OpCode  = EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE;
 | 
						|
  ScriptPciWrite.Length  = Length;
 | 
						|
  ScriptPciWrite.Width   = Width;
 | 
						|
  ScriptPciWrite.Address = Address;
 | 
						|
  ScriptPciWrite.Count   = (UINT32)Count;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptPciWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)), Buffer, WidthInByte * Count);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for a PCI configuration space modify operation into a specified boot script table.
 | 
						|
 | 
						|
  @param Width     The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Address   The address within the PCI configuration space.
 | 
						|
  @param Data      A pointer to the data to be OR-ed.The size depends on Width.
 | 
						|
  @param DataMask    A pointer to the data mask to be AND-ed.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN__SUCCESS           Opcode is added.
 | 
						|
  @note  A known Limitations in the implementation which is 64bits operations are not supported.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSavePciCfgReadWrite (
 | 
						|
  IN  S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN  UINT64                    Address,
 | 
						|
  IN  VOID                      *Data,
 | 
						|
  IN  VOID                      *DataMask
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                                  Length;
 | 
						|
  UINT8                                  *Script;
 | 
						|
  UINT8                                  WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE  ScriptPciReadWrite;
 | 
						|
 | 
						|
  if ((Width == S3BootScriptWidthUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFifoUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFillUint64))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
  Length      = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptPciReadWrite.OpCode  = EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE;
 | 
						|
  ScriptPciReadWrite.Length  = Length;
 | 
						|
  ScriptPciReadWrite.Width   = Width;
 | 
						|
  ScriptPciReadWrite.Address = Address;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptPciReadWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE)), Data, WidthInByte);
 | 
						|
  CopyMem (
 | 
						|
    (VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + WidthInByte),
 | 
						|
    DataMask,
 | 
						|
    WidthInByte
 | 
						|
    );
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for a PCI configuration 2 space write operation into a specified boot script table.
 | 
						|
 | 
						|
  @param Width     The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Segment   The PCI segment number for Address.
 | 
						|
  @param Address   The address within the PCI configuration space.
 | 
						|
  @param Count     The number of PCI operations to perform.
 | 
						|
  @param Buffer    The source buffer from which to write the data.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
  @note  A known Limitations in the implementation which is 64bits operations are not supported.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSavePciCfg2Write (
 | 
						|
  IN S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN UINT16                    Segment,
 | 
						|
  IN UINT64                    Address,
 | 
						|
  IN UINTN                     Count,
 | 
						|
  IN VOID                      *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                              Length;
 | 
						|
  UINT8                              *Script;
 | 
						|
  UINT8                              WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE  ScriptPciWrite2;
 | 
						|
 | 
						|
  if ((Width == S3BootScriptWidthUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFifoUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFillUint64))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
 | 
						|
  //
 | 
						|
  // Truncation check
 | 
						|
  //
 | 
						|
  if ((Count > MAX_UINT8) ||
 | 
						|
      (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)))
 | 
						|
  {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE) + (WidthInByte * Count));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptPciWrite2.OpCode  = EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE;
 | 
						|
  ScriptPciWrite2.Length  = Length;
 | 
						|
  ScriptPciWrite2.Width   = Width;
 | 
						|
  ScriptPciWrite2.Address = Address;
 | 
						|
  ScriptPciWrite2.Segment = Segment;
 | 
						|
  ScriptPciWrite2.Count   = (UINT32)Count;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptPciWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)), Buffer, WidthInByte * Count);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for a PCI configuration 2 space modify operation into a specified boot script table.
 | 
						|
 | 
						|
  @param Width     The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
 | 
						|
  @param Segment   The PCI segment number for Address.
 | 
						|
  @param Address   The address within the PCI configuration space.
 | 
						|
  @param Data      A pointer to the data to be OR-ed. The size depends on Width.
 | 
						|
  @param DataMask    A pointer to the data mask to be AND-ed.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
  @note  A known Limitations in the implementation which is 64bits operations are not supported.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSavePciCfg2ReadWrite (
 | 
						|
  IN S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN UINT16                    Segment,
 | 
						|
  IN UINT64                    Address,
 | 
						|
  IN VOID                      *Data,
 | 
						|
  IN VOID                      *DataMask
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                                   Length;
 | 
						|
  UINT8                                   *Script;
 | 
						|
  UINT8                                   WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE  ScriptPciReadWrite2;
 | 
						|
 | 
						|
  if ((Width == S3BootScriptWidthUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFifoUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFillUint64))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
  Length      = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptPciReadWrite2.OpCode  = EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE;
 | 
						|
  ScriptPciReadWrite2.Length  = Length;
 | 
						|
  ScriptPciReadWrite2.Width   = Width;
 | 
						|
  ScriptPciReadWrite2.Segment = Segment;
 | 
						|
  ScriptPciReadWrite2.Address = Address;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptPciReadWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE)), Data, WidthInByte);
 | 
						|
  CopyMem (
 | 
						|
    (VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + WidthInByte),
 | 
						|
    DataMask,
 | 
						|
    WidthInByte
 | 
						|
    );
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Checks the parameter of S3BootScriptSaveSmbusExecute().
 | 
						|
 | 
						|
  This function checks the input parameters of SmbusExecute().  If the input parameters are valid
 | 
						|
  for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
 | 
						|
  error code based on the input SMBus bus protocol.
 | 
						|
 | 
						|
  @param  SmBusAddress            Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
 | 
						|
                                  and PEC.
 | 
						|
  @param  Operation               Signifies which particular SMBus hardware protocol instance that
 | 
						|
                                  it will use to execute the SMBus transactions. This SMBus
 | 
						|
                                  hardware protocol is defined by the SMBus Specification and is
 | 
						|
                                  not related to EFI.
 | 
						|
  @param  Length                  Signifies the number of bytes that this operation will do. The
 | 
						|
                                  maximum number of bytes can be revision specific and operation
 | 
						|
                                  specific. This field will contain the actual number of bytes that
 | 
						|
                                  are executed for this operation. Not all operations require this
 | 
						|
                                  argument.
 | 
						|
  @param  Buffer                  Contains the value of data to execute to the SMBus slave device.
 | 
						|
                                  Not all operations require this argument. The length of this
 | 
						|
                                  buffer is identified by Length.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             All the parameters are valid for the corresponding SMBus bus
 | 
						|
                                  protocol.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead
 | 
						|
                                  and EfiSmbusQuickWrite. Length is outside the range of valid
 | 
						|
                                  values.
 | 
						|
  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CheckParameters (
 | 
						|
  IN     UINTN                SmBusAddress,
 | 
						|
  IN     EFI_SMBUS_OPERATION  Operation,
 | 
						|
  IN OUT UINTN                *Length,
 | 
						|
  IN     VOID                 *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  UINTN                     RequiredLen;
 | 
						|
  EFI_SMBUS_DEVICE_COMMAND  Command;
 | 
						|
  BOOLEAN                   PecCheck;
 | 
						|
 | 
						|
  Command  = SMBUS_LIB_COMMAND (SmBusAddress);
 | 
						|
  PecCheck = SMBUS_LIB_PEC (SmBusAddress);
 | 
						|
  //
 | 
						|
  // Set default value to be 2:
 | 
						|
  // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
 | 
						|
  //
 | 
						|
  RequiredLen = 2;
 | 
						|
  Status      = EFI_SUCCESS;
 | 
						|
  switch (Operation) {
 | 
						|
    case EfiSmbusQuickRead:
 | 
						|
    case EfiSmbusQuickWrite:
 | 
						|
      if (PecCheck || (Command != 0)) {
 | 
						|
        return EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    case EfiSmbusReceiveByte:
 | 
						|
    case EfiSmbusSendByte:
 | 
						|
      if (Command != 0) {
 | 
						|
        return EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
 | 
						|
    //
 | 
						|
    // Cascade to check length parameter.
 | 
						|
    //
 | 
						|
    case EfiSmbusReadByte:
 | 
						|
    case EfiSmbusWriteByte:
 | 
						|
      RequiredLen = 1;
 | 
						|
    //
 | 
						|
    // Cascade to check length parameter.
 | 
						|
    //
 | 
						|
    case EfiSmbusReadWord:
 | 
						|
    case EfiSmbusWriteWord:
 | 
						|
    case EfiSmbusProcessCall:
 | 
						|
      if ((Buffer == NULL) || (Length == NULL)) {
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      } else if (*Length < RequiredLen) {
 | 
						|
        Status = EFI_BUFFER_TOO_SMALL;
 | 
						|
      }
 | 
						|
 | 
						|
      *Length = RequiredLen;
 | 
						|
      break;
 | 
						|
    case EfiSmbusReadBlock:
 | 
						|
    case EfiSmbusWriteBlock:
 | 
						|
    case EfiSmbusBWBRProcessCall:
 | 
						|
      if ((Buffer == NULL) ||
 | 
						|
          (Length == NULL) ||
 | 
						|
          (*Length < MIN_SMBUS_BLOCK_LEN) ||
 | 
						|
          (*Length > MAX_SMBUS_BLOCK_LEN))
 | 
						|
      {
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for an SMBus command execution into a specified boot script table.
 | 
						|
 | 
						|
  @param  SmBusAddress  Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC.
 | 
						|
  @param Operation      Indicates which particular SMBus protocol it will use to execute the SMBus
 | 
						|
                        transactions.
 | 
						|
  @param Length         A pointer to signify the number of bytes that this operation will do.
 | 
						|
  @param Buffer         Contains the value of data to execute to the SMBUS slave device.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveSmbusExecute (
 | 
						|
  IN  UINTN                SmBusAddress,
 | 
						|
  IN  EFI_SMBUS_OPERATION  Operation,
 | 
						|
  IN  UINTN                *Length,
 | 
						|
  IN  VOID                 *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  UINTN                          BufferLength;
 | 
						|
  UINT8                          DataSize;
 | 
						|
  UINT8                          *Script;
 | 
						|
  EFI_BOOT_SCRIPT_SMBUS_EXECUTE  ScriptSmbusExecute;
 | 
						|
 | 
						|
  if (Length == NULL) {
 | 
						|
    BufferLength = 0;
 | 
						|
  } else {
 | 
						|
    BufferLength = *Length;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = CheckParameters (SmBusAddress, Operation, &BufferLength, Buffer);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Truncation check
 | 
						|
  //
 | 
						|
  if (BufferLength > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + BufferLength);
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (DataSize);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptSmbusExecute.OpCode       = EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE;
 | 
						|
  ScriptSmbusExecute.Length       = DataSize;
 | 
						|
  ScriptSmbusExecute.SmBusAddress = (UINT64)SmBusAddress;
 | 
						|
  ScriptSmbusExecute.Operation    = Operation;
 | 
						|
  ScriptSmbusExecute.DataSize     = (UINT32)BufferLength;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptSmbusExecute, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE));
 | 
						|
  CopyMem (
 | 
						|
    (VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)),
 | 
						|
    Buffer,
 | 
						|
    BufferLength
 | 
						|
    );
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for an execution stall on the processor into a specified boot script table.
 | 
						|
 | 
						|
  @param Duration   Duration in microseconds of the stall
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveStall (
 | 
						|
  IN  UINTN  Duration
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                  Length;
 | 
						|
  UINT8                  *Script;
 | 
						|
  EFI_BOOT_SCRIPT_STALL  ScriptStall;
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_STALL));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptStall.OpCode   = EFI_BOOT_SCRIPT_STALL_OPCODE;
 | 
						|
  ScriptStall.Length   = Length;
 | 
						|
  ScriptStall.Duration = Duration;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptStall, sizeof (EFI_BOOT_SCRIPT_STALL));
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for dispatching specified arbitrary code into a specified boot script table.
 | 
						|
 | 
						|
  @param EntryPoint   Entry point of the code to be dispatched.
 | 
						|
  @param Context      Argument to be passed into the EntryPoint of the code to be dispatched.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveDispatch2 (
 | 
						|
  IN  VOID  *EntryPoint,
 | 
						|
  IN  VOID  *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                       Length;
 | 
						|
  UINT8                       *Script;
 | 
						|
  EFI_BOOT_SCRIPT_DISPATCH_2  ScriptDispatch2;
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptDispatch2.OpCode     = EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE;
 | 
						|
  ScriptDispatch2.Length     = Length;
 | 
						|
  ScriptDispatch2.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
 | 
						|
  ScriptDispatch2.Context    =   (EFI_PHYSICAL_ADDRESS)(UINTN)Context;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptDispatch2, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for memory reads of the memory location and continues when the exit criteria is
 | 
						|
  satisfied or after a defined duration.
 | 
						|
 | 
						|
  Please aware, below interface is different with PI specification, Vol 5:
 | 
						|
  EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.
 | 
						|
  "Duration" below is microseconds, while "Delay" in PI specification means
 | 
						|
  the number of 100ns units to poll.
 | 
						|
 | 
						|
  @param Width     The width of the memory operations.
 | 
						|
  @param Address   The base address of the memory operations.
 | 
						|
  @param BitMask   A pointer to the bit mask to be AND-ed with the data read from the register.
 | 
						|
  @param BitValue  A pointer to the data value after to be Masked.
 | 
						|
  @param Duration  Duration in microseconds of the stall.
 | 
						|
  @param LoopTimes The times of the register polling.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveMemPoll (
 | 
						|
  IN  S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN  UINT64                    Address,
 | 
						|
  IN  VOID                      *BitMask,
 | 
						|
  IN  VOID                      *BitValue,
 | 
						|
  IN  UINTN                     Duration,
 | 
						|
  IN  UINT64                    LoopTimes
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                     Length;
 | 
						|
  UINT8                     *Script;
 | 
						|
  UINT8                     WidthInByte;
 | 
						|
  EFI_BOOT_SCRIPT_MEM_POLL  ScriptMemPoll;
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptMemPoll.OpCode    = EFI_BOOT_SCRIPT_MEM_POLL_OPCODE;
 | 
						|
  ScriptMemPoll.Length    = Length;
 | 
						|
  ScriptMemPoll.Width     = Width;
 | 
						|
  ScriptMemPoll.Address   = Address;
 | 
						|
  ScriptMemPoll.Duration  = Duration;
 | 
						|
  ScriptMemPoll.LoopTimes = LoopTimes;
 | 
						|
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL)), BitValue, WidthInByte);
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + WidthInByte), BitMask, WidthInByte);
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptMemPoll, sizeof (EFI_BOOT_SCRIPT_MEM_POLL));
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Store arbitrary information in the boot script table. This opcode is a no-op on dispatch and is only
 | 
						|
  used for debugging script issues.
 | 
						|
 | 
						|
  @param InformationLength   Length of the data in bytes
 | 
						|
  @param Information       Information to be logged in the boot scrpit
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveInformation (
 | 
						|
  IN  UINT32  InformationLength,
 | 
						|
  IN  VOID    *Information
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                        Length;
 | 
						|
  UINT8                        *Script;
 | 
						|
  EFI_BOOT_SCRIPT_INFORMATION  ScriptInformation;
 | 
						|
 | 
						|
  //
 | 
						|
  // Truncation check
 | 
						|
  //
 | 
						|
  if (InformationLength > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_INFORMATION)) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptInformation.OpCode = EFI_BOOT_SCRIPT_INFORMATION_OPCODE;
 | 
						|
  ScriptInformation.Length = Length;
 | 
						|
 | 
						|
  ScriptInformation.InformationLength = InformationLength;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *)Information, (UINTN)InformationLength);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Store a string in the boot script table. This opcode is a no-op on dispatch and is only
 | 
						|
  used for debugging script issues.
 | 
						|
 | 
						|
  @param String            The string to save to boot script table
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveInformationAsciiString (
 | 
						|
  IN  CONST CHAR8  *String
 | 
						|
  )
 | 
						|
{
 | 
						|
  return S3BootScriptSaveInformation (
 | 
						|
           (UINT32)AsciiStrLen (String) + 1,
 | 
						|
           (VOID *)String
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for dispatching specified arbitrary code into a specified boot script table.
 | 
						|
 | 
						|
  @param EntryPoint   Entry point of the code to be dispatched.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveDispatch (
 | 
						|
  IN  VOID  *EntryPoint
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                     Length;
 | 
						|
  UINT8                     *Script;
 | 
						|
  EFI_BOOT_SCRIPT_DISPATCH  ScriptDispatch;
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptDispatch.OpCode     = EFI_BOOT_SCRIPT_DISPATCH_OPCODE;
 | 
						|
  ScriptDispatch.Length     = Length;
 | 
						|
  ScriptDispatch.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptDispatch, sizeof (EFI_BOOT_SCRIPT_DISPATCH));
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for I/O reads the I/O location and continues when the exit criteria is satisfied or after a
 | 
						|
  defined duration.
 | 
						|
 | 
						|
  @param  Width                 The width of the I/O operations.
 | 
						|
  @param  Address               The base address of the I/O operations.
 | 
						|
  @param  Data                  The comparison value used for the polling exit criteria.
 | 
						|
  @param  DataMask              Mask used for the polling criteria. The bits in the bytes below Width which are zero
 | 
						|
                                in Data are ignored when polling the memory address.
 | 
						|
  @param  Delay                 The number of 100ns units to poll. Note that timer available may be of poorer
 | 
						|
                                granularity so the delay may be longer.
 | 
						|
 | 
						|
 @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
 @retval RETURN_SUCCESS          Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSaveIoPoll (
 | 
						|
  IN S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN UINT64                    Address,
 | 
						|
  IN VOID                      *Data,
 | 
						|
  IN VOID                      *DataMask,
 | 
						|
  IN UINT64                    Delay
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                    WidthInByte;
 | 
						|
  UINT8                    *Script;
 | 
						|
  UINT8                    Length;
 | 
						|
  EFI_BOOT_SCRIPT_IO_POLL  ScriptIoPoll;
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
  Length      = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptIoPoll.OpCode  = EFI_BOOT_SCRIPT_IO_POLL_OPCODE;
 | 
						|
  ScriptIoPoll.Length  = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));
 | 
						|
  ScriptIoPoll.Width   = Width;
 | 
						|
  ScriptIoPoll.Address = Address;
 | 
						|
  ScriptIoPoll.Delay   = Delay;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptIoPoll, sizeof (EFI_BOOT_SCRIPT_IO_POLL));
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL)), Data, WidthInByte);
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL) + WidthInByte), DataMask, WidthInByte);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
 | 
						|
  after a defined duration.
 | 
						|
 | 
						|
  @param  Width                 The width of the I/O operations.
 | 
						|
  @param  Address               The address within the PCI configuration space.
 | 
						|
  @param  Data                  The comparison value used for the polling exit criteria.
 | 
						|
  @param  DataMask              Mask used for the polling criteria. The bits in the bytes below Width which are zero
 | 
						|
                                in Data are ignored when polling the memory address
 | 
						|
  @param  Delay                 The number of 100ns units to poll. Note that timer available may be of poorer
 | 
						|
                                granularity so the delay may be longer.
 | 
						|
 | 
						|
 @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
 @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
  @note  A known Limitations in the implementation which is 64bits operations are not supported.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSavePciPoll (
 | 
						|
  IN S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN UINT64                    Address,
 | 
						|
  IN VOID                      *Data,
 | 
						|
  IN VOID                      *DataMask,
 | 
						|
  IN UINT64                    Delay
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                            *Script;
 | 
						|
  UINT8                            WidthInByte;
 | 
						|
  UINT8                            Length;
 | 
						|
  EFI_BOOT_SCRIPT_PCI_CONFIG_POLL  ScriptPciPoll;
 | 
						|
 | 
						|
  if ((Width == S3BootScriptWidthUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFifoUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFillUint64))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
  Length      = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptPciPoll.OpCode  = EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE;
 | 
						|
  ScriptPciPoll.Length  = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));
 | 
						|
  ScriptPciPoll.Width   = Width;
 | 
						|
  ScriptPciPoll.Address = Address;
 | 
						|
  ScriptPciPoll.Delay   = Delay;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptPciPoll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL)), Data, WidthInByte);
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + WidthInByte), DataMask, WidthInByte);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
 | 
						|
  after a defined duration.
 | 
						|
 | 
						|
  @param  Width                 The width of the I/O operations.
 | 
						|
  @param  Segment               The PCI segment number for Address.
 | 
						|
  @param  Address               The address within the PCI configuration space.
 | 
						|
  @param  Data                  The comparison value used for the polling exit criteria.
 | 
						|
  @param  DataMask              Mask used for the polling criteria. The bits in the bytes below Width which are zero
 | 
						|
                                in Data are ignored when polling the memory address
 | 
						|
  @param  Delay                 The number of 100ns units to poll. Note that timer available may be of poorer
 | 
						|
                                granularity so the delay may be longer.
 | 
						|
 | 
						|
 @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
 @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
  @note  A known Limitations in the implementation which is 64bits operations are not supported.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptSavePci2Poll (
 | 
						|
  IN S3_BOOT_SCRIPT_LIB_WIDTH  Width,
 | 
						|
  IN UINT16                    Segment,
 | 
						|
  IN UINT64                    Address,
 | 
						|
  IN VOID                      *Data,
 | 
						|
  IN VOID                      *DataMask,
 | 
						|
  IN UINT64                    Delay
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                             WidthInByte;
 | 
						|
  UINT8                             *Script;
 | 
						|
  UINT8                             Length;
 | 
						|
  EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL  ScriptPci2Poll;
 | 
						|
 | 
						|
  if ((Width == S3BootScriptWidthUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFifoUint64) ||
 | 
						|
      (Width == S3BootScriptWidthFillUint64))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  WidthInByte = (UINT8)(0x01 << (Width & 0x03));
 | 
						|
  Length      = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptPci2Poll.OpCode  = EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE;
 | 
						|
  ScriptPci2Poll.Length  = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));
 | 
						|
  ScriptPci2Poll.Width   = Width;
 | 
						|
  ScriptPci2Poll.Segment = Segment;
 | 
						|
  ScriptPci2Poll.Address = Address;
 | 
						|
  ScriptPci2Poll.Delay   = Delay;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptPci2Poll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL)), Data, WidthInByte);
 | 
						|
  CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + WidthInByte), DataMask, WidthInByte);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Do the calculation of start address from which a new s3 boot script entry will write into.
 | 
						|
 | 
						|
  @param EntryLength      The new entry length.
 | 
						|
  @param Position         specifies the position in the boot script table where the opcode will be
 | 
						|
                          inserted, either before or after, depending on BeforeOrAfter.
 | 
						|
  @param BeforeOrAfter    The flag to indicate to insert the nod before or after the position.
 | 
						|
                          This parameter is effective when InsertFlag is TRUE
 | 
						|
  @param Script           return out the position from which the a new s3 boot script entry will write into
 | 
						|
**/
 | 
						|
VOID
 | 
						|
S3BootScriptCalculateInsertAddress (
 | 
						|
  IN  UINT8    EntryLength,
 | 
						|
  IN  VOID     *Position OPTIONAL,
 | 
						|
  IN  BOOLEAN  BeforeOrAfter OPTIONAL,
 | 
						|
  OUT UINT8    **Script
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                          TableLength;
 | 
						|
  UINT8                          *S3TableBase;
 | 
						|
  UINTN                          PositionOffset;
 | 
						|
  EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
 | 
						|
 | 
						|
  //
 | 
						|
  // The entry inserting to table is already added to the end of the table
 | 
						|
  //
 | 
						|
  TableLength =  mS3BootScriptTablePtr->TableLength - EntryLength;
 | 
						|
  S3TableBase = mS3BootScriptTablePtr->TableBase;
 | 
						|
  //
 | 
						|
  // calculate the Position offset
 | 
						|
  //
 | 
						|
  if (Position != NULL) {
 | 
						|
    PositionOffset = (UINTN)Position - (UINTN)S3TableBase;
 | 
						|
 | 
						|
    //
 | 
						|
    // If the BeforeOrAfter is FALSE, that means to insert the node right after the node.
 | 
						|
    //
 | 
						|
    if (!BeforeOrAfter) {
 | 
						|
      CopyMem ((VOID *)&ScriptHeader, Position, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
 | 
						|
      PositionOffset += (ScriptHeader.Length);
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Insert the node before the adjusted Position
 | 
						|
    //
 | 
						|
    CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset);
 | 
						|
    //
 | 
						|
    // calculate the the start address for the new entry.
 | 
						|
    //
 | 
						|
    *Script = S3TableBase + PositionOffset;
 | 
						|
  } else {
 | 
						|
    if (!BeforeOrAfter) {
 | 
						|
      //
 | 
						|
      //  Insert the node to the end of the table
 | 
						|
      //
 | 
						|
      *Script = S3TableBase + TableLength;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Insert the node to the beginning of the table
 | 
						|
      //
 | 
						|
      PositionOffset = (UINTN)sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
 | 
						|
      CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset);
 | 
						|
      *Script = S3TableBase + PositionOffset;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Move the last boot script entry to the position
 | 
						|
 | 
						|
  @param  BeforeOrAfter         Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
 | 
						|
                                in the boot script table specified by Position. If Position is NULL or points to
 | 
						|
                                NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
 | 
						|
                                of the table (if FALSE).
 | 
						|
  @param  Position              On entry, specifies the position in the boot script table where the opcode will be
 | 
						|
                                inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
 | 
						|
                                the position of the inserted opcode in the boot script table.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  The table is not available.
 | 
						|
  @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is inserted.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptMoveLastOpcode (
 | 
						|
  IN     BOOLEAN  BeforeOrAfter,
 | 
						|
  IN OUT VOID     **Position OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                          *Script;
 | 
						|
  VOID                           *TempPosition;
 | 
						|
  UINTN                          StartAddress;
 | 
						|
  UINT32                         TableLength;
 | 
						|
  EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
 | 
						|
  BOOLEAN                        ValidatePosition;
 | 
						|
  UINT8                          *LastOpcode;
 | 
						|
  UINT8                          TempBootScriptEntry[BOOT_SCRIPT_NODE_MAX_LENGTH];
 | 
						|
 | 
						|
  ValidatePosition = FALSE;
 | 
						|
  TempPosition     = (Position == NULL) ? NULL : (*Position);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check that the script is initialized and synced without adding an entry to the script.
 | 
						|
  //
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (0);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Script = mS3BootScriptTablePtr->TableBase;
 | 
						|
 | 
						|
  StartAddress = (UINTN)Script;
 | 
						|
  TableLength  = mS3BootScriptTablePtr->TableLength;
 | 
						|
  Script       = Script + sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
 | 
						|
  LastOpcode   = Script;
 | 
						|
  //
 | 
						|
  // Find the last boot Script Entry which is not the terminate node
 | 
						|
  //
 | 
						|
  while ((UINTN)Script < (UINTN)(StartAddress + TableLength)) {
 | 
						|
    CopyMem ((VOID *)&ScriptHeader, Script, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
 | 
						|
    if ((TempPosition != NULL) && (TempPosition == Script)) {
 | 
						|
      //
 | 
						|
      // If the position is specified, the position must be pointed to a boot script entry start address.
 | 
						|
      //
 | 
						|
      ValidatePosition = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ScriptHeader.OpCode != S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE) {
 | 
						|
      LastOpcode = Script;
 | 
						|
    }
 | 
						|
 | 
						|
    Script = Script + ScriptHeader.Length;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If the position is specified, but not the start of a boot script entry, it is a invalid input
 | 
						|
  //
 | 
						|
  if ((TempPosition != NULL) && !ValidatePosition) {
 | 
						|
    return RETURN_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem ((VOID *)&ScriptHeader, LastOpcode, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
 | 
						|
 | 
						|
  CopyMem ((VOID *)TempBootScriptEntry, LastOpcode, ScriptHeader.Length);
 | 
						|
  //
 | 
						|
  // Find the right position to write the node in
 | 
						|
  //
 | 
						|
  S3BootScriptCalculateInsertAddress (
 | 
						|
    ScriptHeader.Length,
 | 
						|
    TempPosition,
 | 
						|
    BeforeOrAfter,
 | 
						|
    &Script
 | 
						|
    );
 | 
						|
  //
 | 
						|
  // Copy the node to Boot script table
 | 
						|
  //
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)TempBootScriptEntry, ScriptHeader.Length);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  //
 | 
						|
  // return out the Position
 | 
						|
  //
 | 
						|
  if (Position != NULL) {
 | 
						|
    *Position = Script;
 | 
						|
  }
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a Label node in the boot script table.
 | 
						|
 | 
						|
  @param  BeforeOrAfter         Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
 | 
						|
                                in the boot script table specified by Position. If Position is NULL or points to
 | 
						|
                                NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
 | 
						|
                                of the table (if FALSE).
 | 
						|
  @param  Position              On entry, specifies the position in the boot script table where the opcode will be
 | 
						|
                                inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
 | 
						|
                                the position of the inserted opcode in the boot script table.
 | 
						|
  @param InformationLength      Length of the label in bytes
 | 
						|
  @param Information            Label to be logged in the boot scrpit
 | 
						|
 | 
						|
  @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.
 | 
						|
  @retval RETURN_SUCCESS           Opcode is added.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptLabelInternal (
 | 
						|
  IN        BOOLEAN  BeforeOrAfter,
 | 
						|
  IN OUT    VOID     **Position OPTIONAL,
 | 
						|
  IN        UINT32   InformationLength,
 | 
						|
  IN CONST  CHAR8    *Information
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                        Length;
 | 
						|
  UINT8                        *Script;
 | 
						|
  EFI_BOOT_SCRIPT_INFORMATION  ScriptInformation;
 | 
						|
 | 
						|
  //
 | 
						|
  // Truncation check
 | 
						|
  //
 | 
						|
  if (InformationLength > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_INFORMATION)) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);
 | 
						|
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (Length);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Build script data
 | 
						|
  //
 | 
						|
  ScriptInformation.OpCode = S3_BOOT_SCRIPT_LIB_LABEL_OPCODE;
 | 
						|
  ScriptInformation.Length = Length;
 | 
						|
 | 
						|
  ScriptInformation.InformationLength = InformationLength;
 | 
						|
 | 
						|
  CopyMem ((VOID *)Script, (VOID *)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));
 | 
						|
  CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *)Information, (UINTN)InformationLength);
 | 
						|
 | 
						|
  SyncBootScript (Script);
 | 
						|
 | 
						|
  return S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find a label within the boot script table and, if not present, optionally create it.
 | 
						|
 | 
						|
  @param  BeforeOrAfter         Specifies whether the opcode is stored before (TRUE)
 | 
						|
                                or after (FALSE) the position in the boot script table
 | 
						|
                                specified by Position.
 | 
						|
  @param  CreateIfNotFound      Specifies whether the label will be created if the label
 | 
						|
                                does not exists (TRUE) or not (FALSE).
 | 
						|
  @param  Position              On entry, specifies the position in the boot script table
 | 
						|
                                where the opcode will be inserted, either before or after,
 | 
						|
                                depending on BeforeOrAfter. On exit, specifies the position
 | 
						|
                                of the inserted opcode in the boot script table.
 | 
						|
  @param  Label                 Points to the label which will be inserted in the boot script table.
 | 
						|
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptLabel (
 | 
						|
  IN       BOOLEAN  BeforeOrAfter,
 | 
						|
  IN       BOOLEAN  CreateIfNotFound,
 | 
						|
  IN OUT   VOID     **Position OPTIONAL,
 | 
						|
  IN CONST CHAR8    *Label
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                          *Script;
 | 
						|
  UINTN                          StartAddress;
 | 
						|
  UINT32                         TableLength;
 | 
						|
  EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
 | 
						|
  EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;
 | 
						|
  UINT32                         LabelLength;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check NULL Label
 | 
						|
  //
 | 
						|
  if (Label == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check empty Label
 | 
						|
  //
 | 
						|
  if (Label[0] == '\0') {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check that the script is initialized and synced without adding an entry to the script.
 | 
						|
  // The code must search for the label first before it knows if a new entry needs
 | 
						|
  // to be added.
 | 
						|
  //
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (0);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the header and search for existing label.
 | 
						|
  //
 | 
						|
  Script = mS3BootScriptTablePtr->TableBase;
 | 
						|
  CopyMem ((VOID *)&TableHeader, Script, sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER));
 | 
						|
  if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  StartAddress = (UINTN)Script;
 | 
						|
  TableLength  = mS3BootScriptTablePtr->TableLength;
 | 
						|
  Script       =     Script + TableHeader.Length;
 | 
						|
  while ((UINTN)Script < (UINTN)(StartAddress + TableLength)) {
 | 
						|
    CopyMem ((VOID *)&ScriptHeader, Script, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
 | 
						|
    if (ScriptHeader.OpCode == S3_BOOT_SCRIPT_LIB_LABEL_OPCODE) {
 | 
						|
      if (AsciiStrCmp ((CHAR8 *)(UINTN)(Script+sizeof (EFI_BOOT_SCRIPT_INFORMATION)), Label) == 0) {
 | 
						|
        (*Position) = Script;
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Script = Script + ScriptHeader.Length;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CreateIfNotFound) {
 | 
						|
    LabelLength = (UINT32)AsciiStrSize (Label);
 | 
						|
    return S3BootScriptLabelInternal (BeforeOrAfter, Position, LabelLength, Label);
 | 
						|
  } else {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Compare two positions in the boot script table and return their relative position.
 | 
						|
  @param  Position1             The positions in the boot script table to compare
 | 
						|
  @param  Position2             The positions in the boot script table to compare
 | 
						|
  @param  RelativePosition      On return, points to the result of the comparison
 | 
						|
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
S3BootScriptCompare (
 | 
						|
  IN  UINT8  *Position1,
 | 
						|
  IN  UINT8  *Position2,
 | 
						|
  OUT UINTN  *RelativePosition
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8   *Script;
 | 
						|
  UINT32  TableLength;
 | 
						|
 | 
						|
  if (RelativePosition == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check that the script is initialized and synced without adding an entry to the script.
 | 
						|
  //
 | 
						|
  Script = S3BootScriptGetEntryAddAddress (0);
 | 
						|
  if (Script == NULL) {
 | 
						|
    return RETURN_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Script = mS3BootScriptTablePtr->TableBase;
 | 
						|
 | 
						|
  //
 | 
						|
  // mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up
 | 
						|
  //
 | 
						|
  TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
 | 
						|
  if ((Position1 < Script) || (Position1 > Script+TableLength)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Position2 < Script) || (Position2 > Script+TableLength)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *RelativePosition = (Position1 < Position2) ? -1 : ((Position1 == Position2) ? 0 : 1);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |