Home | History | Annotate | Download | only in PiDxeS3BootScriptLib
      1 /** @file
      2   Interpret and execute the S3 data in S3 boot script.
      3 
      4   Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions
      8   of the BSD License which accompanies this distribution.  The
      9   full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 #include "InternalBootScriptLib.h"
     17 
     18 /**
     19   Executes an SMBus operation to an SMBus controller. Returns when either the command has been
     20   executed or an error is encountered in doing the operation.
     21 
     22   The SmbusExecute() function provides a standard way to execute an operation as defined in the System
     23   Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus
     24   slave devices accept this transaction or that this function returns with error.
     25 
     26   @param  SmbusAddress            Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
     27                                   and PEC.
     28   @param  Operation               Signifies which particular SMBus hardware protocol instance that
     29                                   it will use to execute the SMBus transactions. This SMBus
     30                                   hardware protocol is defined by the SMBus Specification and is
     31                                   not related to EFI.
     32   @param  Length                  Signifies the number of bytes that this operation will do. The
     33                                   maximum number of bytes can be revision specific and operation
     34                                   specific. This field will contain the actual number of bytes that
     35                                   are executed for this operation. Not all operations require this
     36                                   argument.
     37   @param  Buffer                  Contains the value of data to execute to the SMBus slave device.
     38                                   Not all operations require this argument. The length of this
     39                                   buffer is identified by Length.
     40 
     41   @retval EFI_SUCCESS             The last data that was returned from the access matched the poll
     42                                   exit criteria.
     43   @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
     44   @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is
     45                                   determined by the SMBus host controller device.
     46   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
     47   @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was
     48                                   reflected in the Host Status Register bit. Device errors are a
     49                                   result of a transaction collision, illegal command field,
     50                                   unclaimed cycle (host initiated), or bus errors (collisions).
     51   @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.
     52   @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead
     53                                   and EfiSmbusQuickWrite. Length is outside the range of valid
     54                                   values.
     55   @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
     56   @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
     57 
     58 **/
     59 EFI_STATUS
     60 SmbusExecute (
     61   IN     UINTN                    SmbusAddress,
     62   IN     EFI_SMBUS_OPERATION      Operation,
     63   IN OUT UINTN                    *Length,
     64   IN OUT VOID                     *Buffer
     65   )
     66 {
     67   EFI_STATUS                      Status;
     68   UINT8                           WorkBuffer[MAX_SMBUS_BLOCK_LEN];
     69 
     70   switch (Operation) {
     71     case EfiSmbusQuickRead:
     72       DEBUG ((EFI_D_INFO, "EfiSmbusQuickRead - 0x%08x\n", SmbusAddress));
     73       SmBusQuickRead (SmbusAddress, &Status);
     74       break;
     75     case EfiSmbusQuickWrite:
     76       DEBUG ((EFI_D_INFO, "EfiSmbusQuickWrite - 0x%08x\n", SmbusAddress));
     77       SmBusQuickWrite (SmbusAddress, &Status);
     78       break;
     79     case EfiSmbusReceiveByte:
     80       DEBUG ((EFI_D_INFO, "EfiSmbusReceiveByte - 0x%08x\n", SmbusAddress));
     81       SmBusReceiveByte (SmbusAddress, &Status);
     82       break;
     83     case EfiSmbusSendByte:
     84       DEBUG ((EFI_D_INFO, "EfiSmbusSendByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
     85       SmBusSendByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
     86       break;
     87     case EfiSmbusReadByte:
     88       DEBUG ((EFI_D_INFO, "EfiSmbusReadByte - 0x%08x\n", SmbusAddress));
     89       SmBusReadDataByte (SmbusAddress, &Status);
     90       break;
     91     case EfiSmbusWriteByte:
     92       DEBUG ((EFI_D_INFO, "EfiSmbusWriteByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
     93       SmBusWriteDataByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
     94       break;
     95     case EfiSmbusReadWord:
     96       DEBUG ((EFI_D_INFO, "EfiSmbusReadWord - 0x%08x\n", SmbusAddress));
     97       SmBusReadDataWord (SmbusAddress, &Status);
     98       break;
     99     case EfiSmbusWriteWord:
    100       DEBUG ((EFI_D_INFO, "EfiSmbusWriteWord - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
    101       SmBusWriteDataWord (SmbusAddress, *(UINT16 *) Buffer, &Status);
    102       break;
    103     case EfiSmbusProcessCall:
    104       DEBUG ((EFI_D_INFO, "EfiSmbusProcessCall - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
    105       SmBusProcessCall (SmbusAddress, *(UINT16 *) Buffer, &Status);
    106       break;
    107     case EfiSmbusReadBlock:
    108       DEBUG ((EFI_D_INFO, "EfiSmbusReadBlock - 0x%08x\n", SmbusAddress));
    109       SmBusReadBlock (SmbusAddress, WorkBuffer, &Status);
    110       break;
    111     case EfiSmbusWriteBlock:
    112       DEBUG ((EFI_D_INFO, "EfiSmbusWriteBlock - 0x%08x\n", SmbusAddress));
    113       SmBusWriteBlock ((SmbusAddress + SMBUS_LIB_ADDRESS (0, 0, (*Length), FALSE)), Buffer, &Status);
    114       break;
    115     case EfiSmbusBWBRProcessCall:
    116       DEBUG ((EFI_D_INFO, "EfiSmbusBWBRProcessCall - 0x%08x\n", SmbusAddress));
    117       SmBusBlockProcessCall ((SmbusAddress + SMBUS_LIB_ADDRESS (0, 0, (*Length), FALSE)), Buffer, WorkBuffer, &Status);
    118       break;
    119     default:
    120       return EFI_INVALID_PARAMETER;
    121   }
    122 
    123   return Status;
    124 }
    125 
    126 /**
    127   Translates boot script width and address stride to MDE library interface.
    128 
    129 
    130   @param Width          Width of the operation.
    131   @param Address        Address of the operation.
    132   @param AddressStride  Instride for stepping input buffer.
    133   @param BufferStride   Outstride for stepping output buffer.
    134 
    135   @retval EFI_SUCCESS  Successful translation.
    136   @retval EFI_INVALID_PARAMETER Width or Address is invalid.
    137 **/
    138 EFI_STATUS
    139 BuildLoopData (
    140   IN  S3_BOOT_SCRIPT_LIB_WIDTH      Width,
    141   IN  UINT64                    Address,
    142   OUT UINTN                     *AddressStride,
    143   OUT UINTN                     *BufferStride
    144   )
    145 {
    146   UINTN AlignMask;
    147 
    148   if (Width >= S3BootScriptWidthMaximum) {
    149     return EFI_INVALID_PARAMETER;
    150   }
    151 
    152   *AddressStride  = (UINT32)(1 << (Width & 0x03));
    153   *BufferStride   = *AddressStride;
    154 
    155   AlignMask       = *AddressStride - 1;
    156   if ((Address & AlignMask) != 0) {
    157     return EFI_INVALID_PARAMETER;
    158   }
    159 
    160   if (Width >= S3BootScriptWidthFifoUint8 && Width <= S3BootScriptWidthFifoUint64) {
    161     *AddressStride = 0;
    162   }
    163 
    164   if (Width >= S3BootScriptWidthFillUint8 && Width <= S3BootScriptWidthFillUint64) {
    165     *BufferStride = 0;
    166   }
    167 
    168   return EFI_SUCCESS;
    169 }
    170 
    171 /**
    172   Perform IO read operation
    173 
    174   @param[in]  Width   Width of the operation.
    175   @param[in]  Address Address of the operation.
    176   @param[in]  Count   Count of the number of accesses to perform.
    177   @param[out] Buffer  Pointer to the buffer to read from I/O space.
    178 
    179   @retval EFI_SUCCESS The data was written to the EFI System.
    180   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
    181                                 Buffer is NULL.
    182                                 The Buffer is not aligned for the given Width.
    183                                 Address is outside the legal range of I/O ports.
    184 
    185 **/
    186 EFI_STATUS
    187 ScriptIoRead (
    188   IN      S3_BOOT_SCRIPT_LIB_WIDTH Width,
    189   IN      UINT64                   Address,
    190   IN      UINTN                    Count,
    191   OUT     VOID                     *Buffer
    192   )
    193 {
    194   EFI_STATUS  Status;
    195   UINTN       AddressStride;
    196   UINTN       BufferStride;
    197   PTR         Out;
    198 
    199   Out.Buf = (UINT8 *) Buffer;
    200 
    201   if (Address > MAX_IO_ADDRESS) {
    202     return EFI_INVALID_PARAMETER;
    203   }
    204 
    205   Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
    206   if (EFI_ERROR (Status)) {
    207     return Status;
    208   }
    209   //
    210   // Loop for each iteration and move the data
    211   //
    212   for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
    213     switch (Width) {
    214 
    215     case S3BootScriptWidthUint8:
    216       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN) Address));
    217       *Out.Uint8 = IoRead8 ((UINTN) Address);
    218       break;
    219     case S3BootScriptWidthFifoUint8:
    220       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN) Address));
    221       *Out.Uint8 = IoRead8 ((UINTN) Address);
    222       break;
    223     case S3BootScriptWidthFillUint8:
    224       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN) Address));
    225       *Out.Uint8 = IoRead8 ((UINTN) Address);
    226       break;
    227 
    228     case S3BootScriptWidthUint16:
    229       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN) Address));
    230       *Out.Uint16 = IoRead16 ((UINTN) Address);
    231       break;
    232     case S3BootScriptWidthFifoUint16:
    233       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN) Address));
    234       *Out.Uint16 = IoRead16 ((UINTN) Address);
    235       break;
    236     case S3BootScriptWidthFillUint16:
    237       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN) Address));
    238       *Out.Uint16 = IoRead16 ((UINTN) Address);
    239       break;
    240 
    241     case S3BootScriptWidthUint32:
    242       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN) Address));
    243       *Out.Uint32 = IoRead32 ((UINTN) Address);
    244       break;
    245     case S3BootScriptWidthFifoUint32:
    246       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN) Address));
    247       *Out.Uint32 = IoRead32 ((UINTN) Address);
    248       break;
    249     case S3BootScriptWidthFillUint32:
    250       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN) Address));
    251       *Out.Uint32 = IoRead32 ((UINTN) Address);
    252       break;
    253 
    254     case S3BootScriptWidthUint64:
    255       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN) Address));
    256       *Out.Uint64 = IoRead64 ((UINTN) Address);
    257       break;
    258     case S3BootScriptWidthFifoUint64:
    259       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN) Address));
    260       *Out.Uint64 = IoRead64 ((UINTN) Address);
    261       break;
    262     case S3BootScriptWidthFillUint64:
    263       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN) Address));
    264       *Out.Uint64 = IoRead64 ((UINTN) Address);
    265       break;
    266 
    267     default:
    268       return EFI_INVALID_PARAMETER;
    269     }
    270   }
    271 
    272   return EFI_SUCCESS;
    273 }
    274 
    275 /**
    276   Perform IO write operation
    277 
    278   @param[in]  Width Width of the operation.
    279   @param[in]  Address Address of the operation.
    280   @param[in]  Count Count of the number of accesses to perform.
    281   @param[in]  Buffer Pointer to the buffer to write to I/O space.
    282 
    283   @retval EFI_SUCCESS The data was written to the EFI System.
    284   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
    285                                 Buffer is NULL.
    286                                 The Buffer is not aligned for the given Width.
    287                                 Address is outside the legal range of I/O ports.
    288 
    289 **/
    290 EFI_STATUS
    291 ScriptIoWrite (
    292   IN      S3_BOOT_SCRIPT_LIB_WIDTH  Width,
    293   IN      UINT64                 Address,
    294   IN      UINTN                  Count,
    295   IN      VOID                   *Buffer
    296   )
    297 {
    298   EFI_STATUS  Status;
    299   UINTN       AddressStride;
    300   UINTN       BufferStride;
    301   UINT64      OriginalAddress;
    302   PTR         In;
    303   PTR         OriginalIn;
    304 
    305   In.Buf = (UINT8 *) Buffer;
    306 
    307   if (Address > MAX_IO_ADDRESS) {
    308     return EFI_INVALID_PARAMETER;
    309   }
    310 
    311   Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
    312   if (EFI_ERROR (Status)) {
    313     return Status;
    314   }
    315   //
    316   // Loop for each iteration and move the data
    317   //
    318   OriginalAddress = Address;
    319   OriginalIn.Buf = In.Buf;
    320   for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
    321     switch (Width) {
    322       case S3BootScriptWidthUint8:
    323         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
    324         IoWrite8 ((UINTN) Address, *In.Uint8);
    325         break;
    326       case S3BootScriptWidthFifoUint8:
    327         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
    328         IoWrite8 ((UINTN) OriginalAddress, *In.Uint8);
    329         break;
    330       case S3BootScriptWidthFillUint8:
    331         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
    332         IoWrite8 ((UINTN) Address, *OriginalIn.Uint8);
    333         break;
    334       case S3BootScriptWidthUint16:
    335         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
    336         IoWrite16 ((UINTN) Address, *In.Uint16);
    337         break;
    338       case S3BootScriptWidthFifoUint16:
    339         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
    340         IoWrite16 ((UINTN) OriginalAddress, *In.Uint16);
    341         break;
    342       case S3BootScriptWidthFillUint16:
    343         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
    344         IoWrite16 ((UINTN) Address, *OriginalIn.Uint16);
    345         break;
    346       case S3BootScriptWidthUint32:
    347         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
    348         IoWrite32 ((UINTN) Address, *In.Uint32);
    349         break;
    350       case S3BootScriptWidthFifoUint32:
    351         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
    352         IoWrite32 ((UINTN) OriginalAddress, *In.Uint32);
    353         break;
    354       case S3BootScriptWidthFillUint32:
    355         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
    356         IoWrite32 ((UINTN) Address, *OriginalIn.Uint32);
    357         break;
    358       case S3BootScriptWidthUint64:
    359         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
    360         IoWrite64 ((UINTN) Address, *In.Uint64);
    361         break;
    362       case S3BootScriptWidthFifoUint64:
    363         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
    364         IoWrite64 ((UINTN) OriginalAddress, *In.Uint64);
    365         break;
    366       case S3BootScriptWidthFillUint64:
    367         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
    368         IoWrite64 ((UINTN) Address, *OriginalIn.Uint64);
    369         break;
    370       default:
    371         return EFI_INVALID_PARAMETER;
    372     }
    373   }
    374 
    375 
    376   return EFI_SUCCESS;
    377 }
    378 /**
    379   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_WRITE OP code.
    380 
    381   @param Script       Pointer to the node which is to be interpreted.
    382 
    383   @retval EFI_SUCCESS The data was written to the EFI System.
    384   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
    385                                 Buffer is NULL.
    386                                 The Buffer is not aligned for the given Width.
    387                                 Address is outside the legal range of I/O ports.
    388 
    389 **/
    390 EFI_STATUS
    391 BootScriptExecuteIoWrite (
    392   IN UINT8                    *Script
    393   )
    394 {
    395   S3_BOOT_SCRIPT_LIB_WIDTH   Width;
    396   UINT64                     Address;
    397   UINTN                      Count;
    398   VOID                      *Buffer;
    399   EFI_BOOT_SCRIPT_IO_WRITE   IoWrite;
    400 
    401   CopyMem ((VOID*)&IoWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));
    402   Width = (S3_BOOT_SCRIPT_LIB_WIDTH) IoWrite.Width;
    403   Address = IoWrite.Address;
    404   Count = IoWrite.Count;
    405   Buffer = Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE);
    406 
    407   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
    408   return ScriptIoWrite(Width, Address, Count, Buffer);
    409 }
    410 /**
    411   Perform memory read operation
    412 
    413   @param  Width Width of the operation.
    414   @param  Address Address of the operation.
    415   @param  Count Count of the number of accesses to perform.
    416   @param  Buffer Pointer to the buffer read from memory.
    417 
    418   @retval EFI_SUCCESS The data was written to the EFI System.
    419   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
    420                                 Buffer is NULL.
    421                                 The Buffer is not aligned for the given Width.
    422   @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
    423                           is not valid for this EFI System.
    424 
    425 **/
    426 EFI_STATUS
    427 ScriptMemoryRead (
    428   IN       S3_BOOT_SCRIPT_LIB_WIDTH    Width,
    429   IN       UINT64                   Address,
    430   IN       UINTN                    Count,
    431   IN OUT   VOID                     *Buffer
    432   )
    433 {
    434   EFI_STATUS  Status;
    435   UINTN       AddressStride;
    436   UINTN       BufferStride;
    437   PTR         Out;
    438 
    439   Out.Buf = Buffer;
    440 
    441   Status  = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
    442   if (EFI_ERROR (Status)) {
    443     return Status;
    444   }
    445   //
    446   // Loop for each iteration and move the data
    447   //
    448   for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
    449     switch (Width) {
    450     case S3BootScriptWidthUint8:
    451       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN)Address));
    452       *Out.Uint8 = MmioRead8 ((UINTN) Address);
    453       break;
    454     case S3BootScriptWidthFifoUint8:
    455       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN)Address));
    456       *Out.Uint8 = MmioRead8 ((UINTN) Address);
    457       break;
    458     case S3BootScriptWidthFillUint8:
    459       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN)Address));
    460       *Out.Uint8 = MmioRead8 ((UINTN) Address);
    461       break;
    462 
    463     case S3BootScriptWidthUint16:
    464       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN)Address));
    465       *Out.Uint16 = MmioRead16 ((UINTN) Address);
    466       break;
    467     case S3BootScriptWidthFifoUint16:
    468       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN)Address));
    469       *Out.Uint16 = MmioRead16 ((UINTN) Address);
    470       break;
    471     case S3BootScriptWidthFillUint16:
    472       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN)Address));
    473       *Out.Uint16 = MmioRead16 ((UINTN) Address);
    474       break;
    475 
    476     case S3BootScriptWidthUint32:
    477       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN)Address));
    478       *Out.Uint32 = MmioRead32 ((UINTN) Address);
    479       break;
    480     case S3BootScriptWidthFifoUint32:
    481       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN)Address));
    482       *Out.Uint32 = MmioRead32 ((UINTN) Address);
    483       break;
    484     case S3BootScriptWidthFillUint32:
    485       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN)Address));
    486       *Out.Uint32 = MmioRead32 ((UINTN) Address);
    487       break;
    488 
    489     case S3BootScriptWidthUint64:
    490       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN)Address));
    491       *Out.Uint64 = MmioRead64 ((UINTN) Address);
    492       break;
    493     case S3BootScriptWidthFifoUint64:
    494       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN)Address));
    495       *Out.Uint64 = MmioRead64 ((UINTN) Address);
    496       break;
    497     case S3BootScriptWidthFillUint64:
    498       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN)Address));
    499       *Out.Uint64 = MmioRead64 ((UINTN) Address);
    500       break;
    501 
    502     default:
    503       return EFI_UNSUPPORTED;
    504     }
    505   }
    506 
    507   return EFI_SUCCESS;
    508 }
    509 /**
    510   Perform memory write operation
    511 
    512   @param   Width   Width of the operation.
    513   @param   Address Address of the operation.
    514   @param   Count   Count of the number of accesses to perform.
    515   @param   Buffer  Pointer to the buffer write to memory.
    516 
    517   @retval EFI_SUCCESS The data was written to the EFI System.
    518   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
    519                                 Buffer is NULL.
    520                                 The Buffer is not aligned for the given Width.
    521   @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
    522                           is not valid for this EFI System.
    523 
    524 **/
    525 EFI_STATUS
    526 ScriptMemoryWrite (
    527   IN      S3_BOOT_SCRIPT_LIB_WIDTH Width,
    528   IN      UINT64                Address,
    529   IN      UINTN                 Count,
    530   IN OUT  VOID                 *Buffer
    531   )
    532 {
    533   EFI_STATUS  Status;
    534   UINTN       AddressStride;
    535   UINT64      OriginalAddress;
    536   UINTN       BufferStride;
    537   PTR         In;
    538   PTR         OriginalIn;
    539 
    540   In.Buf  = Buffer;
    541 
    542   Status  = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
    543   if (EFI_ERROR (Status)) {
    544     return Status;
    545   }
    546   //
    547   // Loop for each iteration and move the data
    548   //
    549   OriginalAddress = Address;
    550   OriginalIn.Buf = In.Buf;
    551   for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
    552     switch (Width) {
    553       case S3BootScriptWidthUint8:
    554         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
    555         MmioWrite8 ((UINTN) Address, *In.Uint8);
    556         break;
    557       case S3BootScriptWidthFifoUint8:
    558         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
    559         MmioWrite8 ((UINTN) OriginalAddress, *In.Uint8);
    560         break;
    561       case S3BootScriptWidthFillUint8:
    562         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
    563         MmioWrite8 ((UINTN) Address, *OriginalIn.Uint8);
    564         break;
    565       case S3BootScriptWidthUint16:
    566         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
    567         MmioWrite16 ((UINTN) Address, *In.Uint16);
    568         break;
    569       case S3BootScriptWidthFifoUint16:
    570         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
    571         MmioWrite16 ((UINTN) OriginalAddress, *In.Uint16);
    572         break;
    573       case S3BootScriptWidthFillUint16:
    574         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
    575         MmioWrite16 ((UINTN) Address, *OriginalIn.Uint16);
    576         break;
    577       case S3BootScriptWidthUint32:
    578         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
    579         MmioWrite32 ((UINTN) Address, *In.Uint32);
    580         break;
    581       case S3BootScriptWidthFifoUint32:
    582         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
    583         MmioWrite32 ((UINTN) OriginalAddress, *In.Uint32);
    584         break;
    585       case S3BootScriptWidthFillUint32:
    586         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
    587         MmioWrite32 ((UINTN) Address, *OriginalIn.Uint32);
    588         break;
    589       case S3BootScriptWidthUint64:
    590         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
    591         MmioWrite64 ((UINTN) Address, *In.Uint64);
    592         break;
    593       case S3BootScriptWidthFifoUint64:
    594         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
    595         MmioWrite64 ((UINTN) OriginalAddress, *In.Uint64);
    596         break;
    597       case S3BootScriptWidthFillUint64:
    598         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
    599         MmioWrite64 ((UINTN) Address, *OriginalIn.Uint64);
    600         break;
    601       default:
    602         return EFI_UNSUPPORTED;
    603     }
    604   }
    605   return EFI_SUCCESS;
    606 }
    607 /**
    608   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_WRITE OP code.
    609 
    610   @param[in]  Script Pointer to the node which is to be interpreted.
    611 
    612   @retval EFI_SUCCESS The data was written to the EFI System.
    613   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
    614                                 Buffer is NULL.
    615                                 The Buffer is not aligned for the given Width.
    616   @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
    617                           is not valid for this EFI System.
    618 
    619 **/
    620 EFI_STATUS
    621 BootScriptExecuteMemoryWrite (
    622   IN UINT8             *Script
    623   )
    624 {
    625   VOID            *Buffer;
    626   S3_BOOT_SCRIPT_LIB_WIDTH Width;
    627   UINT64           Address;
    628   UINTN            Count;
    629   EFI_BOOT_SCRIPT_MEM_WRITE  MemWrite;
    630 
    631   CopyMem((VOID*)&MemWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));
    632   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)MemWrite.Width;
    633   Address = MemWrite.Address;
    634   Count   = MemWrite.Count;
    635   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_MEM_WRITE);
    636 
    637   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
    638   return ScriptMemoryWrite (Width,Address, Count,  Buffer);
    639 
    640 }
    641 /**
    642   Performance PCI configuration read operation
    643 
    644   @param  Width   Width of the operation.
    645   @param  Address Address of the operation.
    646   @param  Count   Count of the number of accesses to perform.
    647   @param  Buffer  Pointer to the buffer read from PCI config space
    648 
    649   @retval EFI_SUCCESS The read succeed.
    650   @retval EFI_INVALID_PARAMETER if Width is not defined
    651   @note  A known Limitations in the implementation which is 64bits operations are not supported.
    652 
    653 **/
    654 EFI_STATUS
    655 ScriptPciCfgRead (
    656   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
    657   IN  UINT64                       Address,
    658   IN  UINTN                        Count,
    659   OUT VOID                        *Buffer
    660   )
    661 {
    662   EFI_STATUS  Status;
    663   UINTN       AddressStride;
    664   UINTN       BufferStride;
    665   PTR         Out;
    666   UINTN       PciAddress;
    667 
    668   Out.Buf = (UINT8 *) Buffer;
    669 
    670   PciAddress = PCI_ADDRESS_ENCODE (Address);
    671 
    672   Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
    673   if (EFI_ERROR (Status)) {
    674     return Status;
    675   }
    676   //
    677   // Loop for each iteration and move the data
    678   //
    679   for (; Count > 0; Count--, PciAddress += AddressStride, Out.Buf += BufferStride) {
    680     switch (Width) {
    681     case S3BootScriptWidthUint8:
    682       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", PciAddress));
    683       *Out.Uint8 = PciRead8 (PciAddress);
    684       break;
    685     case S3BootScriptWidthFifoUint8:
    686       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", PciAddress));
    687       *Out.Uint8 = PciRead8 (PciAddress);
    688       break;
    689     case S3BootScriptWidthFillUint8:
    690       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", PciAddress));
    691       *Out.Uint8 = PciRead8 (PciAddress);
    692       break;
    693 
    694     case S3BootScriptWidthUint16:
    695       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", PciAddress));
    696       *Out.Uint16 = PciRead16 (PciAddress);
    697       break;
    698     case S3BootScriptWidthFifoUint16:
    699       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", PciAddress));
    700       *Out.Uint16 = PciRead16 (PciAddress);
    701       break;
    702     case S3BootScriptWidthFillUint16:
    703       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", PciAddress));
    704       *Out.Uint16 = PciRead16 (PciAddress);
    705       break;
    706 
    707     case S3BootScriptWidthUint32:
    708       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", PciAddress));
    709       *Out.Uint32 = PciRead32 (PciAddress);
    710       break;
    711     case S3BootScriptWidthFifoUint32:
    712       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", PciAddress));
    713       *Out.Uint32 = PciRead32 (PciAddress);
    714       break;
    715     case S3BootScriptWidthFillUint32:
    716       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", PciAddress));
    717       *Out.Uint32 = PciRead32 (PciAddress);
    718       break;
    719 
    720     default:
    721       return EFI_INVALID_PARAMETER;
    722     }
    723   }
    724   return EFI_SUCCESS;
    725 }
    726 
    727 /**
    728   Performance PCI configuration write operation
    729 
    730   @param  Width   Width of the operation.
    731   @param  Address Address of the operation.
    732   @param  Count   Count of the number of accesses to perform.
    733   @param  Buffer  Pointer to the buffer write to PCI config space
    734 
    735   @retval EFI_SUCCESS The write succeed.
    736   @retval EFI_INVALID_PARAMETER if Width is not defined
    737   @note  A known Limitations in the implementation which is 64bits operations are not supported.
    738 
    739 **/
    740 EFI_STATUS
    741 ScriptPciCfgWrite (
    742   IN  S3_BOOT_SCRIPT_LIB_WIDTH     Width,
    743   IN  UINT64                       Address,
    744   IN  UINTN                        Count,
    745   IN  VOID                         *Buffer
    746   )
    747 {
    748   EFI_STATUS  Status;
    749   UINTN       AddressStride;
    750   UINTN       BufferStride;
    751   UINTN       OriginalPciAddress;
    752   PTR         In;
    753   PTR         OriginalIn;
    754   UINTN       PciAddress;
    755 
    756   In.Buf = (UINT8 *) Buffer;
    757 
    758   PciAddress = PCI_ADDRESS_ENCODE (Address);
    759 
    760   Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
    761   if (EFI_ERROR (Status)) {
    762     return Status;
    763   }
    764   //
    765   // Loop for each iteration and move the data
    766   //
    767   OriginalPciAddress = PciAddress;
    768   OriginalIn.Buf = In.Buf;
    769   for (; Count > 0; Count--, PciAddress += AddressStride, In.Buf += BufferStride) {
    770     switch (Width) {
    771       case S3BootScriptWidthUint8:
    772         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", PciAddress, (UINTN)*In.Uint8));
    773         PciWrite8 (PciAddress, *In.Uint8);
    774         break;
    775       case S3BootScriptWidthFifoUint8:
    776         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", OriginalPciAddress, (UINTN)*In.Uint8));
    777         PciWrite8 (OriginalPciAddress, *In.Uint8);
    778         break;
    779       case S3BootScriptWidthFillUint8:
    780         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", PciAddress, (UINTN)*OriginalIn.Uint8));
    781         PciWrite8 (PciAddress, *OriginalIn.Uint8);
    782         break;
    783       case S3BootScriptWidthUint16:
    784         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", PciAddress, (UINTN)*In.Uint16));
    785         PciWrite16 (PciAddress, *In.Uint16);
    786         break;
    787       case S3BootScriptWidthFifoUint16:
    788         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", OriginalPciAddress, (UINTN)*In.Uint16));
    789         PciWrite16 (OriginalPciAddress, *In.Uint16);
    790         break;
    791       case S3BootScriptWidthFillUint16:
    792         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", PciAddress, (UINTN)*OriginalIn.Uint16));
    793         PciWrite16 (PciAddress, *OriginalIn.Uint16);
    794         break;
    795       case S3BootScriptWidthUint32:
    796         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", PciAddress, (UINTN)*In.Uint32));
    797         PciWrite32 (PciAddress, *In.Uint32);
    798         break;
    799       case S3BootScriptWidthFifoUint32:
    800         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", OriginalPciAddress, (UINTN)*In.Uint32));
    801         PciWrite32 (OriginalPciAddress, *In.Uint32);
    802         break;
    803       case S3BootScriptWidthFillUint32:
    804         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)PciAddress, (UINTN)*OriginalIn.Uint32));
    805         PciWrite32 (PciAddress, *OriginalIn.Uint32);
    806         break;
    807       default:
    808         return EFI_INVALID_PARAMETER;
    809     }
    810   }
    811   return EFI_SUCCESS;
    812 }
    813 /**
    814   Performance PCI configuration 2 read operation
    815 
    816   @param     Width                      Width of the operation.
    817   @param     Segment                    Pci segment number
    818   @param     Address                    Address of the operation.
    819   @param     Count                      Count of the number of accesses to perform.
    820   @param     Buffer                     Pointer to the buffer to read from PCI config space.
    821 
    822   @retval    EFI_SUCCESS                The data was written to the EFI System.
    823   @retval    EFI_INVALID_PARAMETER      Width is invalid for this EFI System.
    824                                         Buffer is NULL.
    825                                         The Buffer is not aligned for the given Width.
    826                                         Address is outside the legal range of I/O ports.
    827   @note  A known Limitations in the implementation which is the 'Segment' parameter is assumed as
    828          Zero, or else, assert.
    829 **/
    830 EFI_STATUS
    831 ScriptPciCfg2Read (
    832   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
    833   IN  UINT16                   Segment,
    834   IN  UINT64                   Address,
    835   IN  UINTN                    Count,
    836   OUT VOID                     *Buffer
    837   )
    838 {
    839   ASSERT (Segment==0);
    840 
    841   return ScriptPciCfgRead (Width, Address, Count, Buffer);
    842 }
    843 /**
    844   Performance PCI configuration 2 write operation
    845 
    846   @param     Width                      Width of the operation.
    847   @param     Segment                    Pci segment number
    848   @param     Address                    Address of the operation.
    849   @param     Count                      Count of the number of accesses to perform.
    850   @param     Buffer                     Pointer to the buffer to write to PCI config space.
    851 
    852   @retval    EFI_SUCCESS                The data was written to the EFI System.
    853   @retval    EFI_INVALID_PARAMETER      Width is invalid for this EFI System.
    854                                         Buffer is NULL.
    855                                         The Buffer is not aligned for the given Width.
    856                                         Address is outside the legal range of I/O ports.
    857   @note  A known Limitations in the implementation which is the 'Segment' parameter is assumed as
    858          Zero, or else, assert.
    859 
    860 **/
    861 EFI_STATUS
    862 EFIAPI
    863 ScriptPciCfg2Write (
    864   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
    865   IN  UINT16                   Segment,
    866   IN  UINT64                   Address,
    867   IN  UINTN                    Count,
    868   IN  VOID                     *Buffer
    869   )
    870 {
    871   ASSERT (Segment==0);
    872   return ScriptPciCfgWrite (Width, Address, Count, Buffer);
    873 }
    874 /**
    875   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE OP code.
    876 
    877   @param  Script        The pointer of typed node in boot script table
    878 
    879   @retval EFI_SUCCESS  The operation was executed successfully
    880 **/
    881 EFI_STATUS
    882 BootScriptExecutePciCfgWrite (
    883   IN UINT8                    *Script
    884   )
    885 {
    886   VOID                              *Buffer;
    887   S3_BOOT_SCRIPT_LIB_WIDTH          Width;
    888   UINT64                            Address;
    889   UINTN                             Count;
    890   EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE  PciCfgWrite;
    891 
    892   CopyMem ((VOID*)&PciCfgWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
    893 
    894   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfgWrite.Width;
    895   Address = PciCfgWrite.Address;
    896   Count   = PciCfgWrite.Count;
    897   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE);
    898 
    899   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgWrite - 0x%08x, 0x%08x, 0x%08x\n", PCI_ADDRESS_ENCODE (Address), Count, (UINTN)Width));
    900   return ScriptPciCfgWrite (Width, Address, Count, Buffer);
    901 }
    902 /**
    903   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_READ_WRITE OP code.
    904 
    905   @param Script   The pointer of typed node in boot script table
    906   @param AndMask  Mask value for 'and' operation
    907   @param OrMask   Mask value for 'or' operation
    908 
    909   @retval EFI_SUCCESS    The operation was executed successfully
    910 **/
    911 EFI_STATUS
    912 BootScriptExecuteIoReadWrite (
    913   IN  UINT8                        *Script,
    914   IN  UINT64                       AndMask,
    915   IN  UINT64                        OrMask
    916   )
    917 
    918 {
    919   EFI_STATUS  Status;
    920   UINT64      Data;
    921   EFI_BOOT_SCRIPT_IO_READ_WRITE IoReadWrite;
    922 
    923   Data = 0;
    924 
    925   CopyMem((VOID*)&IoReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));
    926 
    927   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoReadWrite.Address, AndMask, OrMask));
    928 
    929   Status = ScriptIoRead (
    930              (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
    931              IoReadWrite.Address,
    932              1,
    933              &Data
    934              );
    935   if (!EFI_ERROR (Status)) {
    936     Data = (Data & AndMask) | OrMask;
    937     Status = ScriptIoWrite (
    938                (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
    939                IoReadWrite.Address,
    940                1,
    941                &Data
    942                );
    943   }
    944   return Status;
    945 }
    946 /**
    947   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_READ_WRITE OP code.
    948 
    949   @param Script    The pointer of typed node in boot script table
    950   @param AndMask   Mask value for 'and' operation
    951   @param OrMask    Mask value for 'or' operation
    952 
    953   @retval EFI_SUCCESS The operation was executed successfully
    954 **/
    955 EFI_STATUS
    956 BootScriptExecuteMemoryReadWrite (
    957   IN UINT8                        *Script,
    958   IN UINT64                        AndMask,
    959   IN UINT64                        OrMask
    960   )
    961 
    962 {
    963   EFI_STATUS  Status;
    964   UINT64      Data;
    965   EFI_BOOT_SCRIPT_MEM_READ_WRITE  MemReadWrite;
    966 
    967   Data = 0;
    968 
    969   CopyMem((VOID*)&MemReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_READ_WRITE));
    970 
    971   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemReadWrite.Address, AndMask, OrMask));
    972 
    973   Status = ScriptMemoryRead (
    974              (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
    975              MemReadWrite.Address,
    976              1,
    977              &Data
    978              );
    979   if (!EFI_ERROR (Status)) {
    980     Data = (Data & AndMask) | OrMask;
    981     Status = ScriptMemoryWrite (
    982                (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
    983                MemReadWrite.Address,
    984                1,
    985                &Data
    986                );
    987   }
    988   return Status;
    989 }
    990 /**
    991   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CFG_READ_WRITE OP code.
    992 
    993   @param Script   The pointer of typed node in boot script table
    994   @param AndMask  Mask value for 'and' operation
    995   @param OrMask   Mask value for 'or' operation
    996 
    997   @retval EFI_SUCCESS   The operation was executed successfully
    998 **/
    999 EFI_STATUS
   1000 BootScriptExecutePciCfgReadWrite (
   1001   IN UINT8                     *Script,
   1002   IN UINT64                    AndMask,
   1003   IN UINT64                    OrMask
   1004   )
   1005 
   1006 {
   1007   EFI_STATUS  Status;
   1008   UINT64      Data;
   1009   EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE  PciCfgReadWrite;
   1010 
   1011   Data = 0;
   1012 
   1013   CopyMem((VOID*)&PciCfgReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
   1014 
   1015   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgReadWrite.Address), AndMask, OrMask));
   1016 
   1017   Status = ScriptPciCfgRead (
   1018              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
   1019              PciCfgReadWrite.Address,
   1020              1,
   1021              &Data
   1022              );
   1023   if (EFI_ERROR (Status)) {
   1024     return Status;
   1025   }
   1026 
   1027   Data = (Data & AndMask) | OrMask;
   1028 
   1029   Status = ScriptPciCfgWrite (
   1030              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
   1031              PciCfgReadWrite.Address,
   1032              1,
   1033              &Data
   1034              );
   1035 
   1036   return Status;
   1037 }
   1038 /**
   1039   Interprete the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
   1040 
   1041   @param Script  The pointer of typed node in boot script table
   1042 
   1043   @retval EFI_SUCCESS      The operation was executed successfully
   1044   @retval EFI_UNSUPPORTED  Cannot locate smbus ppi or occur error of script execution
   1045   @retval Others           Result of script execution
   1046 **/
   1047 EFI_STATUS
   1048 BootScriptExecuteSmbusExecute (
   1049   IN UINT8                     *Script
   1050   )
   1051 {
   1052   UINTN                    SmBusAddress;
   1053   UINTN                    DataSize;
   1054   EFI_BOOT_SCRIPT_SMBUS_EXECUTE SmbusExecuteEntry;
   1055 
   1056   CopyMem ((VOID*)&SmbusExecuteEntry, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_SMBUS_EXECUTE ));
   1057 
   1058   DEBUG ((EFI_D_INFO, "BootScriptExecuteSmbusExecute - 0x%08x, 0x%08x\n", (UINTN)SmbusExecuteEntry.SmBusAddress, (UINTN)SmbusExecuteEntry.Operation));
   1059 
   1060   SmBusAddress = (UINTN)SmbusExecuteEntry.SmBusAddress;
   1061   DataSize = (UINTN) SmbusExecuteEntry.DataSize;
   1062   return SmbusExecute (
   1063            SmBusAddress,
   1064            (EFI_SMBUS_OPERATION) SmbusExecuteEntry.Operation,
   1065            &DataSize,
   1066            Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)
   1067            );
   1068 }
   1069 /**
   1070   Interprete the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
   1071 
   1072   @param Script      The pointer of typed node in boot script table
   1073 
   1074   @retval EFI_SUCCESS The operation was executed successfully
   1075 **/
   1076 EFI_STATUS
   1077 BootScriptExecuteStall (
   1078   IN UINT8                 *Script
   1079   )
   1080 {
   1081   EFI_BOOT_SCRIPT_STALL    Stall;
   1082 
   1083   CopyMem ((VOID*)&Stall, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_STALL));
   1084 
   1085   DEBUG ((EFI_D_INFO, "BootScriptExecuteStall - 0x%08x\n", (UINTN)Stall.Duration));
   1086 
   1087   MicroSecondDelay ((UINTN) Stall.Duration);
   1088   return EFI_SUCCESS;
   1089 }
   1090 /**
   1091   Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
   1092 
   1093   @param Script  The pointer of typed node in boot script table
   1094   @retval EFI_SUCCESS  The operation was executed successfully
   1095 **/
   1096 EFI_STATUS
   1097 BootScriptExecuteDispatch (
   1098   IN UINT8                  *Script
   1099   )
   1100 {
   1101   EFI_STATUS                Status;
   1102   DISPATCH_ENTRYPOINT_FUNC  EntryFunc;
   1103   EFI_BOOT_SCRIPT_DISPATCH  ScriptDispatch;
   1104 
   1105   CopyMem ((VOID*)&ScriptDispatch, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH));
   1106   EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch.EntryPoint);
   1107 
   1108   DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch - 0x%08x\n", (UINTN)ScriptDispatch.EntryPoint));
   1109 
   1110   Status    = EntryFunc (NULL, NULL);
   1111 
   1112   return Status;
   1113 }
   1114 /**
   1115   Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
   1116 
   1117   @param  Script       The pointer of typed node in boot script table
   1118   @retval EFI_SUCCESS  The operation was executed successfully
   1119 **/
   1120 EFI_STATUS
   1121 BootScriptExecuteDispatch2 (
   1122   IN UINT8                  *Script
   1123   )
   1124 {
   1125   EFI_STATUS                Status;
   1126   DISPATCH_ENTRYPOINT_FUNC  EntryFunc;
   1127   EFI_BOOT_SCRIPT_DISPATCH_2  ScriptDispatch2;
   1128 
   1129   CopyMem ((VOID*)&ScriptDispatch2, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH_2));
   1130 
   1131   DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch2 - 0x%08x(0x%08x)\n", (UINTN)ScriptDispatch2.EntryPoint, (UINTN)ScriptDispatch2.Context));
   1132 
   1133   EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch2.EntryPoint);
   1134 
   1135   Status    = EntryFunc (NULL, (VOID *) (UINTN) ScriptDispatch2.Context);
   1136 
   1137   return Status;
   1138 }
   1139 /**
   1140   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
   1141 
   1142   @param  Script  The pointer of typed node in boot script table
   1143   @param  AndMask  Mask value for 'and' operation
   1144   @param  OrMask   Mask value for 'or' operation
   1145 
   1146   @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
   1147                            the epecting data within the Loop Times.
   1148   @retval EFI_SUCCESS      The operation was executed successfully
   1149 **/
   1150 EFI_STATUS
   1151 BootScriptExecuteMemPoll (
   1152   IN UINT8                        *Script,
   1153   IN UINT64                        AndMask,
   1154   IN UINT64                        OrMask
   1155   )
   1156 {
   1157 
   1158   UINT64        Data;
   1159   UINT64        LoopTimes;
   1160   EFI_STATUS    Status;
   1161   EFI_BOOT_SCRIPT_MEM_POLL       MemPoll;
   1162 
   1163   CopyMem ((VOID*)&MemPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_POLL));
   1164 
   1165   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemPoll.Address, AndMask, OrMask));
   1166 
   1167   Data = 0;
   1168   Status = ScriptMemoryRead (
   1169                (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
   1170                MemPoll.Address,
   1171                1,
   1172                &Data
   1173                );
   1174   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
   1175     return EFI_SUCCESS;
   1176   }
   1177 
   1178   for (LoopTimes = 0; LoopTimes < MemPoll.LoopTimes; LoopTimes++) {
   1179     MicroSecondDelay ((UINTN)MemPoll.Duration);
   1180 
   1181     Data = 0;
   1182     Status = ScriptMemoryRead (
   1183                (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
   1184                MemPoll.Address,
   1185                1,
   1186                &Data
   1187                );
   1188    if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
   1189     return EFI_SUCCESS;
   1190    }
   1191   }
   1192 
   1193   if (LoopTimes < MemPoll.LoopTimes) {
   1194     return EFI_SUCCESS;
   1195   } else {
   1196     return EFI_DEVICE_ERROR;
   1197   }
   1198 }
   1199 /**
   1200   Execute the boot script to interpret the Store arbitrary information.
   1201   This opcode is a no-op on dispatch and is only used for debugging script issues.
   1202 
   1203   @param Script       The pointer of node in boot script table
   1204 
   1205 **/
   1206 VOID
   1207 BootScriptExecuteInformation (
   1208   IN UINT8       *Script
   1209   )
   1210 
   1211 {
   1212   UINT32                        Index;
   1213   EFI_BOOT_SCRIPT_INFORMATION   Information;
   1214   UINT8                         *InformationData;
   1215 
   1216   CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
   1217 
   1218   InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
   1219   DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN) InformationData));
   1220 
   1221   DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
   1222   for (Index = 0; Index < Information.InformationLength; Index++) {
   1223     DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
   1224   }
   1225   DEBUG ((EFI_D_INFO, "\n"));
   1226 }
   1227 
   1228 /**
   1229   Execute the boot script to interpret the Label information.
   1230 
   1231   @param Script       The pointer of node in boot script table
   1232 
   1233 **/
   1234 VOID
   1235 BootScriptExecuteLabel (
   1236   IN UINT8       *Script
   1237   )
   1238 
   1239 {
   1240   UINT32                        Index;
   1241   EFI_BOOT_SCRIPT_INFORMATION   Information;
   1242   UINT8                         *InformationData;
   1243 
   1244   CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
   1245 
   1246   InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
   1247   DEBUG ((EFI_D_INFO, "BootScriptExecuteLabel - 0x%08x\n", (UINTN) InformationData));
   1248 
   1249   DEBUG ((EFI_D_INFO, "BootScriptLabel: "));
   1250   for (Index = 0; Index < Information.InformationLength; Index++) {
   1251     DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
   1252   }
   1253   DEBUG ((EFI_D_INFO, "\n"));
   1254 }
   1255 
   1256 /**
   1257   calculate the mask value for 'and' and 'or' operation
   1258   @param ScriptHeader   The pointer of header of node in boot script table
   1259   @param AndMask  The Mask value for 'and' operation
   1260   @param OrMask   The Mask value for 'or' operation
   1261   @param Script   Pointer to the entry.
   1262 
   1263 **/
   1264 VOID
   1265 CheckAndOrMask (
   1266   IN   EFI_BOOT_SCRIPT_COMMON_HEADER  *ScriptHeader,
   1267   OUT UINT64                      *AndMask,
   1268   OUT UINT64                      *OrMask,
   1269   IN  UINT8                       *Script
   1270   )
   1271 {
   1272   UINT8 *DataPtr;
   1273   UINTN Size;
   1274 
   1275   switch (ScriptHeader->OpCode) {
   1276   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
   1277     Size = sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE);
   1278     break;
   1279 
   1280   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
   1281     Size = sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE);
   1282     break;
   1283 
   1284   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
   1285     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE);
   1286     break;
   1287   case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
   1288     Size = sizeof (EFI_BOOT_SCRIPT_MEM_POLL);
   1289     break;
   1290 
   1291   case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
   1292     Size = sizeof (EFI_BOOT_SCRIPT_IO_POLL);
   1293     break;
   1294 
   1295   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
   1296     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE);
   1297     break;
   1298 
   1299   case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
   1300     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL);
   1301     break;
   1302 
   1303   case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
   1304     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL);
   1305     break;
   1306 
   1307   default:
   1308     return;
   1309   }
   1310 
   1311   DataPtr = Script + Size;
   1312 
   1313   switch (ScriptHeader->Width) {
   1314   case S3BootScriptWidthUint8:
   1315     *AndMask  = (UINT64) (*(UINT8*) (DataPtr + 1));
   1316     *OrMask   = (UINT64) (*DataPtr);
   1317     break;
   1318 
   1319   case S3BootScriptWidthUint16:
   1320     *AndMask  = (UINT64) (*(UINT16 *) (DataPtr + 2));
   1321     *OrMask   = (UINT64) (*(UINT16 *) DataPtr);
   1322     break;
   1323 
   1324   case S3BootScriptWidthUint32:
   1325     *AndMask  = (UINT64) (*(UINT32 *) (DataPtr + 4));
   1326     *OrMask   = (UINT64) (*(UINT32 *) DataPtr);
   1327     break;
   1328 
   1329   case S3BootScriptWidthUint64:
   1330     *AndMask  = (UINT64) (*(UINT64 *) (DataPtr + 8));
   1331     *OrMask   = (UINT64) (*(UINT64 *) DataPtr);
   1332     break;
   1333 
   1334   default:
   1335     break;
   1336   }
   1337 
   1338   return;
   1339 }
   1340 /**
   1341   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
   1342 
   1343   @param  Script  The pointer of typed node in boot script table
   1344   @param  AndMask  Mask value for 'and' operation
   1345   @param  OrMask   Mask value for 'or' operation
   1346 
   1347   @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
   1348                            the epecting data within the Loop Times.
   1349   @retval EFI_SUCCESS      The operation was executed successfully
   1350 **/
   1351 EFI_STATUS
   1352 BootScriptExecuteIoPoll (
   1353   IN UINT8       *Script,
   1354   IN UINT64      AndMask,
   1355   IN UINT64      OrMask
   1356   )
   1357 {
   1358   EFI_STATUS    Status;
   1359   UINT64        Data;
   1360   UINT64        LoopTimes;
   1361   EFI_BOOT_SCRIPT_IO_POLL       IoPoll;
   1362 
   1363   CopyMem ((VOID*)&IoPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_POLL));
   1364 
   1365   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoPoll.Address, AndMask, OrMask));
   1366 
   1367   Data = 0;
   1368   Status = ScriptIoRead (
   1369              (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
   1370              IoPoll.Address,
   1371              1,
   1372              &Data
   1373              );
   1374   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
   1375     return EFI_SUCCESS;
   1376   }
   1377   for (LoopTimes = 0; LoopTimes < IoPoll.Delay; LoopTimes++) {
   1378     NanoSecondDelay (100);
   1379     Data = 0;
   1380     Status = ScriptIoRead (
   1381                (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
   1382                IoPoll.Address,
   1383                1,
   1384                &Data
   1385                );
   1386     if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
   1387       return EFI_SUCCESS;
   1388     }
   1389   }
   1390 
   1391   if (LoopTimes < IoPoll.Delay) {
   1392     return EFI_SUCCESS;
   1393   } else {
   1394     return EFI_DEVICE_ERROR;
   1395   }
   1396 }
   1397 /**
   1398   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
   1399 
   1400   @param    Script              The pointer of S3 boot script
   1401 
   1402   @retval   EFI_SUCCESS         The operation was executed successfully
   1403 
   1404 **/
   1405 EFI_STATUS
   1406 BootScriptExecutePciCfg2Write (
   1407   IN UINT8             *Script
   1408   )
   1409 {
   1410   VOID                              *Buffer;
   1411   S3_BOOT_SCRIPT_LIB_WIDTH          Width;
   1412   UINT16                            Segment;
   1413   UINT64                            Address;
   1414   UINTN                             Count;
   1415   EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE PciCfg2Write;
   1416 
   1417   CopyMem ((VOID*)&PciCfg2Write, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
   1418 
   1419   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfg2Write.Width;
   1420   Segment = PciCfg2Write.Segment;
   1421   Address = PciCfg2Write.Address;
   1422   Count   = PciCfg2Write.Count;
   1423   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE);
   1424 
   1425   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2Write - 0x%04x, 0x%08x, 0x%08x, 0x%08x\n", Segment, PCI_ADDRESS_ENCODE (Address), Count, (UINTN)Width));
   1426   return ScriptPciCfg2Write (Width, Segment, Address, Count, Buffer);
   1427 }
   1428 
   1429 
   1430 /**
   1431   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
   1432 
   1433   @param     Script                     The pointer of S3 boot script
   1434   @param     AndMask                    Mask value for 'and' operation
   1435   @param     OrMask                     Mask value for 'or' operation
   1436 
   1437   @retval    EFI_SUCCESS                The operation was executed successfully
   1438 
   1439 **/
   1440 EFI_STATUS
   1441 BootScriptExecutePciCfg2ReadWrite (
   1442   IN UINT8                        *Script,
   1443   IN UINT64                        AndMask,
   1444   IN UINT64                        OrMask
   1445   )
   1446 {
   1447   UINT64      Data;
   1448   EFI_STATUS  Status;
   1449   EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE PciCfg2ReadWrite;
   1450 
   1451   Data = 0;
   1452 
   1453   CopyMem ((VOID*)&PciCfg2ReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
   1454 
   1455   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2ReadWrite - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2ReadWrite.Segment, PCI_ADDRESS_ENCODE (PciCfg2ReadWrite.Address), AndMask, OrMask));
   1456 
   1457   Status = ScriptPciCfg2Read (
   1458              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
   1459              PciCfg2ReadWrite.Segment,
   1460              PciCfg2ReadWrite.Address,
   1461              1,
   1462              &Data
   1463              );
   1464   if (EFI_ERROR (Status)) {
   1465     return Status;
   1466   }
   1467 
   1468   Data = (Data & AndMask) | OrMask;
   1469   Status = ScriptPciCfg2Write (
   1470              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
   1471              PciCfg2ReadWrite.Segment,
   1472              PciCfg2ReadWrite.Address,
   1473              1,
   1474              &Data
   1475              );
   1476   return Status;
   1477 }
   1478 /**
   1479   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
   1480 
   1481   @param     Script                     The pointer of S3 boot script
   1482   @param     AndMask                    Mask value for 'and' operation
   1483   @param     OrMask                     Mask value for 'or' operation
   1484 
   1485   @retval    EFI_SUCCESS                The operation was executed successfully
   1486   @retval    EFI_DEVICE_ERROR           Data polled from Pci configuration space does not equal to
   1487                                         epecting data within the Loop Times.
   1488 **/
   1489 EFI_STATUS
   1490 BootScriptPciCfgPoll (
   1491   IN UINT8                         *Script,
   1492   IN UINT64                        AndMask,
   1493   IN UINT64                        OrMask
   1494   )
   1495 {
   1496   UINT64        Data;
   1497   UINT64        LoopTimes;
   1498   EFI_STATUS    Status;
   1499   EFI_BOOT_SCRIPT_PCI_CONFIG_POLL PciCfgPoll;
   1500   CopyMem ((VOID*)&PciCfgPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
   1501 
   1502   DEBUG ((EFI_D_INFO, "BootScriptPciCfgPoll - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgPoll.Address), AndMask, OrMask));
   1503 
   1504   Data = 0;
   1505   Status = ScriptPciCfgRead (
   1506              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
   1507              PciCfgPoll.Address,
   1508              1,
   1509              &Data
   1510              );
   1511   if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
   1512     return EFI_SUCCESS;
   1513   }
   1514 
   1515   for (LoopTimes = 0; LoopTimes < PciCfgPoll.Delay; LoopTimes++) {
   1516     NanoSecondDelay (100);
   1517     Data = 0;
   1518     Status = ScriptPciCfgRead (
   1519                (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
   1520                PciCfgPoll.Address,
   1521                1,
   1522                &Data
   1523                );
   1524     if ((!EFI_ERROR (Status)) &&
   1525        (Data & AndMask) == OrMask) {
   1526       return EFI_SUCCESS;
   1527     }
   1528   }
   1529 
   1530   if (LoopTimes < PciCfgPoll.Delay) {
   1531     return EFI_SUCCESS;
   1532   } else {
   1533     return EFI_DEVICE_ERROR;
   1534   }
   1535 }
   1536 
   1537 /**
   1538   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
   1539 
   1540   @param     Script                     The pointer of S3 Boot Script
   1541   @param     AndMask                    Mask value for 'and' operation
   1542   @param     OrMask                     Mask value for 'or' operation
   1543 
   1544   @retval    EFI_SUCCESS                The operation was executed successfully
   1545   @retval    EFI_DEVICE_ERROR           Data polled from Pci configuration space does not equal to
   1546                                         epecting data within the Loop Times.
   1547 
   1548 **/
   1549 EFI_STATUS
   1550 BootScriptPciCfg2Poll (
   1551   IN UINT8                        *Script,
   1552   IN UINT64                        AndMask,
   1553   IN UINT64                        OrMask
   1554   )
   1555 {
   1556   EFI_STATUS    Status;
   1557   UINT64        Data;
   1558   UINT64        LoopTimes;
   1559   EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL PciCfg2Poll;
   1560 
   1561   Data = 0;
   1562   CopyMem ((VOID*)&PciCfg2Poll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
   1563 
   1564   DEBUG ((EFI_D_INFO, "BootScriptPciCfg2Poll - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2Poll.Segment, PCI_ADDRESS_ENCODE (PciCfg2Poll.Address), AndMask, OrMask));
   1565 
   1566   Status = ScriptPciCfg2Read (
   1567              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
   1568              PciCfg2Poll.Segment,
   1569              PciCfg2Poll.Address,
   1570              1,
   1571              &Data
   1572              );
   1573   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
   1574     return EFI_SUCCESS;
   1575   }
   1576 
   1577   for (LoopTimes = 0; LoopTimes < PciCfg2Poll.Delay; LoopTimes++) {
   1578     NanoSecondDelay (100);
   1579 
   1580     Data = 0;
   1581     Status = ScriptPciCfg2Read (
   1582                (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
   1583                PciCfg2Poll.Segment,
   1584                PciCfg2Poll.Address,
   1585                1,
   1586                &Data
   1587                );
   1588     if ((!EFI_ERROR (Status)) &&  (Data & AndMask) == OrMask) {
   1589       return EFI_SUCCESS;
   1590     }
   1591   }
   1592 
   1593   if (LoopTimes < PciCfg2Poll.Delay) {
   1594     return EFI_SUCCESS;
   1595   } else {
   1596     return EFI_DEVICE_ERROR;
   1597   }
   1598 
   1599 }
   1600 
   1601 /**
   1602   Executes the S3 boot script table.
   1603 
   1604   @retval RETURN_SUCCESS           The boot script table was executed successfully.
   1605   @retval RETURN_UNSUPPORTED       Invalid script table or opcode.
   1606 
   1607   @note  A known Limitations in the implementation: When interpreting the opcode  EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
   1608          EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as
   1609          Zero, or else, assert.
   1610 **/
   1611 RETURN_STATUS
   1612 EFIAPI
   1613 S3BootScriptExecute (
   1614   VOID
   1615   )
   1616 {
   1617   EFI_STATUS            Status;
   1618   UINT8*                Script;
   1619   UINTN                 StartAddress;
   1620   UINT32                TableLength;
   1621   UINT64                AndMask;
   1622   UINT64                OrMask;
   1623   EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
   1624   EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;
   1625   Script = mS3BootScriptTablePtr->TableBase;
   1626   if (Script != 0) {
   1627     CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
   1628   } else {
   1629     return EFI_INVALID_PARAMETER;
   1630   }
   1631 
   1632   DEBUG ((EFI_D_INFO, "S3BootScriptExecute:\n"));
   1633   if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
   1634     return EFI_UNSUPPORTED;
   1635   }
   1636 
   1637   DEBUG ((EFI_D_INFO, "TableHeader - 0x%08x\n", Script));
   1638 
   1639   StartAddress  = (UINTN) Script;
   1640   TableLength   = TableHeader.TableLength;
   1641   Script    =    Script + TableHeader.Length;
   1642   Status        = EFI_SUCCESS;
   1643   AndMask       = 0;
   1644   OrMask        = 0;
   1645 
   1646   DEBUG ((EFI_D_INFO, "TableHeader.Version - 0x%04x\n", (UINTN)TableHeader.Version));
   1647   DEBUG ((EFI_D_INFO, "TableHeader.TableLength - 0x%08x\n", (UINTN)TableLength));
   1648 
   1649   while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
   1650     DEBUG ((EFI_D_INFO, "ExecuteBootScript - %08x\n", (UINTN)Script));
   1651 
   1652     CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
   1653     switch (ScriptHeader.OpCode) {
   1654 
   1655     case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
   1656       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE\n"));
   1657       Status = BootScriptExecuteMemoryWrite (Script);
   1658       break;
   1659 
   1660     case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
   1661       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE\n"));
   1662       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1663       Status = BootScriptExecuteMemoryReadWrite (
   1664                  Script,
   1665                  AndMask,
   1666                  OrMask
   1667                  );
   1668       break;
   1669 
   1670     case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
   1671       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_WRITE_OPCODE\n"));
   1672       Status = BootScriptExecuteIoWrite (Script);
   1673       break;
   1674 
   1675     case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
   1676       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE\n"));
   1677       Status = BootScriptExecutePciCfgWrite (Script);
   1678       break;
   1679 
   1680     case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
   1681       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE\n"));
   1682       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1683       Status = BootScriptExecutePciCfgReadWrite (
   1684                  Script,
   1685                  AndMask,
   1686                  OrMask
   1687                  );
   1688       break;
   1689     case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
   1690       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\n"));
   1691       Status = BootScriptExecutePciCfg2Write (Script);
   1692       break;
   1693 
   1694     case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
   1695       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE\n"));
   1696       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1697       Status = BootScriptExecutePciCfg2ReadWrite (
   1698                  Script,
   1699                  AndMask,
   1700                  OrMask
   1701                  );
   1702       break;
   1703     case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
   1704       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_OPCODE\n"));
   1705       Status = BootScriptExecuteDispatch (Script);
   1706       break;
   1707 
   1708     case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
   1709       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE\n"));
   1710       Status = BootScriptExecuteDispatch2 (Script);
   1711       break;
   1712 
   1713     case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
   1714       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_INFORMATION_OPCODE\n"));
   1715       BootScriptExecuteInformation (Script);
   1716       break;
   1717 
   1718     case S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE:
   1719       DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE\n"));
   1720       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_SUCCESS));
   1721       return EFI_SUCCESS;
   1722 
   1723     case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
   1724       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE\n"));
   1725       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1726       Status = BootScriptExecuteIoReadWrite (
   1727                 Script,
   1728                 AndMask,
   1729                 OrMask
   1730                 );
   1731       break;
   1732 
   1733     case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
   1734       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE\n"));
   1735       Status = BootScriptExecuteSmbusExecute (Script);
   1736       break;
   1737 
   1738     case EFI_BOOT_SCRIPT_STALL_OPCODE:
   1739       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_STALL_OPCODE\n"));
   1740       Status = BootScriptExecuteStall (Script);
   1741       break;
   1742 
   1743     case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
   1744       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_POLL_OPCODE\n"));
   1745       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1746       Status = BootScriptExecuteMemPoll (Script, AndMask, OrMask);
   1747 
   1748       break;
   1749 
   1750     case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
   1751       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_POLL_OPCODE\n"));
   1752       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1753       Status = BootScriptExecuteIoPoll (Script, AndMask, OrMask);
   1754       break;
   1755 
   1756     case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
   1757       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE\n"));
   1758       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1759       Status = BootScriptPciCfgPoll (Script, AndMask, OrMask);
   1760       break;
   1761 
   1762     case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
   1763      DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE\n"));
   1764      CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
   1765      Status = BootScriptPciCfg2Poll (Script, AndMask, OrMask);
   1766      break;
   1767 
   1768     case S3_BOOT_SCRIPT_LIB_LABEL_OPCODE:
   1769       //
   1770       // For label
   1771       //
   1772       DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_LABEL_OPCODE\n"));
   1773       BootScriptExecuteLabel (Script);
   1774       break;
   1775     default:
   1776       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_UNSUPPORTED));
   1777       return EFI_UNSUPPORTED;
   1778     }
   1779 
   1780     if (EFI_ERROR (Status)) {
   1781       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
   1782       return Status;
   1783     }
   1784 
   1785     Script  = Script + ScriptHeader.Length;
   1786   }
   1787 
   1788   DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
   1789 
   1790   return Status;
   1791 }
   1792 
   1793