| /** @file | |
| Implementation for S3 SMM Boot Script Saver state driver. | |
| Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #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); | |
| Segment = VA_ARG (Marker, UINT16); | |
| Address = VA_ARG (Marker, UINT64); | |
| Count = VA_ARG (Marker, UINTN); | |
| Buffer = VA_ARG (Marker, UINT8 *); | |
| 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); | |
| Segment = VA_ARG (Marker, UINT16); | |
| Address = VA_ARG (Marker, UINT64); | |
| Data = VA_ARG (Marker, UINT8 *); | |
| DataMask = VA_ARG (Marker, UINT8 *); | |
| return S3BootScriptSavePciCfg2ReadWrite (Width, Segment, Address, Data, DataMask); | |
| } | |
| /** | |
| Internal function to add smbus execute opcode to the table. | |
| @param Marker The variable argument list to get the opcode | |
| and associated attributes. | |
| @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. | |
| @retval EFI_SUCCESS Opcode is added. | |
| **/ | |
| EFI_STATUS | |
| 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; | |
| UINT64 Delay; | |
| UINT64 LoopTimes; | |
| UINT32 Remainder; | |
| 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 = VA_ARG (Marker, UINT64); | |
| // | |
| // According to the spec, the interval between 2 polls is 100ns, | |
| // but the unit of Duration for S3BootScriptSaveMemPoll() is microsecond(1000ns). | |
| // Duration * 1000ns * LoopTimes = Delay * 100ns | |
| // Duration will be minimum 1(microsecond) to be minimum deviation, | |
| // so LoopTimes = Delay / 10. | |
| // | |
| LoopTimes = DivU64x32Remainder ( | |
| Delay, | |
| 10, | |
| &Remainder | |
| ); | |
| if (Remainder != 0) { | |
| // | |
| // If Remainder is not zero, LoopTimes will be rounded up by 1. | |
| // | |
| LoopTimes += 1; | |
| } | |
| return S3BootScriptSaveMemPoll (Width, Address, DataMask, Data, 1, LoopTimes); | |
| } | |
| /** | |
| 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 UINTN 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 UINTN 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, (VOID **)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 Label is NULL or points to an empty string. | |
| @retval EFI_INVALID_PARAMETER 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, (VOID **)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. | |
| @retval EFI_INVALID_PARAMETER The RelativePosition is NULL. | |
| **/ | |
| 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 occurred. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| InitializeSmmS3SaveState ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| EFI_HANDLE Handle; | |
| if (!PcdGetBool (PcdAcpiS3Enable)) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| Handle = NULL; | |
| return gSmst->SmmInstallProtocolInterface ( | |
| &Handle, | |
| &gEfiS3SmmSaveStateProtocolGuid, | |
| EFI_NATIVE_INTERFACE, | |
| &mS3SmmSaveState | |
| ); | |
| } |