summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc2
-rw-r--r--MdeModulePkg/Universal/Acpi/S3SaveStateDxe/InternalS3SaveState.h162
-rw-r--r--MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c901
-rw-r--r--MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf57
-rw-r--r--MdeModulePkg/Universal/Acpi/SmmS3SaveState/InternalSmmSaveState.h161
-rw-r--r--MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c898
-rw-r--r--MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf56
7 files changed, 2237 insertions, 0 deletions
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 1a97ef29e0..7a42d12c85 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -328,4 +328,6 @@
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+ MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+ MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf
diff --git a/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/InternalS3SaveState.h b/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/InternalS3SaveState.h
new file mode 100644
index 0000000000..a9b724d199
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/InternalS3SaveState.h
@@ -0,0 +1,162 @@
+/** @file
+ Internal header file for S3 Boot Script Saver state driver.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _INTERNAL_S3_SAVE_STATE_H_
+#define _INTERNAL_S3_SAVE_STATE_H_
+#include <PiDxe.h>
+
+#include <Protocol/S3SaveState.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SmbusLib.h>
+#include <IndustryStandard/SmBus.h>
+/**
+ Adds a record into S3 boot script table.
+
+ This function is used to store a boot script record into a given boot
+ script table. If the table specified by TableName is nonexistent in the
+ system, a new table will automatically be created and then the script record
+ will be added into the new table. This function is responsible for allocating
+ necessary memory for the script.
+
+ This function has a variable parameter list. The exact parameter list depends on
+ the OpCode that is passed into the function. If an unsupported OpCode or illegal
+ parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
+ If there are not enough resources available for storing more scripts, this function returns
+ EFI_OUT_OF_RESOURCES.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
+ If the opcode is unknow or not supported because of the PCD
+ Feature Flags.
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptWrite (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN UINT16 OpCode,
+ ...
+ );
+/**
+ Insert a record into a specified Framework boot script table.
+
+ This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is
+ assumed this protocol has platform specific mechanism to store the OpCode set and replay them
+ during the S3 resume.
+ The opcode is inserted before or after the specified position in the boot script table. If Position is
+ NULL then that position is after the last opcode in the table (BeforeOrAfter is FALSE) or before
+ the first opcode in the table (BeforeOrAfter is TRUE). The position which is pointed to by
+ Position upon return can be used for subsequent insertions.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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 OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptInsert (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN UINT16 OpCode,
+ ...
+ );
+/**
+ Find a label within the boot script table and, if not present, optionally create it.
+
+ If the label Label is already exists in the boot script table, then no new label is created, the
+ position of the Label is returned in *Position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is TRUE, then it will be
+ created before or after the specified position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is FALSE, then
+ EFI_NOT_FOUND is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param BeforeOrAfter Specifies whether the label 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 label is inserted at the beginning of the table (if TRUE) or end of
+ the table (if FALSE).
+ @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 label will be inserted,
+ either before or after, depending on BeforeOrAfter. On exit, specifies the position
+ of the inserted label in the boot script table.
+ @param Label Points to the label which will be inserted in the boot script table.
+
+ @retval EFI_SUCCESS The label already exists or was inserted.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptLabel (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN BOOLEAN CreateIfNotFound,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN CONST CHAR8 *Label
+ );
+/**
+ Compare two positions in the boot script table and return their relative position.
+
+ This function compares two positions in the boot script table and returns their relative positions. If
+ Position1 is before Position2, then -1 is returned. If Position1 is equal to Position2,
+ then 0 is returned. If Position1 is after Position2, then 1 is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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.
+ @retval EFI_INVALID_PARAMETER The Position1 or Position2 is not a valid position in the boot script table.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptCompare (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position1,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position2,
+ OUT UINTN *RelativePosition
+ );
+
+#endif //_INTERNAL_S3_SAVE_STATE_H_
diff --git a/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c b/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c
new file mode 100644
index 0000000000..15c4b6b90f
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c
@@ -0,0 +1,901 @@
+/** @file
+ Implementation for S3 Boot Script Saver state driver.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "InternalS3SaveState.h"
+
+EFI_HANDLE mHandle = NULL;
+EFI_S3_SAVE_STATE_PROTOCOL mS3SaveState = {
+ BootScriptWrite,
+ BootScriptInsert,
+ BootScriptLabel,
+ BootScriptCompare
+ };
+/**
+ Internal function to add IO write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteIoWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveIoWrite (Width, Address, Count, Buffer);
+}
+/**
+ Internal function to add IO read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteIoReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveIoReadWrite (Width, Address, Data, DataMask);
+}
+
+/**
+ Internal function to add memory write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteMemWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveMemWrite (Width, Address, Count, Buffer);
+}
+
+/**
+ Internal function to add memory read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteMemReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveMemReadWrite (Width, Address, Data, DataMask);
+}
+
+/**
+ Internal function to add PciCfg write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfgWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSavePciCfgWrite (Width, Address, Count, Buffer);
+}
+
+/**
+ Internal function to PciCfg read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfgReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSavePciCfgReadWrite (Width, Address, Data, DataMask);
+}
+/**
+ Internal function to add PciCfg2 write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfg2Write (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+ UINT16 Segment;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+ Segment = VA_ARG (Marker, UINT16);
+
+ return S3BootScriptSavePciCfg2Write (Width, Segment, Address, Count, Buffer);
+}
+
+/**
+ Internal function to PciCfg2 read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfg2ReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT16 Segment;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Segment = VA_ARG (Marker, UINT16);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSavePciCfg2ReadWrite (Width, Segment, Address, Data, DataMask);
+}
+/**
+ Internal function to add smbus excute opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteSmbusExecute (
+ IN VA_LIST Marker
+ )
+{
+ EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;
+ EFI_SMBUS_DEVICE_COMMAND Command;
+ EFI_SMBUS_OPERATION Operation;
+ BOOLEAN PecCheck;
+ VOID *Buffer;
+ UINTN *DataSize;
+ UINTN SmBusAddress;
+
+ SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN);
+ Command = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND);
+ Operation = VA_ARG (Marker, EFI_SMBUS_OPERATION);
+ PecCheck = VA_ARG (Marker, BOOLEAN);
+ SmBusAddress = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress,Command,0,PecCheck);
+ DataSize = VA_ARG (Marker, UINTN *);
+ Buffer = VA_ARG (Marker, VOID *);
+
+ return S3BootScriptSaveSmbusExecute (SmBusAddress, Operation, DataSize, Buffer);
+}
+/**
+ Internal function to add stall opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteStall (
+ IN VA_LIST Marker
+ )
+{
+ UINT32 Duration;
+
+ Duration = VA_ARG (Marker, UINT32);
+
+ return S3BootScriptSaveStall (Duration);
+}
+
+/**
+ Internal function to add Save jmp address according to DISPATCH_OPCODE.
+ We ignore "Context" parameter
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteDispatch (
+ IN VA_LIST Marker
+ )
+{
+ VOID *EntryPoint;
+
+ EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+ return S3BootScriptSaveDispatch (EntryPoint);
+}
+
+/**
+ Internal function to add memory pool operation to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteMemPoll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINTN Delay;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINTN)VA_ARG (Marker, UINT64);
+ //
+ // According to the spec, the interval between 2 pools is 100ns
+ //
+ return S3BootScriptSaveMemPoll (Width, Address, DataMask, Data, 100, Delay);
+
+}
+
+/**
+ Internal function to add Save jmp address according to DISPATCH_OPCODE2.
+ The "Context" parameter is not ignored.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteDispatch2 (
+ IN VA_LIST Marker
+ )
+{
+ VOID *EntryPoint;
+ VOID *Context;
+
+ EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+ Context = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+
+ return S3BootScriptSaveDispatch2 (EntryPoint, Context);
+}
+/**
+ Internal function to add INFORAMTION opcode node to the table
+ list.
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWriteInformation (
+ IN VA_LIST Marker
+ )
+{
+ UINT32 InformationLength;
+ EFI_PHYSICAL_ADDRESS Information;
+
+ InformationLength = VA_ARG (Marker, UINT32);
+ Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+ return S3BootScriptSaveInformation (InformationLength, (VOID*)(UINTN)Information);
+}
+/**
+ Internal function to add IO poll opcode node to the table
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWriteIoPoll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINT64 Delay;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINT64)VA_ARG (Marker, UINT64);
+
+ return S3BootScriptSaveIoPoll (Width, Address, Data, DataMask, Delay);
+}
+/**
+ Internal function to add PCI config poll opcode node to the table
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWritePciConfigPoll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINT64 Delay;
+
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINT64)VA_ARG (Marker, UINT64);
+
+ return S3BootScriptSavePciPoll (Width, Address, Data, DataMask, Delay);
+}
+/**
+ Internal function to add PCI config 2 poll opcode node to the table
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWritePciConfig2Poll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT16 Segment;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINT64 Delay;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Segment = VA_ARG (Marker, UINT16);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINT64)VA_ARG (Marker, UINT64);
+
+ return S3BootScriptSavePci2Poll (Width, Segment, Address, Data, DataMask, Delay);
+}
+
+
+/**
+ Adds a record into S3 boot script table.
+
+ This function is used to store a boot script record into a given boot
+ script table. If the table specified by TableName is nonexistent in the
+ system, a new table will automatically be created and then the script record
+ will be added into the new table. This function is responsible for allocating
+ necessary memory for the script.
+
+ This function has a variable parameter list. The exact parameter list depends on
+ the OpCode that is passed into the function. If an unsupported OpCode or illegal
+ parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
+ If there are not enough resources available for storing more scripts, this function returns
+ EFI_OUT_OF_RESOURCES.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
+ If the opcode is unknow or not supported because of the PCD
+ Feature Flags.
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptWrite (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN UINT16 OpCode,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+ //
+ // Build script according to opcode
+ //
+ switch (OpCode) {
+
+ case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteSmbusExecute (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_STALL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteStall (Marker);
+ VA_END (Marker);
+
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch2 (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteInformation (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2Write (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2ReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfigPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfig2Poll (Marker);
+ VA_END (Marker);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+/**
+ Insert a record into a specified Framework boot script table.
+
+ This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is
+ assumed this protocol has platform specific mechanism to store the OpCode set and replay them
+ during the S3 resume.
+ The opcode is inserted before or after the specified position in the boot script table. If Position is
+ NULL then that position is after the last opcode in the table (BeforeOrAfter is FALSE) or before
+ the first opcode in the table (BeforeOrAfter is TRUE). The position which is pointed to by
+ Position upon return can be used for subsequent insertions.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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 OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptInsert (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN UINT16 OpCode,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+ //
+ // Build script according to opcode
+ //
+ switch (OpCode) {
+
+ case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteSmbusExecute (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_STALL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteStall (Marker);
+ VA_END (Marker);
+
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch2 (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteInformation (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2Write (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2ReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfigPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfig2Poll (Marker);
+ VA_END (Marker);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
+ }
+ return Status;
+}
+/**
+ Find a label within the boot script table and, if not present, optionally create it.
+
+ If the label Label is already exists in the boot script table, then no new label is created, the
+ position of the Label is returned in *Position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is TRUE, then it will be
+ created before or after the specified position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is FALSE, then
+ EFI_NOT_FOUND is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param BeforeOrAfter Specifies whether the label 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 label is inserted at the beginning of the table (if TRUE) or end of
+ the table (if FALSE).
+ @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 label will be inserted,
+ either before or after, depending on BeforeOrAfter. On exit, specifies the position
+ of the inserted label in the boot script table.
+ @param Label Points to the label which will be inserted in the boot script table.
+
+ @retval EFI_SUCCESS The label already exists or was inserted.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptLabel (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN BOOLEAN CreateIfNotFound,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN CONST CHAR8 *Label
+ )
+{
+ return S3BootScriptLabel (BeforeOrAfter, CreateIfNotFound, Position, Label);
+}
+/**
+ Compare two positions in the boot script table and return their relative position.
+
+ This function compares two positions in the boot script table and returns their relative positions. If
+ Position1 is before Position2, then -1 is returned. If Position1 is equal to Position2,
+ then 0 is returned. If Position1 is after Position2, then 1 is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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.
+ @retval EFI_INVALID_PARAMETER The Position1 or Position2 is not a valid position in the boot script table.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptCompare (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position1,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position2,
+ OUT UINTN *RelativePosition
+ )
+{
+ return S3BootScriptCompare (Position1, Position2, RelativePosition);
+}
+/**
+ This routine is entry point of ScriptSave driver.
+
+ @param ImageHandle Handle for this drivers loaded image protocol.
+ @param SystemTable EFI system table.
+
+ @retval EFI_OUT_OF_RESOURCES No enough resource
+ @retval EFI_SUCCESS Succesfully installed the ScriptSave driver.
+ @retval other Errors occured.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeS3SaveState (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+
+
+ return gBS->InstallProtocolInterface (
+ &mHandle,
+ &gEfiS3SaveStateProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mS3SaveState
+ );
+
+}
+
+
diff --git a/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf b/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
new file mode 100644
index 0000000000..9a2cf966cc
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
@@ -0,0 +1,57 @@
+## @file
+# Component description file for ScriptSave module.
+#
+# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are
+# licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = S3SaveStateDxe
+ FILE_GUID = BDCE85BB-FBAA-4f4e-9264-501A2C249581
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeS3SaveState
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ S3SaveState.c
+ InternalS3SaveState.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ S3BootScriptLib
+
+[Protocols]
+ gEfiS3SaveStateProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+
+[Depex]
+ TRUE
+ \ No newline at end of file
diff --git a/MdeModulePkg/Universal/Acpi/SmmS3SaveState/InternalSmmSaveState.h b/MdeModulePkg/Universal/Acpi/SmmS3SaveState/InternalSmmSaveState.h
new file mode 100644
index 0000000000..d6263fd727
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/SmmS3SaveState/InternalSmmSaveState.h
@@ -0,0 +1,161 @@
+/** @file
+ Internal header file for SMM S3 Boot Script Saver state driver.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _INTERNAL_SMM_S3_SAVE_STATE_H_
+#define _INTERNAL_SMM_S3_SAVE_STATE_H_
+#include <PiDxe.h>
+
+#include <Protocol/S3SmmSaveState.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SmbusLib.h>
+#include <IndustryStandard/SmBus.h>
+/**
+ Adds a record into S3 boot script table.
+
+ This function is used to store a boot script record into a given boot
+ script table. If the table specified by TableName is nonexistent in the
+ system, a new table will automatically be created and then the script record
+ will be added into the new table. This function is responsible for allocating
+ necessary memory for the script.
+
+ This function has a variable parameter list. The exact parameter list depends on
+ the OpCode that is passed into the function. If an unsupported OpCode or illegal
+ parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
+ If there are not enough resources available for storing more scripts, this function returns
+ EFI_OUT_OF_RESOURCES.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
+ If the opcode is unknow or not supported because of the PCD
+ Feature Flags.
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptWrite (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN UINT16 OpCode,
+ ...
+ );
+/**
+ Insert a record into a specified Framework boot script table.
+
+ This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is
+ assumed this protocol has platform specific mechanism to store the OpCode set and replay them
+ during the S3 resume.
+ The opcode is inserted before or after the specified position in the boot script table. If Position is
+ NULL then that position is after the last opcode in the table (BeforeOrAfter is FALSE) or before
+ the first opcode in the table (BeforeOrAfter is TRUE). The position which is pointed to by
+ Position upon return can be used for subsequent insertions.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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 OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptInsert (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN UINT16 OpCode,
+ ...
+ );
+/**
+ Find a label within the boot script table and, if not present, optionally create it.
+
+ If the label Label is already exists in the boot script table, then no new label is created, the
+ position of the Label is returned in *Position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is TRUE, then it will be
+ created before or after the specified position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is FALSE, then
+ EFI_NOT_FOUND is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param BeforeOrAfter Specifies whether the label 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 label is inserted at the beginning of the table (if TRUE) or end of
+ the table (if FALSE).
+ @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 label will be inserted,
+ either before or after, depending on BeforeOrAfter. On exit, specifies the position
+ of the inserted label in the boot script table.
+ @param Label Points to the label which will be inserted in the boot script table.
+
+ @retval EFI_SUCCESS The label already exists or was inserted.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptLabel (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN BOOLEAN CreateIfNotFound,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN CONST CHAR8 *Label
+ );
+/**
+ Compare two positions in the boot script table and return their relative position.
+
+ This function compares two positions in the boot script table and returns their relative positions. If
+ Position1 is before Position2, then -1 is returned. If Position1 is equal to Position2,
+ then 0 is returned. If Position1 is after Position2, then 1 is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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.
+ @retval EFI_INVALID_PARAMETER The Position1 or Position2 is not a valid position in the boot script table.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptCompare (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position1,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position2,
+ OUT UINTN *RelativePosition
+ );
+
+#endif //_INTERNAL_SMM_S3_SAVE_STATE_H_
diff --git a/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c b/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c
new file mode 100644
index 0000000000..9879143e4b
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c
@@ -0,0 +1,898 @@
+/** @file
+ Implementation for S3 SMM Boot Script Saver state driver.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "InternalSmmSaveState.h"
+
+EFI_S3_SMM_SAVE_STATE_PROTOCOL mS3SmmSaveState = {
+ BootScriptWrite,
+ BootScriptInsert,
+ BootScriptLabel,
+ BootScriptCompare
+ };
+/**
+ Internal function to add IO write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteIoWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveIoWrite (Width, Address, Count, Buffer);
+}
+/**
+ Internal function to add IO read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteIoReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveIoReadWrite (Width, Address, Data, DataMask);
+}
+
+/**
+ Internal function to add memory write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteMemWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveMemWrite (Width, Address, Count, Buffer);
+}
+
+/**
+ Internal function to add memory read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteMemReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSaveMemReadWrite (Width, Address, Data, DataMask);
+}
+
+/**
+ Internal function to add PciCfg write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfgWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSavePciCfgWrite (Width, Address, Count, Buffer);
+}
+
+/**
+ Internal function to PciCfg read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfgReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSavePciCfgReadWrite (Width, Address, Data, DataMask);
+}
+/**
+ Internal function to add PciCfg2 write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfg2Write (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+ UINT16 Segment;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+ Segment = VA_ARG (Marker, UINT16);
+
+ return S3BootScriptSavePciCfg2Write (Width, Segment, Address, Count, Buffer);
+}
+
+/**
+ Internal function to PciCfg2 read/write opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWritePciCfg2ReadWrite (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT16 Segment;
+ UINT64 Address;
+ UINT8 *Data;
+ UINT8 *DataMask;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Segment = VA_ARG (Marker, UINT16);
+ Data = VA_ARG (Marker, UINT8 *);
+ DataMask = VA_ARG (Marker, UINT8 *);
+
+ return S3BootScriptSavePciCfg2ReadWrite (Width, Segment, Address, Data, DataMask);
+}
+/**
+ Internal function to add smbus excute opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteSmbusExecute (
+ IN VA_LIST Marker
+ )
+{
+ EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;
+ EFI_SMBUS_DEVICE_COMMAND Command;
+ EFI_SMBUS_OPERATION Operation;
+ BOOLEAN PecCheck;
+ VOID *Buffer;
+ UINTN *DataSize;
+ UINTN SmBusAddress;
+
+ SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN);
+ Command = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND);
+ Operation = VA_ARG (Marker, EFI_SMBUS_OPERATION);
+ PecCheck = VA_ARG (Marker, BOOLEAN);
+ SmBusAddress = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress,Command,0,PecCheck);
+ DataSize = VA_ARG (Marker, UINTN *);
+ Buffer = VA_ARG (Marker, VOID *);
+
+ return S3BootScriptSaveSmbusExecute (SmBusAddress, Operation, DataSize, Buffer);
+}
+/**
+ Internal function to add stall opcode to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteStall (
+ IN VA_LIST Marker
+ )
+{
+ UINT32 Duration;
+
+ Duration = VA_ARG (Marker, UINT32);
+
+ return S3BootScriptSaveStall (Duration);
+}
+
+/**
+ Internal function to add Save jmp address according to DISPATCH_OPCODE.
+ We ignore "Context" parameter
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteDispatch (
+ IN VA_LIST Marker
+ )
+{
+ VOID *EntryPoint;
+
+ EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+ return S3BootScriptSaveDispatch (EntryPoint);
+}
+
+/**
+ Internal function to add memory pool operation to the table.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteMemPoll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINTN Delay;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINTN)VA_ARG (Marker, UINT64);
+ //
+ // According to the spec, the interval between 2 pools is 100ns
+ //
+ return S3BootScriptSaveMemPoll (Width, Address, DataMask, Data, 100, Delay);
+
+}
+
+/**
+ Internal function to add Save jmp address according to DISPATCH_OPCODE2.
+ The "Context" parameter is not ignored.
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
+ @retval EFI_SUCCESS Opcode is added.
+
+**/
+EFI_STATUS
+BootScriptWriteDispatch2 (
+ IN VA_LIST Marker
+ )
+{
+ VOID *EntryPoint;
+ VOID *Context;
+
+ EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+ Context = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+
+ return S3BootScriptSaveDispatch2 (EntryPoint, Context);
+}
+/**
+ Internal function to add INFORAMTION opcode node to the table
+ list.
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWriteInformation (
+ IN VA_LIST Marker
+ )
+{
+ UINT32 InformationLength;
+ EFI_PHYSICAL_ADDRESS Information;
+
+ InformationLength = VA_ARG (Marker, UINT32);
+ Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
+ return S3BootScriptSaveInformation (InformationLength, (VOID*)(UINTN)Information);
+}
+/**
+ Internal function to add IO poll opcode node to the table
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWriteIoPoll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINT64 Delay;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINT64)VA_ARG (Marker, UINT64);
+
+ return S3BootScriptSaveIoPoll (Width, Address, Data, DataMask, Delay);
+}
+/**
+ Internal function to add PCI config poll opcode node to the table
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWritePciConfigPoll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINT64 Delay;
+
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINT64)VA_ARG (Marker, UINT64);
+
+ return S3BootScriptSavePciPoll (Width, Address, Data, DataMask, Delay);
+}
+/**
+ Internal function to add PCI config 2 poll opcode node to the table
+
+ @param Marker The variable argument list to get the opcode
+ and associated attributes.
+
+ @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
+ @retval EFI_SUCCESS The opcode entry is added to the table
+ successfully.
+**/
+EFI_STATUS
+BootScriptWritePciConfig2Poll (
+ IN VA_LIST Marker
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT16 Segment;
+ UINT64 Address;
+ VOID *Data;
+ VOID *DataMask;
+ UINT64 Delay;
+
+ Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
+ Segment = VA_ARG (Marker, UINT16);
+ Address = VA_ARG (Marker, UINT64);
+ Data = VA_ARG (Marker, VOID *);
+ DataMask = VA_ARG (Marker, VOID *);
+ Delay = (UINT64)VA_ARG (Marker, UINT64);
+
+ return S3BootScriptSavePci2Poll (Width, Segment, Address, Data, DataMask, Delay);
+}
+
+/**
+ Adds a record into S3 boot script table.
+
+ This function is used to store a boot script record into a given boot
+ script table. If the table specified by TableName is nonexistent in the
+ system, a new table will automatically be created and then the script record
+ will be added into the new table. This function is responsible for allocating
+ necessary memory for the script.
+
+ This function has a variable parameter list. The exact parameter list depends on
+ the OpCode that is passed into the function. If an unsupported OpCode or illegal
+ parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
+ If there are not enough resources available for storing more scripts, this function returns
+ EFI_OUT_OF_RESOURCES.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
+ If the opcode is unknow or not supported because of the PCD
+ Feature Flags.
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptWrite (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN UINT16 OpCode,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+ //
+ // Build script according to opcode
+ //
+ switch (OpCode) {
+
+ case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteSmbusExecute (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_STALL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteStall (Marker);
+ VA_END (Marker);
+
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch2 (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteInformation (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2Write (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2ReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfigPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfig2Poll (Marker);
+ VA_END (Marker);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+/**
+ Insert a record into a specified Framework boot script table.
+
+ This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is
+ assumed this protocol has platform specific mechanism to store the OpCode set and replay them
+ during the S3 resume.
+ The opcode is inserted before or after the specified position in the boot script table. If Position is
+ NULL then that position is after the last opcode in the table (BeforeOrAfter is FALSE) or before
+ the first opcode in the table (BeforeOrAfter is TRUE). The position which is pointed to by
+ Position upon return can be used for subsequent insertions.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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 OpCode The operation code (opcode) number.
+ @param ... Argument list that is specific to each opcode.
+
+ @retval EFI_SUCCESS The operation succeeded. A record was added into the
+ specified script table.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+ @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptInsert (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN UINT16 OpCode,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+ //
+ // Build script according to opcode
+ //
+ switch (OpCode) {
+
+ case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfgReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteSmbusExecute (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_STALL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteStall (Marker);
+ VA_END (Marker);
+
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteDispatch2 (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteInformation (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteMemPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2Write (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciCfg2ReadWrite (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWriteIoPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfigPoll (Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptWritePciConfig2Poll (Marker);
+ VA_END (Marker);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
+ }
+ return Status;
+}
+/**
+ Find a label within the boot script table and, if not present, optionally create it.
+
+ If the label Label is already exists in the boot script table, then no new label is created, the
+ position of the Label is returned in *Position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is TRUE, then it will be
+ created before or after the specified position and EFI_SUCCESS is returned.
+ If the label Label does not already exist and CreateIfNotFound is FALSE, then
+ EFI_NOT_FOUND is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @param BeforeOrAfter Specifies whether the label 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 label is inserted at the beginning of the table (if TRUE) or end of
+ the table (if FALSE).
+ @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 label will be inserted,
+ either before or after, depending on BeforeOrAfter. On exit, specifies the position
+ of the inserted label in the boot script table.
+ @param Label Points to the label which will be inserted in the boot script table.
+
+ @retval EFI_SUCCESS The label already exists or was inserted.
+ @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptLabel (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN BOOLEAN BeforeOrAfter,
+ IN BOOLEAN CreateIfNotFound,
+ IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL,
+ IN CONST CHAR8 *Label
+ )
+{
+ return S3BootScriptLabel (BeforeOrAfter, CreateIfNotFound, Position, Label);
+}
+/**
+ Compare two positions in the boot script table and return their relative position.
+
+ This function compares two positions in the boot script table and returns their relative positions. If
+ Position1 is before Position2, then -1 is returned. If Position1 is equal to Position2,
+ then 0 is returned. If Position1 is after Position2, then 1 is returned.
+
+ @param This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
+ @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.
+ @retval EFI_INVALID_PARAMETER The Position1 or Position2 is not a valid position in the boot script table.
+
+**/
+EFI_STATUS
+EFIAPI
+BootScriptCompare (
+ IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position1,
+ IN EFI_S3_BOOT_SCRIPT_POSITION Position2,
+ OUT UINTN *RelativePosition
+ )
+{
+ return S3BootScriptCompare (Position1, Position2, RelativePosition);
+}
+/**
+ This routine is entry point of ScriptSave driver.
+
+ @param ImageHandle Handle for this drivers loaded image protocol.
+ @param SystemTable EFI system table.
+
+ @retval EFI_OUT_OF_RESOURCES No enough resource
+ @retval EFI_SUCCESS Succesfully installed the ScriptSave driver.
+ @retval other Errors occured.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmmS3SaveState (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE Handle;
+
+
+ Handle = NULL;
+ return gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gEfiS3SmmSaveStateProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mS3SmmSaveState
+ );
+}
diff --git a/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf b/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf
new file mode 100644
index 0000000000..7daa922091
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf
@@ -0,0 +1,56 @@
+## @file
+# Component description file for ScriptSave Lite module.
+#
+# This is an implementation of the Boot Script Save protocol.
+#
+# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are
+# licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmS3SaveState
+ FILE_GUID = 2D59F041-53A4-40d0-A6CD-844DC0DFEF17
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+
+ ENTRY_POINT = InitializeSmmS3SaveState
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ SmmS3SaveState.c
+ InternalSmmSaveState.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ SmmServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ S3BootScriptLib
+
+[Protocols]
+ gEfiS3SmmSaveStateProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Depex]
+ TRUE
+