summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c1776
1 files changed, 1776 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
new file mode 100644
index 00000000..60cc6fdf
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
@@ -0,0 +1,1776 @@
+/** @file
+ Interpret and execute the S3 data in S3 boot script.
+
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "InternalBootScriptLib.h"
+
+/**
+ Executes an SMBus operation to an SMBus controller. Returns when either the command has been
+ executed or an error is encountered in doing the operation.
+
+ The SmbusExecute() function provides a standard way to execute an operation as defined in the System
+ Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus
+ slave devices accept this transaction or that this function returns with error.
+
+ @param SmbusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
+ and PEC.
+ @param Operation Signifies which particular SMBus hardware protocol instance that
+ it will use to execute the SMBus transactions. This SMBus
+ hardware protocol is defined by the SMBus Specification and is
+ not related to EFI.
+ @param Length Signifies the number of bytes that this operation will do. The
+ maximum number of bytes can be revision specific and operation
+ specific. This field will contain the actual number of bytes that
+ are executed for this operation. Not all operations require this
+ argument.
+ @param Buffer Contains the value of data to execute to the SMBus slave device.
+ Not all operations require this argument. The length of this
+ buffer is identified by Length.
+
+ @retval EFI_SUCCESS The last data that was returned from the access matched the poll
+ exit criteria.
+ @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
+ @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
+ determined by the SMBus host controller device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
+ reflected in the Host Status Register bit. Device errors are a
+ result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+ @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
+ @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
+ and EfiSmbusQuickWrite. Length is outside the range of valid
+ values.
+ @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+InternalSmbusExecute (
+ IN UINTN SmbusAddress,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 WorkBuffer[MAX_SMBUS_BLOCK_LEN];
+
+ switch (Operation) {
+ case EfiSmbusQuickRead:
+ DEBUG ((EFI_D_INFO, "EfiSmbusQuickRead - 0x%08x\n", SmbusAddress));
+ SmBusQuickRead (SmbusAddress, &Status);
+ break;
+ case EfiSmbusQuickWrite:
+ DEBUG ((EFI_D_INFO, "EfiSmbusQuickWrite - 0x%08x\n", SmbusAddress));
+ SmBusQuickWrite (SmbusAddress, &Status);
+ break;
+ case EfiSmbusReceiveByte:
+ DEBUG ((EFI_D_INFO, "EfiSmbusReceiveByte - 0x%08x\n", SmbusAddress));
+ SmBusReceiveByte (SmbusAddress, &Status);
+ break;
+ case EfiSmbusSendByte:
+ DEBUG ((EFI_D_INFO, "EfiSmbusSendByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
+ SmBusSendByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
+ break;
+ case EfiSmbusReadByte:
+ DEBUG ((EFI_D_INFO, "EfiSmbusReadByte - 0x%08x\n", SmbusAddress));
+ SmBusReadDataByte (SmbusAddress, &Status);
+ break;
+ case EfiSmbusWriteByte:
+ DEBUG ((EFI_D_INFO, "EfiSmbusWriteByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
+ SmBusWriteDataByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
+ break;
+ case EfiSmbusReadWord:
+ DEBUG ((EFI_D_INFO, "EfiSmbusReadWord - 0x%08x\n", SmbusAddress));
+ SmBusReadDataWord (SmbusAddress, &Status);
+ break;
+ case EfiSmbusWriteWord:
+ DEBUG ((EFI_D_INFO, "EfiSmbusWriteWord - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
+ SmBusWriteDataWord (SmbusAddress, *(UINT16 *) Buffer, &Status);
+ break;
+ case EfiSmbusProcessCall:
+ DEBUG ((EFI_D_INFO, "EfiSmbusProcessCall - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
+ SmBusProcessCall (SmbusAddress, *(UINT16 *) Buffer, &Status);
+ break;
+ case EfiSmbusReadBlock:
+ DEBUG ((EFI_D_INFO, "EfiSmbusReadBlock - 0x%08x\n", SmbusAddress));
+ SmBusReadBlock (SmbusAddress, WorkBuffer, &Status);
+ break;
+ case EfiSmbusWriteBlock:
+ DEBUG ((EFI_D_INFO, "EfiSmbusWriteBlock - 0x%08x\n", SmbusAddress));
+ SmBusWriteBlock ((SmbusAddress + SMBUS_LIB_ADDRESS (0, 0, (*Length), FALSE)), Buffer, &Status);
+ break;
+ case EfiSmbusBWBRProcessCall:
+ DEBUG ((EFI_D_INFO, "EfiSmbusBWBRProcessCall - 0x%08x\n", SmbusAddress));
+ SmBusBlockProcessCall ((SmbusAddress + SMBUS_LIB_ADDRESS (0, 0, (*Length), FALSE)), Buffer, WorkBuffer, &Status);
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/**
+ Translates boot script width and address stride to MDE library interface.
+
+
+ @param Width Width of the operation.
+ @param Address Address of the operation.
+ @param AddressStride Instride for stepping input buffer.
+ @param BufferStride Outstride for stepping output buffer.
+
+ @retval EFI_SUCCESS Successful translation.
+ @retval EFI_INVALID_PARAMETER Width or Address is invalid.
+**/
+EFI_STATUS
+BuildLoopData (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT64 Address,
+ OUT UINTN *AddressStride,
+ OUT UINTN *BufferStride
+ )
+{
+ UINTN AlignMask;
+
+ if (Width >= S3BootScriptWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *AddressStride = (UINT32)(1 << (Width & 0x03));
+ *BufferStride = *AddressStride;
+
+ AlignMask = *AddressStride - 1;
+ if ((Address & AlignMask) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= S3BootScriptWidthFifoUint8 && Width <= S3BootScriptWidthFifoUint64) {
+ *AddressStride = 0;
+ }
+
+ if (Width >= S3BootScriptWidthFillUint8 && Width <= S3BootScriptWidthFillUint64) {
+ *BufferStride = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform IO read operation
+
+ @param[in] Width Width of the operation.
+ @param[in] Address Address of the operation.
+ @param[in] Count Count of the number of accesses to perform.
+ @param[out] Buffer Pointer to the buffer to read from I/O space.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ Address is outside the legal range of I/O ports.
+
+**/
+EFI_STATUS
+ScriptIoRead (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN AddressStride;
+ UINTN BufferStride;
+ PTR Out;
+
+ Out.Buf = (UINT8 *) Buffer;
+
+ if (Address > MAX_IO_ADDRESS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Loop for each iteration and move the data
+ //
+ for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
+ switch (Width) {
+
+ case S3BootScriptWidthUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint8 = IoRead8 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint8 = IoRead8 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint8 = IoRead8 ((UINTN) Address);
+ break;
+
+ case S3BootScriptWidthUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint16 = IoRead16 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint16 = IoRead16 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint16 = IoRead16 ((UINTN) Address);
+ break;
+
+ case S3BootScriptWidthUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint32 = IoRead32 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint32 = IoRead32 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint32 = IoRead32 ((UINTN) Address);
+ break;
+
+ case S3BootScriptWidthUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint64 = IoRead64 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint64 = IoRead64 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN) Address));
+ *Out.Uint64 = IoRead64 ((UINTN) Address);
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform IO write operation
+
+ @param[in] Width Width of the operation.
+ @param[in] Address Address of the operation.
+ @param[in] Count Count of the number of accesses to perform.
+ @param[in] Buffer Pointer to the buffer to write to I/O space.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ Address is outside the legal range of I/O ports.
+
+**/
+EFI_STATUS
+ScriptIoWrite (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN AddressStride;
+ UINTN BufferStride;
+ UINT64 OriginalAddress;
+ PTR In;
+ PTR OriginalIn;
+
+ In.Buf = (UINT8 *) Buffer;
+
+ if (Address > MAX_IO_ADDRESS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Loop for each iteration and move the data
+ //
+ OriginalAddress = Address;
+ OriginalIn.Buf = In.Buf;
+ for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
+ switch (Width) {
+ case S3BootScriptWidthUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
+ IoWrite8 ((UINTN) Address, *In.Uint8);
+ break;
+ case S3BootScriptWidthFifoUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
+ IoWrite8 ((UINTN) OriginalAddress, *In.Uint8);
+ break;
+ case S3BootScriptWidthFillUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
+ IoWrite8 ((UINTN) Address, *OriginalIn.Uint8);
+ break;
+ case S3BootScriptWidthUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
+ IoWrite16 ((UINTN) Address, *In.Uint16);
+ break;
+ case S3BootScriptWidthFifoUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
+ IoWrite16 ((UINTN) OriginalAddress, *In.Uint16);
+ break;
+ case S3BootScriptWidthFillUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
+ IoWrite16 ((UINTN) Address, *OriginalIn.Uint16);
+ break;
+ case S3BootScriptWidthUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
+ IoWrite32 ((UINTN) Address, *In.Uint32);
+ break;
+ case S3BootScriptWidthFifoUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
+ IoWrite32 ((UINTN) OriginalAddress, *In.Uint32);
+ break;
+ case S3BootScriptWidthFillUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
+ IoWrite32 ((UINTN) Address, *OriginalIn.Uint32);
+ break;
+ case S3BootScriptWidthUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
+ IoWrite64 ((UINTN) Address, *In.Uint64);
+ break;
+ case S3BootScriptWidthFifoUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
+ IoWrite64 ((UINTN) OriginalAddress, *In.Uint64);
+ break;
+ case S3BootScriptWidthFillUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
+ IoWrite64 ((UINTN) Address, *OriginalIn.Uint64);
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+
+ return EFI_SUCCESS;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_IO_WRITE OP code.
+
+ @param Script Pointer to the node which is to be interpreted.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ Address is outside the legal range of I/O ports.
+
+**/
+EFI_STATUS
+BootScriptExecuteIoWrite (
+ IN UINT8 *Script
+ )
+{
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ VOID *Buffer;
+ EFI_BOOT_SCRIPT_IO_WRITE IoWrite;
+
+ CopyMem ((VOID*)&IoWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));
+ Width = (S3_BOOT_SCRIPT_LIB_WIDTH) IoWrite.Width;
+ Address = IoWrite.Address;
+ Count = IoWrite.Count;
+ Buffer = Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE);
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteIoWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
+ return ScriptIoWrite(Width, Address, Count, Buffer);
+}
+/**
+ Perform memory read operation
+
+ @param Width Width of the operation.
+ @param Address Address of the operation.
+ @param Count Count of the number of accesses to perform.
+ @param Buffer Pointer to the buffer read from memory.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
+ is not valid for this EFI System.
+
+**/
+EFI_STATUS
+ScriptMemoryRead (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN AddressStride;
+ UINTN BufferStride;
+ PTR Out;
+
+ Out.Buf = Buffer;
+
+ Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Loop for each iteration and move the data
+ //
+ for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
+ switch (Width) {
+ case S3BootScriptWidthUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint8 = MmioRead8 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint8 = MmioRead8 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint8 = MmioRead8 ((UINTN) Address);
+ break;
+
+ case S3BootScriptWidthUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint16 = MmioRead16 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint16 = MmioRead16 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint16 = MmioRead16 ((UINTN) Address);
+ break;
+
+ case S3BootScriptWidthUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint32 = MmioRead32 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint32 = MmioRead32 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint32 = MmioRead32 ((UINTN) Address);
+ break;
+
+ case S3BootScriptWidthUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint64 = MmioRead64 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFifoUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint64 = MmioRead64 ((UINTN) Address);
+ break;
+ case S3BootScriptWidthFillUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN)Address));
+ *Out.Uint64 = MmioRead64 ((UINTN) Address);
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Perform memory write operation
+
+ @param Width Width of the operation.
+ @param Address Address of the operation.
+ @param Count Count of the number of accesses to perform.
+ @param Buffer Pointer to the buffer write to memory.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
+ is not valid for this EFI System.
+
+**/
+EFI_STATUS
+ScriptMemoryWrite (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN AddressStride;
+ UINT64 OriginalAddress;
+ UINTN BufferStride;
+ PTR In;
+ PTR OriginalIn;
+
+ In.Buf = Buffer;
+
+ Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Loop for each iteration and move the data
+ //
+ OriginalAddress = Address;
+ OriginalIn.Buf = In.Buf;
+ for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
+ switch (Width) {
+ case S3BootScriptWidthUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
+ MmioWrite8 ((UINTN) Address, *In.Uint8);
+ break;
+ case S3BootScriptWidthFifoUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
+ MmioWrite8 ((UINTN) OriginalAddress, *In.Uint8);
+ break;
+ case S3BootScriptWidthFillUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
+ MmioWrite8 ((UINTN) Address, *OriginalIn.Uint8);
+ break;
+ case S3BootScriptWidthUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
+ MmioWrite16 ((UINTN) Address, *In.Uint16);
+ break;
+ case S3BootScriptWidthFifoUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
+ MmioWrite16 ((UINTN) OriginalAddress, *In.Uint16);
+ break;
+ case S3BootScriptWidthFillUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
+ MmioWrite16 ((UINTN) Address, *OriginalIn.Uint16);
+ break;
+ case S3BootScriptWidthUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
+ MmioWrite32 ((UINTN) Address, *In.Uint32);
+ break;
+ case S3BootScriptWidthFifoUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
+ MmioWrite32 ((UINTN) OriginalAddress, *In.Uint32);
+ break;
+ case S3BootScriptWidthFillUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
+ MmioWrite32 ((UINTN) Address, *OriginalIn.Uint32);
+ break;
+ case S3BootScriptWidthUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
+ MmioWrite64 ((UINTN) Address, *In.Uint64);
+ break;
+ case S3BootScriptWidthFifoUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
+ MmioWrite64 ((UINTN) OriginalAddress, *In.Uint64);
+ break;
+ case S3BootScriptWidthFillUint64:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
+ MmioWrite64 ((UINTN) Address, *OriginalIn.Uint64);
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_MEM_WRITE OP code.
+
+ @param[in] Script Pointer to the node which is to be interpreted.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
+ is not valid for this EFI System.
+
+**/
+EFI_STATUS
+BootScriptExecuteMemoryWrite (
+ IN UINT8 *Script
+ )
+{
+ VOID *Buffer;
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ EFI_BOOT_SCRIPT_MEM_WRITE MemWrite;
+
+ CopyMem((VOID*)&MemWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));
+ Width = (S3_BOOT_SCRIPT_LIB_WIDTH)MemWrite.Width;
+ Address = MemWrite.Address;
+ Count = MemWrite.Count;
+ Buffer = Script + sizeof(EFI_BOOT_SCRIPT_MEM_WRITE);
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
+ return ScriptMemoryWrite (Width,Address, Count, Buffer);
+
+}
+/**
+ Performance PCI configuration 2 read operation
+
+ @param Width Width of the operation.
+ @param Segment Pci segment number
+ @param Address Address of the operation.
+ @param Count Count of the number of accesses to perform.
+ @param Buffer Pointer to the buffer read from PCI config space
+
+ @retval EFI_SUCCESS The read succeed.
+ @retval EFI_INVALID_PARAMETER if Width is not defined
+ @note A known Limitations in the implementation which is 64bits operations are not supported.
+
+**/
+EFI_STATUS
+ScriptPciCfg2Read (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT16 Segment,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN AddressStride;
+ UINTN BufferStride;
+ PTR Out;
+ UINT64 PciAddress;
+
+ Out.Buf = (UINT8 *) Buffer;
+
+ PciAddress = PCI_ADDRESS_ENCODE (Segment, Address);
+
+ Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Loop for each iteration and move the data
+ //
+ for (; Count > 0; Count--, PciAddress += AddressStride, Out.Buf += BufferStride) {
+ switch (Width) {
+ case S3BootScriptWidthUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%016lx\n", PciAddress));
+ *Out.Uint8 = PciSegmentRead8 (PciAddress);
+ break;
+ case S3BootScriptWidthFifoUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%016lx\n", PciAddress));
+ *Out.Uint8 = PciSegmentRead8 (PciAddress);
+ break;
+ case S3BootScriptWidthFillUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%016lx\n", PciAddress));
+ *Out.Uint8 = PciSegmentRead8 (PciAddress);
+ break;
+
+ case S3BootScriptWidthUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%016lx\n", PciAddress));
+ *Out.Uint16 = PciSegmentRead16 (PciAddress);
+ break;
+ case S3BootScriptWidthFifoUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%016lx\n", PciAddress));
+ *Out.Uint16 = PciSegmentRead16 (PciAddress);
+ break;
+ case S3BootScriptWidthFillUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%016lx\n", PciAddress));
+ *Out.Uint16 = PciSegmentRead16 (PciAddress);
+ break;
+
+ case S3BootScriptWidthUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%016lx\n", PciAddress));
+ *Out.Uint32 = PciSegmentRead32 (PciAddress);
+ break;
+ case S3BootScriptWidthFifoUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%016lx\n", PciAddress));
+ *Out.Uint32 = PciSegmentRead32 (PciAddress);
+ break;
+ case S3BootScriptWidthFillUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%016lx\n", PciAddress));
+ *Out.Uint32 = PciSegmentRead32 (PciAddress);
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Performance PCI configuration 2 write operation
+
+ @param Width Width of the operation.
+ @param Segment Pci segment number
+ @param Address Address of the operation.
+ @param Count Count of the number of accesses to perform.
+ @param Buffer Pointer to the buffer write to PCI config space
+
+ @retval EFI_SUCCESS The write succeed.
+ @retval EFI_INVALID_PARAMETER if Width is not defined
+ @note A known Limitations in the implementation which is 64bits operations are not supported.
+
+**/
+EFI_STATUS
+ScriptPciCfg2Write (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT16 Segment,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN AddressStride;
+ UINTN BufferStride;
+ UINT64 OriginalPciAddress;
+ PTR In;
+ PTR OriginalIn;
+ UINT64 PciAddress;
+
+ In.Buf = (UINT8 *) Buffer;
+
+ PciAddress = PCI_ADDRESS_ENCODE (Segment, Address);
+
+ Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Loop for each iteration and move the data
+ //
+ OriginalPciAddress = PciAddress;
+ OriginalIn.Buf = In.Buf;
+ for (; Count > 0; Count--, PciAddress += AddressStride, In.Buf += BufferStride) {
+ switch (Width) {
+ case S3BootScriptWidthUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%016lx (0x%02x)\n", PciAddress, (UINTN)*In.Uint8));
+ PciSegmentWrite8 (PciAddress, *In.Uint8);
+ break;
+ case S3BootScriptWidthFifoUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%016lx (0x%02x)\n", OriginalPciAddress, (UINTN)*In.Uint8));
+ PciSegmentWrite8 (OriginalPciAddress, *In.Uint8);
+ break;
+ case S3BootScriptWidthFillUint8:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%016lx (0x%02x)\n", PciAddress, (UINTN)*OriginalIn.Uint8));
+ PciSegmentWrite8 (PciAddress, *OriginalIn.Uint8);
+ break;
+ case S3BootScriptWidthUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%016lx (0x%04x)\n", PciAddress, (UINTN)*In.Uint16));
+ PciSegmentWrite16 (PciAddress, *In.Uint16);
+ break;
+ case S3BootScriptWidthFifoUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%016lx (0x%04x)\n", OriginalPciAddress, (UINTN)*In.Uint16));
+ PciSegmentWrite16 (OriginalPciAddress, *In.Uint16);
+ break;
+ case S3BootScriptWidthFillUint16:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%016lx (0x%04x)\n", PciAddress, (UINTN)*OriginalIn.Uint16));
+ PciSegmentWrite16 (PciAddress, *OriginalIn.Uint16);
+ break;
+ case S3BootScriptWidthUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%016lx (0x%08x)\n", PciAddress, (UINTN)*In.Uint32));
+ PciSegmentWrite32 (PciAddress, *In.Uint32);
+ break;
+ case S3BootScriptWidthFifoUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%016lx (0x%08x)\n", OriginalPciAddress, (UINTN)*In.Uint32));
+ PciSegmentWrite32 (OriginalPciAddress, *In.Uint32);
+ break;
+ case S3BootScriptWidthFillUint32:
+ DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%016lx (0x%08x)\n", (UINTN)PciAddress, (UINTN)*OriginalIn.Uint32));
+ PciSegmentWrite32 (PciAddress, *OriginalIn.Uint32);
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ return EFI_SUCCESS;
+}
+/**
+ Performance PCI configuration read operation
+
+ @param Width Width of the operation.
+ @param Address Address of the operation.
+ @param Count Count of the number of accesses to perform.
+ @param Buffer Pointer to the buffer to read from PCI config space.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ Address is outside the legal range of I/O ports.
+
+**/
+EFI_STATUS
+ScriptPciCfgRead (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return ScriptPciCfg2Read (Width, 0, Address, Count, Buffer);
+}
+/**
+ Performance PCI configuration write operation
+
+ @param Width Width of the operation.
+ @param Address Address of the operation.
+ @param Count Count of the number of accesses to perform.
+ @param Buffer Pointer to the buffer to write to PCI config space.
+
+ @retval EFI_SUCCESS The data was written to the EFI System.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
+ Buffer is NULL.
+ The Buffer is not aligned for the given Width.
+ Address is outside the legal range of I/O ports.
+
+**/
+EFI_STATUS
+EFIAPI
+ScriptPciCfgWrite (
+ IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return ScriptPciCfg2Write (Width, 0, Address, Count, Buffer);
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE OP code.
+
+ @param Script The pointer of typed node in boot script table
+
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecutePciCfgWrite (
+ IN UINT8 *Script
+ )
+{
+ VOID *Buffer;
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE PciCfgWrite;
+
+ CopyMem ((VOID*)&PciCfgWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
+
+ Width = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfgWrite.Width;
+ Address = PciCfgWrite.Address;
+ Count = PciCfgWrite.Count;
+ Buffer = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE);
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgWrite - 0x%016lx, 0x%08x, 0x%08x\n", PCI_ADDRESS_ENCODE (0, Address), Count, (UINTN)Width));
+ return ScriptPciCfgWrite (Width, Address, Count, Buffer);
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_IO_READ_WRITE OP code.
+
+ @param Script The pointer of typed node in boot script table
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecuteIoReadWrite (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+
+{
+ EFI_STATUS Status;
+ UINT64 Data;
+ EFI_BOOT_SCRIPT_IO_READ_WRITE IoReadWrite;
+
+ Data = 0;
+
+ CopyMem((VOID*)&IoReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteIoReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoReadWrite.Address, AndMask, OrMask));
+
+ Status = ScriptIoRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
+ IoReadWrite.Address,
+ 1,
+ &Data
+ );
+ if (!EFI_ERROR (Status)) {
+ Data = (Data & AndMask) | OrMask;
+ Status = ScriptIoWrite (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
+ IoReadWrite.Address,
+ 1,
+ &Data
+ );
+ }
+ return Status;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_MEM_READ_WRITE OP code.
+
+ @param Script The pointer of typed node in boot script table
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecuteMemoryReadWrite (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+
+{
+ EFI_STATUS Status;
+ UINT64 Data;
+ EFI_BOOT_SCRIPT_MEM_READ_WRITE MemReadWrite;
+
+ Data = 0;
+
+ CopyMem((VOID*)&MemReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_READ_WRITE));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemReadWrite.Address, AndMask, OrMask));
+
+ Status = ScriptMemoryRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
+ MemReadWrite.Address,
+ 1,
+ &Data
+ );
+ if (!EFI_ERROR (Status)) {
+ Data = (Data & AndMask) | OrMask;
+ Status = ScriptMemoryWrite (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
+ MemReadWrite.Address,
+ 1,
+ &Data
+ );
+ }
+ return Status;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CFG_READ_WRITE OP code.
+
+ @param Script The pointer of typed node in boot script table
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecutePciCfgReadWrite (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+
+{
+ EFI_STATUS Status;
+ UINT64 Data;
+ EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE PciCfgReadWrite;
+
+ Data = 0;
+
+ CopyMem((VOID*)&PciCfgReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgReadWrite - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (0, PciCfgReadWrite.Address), AndMask, OrMask));
+
+ Status = ScriptPciCfgRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
+ PciCfgReadWrite.Address,
+ 1,
+ &Data
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Data = (Data & AndMask) | OrMask;
+
+ Status = ScriptPciCfgWrite (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
+ PciCfgReadWrite.Address,
+ 1,
+ &Data
+ );
+
+ return Status;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
+
+ @param Script The pointer of typed node in boot script table
+
+ @retval EFI_SUCCESS The operation was executed successfully
+ @retval EFI_UNSUPPORTED Cannot locate smbus ppi or occur error of script execution
+ @retval Others Result of script execution
+**/
+EFI_STATUS
+BootScriptExecuteSmbusExecute (
+ IN UINT8 *Script
+ )
+{
+ UINTN SmBusAddress;
+ UINTN DataSize;
+ EFI_BOOT_SCRIPT_SMBUS_EXECUTE SmbusExecuteEntry;
+
+ CopyMem ((VOID*)&SmbusExecuteEntry, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_SMBUS_EXECUTE ));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteSmbusExecute - 0x%08x, 0x%08x\n", (UINTN)SmbusExecuteEntry.SmBusAddress, (UINTN)SmbusExecuteEntry.Operation));
+
+ SmBusAddress = (UINTN)SmbusExecuteEntry.SmBusAddress;
+ DataSize = (UINTN) SmbusExecuteEntry.DataSize;
+ return InternalSmbusExecute (
+ SmBusAddress,
+ (EFI_SMBUS_OPERATION) SmbusExecuteEntry.Operation,
+ &DataSize,
+ Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)
+ );
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
+
+ @param Script The pointer of typed node in boot script table
+
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecuteStall (
+ IN UINT8 *Script
+ )
+{
+ EFI_BOOT_SCRIPT_STALL Stall;
+
+ CopyMem ((VOID*)&Stall, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_STALL));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteStall - 0x%08x\n", (UINTN)Stall.Duration));
+
+ MicroSecondDelay ((UINTN) Stall.Duration);
+ return EFI_SUCCESS;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
+
+ @param Script The pointer of typed node in boot script table
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecuteDispatch (
+ IN UINT8 *Script
+ )
+{
+ EFI_STATUS Status;
+ DISPATCH_ENTRYPOINT_FUNC EntryFunc;
+ EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch;
+
+ CopyMem ((VOID*)&ScriptDispatch, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH));
+ EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch.EntryPoint);
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch - 0x%08x\n", (UINTN)ScriptDispatch.EntryPoint));
+
+ Status = EntryFunc (NULL, NULL);
+
+ return Status;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
+
+ @param Script The pointer of typed node in boot script table
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecuteDispatch2 (
+ IN UINT8 *Script
+ )
+{
+ EFI_STATUS Status;
+ DISPATCH_ENTRYPOINT_FUNC EntryFunc;
+ EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2;
+
+ CopyMem ((VOID*)&ScriptDispatch2, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH_2));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch2 - 0x%08x(0x%08x)\n", (UINTN)ScriptDispatch2.EntryPoint, (UINTN)ScriptDispatch2.Context));
+
+ EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch2.EntryPoint);
+
+ Status = EntryFunc (NULL, (VOID *) (UINTN) ScriptDispatch2.Context);
+
+ return Status;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
+
+ @param Script The pointer of typed node in boot script table
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
+ the epecting data within the Loop Times.
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecuteMemPoll (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+{
+
+ UINT64 Data;
+ UINT64 LoopTimes;
+ EFI_STATUS Status;
+ EFI_BOOT_SCRIPT_MEM_POLL MemPoll;
+
+ CopyMem ((VOID*)&MemPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_POLL));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteMemPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemPoll.Address, AndMask, OrMask));
+
+ Data = 0;
+ Status = ScriptMemoryRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
+ MemPoll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+
+ for (LoopTimes = 0; LoopTimes < MemPoll.LoopTimes; LoopTimes++) {
+ MicroSecondDelay ((UINTN)MemPoll.Duration);
+
+ Data = 0;
+ Status = ScriptMemoryRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
+ MemPoll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (LoopTimes < MemPoll.LoopTimes) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+}
+/**
+ Execute the boot script to interpret the Store arbitrary information.
+ This opcode is a no-op on dispatch and is only used for debugging script issues.
+
+ @param Script The pointer of node in boot script table
+
+**/
+VOID
+BootScriptExecuteInformation (
+ IN UINT8 *Script
+ )
+
+{
+ UINT32 Index;
+ EFI_BOOT_SCRIPT_INFORMATION Information;
+ UINT8 *InformationData;
+
+ CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
+
+ InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN) InformationData));
+
+ DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
+ for (Index = 0; Index < Information.InformationLength; Index++) {
+ DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+}
+
+/**
+ Execute the boot script to interpret the Label information.
+
+ @param Script The pointer of node in boot script table
+
+**/
+VOID
+BootScriptExecuteLabel (
+ IN UINT8 *Script
+ )
+
+{
+ UINT32 Index;
+ EFI_BOOT_SCRIPT_INFORMATION Information;
+ UINT8 *InformationData;
+
+ CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
+
+ InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteLabel - 0x%08x\n", (UINTN) InformationData));
+
+ DEBUG ((EFI_D_INFO, "BootScriptLabel: "));
+ for (Index = 0; Index < Information.InformationLength; Index++) {
+ DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+}
+
+/**
+ calculate the mask value for 'and' and 'or' operation
+ @param ScriptHeader The pointer of header of node in boot script table
+ @param AndMask The Mask value for 'and' operation
+ @param OrMask The Mask value for 'or' operation
+ @param Script Pointer to the entry.
+
+**/
+VOID
+CheckAndOrMask (
+ IN EFI_BOOT_SCRIPT_COMMON_HEADER *ScriptHeader,
+ OUT UINT64 *AndMask,
+ OUT UINT64 *OrMask,
+ IN UINT8 *Script
+ )
+{
+ UINT8 *DataPtr;
+ UINTN Size;
+
+ switch (ScriptHeader->OpCode) {
+ case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE);
+ break;
+ case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_MEM_POLL);
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_IO_POLL);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
+ Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL);
+ break;
+
+ default:
+ return;
+ }
+
+ DataPtr = Script + Size;
+
+ switch (ScriptHeader->Width) {
+ case S3BootScriptWidthUint8:
+ *AndMask = (UINT64) (*(UINT8*) (DataPtr + 1));
+ *OrMask = (UINT64) (*DataPtr);
+ break;
+
+ case S3BootScriptWidthUint16:
+ *AndMask = (UINT64) (*(UINT16 *) (DataPtr + 2));
+ *OrMask = (UINT64) (*(UINT16 *) DataPtr);
+ break;
+
+ case S3BootScriptWidthUint32:
+ *AndMask = (UINT64) (*(UINT32 *) (DataPtr + 4));
+ *OrMask = (UINT64) (*(UINT32 *) DataPtr);
+ break;
+
+ case S3BootScriptWidthUint64:
+ *AndMask = (UINT64) (*(UINT64 *) (DataPtr + 8));
+ *OrMask = (UINT64) (*(UINT64 *) DataPtr);
+ break;
+
+ default:
+ break;
+ }
+
+ return;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
+
+ @param Script The pointer of typed node in boot script table
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
+ the epecting data within the Loop Times.
+ @retval EFI_SUCCESS The operation was executed successfully
+**/
+EFI_STATUS
+BootScriptExecuteIoPoll (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Data;
+ UINT64 LoopTimes;
+ EFI_BOOT_SCRIPT_IO_POLL IoPoll;
+
+ CopyMem ((VOID*)&IoPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_POLL));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteIoPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoPoll.Address, AndMask, OrMask));
+
+ Data = 0;
+ Status = ScriptIoRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
+ IoPoll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+ for (LoopTimes = 0; LoopTimes < IoPoll.Delay; LoopTimes++) {
+ NanoSecondDelay (100);
+ Data = 0;
+ Status = ScriptIoRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
+ IoPoll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (LoopTimes < IoPoll.Delay) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
+
+ @param Script The pointer of S3 boot script
+
+ @retval EFI_SUCCESS The operation was executed successfully
+
+**/
+EFI_STATUS
+BootScriptExecutePciCfg2Write (
+ IN UINT8 *Script
+ )
+{
+ VOID *Buffer;
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT16 Segment;
+ UINT64 Address;
+ UINTN Count;
+ EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE PciCfg2Write;
+
+ CopyMem ((VOID*)&PciCfg2Write, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
+
+ Width = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfg2Write.Width;
+ Segment = PciCfg2Write.Segment;
+ Address = PciCfg2Write.Address;
+ Count = PciCfg2Write.Count;
+ Buffer = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE);
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2Write - 0x%016lx, 0x%08x, 0x%08x\n", PCI_ADDRESS_ENCODE (Segment, Address), Count, (UINTN)Width));
+ return ScriptPciCfg2Write (Width, Segment, Address, Count, Buffer);
+}
+
+
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
+
+ @param Script The pointer of S3 boot script
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_SUCCESS The operation was executed successfully
+
+**/
+EFI_STATUS
+BootScriptExecutePciCfg2ReadWrite (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+{
+ UINT64 Data;
+ EFI_STATUS Status;
+ EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE PciCfg2ReadWrite;
+
+ Data = 0;
+
+ CopyMem ((VOID*)&PciCfg2ReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2ReadWrite - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfg2ReadWrite.Segment, PciCfg2ReadWrite.Address), AndMask, OrMask));
+
+ Status = ScriptPciCfg2Read (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
+ PciCfg2ReadWrite.Segment,
+ PciCfg2ReadWrite.Address,
+ 1,
+ &Data
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Data = (Data & AndMask) | OrMask;
+ Status = ScriptPciCfg2Write (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
+ PciCfg2ReadWrite.Segment,
+ PciCfg2ReadWrite.Address,
+ 1,
+ &Data
+ );
+ return Status;
+}
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
+
+ @param Script The pointer of S3 boot script
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_SUCCESS The operation was executed successfully
+ @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
+ epecting data within the Loop Times.
+**/
+EFI_STATUS
+BootScriptPciCfgPoll (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+{
+ UINT64 Data;
+ UINT64 LoopTimes;
+ EFI_STATUS Status;
+ EFI_BOOT_SCRIPT_PCI_CONFIG_POLL PciCfgPoll;
+ CopyMem ((VOID*)&PciCfgPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
+
+ DEBUG ((EFI_D_INFO, "BootScriptPciCfgPoll - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (0, PciCfgPoll.Address), AndMask, OrMask));
+
+ Data = 0;
+ Status = ScriptPciCfgRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
+ PciCfgPoll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+
+ for (LoopTimes = 0; LoopTimes < PciCfgPoll.Delay; LoopTimes++) {
+ NanoSecondDelay (100);
+ Data = 0;
+ Status = ScriptPciCfgRead (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
+ PciCfgPoll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) &&
+ (Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (LoopTimes < PciCfgPoll.Delay) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+/**
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
+
+ @param Script The pointer of S3 Boot Script
+ @param AndMask Mask value for 'and' operation
+ @param OrMask Mask value for 'or' operation
+
+ @retval EFI_SUCCESS The operation was executed successfully
+ @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
+ epecting data within the Loop Times.
+
+**/
+EFI_STATUS
+BootScriptPciCfg2Poll (
+ IN UINT8 *Script,
+ IN UINT64 AndMask,
+ IN UINT64 OrMask
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Data;
+ UINT64 LoopTimes;
+ EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL PciCfg2Poll;
+
+ Data = 0;
+ CopyMem ((VOID*)&PciCfg2Poll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
+
+ DEBUG ((EFI_D_INFO, "BootScriptPciCfg2Poll - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfg2Poll.Segment, PciCfg2Poll.Address), AndMask, OrMask));
+
+ Status = ScriptPciCfg2Read (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
+ PciCfg2Poll.Segment,
+ PciCfg2Poll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+
+ for (LoopTimes = 0; LoopTimes < PciCfg2Poll.Delay; LoopTimes++) {
+ NanoSecondDelay (100);
+
+ Data = 0;
+ Status = ScriptPciCfg2Read (
+ (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
+ PciCfg2Poll.Segment,
+ PciCfg2Poll.Address,
+ 1,
+ &Data
+ );
+ if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (LoopTimes < PciCfg2Poll.Delay) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+
+}
+
+/**
+ Executes the S3 boot script table.
+
+ @retval RETURN_SUCCESS The boot script table was executed successfully.
+ @retval RETURN_UNSUPPORTED Invalid script table or opcode.
+
+**/
+RETURN_STATUS
+EFIAPI
+S3BootScriptExecute (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT8* Script;
+ UINTN StartAddress;
+ UINT32 TableLength;
+ UINT64 AndMask;
+ UINT64 OrMask;
+ EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
+ EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
+ Script = mS3BootScriptTablePtr->TableBase;
+ if (Script != 0) {
+ CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((EFI_D_INFO, "S3BootScriptExecute:\n"));
+ if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "TableHeader - 0x%08x\n", Script));
+
+ StartAddress = (UINTN) Script;
+ TableLength = TableHeader.TableLength;
+ Script = Script + TableHeader.Length;
+ Status = EFI_SUCCESS;
+ AndMask = 0;
+ OrMask = 0;
+
+ DEBUG ((EFI_D_INFO, "TableHeader.Version - 0x%04x\n", (UINTN)TableHeader.Version));
+ DEBUG ((EFI_D_INFO, "TableHeader.TableLength - 0x%08x\n", (UINTN)TableLength));
+
+ while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
+ DEBUG ((EFI_D_INFO, "ExecuteBootScript - %08x\n", (UINTN)Script));
+
+ CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
+ switch (ScriptHeader.OpCode) {
+
+ case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE\n"));
+ Status = BootScriptExecuteMemoryWrite (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptExecuteMemoryReadWrite (
+ Script,
+ AndMask,
+ OrMask
+ );
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_WRITE_OPCODE\n"));
+ Status = BootScriptExecuteIoWrite (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE\n"));
+ Status = BootScriptExecutePciCfgWrite (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptExecutePciCfgReadWrite (
+ Script,
+ AndMask,
+ OrMask
+ );
+ break;
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\n"));
+ Status = BootScriptExecutePciCfg2Write (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptExecutePciCfg2ReadWrite (
+ Script,
+ AndMask,
+ OrMask
+ );
+ break;
+ case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_OPCODE\n"));
+ Status = BootScriptExecuteDispatch (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE\n"));
+ Status = BootScriptExecuteDispatch2 (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_INFORMATION_OPCODE\n"));
+ BootScriptExecuteInformation (Script);
+ break;
+
+ case S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE:
+ DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE\n"));
+ DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_SUCCESS));
+ return EFI_SUCCESS;
+
+ case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptExecuteIoReadWrite (
+ Script,
+ AndMask,
+ OrMask
+ );
+ break;
+
+ case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE\n"));
+ Status = BootScriptExecuteSmbusExecute (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_STALL_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_STALL_OPCODE\n"));
+ Status = BootScriptExecuteStall (Script);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_POLL_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptExecuteMemPoll (Script, AndMask, OrMask);
+
+ break;
+
+ case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_POLL_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptExecuteIoPoll (Script, AndMask, OrMask);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptPciCfgPoll (Script, AndMask, OrMask);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
+ DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE\n"));
+ CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
+ Status = BootScriptPciCfg2Poll (Script, AndMask, OrMask);
+ break;
+
+ case S3_BOOT_SCRIPT_LIB_LABEL_OPCODE:
+ //
+ // For label
+ //
+ DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_LABEL_OPCODE\n"));
+ BootScriptExecuteLabel (Script);
+ break;
+ default:
+ DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_UNSUPPORTED));
+ return EFI_UNSUPPORTED;
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
+ return Status;
+ }
+
+ Script = Script + ScriptHeader.Length;
+ }
+
+ DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
+
+ return Status;
+}
+