Home | History | Annotate | Download | only in SmmS3SaveState
      1 /** @file
      2   Implementation for S3 SMM Boot Script Saver state driver.
      3 
      4   Copyright (c) 2010 - 2013, 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 "InternalSmmSaveState.h"
     17 
     18 EFI_S3_SMM_SAVE_STATE_PROTOCOL    mS3SmmSaveState = {
     19    BootScriptWrite,
     20    BootScriptInsert,
     21    BootScriptLabel,
     22    BootScriptCompare
     23   };
     24 /**
     25   Internal function to add IO write opcode to the table.
     26 
     27   @param  Marker                The variable argument list to get the opcode
     28                                 and associated attributes.
     29 
     30   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
     31   @retval EFI_SUCCESS           Opcode is added.
     32 
     33 **/
     34 EFI_STATUS
     35 BootScriptWriteIoWrite (
     36   IN VA_LIST                       Marker
     37   )
     38 {
     39   S3_BOOT_SCRIPT_LIB_WIDTH Width;
     40   UINT64                Address;
     41   UINTN                 Count;
     42   UINT8                 *Buffer;
     43 
     44   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
     45   Address     = VA_ARG (Marker, UINT64);
     46   Count       = VA_ARG (Marker, UINTN);
     47   Buffer      = VA_ARG (Marker, UINT8 *);
     48 
     49   return S3BootScriptSaveIoWrite (Width, Address, Count, Buffer);
     50 }
     51 /**
     52   Internal function to add IO read/write opcode to the table.
     53 
     54   @param  Marker                The variable argument list to get the opcode
     55                                 and associated attributes.
     56 
     57   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
     58   @retval EFI_SUCCESS           Opcode is added.
     59 
     60 **/
     61 EFI_STATUS
     62 BootScriptWriteIoReadWrite (
     63   IN VA_LIST                       Marker
     64   )
     65 {
     66   S3_BOOT_SCRIPT_LIB_WIDTH Width;
     67   UINT64                Address;
     68   UINT8                 *Data;
     69   UINT8                 *DataMask;
     70 
     71   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
     72   Address     = VA_ARG (Marker, UINT64);
     73   Data        = VA_ARG (Marker, UINT8 *);
     74   DataMask    = VA_ARG (Marker, UINT8 *);
     75 
     76   return S3BootScriptSaveIoReadWrite (Width, Address, Data, DataMask);
     77 }
     78 
     79 /**
     80   Internal function to add memory write opcode to the table.
     81 
     82   @param  Marker                The variable argument list to get the opcode
     83                                 and associated attributes.
     84 
     85   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
     86   @retval EFI_SUCCESS           Opcode is added.
     87 
     88 **/
     89 EFI_STATUS
     90 BootScriptWriteMemWrite (
     91   IN VA_LIST                       Marker
     92   )
     93 {
     94   S3_BOOT_SCRIPT_LIB_WIDTH Width;
     95   UINT64                Address;
     96   UINTN                 Count;
     97   UINT8                 *Buffer;
     98 
     99   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    100   Address     = VA_ARG (Marker, UINT64);
    101   Count       = VA_ARG (Marker, UINTN);
    102   Buffer      = VA_ARG (Marker, UINT8 *);
    103 
    104   return S3BootScriptSaveMemWrite (Width, Address, Count, Buffer);
    105 }
    106 
    107 /**
    108   Internal function to add memory read/write opcode to the table.
    109 
    110   @param  Marker                The variable argument list to get the opcode
    111                                 and associated attributes.
    112 
    113   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    114   @retval EFI_SUCCESS           Opcode is added.
    115 
    116 **/
    117 EFI_STATUS
    118 BootScriptWriteMemReadWrite (
    119   IN VA_LIST                       Marker
    120   )
    121 {
    122   S3_BOOT_SCRIPT_LIB_WIDTH Width;
    123   UINT64                Address;
    124   UINT8                 *Data;
    125   UINT8                 *DataMask;
    126 
    127   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    128   Address     = VA_ARG (Marker, UINT64);
    129   Data        = VA_ARG (Marker, UINT8 *);
    130   DataMask    = VA_ARG (Marker, UINT8 *);
    131 
    132   return S3BootScriptSaveMemReadWrite (Width, Address, Data, DataMask);
    133 }
    134 
    135 /**
    136   Internal function to add PciCfg write opcode to the table.
    137 
    138   @param  Marker                The variable argument list to get the opcode
    139                                 and associated attributes.
    140 
    141   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    142   @retval EFI_SUCCESS           Opcode is added.
    143 
    144 **/
    145 EFI_STATUS
    146 BootScriptWritePciCfgWrite (
    147   IN VA_LIST                       Marker
    148   )
    149 {
    150   S3_BOOT_SCRIPT_LIB_WIDTH Width;
    151   UINT64                Address;
    152   UINTN                 Count;
    153   UINT8                 *Buffer;
    154 
    155   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    156   Address     = VA_ARG (Marker, UINT64);
    157   Count       = VA_ARG (Marker, UINTN);
    158   Buffer      = VA_ARG (Marker, UINT8 *);
    159 
    160   return S3BootScriptSavePciCfgWrite (Width, Address, Count, Buffer);
    161 }
    162 
    163 /**
    164   Internal function to PciCfg read/write opcode to the table.
    165 
    166   @param  Marker                The variable argument list to get the opcode
    167                                 and associated attributes.
    168 
    169   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    170   @retval EFI_SUCCESS           Opcode is added.
    171 
    172 **/
    173 EFI_STATUS
    174 BootScriptWritePciCfgReadWrite (
    175   IN VA_LIST                       Marker
    176   )
    177 {
    178   S3_BOOT_SCRIPT_LIB_WIDTH Width;
    179   UINT64                Address;
    180   UINT8                 *Data;
    181   UINT8                 *DataMask;
    182 
    183   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    184   Address     = VA_ARG (Marker, UINT64);
    185   Data        = VA_ARG (Marker, UINT8 *);
    186   DataMask    = VA_ARG (Marker, UINT8 *);
    187 
    188   return S3BootScriptSavePciCfgReadWrite (Width, Address, Data, DataMask);
    189 }
    190 /**
    191   Internal function to add PciCfg2 write opcode to the table.
    192 
    193   @param  Marker                The variable argument list to get the opcode
    194                                 and associated attributes.
    195 
    196   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    197   @retval EFI_SUCCESS           Opcode is added.
    198 
    199 **/
    200 EFI_STATUS
    201 BootScriptWritePciCfg2Write (
    202   IN VA_LIST                       Marker
    203   )
    204 {
    205   S3_BOOT_SCRIPT_LIB_WIDTH Width;
    206   UINT64                Address;
    207   UINTN                 Count;
    208   UINT8                 *Buffer;
    209   UINT16                Segment;
    210 
    211   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    212   Address     = VA_ARG (Marker, UINT64);
    213   Count       = VA_ARG (Marker, UINTN);
    214   Buffer      = VA_ARG (Marker, UINT8 *);
    215   Segment     = VA_ARG (Marker, UINT16);
    216 
    217   return S3BootScriptSavePciCfg2Write (Width, Segment, Address, Count, Buffer);
    218 }
    219 
    220 /**
    221   Internal function to PciCfg2 read/write opcode to the table.
    222 
    223   @param  Marker                The variable argument list to get the opcode
    224                                 and associated attributes.
    225 
    226   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    227   @retval EFI_SUCCESS           Opcode is added.
    228 
    229 **/
    230 EFI_STATUS
    231 BootScriptWritePciCfg2ReadWrite (
    232   IN VA_LIST                       Marker
    233   )
    234 {
    235   S3_BOOT_SCRIPT_LIB_WIDTH Width;
    236   UINT16                Segment;
    237   UINT64                Address;
    238   UINT8                 *Data;
    239   UINT8                 *DataMask;
    240 
    241   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    242   Address     = VA_ARG (Marker, UINT64);
    243   Segment     = VA_ARG (Marker, UINT16);
    244   Data        = VA_ARG (Marker, UINT8 *);
    245   DataMask    = VA_ARG (Marker, UINT8 *);
    246 
    247   return S3BootScriptSavePciCfg2ReadWrite (Width, Segment, Address, Data, DataMask);
    248 }
    249 /**
    250   Internal function to add smbus excute opcode to the table.
    251 
    252   @param  Marker                The variable argument list to get the opcode
    253                                 and associated attributes.
    254 
    255   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    256   @retval EFI_SUCCESS           Opcode is added.
    257 
    258 **/
    259 EFI_STATUS
    260 BootScriptWriteSmbusExecute (
    261   IN VA_LIST                       Marker
    262   )
    263 {
    264   EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress;
    265   EFI_SMBUS_DEVICE_COMMAND  Command;
    266   EFI_SMBUS_OPERATION       Operation;
    267   BOOLEAN                   PecCheck;
    268   VOID                     *Buffer;
    269   UINTN                    *DataSize;
    270   UINTN                     SmBusAddress;
    271 
    272   SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN);
    273   Command                         = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND);
    274   Operation                       = VA_ARG (Marker, EFI_SMBUS_OPERATION);
    275   PecCheck                        = VA_ARG (Marker, BOOLEAN);
    276   SmBusAddress                    = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress,Command,0,PecCheck);
    277   DataSize                        = VA_ARG (Marker, UINTN *);
    278   Buffer                          = VA_ARG (Marker, VOID *);
    279 
    280   return S3BootScriptSaveSmbusExecute (SmBusAddress, Operation, DataSize, Buffer);
    281 }
    282 /**
    283   Internal function to add stall opcode to the table.
    284 
    285   @param  Marker                The variable argument list to get the opcode
    286                                 and associated attributes.
    287 
    288   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    289   @retval EFI_SUCCESS           Opcode is added.
    290 
    291 **/
    292 EFI_STATUS
    293 BootScriptWriteStall (
    294   IN VA_LIST                       Marker
    295   )
    296 {
    297   UINT32                Duration;
    298 
    299   Duration    = VA_ARG (Marker, UINT32);
    300 
    301   return S3BootScriptSaveStall (Duration);
    302 }
    303 
    304 /**
    305   Internal function to add Save jmp address according to DISPATCH_OPCODE.
    306   We ignore "Context" parameter
    307 
    308   @param  Marker                The variable argument list to get the opcode
    309                                 and associated attributes.
    310 
    311   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    312   @retval EFI_SUCCESS           Opcode is added.
    313 
    314 **/
    315 EFI_STATUS
    316 BootScriptWriteDispatch (
    317   IN VA_LIST                       Marker
    318   )
    319 {
    320   VOID        *EntryPoint;
    321 
    322   EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
    323   return S3BootScriptSaveDispatch (EntryPoint);
    324 }
    325 
    326 /**
    327   Internal function to add memory pool operation to the table.
    328 
    329   @param  Marker                The variable argument list to get the opcode
    330                                 and associated attributes.
    331 
    332   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    333   @retval EFI_SUCCESS           Opcode is added.
    334 
    335 **/
    336 EFI_STATUS
    337 BootScriptWriteMemPoll (
    338   IN VA_LIST                       Marker
    339   )
    340 {
    341   S3_BOOT_SCRIPT_LIB_WIDTH   Width;
    342   UINT64                     Address;
    343   VOID                      *Data;
    344   VOID                      *DataMask;
    345   UINTN                      Delay;
    346   UINTN                      LoopTimes;
    347   UINT32                     Remainder;
    348 
    349   Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    350   Address  = VA_ARG (Marker, UINT64);
    351   Data     = VA_ARG (Marker, VOID *);
    352   DataMask = VA_ARG (Marker, VOID *);
    353   Delay    = (UINTN)VA_ARG (Marker, UINT64);
    354   //
    355   // According to the spec, the interval between 2 polls is 100ns,
    356   // but the unit of Duration for S3BootScriptSaveMemPoll() is microsecond(1000ns).
    357   // Duration * 1000ns * LoopTimes = Delay * 100ns
    358   // Duration will be minimum 1(microsecond) to be minimum deviation,
    359   // so LoopTimes = Delay / 10.
    360   //
    361   LoopTimes = (UINTN) DivU64x32Remainder (
    362                 Delay,
    363                 10,
    364                 &Remainder
    365                 );
    366   if (Remainder != 0) {
    367     //
    368     // If Remainder is not zero, LoopTimes will be rounded up by 1.
    369     //
    370     LoopTimes +=1;
    371   }
    372   return S3BootScriptSaveMemPoll (Width, Address, DataMask, Data, 1, LoopTimes);
    373 
    374 }
    375 
    376 /**
    377   Internal function to add Save jmp address according to DISPATCH_OPCODE2.
    378   The "Context" parameter is not ignored.
    379 
    380   @param  Marker                The variable argument list to get the opcode
    381                                 and associated attributes.
    382 
    383   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
    384   @retval EFI_SUCCESS           Opcode is added.
    385 
    386 **/
    387 EFI_STATUS
    388 BootScriptWriteDispatch2 (
    389   IN VA_LIST                       Marker
    390   )
    391 {
    392   VOID                  *EntryPoint;
    393   VOID                  *Context;
    394 
    395   EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
    396   Context    = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
    397 
    398   return S3BootScriptSaveDispatch2 (EntryPoint, Context);
    399 }
    400 /**
    401   Internal function to add INFORAMTION opcode node to the table
    402   list.
    403   @param  Marker                The variable argument list to get the opcode
    404                                 and associated attributes.
    405 
    406   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
    407   @retval EFI_SUCCESS           The opcode entry is added to the  table
    408                                 successfully.
    409 **/
    410 EFI_STATUS
    411 BootScriptWriteInformation (
    412   IN VA_LIST                       Marker
    413   )
    414 {
    415   UINT32                InformationLength;
    416   EFI_PHYSICAL_ADDRESS  Information;
    417 
    418   InformationLength = VA_ARG (Marker, UINT32);
    419   Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
    420   return S3BootScriptSaveInformation (InformationLength, (VOID*)(UINTN)Information);
    421 }
    422 /**
    423   Internal function to add IO poll opcode node  to the table
    424   @param  Marker                The variable argument list to get the opcode
    425                                 and associated attributes.
    426 
    427   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
    428   @retval EFI_SUCCESS           The opcode entry is added to the  table
    429                                 successfully.
    430 **/
    431 EFI_STATUS
    432 BootScriptWriteIoPoll (
    433   IN VA_LIST                       Marker
    434   )
    435 {
    436    S3_BOOT_SCRIPT_LIB_WIDTH     Width;
    437    UINT64                     Address;
    438    VOID                      *Data;
    439    VOID                      *DataMask;
    440    UINT64                     Delay;
    441 
    442    Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    443    Address  = VA_ARG (Marker, UINT64);
    444    Data     = VA_ARG (Marker, VOID *);
    445    DataMask = VA_ARG (Marker, VOID *);
    446    Delay    = (UINT64)VA_ARG (Marker, UINT64);
    447 
    448    return S3BootScriptSaveIoPoll (Width, Address, Data, DataMask, Delay);
    449 }
    450 /**
    451   Internal function to add PCI config poll opcode node to the table
    452 
    453   @param  Marker                The variable argument list to get the opcode
    454                                 and associated attributes.
    455 
    456   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
    457   @retval EFI_SUCCESS           The opcode entry is added to the  table
    458                                 successfully.
    459 **/
    460 EFI_STATUS
    461 BootScriptWritePciConfigPoll (
    462   IN VA_LIST                       Marker
    463   )
    464 {
    465    S3_BOOT_SCRIPT_LIB_WIDTH   Width;
    466    UINT64                     Address;
    467    VOID                      *Data;
    468    VOID                      *DataMask;
    469    UINT64                     Delay;
    470 
    471 
    472    Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    473    Address  = VA_ARG (Marker, UINT64);
    474    Data     = VA_ARG (Marker, VOID *);
    475    DataMask = VA_ARG (Marker, VOID *);
    476    Delay    = (UINT64)VA_ARG (Marker, UINT64);
    477 
    478    return S3BootScriptSavePciPoll (Width, Address, Data, DataMask, Delay);
    479 }
    480 /**
    481   Internal function to add PCI config 2 poll opcode node to the table
    482 
    483   @param  Marker                The variable argument list to get the opcode
    484                                 and associated attributes.
    485 
    486   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
    487   @retval EFI_SUCCESS           The opcode entry is added to the  table
    488                                 successfully.
    489 **/
    490 EFI_STATUS
    491 BootScriptWritePciConfig2Poll (
    492   IN VA_LIST                       Marker
    493   )
    494 {
    495    S3_BOOT_SCRIPT_LIB_WIDTH      Width;
    496    UINT16                        Segment;
    497    UINT64                        Address;
    498    VOID                         *Data;
    499    VOID                         *DataMask;
    500    UINT64                        Delay;
    501 
    502    Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
    503    Segment  = VA_ARG (Marker, UINT16);
    504    Address  = VA_ARG (Marker, UINT64);
    505    Data     = VA_ARG (Marker, VOID *);
    506    DataMask = VA_ARG (Marker, VOID *);
    507    Delay    = (UINT64)VA_ARG (Marker, UINT64);
    508 
    509    return S3BootScriptSavePci2Poll (Width, Segment, Address, Data, DataMask, Delay);
    510 }
    511 
    512 /**
    513   Adds a record into S3 boot script table.
    514 
    515   This function is used to store a boot script record into a given boot
    516   script table. If the table specified by TableName is nonexistent in the
    517   system, a new table will automatically be created and then the script record
    518   will be added into the new table. This function is responsible for allocating
    519   necessary memory for the script.
    520 
    521   This function has a variable parameter list. The exact parameter list depends on
    522   the OpCode that is passed into the function. If an unsupported OpCode or illegal
    523   parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
    524   If there are not enough resources available for storing more scripts, this function returns
    525   EFI_OUT_OF_RESOURCES.
    526 
    527   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
    528   @param  OpCode                The operation code (opcode) number.
    529   @param  ...                   Argument list that is specific to each opcode.
    530 
    531   @retval EFI_SUCCESS           The operation succeeded. A record was added into the
    532                                 specified script table.
    533   @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
    534                                 If the opcode is unknow or not supported because of the PCD
    535                                 Feature Flags.
    536   @retval EFI_OUT_OF_RESOURCES  There is insufficient memory to store the boot script.
    537 
    538 **/
    539 EFI_STATUS
    540 EFIAPI
    541 BootScriptWrite (
    542   IN CONST EFI_S3_SAVE_STATE_PROTOCOL         *This,
    543   IN UINT16                                    OpCode,
    544   ...
    545   )
    546 {
    547   EFI_STATUS                Status;
    548   VA_LIST                   Marker;
    549   //
    550   // Build script according to opcode
    551   //
    552   switch (OpCode) {
    553 
    554   case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
    555     VA_START (Marker, OpCode);
    556     Status = BootScriptWriteIoWrite (Marker);
    557     VA_END (Marker);
    558     break;
    559 
    560   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
    561     VA_START (Marker, OpCode);
    562     Status = BootScriptWriteIoReadWrite (Marker);
    563     VA_END (Marker);
    564     break;
    565 
    566   case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
    567     VA_START (Marker, OpCode);
    568     Status = BootScriptWriteMemWrite (Marker);
    569     VA_END (Marker);
    570     break;
    571 
    572   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
    573     VA_START (Marker, OpCode);
    574     Status = BootScriptWriteMemReadWrite (Marker);
    575     VA_END (Marker);
    576     break;
    577 
    578   case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
    579     VA_START (Marker, OpCode);
    580     Status = BootScriptWritePciCfgWrite (Marker);
    581     VA_END (Marker);
    582     break;
    583 
    584   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
    585     VA_START (Marker, OpCode);
    586     Status = BootScriptWritePciCfgReadWrite (Marker);
    587     VA_END (Marker);
    588     break;
    589 
    590   case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
    591     VA_START (Marker, OpCode);
    592     Status = BootScriptWriteSmbusExecute (Marker);
    593     VA_END (Marker);
    594     break;
    595 
    596   case EFI_BOOT_SCRIPT_STALL_OPCODE:
    597     VA_START (Marker, OpCode);
    598     Status = BootScriptWriteStall (Marker);
    599     VA_END (Marker);
    600 
    601     break;
    602 
    603   case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
    604     VA_START (Marker, OpCode);
    605     Status = BootScriptWriteDispatch (Marker);
    606     VA_END (Marker);
    607     break;
    608 
    609   case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
    610     VA_START (Marker, OpCode);
    611     Status = BootScriptWriteDispatch2 (Marker);
    612     VA_END (Marker);
    613     break;
    614 
    615   case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
    616     VA_START (Marker, OpCode);
    617     Status = BootScriptWriteInformation (Marker);
    618     VA_END (Marker);
    619     break;
    620 
    621   case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
    622     VA_START (Marker, OpCode);
    623     Status = BootScriptWriteMemPoll (Marker);
    624     VA_END (Marker);
    625     break;
    626 
    627   case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
    628     VA_START (Marker, OpCode);
    629     Status = BootScriptWritePciCfg2Write (Marker);
    630     VA_END (Marker);
    631     break;
    632 
    633   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
    634     VA_START (Marker, OpCode);
    635     Status = BootScriptWritePciCfg2ReadWrite (Marker);
    636     VA_END (Marker);
    637     break;
    638 
    639   case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
    640     VA_START (Marker, OpCode);
    641     Status = BootScriptWriteIoPoll (Marker);
    642     VA_END (Marker);
    643     break;
    644 
    645   case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
    646     VA_START (Marker, OpCode);
    647     Status = BootScriptWritePciConfigPoll (Marker);
    648     VA_END (Marker);
    649     break;
    650 
    651   case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
    652     VA_START (Marker, OpCode);
    653     Status = BootScriptWritePciConfig2Poll (Marker);
    654     VA_END (Marker);
    655     break;
    656 
    657   default:
    658     Status = EFI_INVALID_PARAMETER;
    659     break;
    660   }
    661 
    662   return Status;
    663 }
    664 /**
    665   Insert a record into a specified Framework boot script table.
    666 
    667   This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is
    668   assumed this protocol has platform specific mechanism to store the OpCode set and replay them
    669   during the S3 resume.
    670   The opcode is inserted before or after the specified position in the boot script table. If Position is
    671   NULL then that position is after the last opcode in the table (BeforeOrAfter is FALSE) or before
    672   the first opcode in the table (BeforeOrAfter is TRUE). The position which is pointed to by
    673   Position upon return can be used for subsequent insertions.
    674 
    675   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
    676   @param  BeforeOrAfter         Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
    677                                 in the boot script table specified by Position. If Position is NULL or points to
    678                                 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
    679                                 of the table (if FALSE).
    680   @param  Position              On entry, specifies the position in the boot script table where the opcode will be
    681                                 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
    682                                 the position of the inserted opcode in the boot script table.
    683   @param  OpCode                The operation code (opcode) number.
    684   @param  ...                   Argument list that is specific to each opcode.
    685 
    686   @retval EFI_SUCCESS           The operation succeeded. A record was added into the
    687                                 specified script table.
    688   @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
    689   @retval EFI_OUT_OF_RESOURCES  There is insufficient memory to store the boot script.
    690 
    691 **/
    692 EFI_STATUS
    693 EFIAPI
    694 BootScriptInsert (
    695   IN CONST EFI_S3_SAVE_STATE_PROTOCOL    *This,
    696   IN       BOOLEAN                          BeforeOrAfter,
    697   IN OUT   EFI_S3_BOOT_SCRIPT_POSITION     *Position OPTIONAL,
    698   IN       UINT16                           OpCode,
    699   ...
    700   )
    701 {
    702   EFI_STATUS                Status;
    703   VA_LIST                   Marker;
    704   //
    705   // Build script according to opcode
    706   //
    707   switch (OpCode) {
    708 
    709   case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
    710     VA_START (Marker, OpCode);
    711     Status = BootScriptWriteIoWrite (Marker);
    712     VA_END (Marker);
    713     break;
    714 
    715   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
    716     VA_START (Marker, OpCode);
    717     Status = BootScriptWriteIoReadWrite (Marker);
    718     VA_END (Marker);
    719     break;
    720 
    721   case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
    722     VA_START (Marker, OpCode);
    723     Status = BootScriptWriteMemWrite (Marker);
    724     VA_END (Marker);
    725     break;
    726 
    727   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
    728     VA_START (Marker, OpCode);
    729     Status = BootScriptWriteMemReadWrite (Marker);
    730     VA_END (Marker);
    731     break;
    732 
    733   case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
    734     VA_START (Marker, OpCode);
    735     Status = BootScriptWritePciCfgWrite (Marker);
    736     VA_END (Marker);
    737     break;
    738 
    739   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
    740     VA_START (Marker, OpCode);
    741     Status = BootScriptWritePciCfgReadWrite (Marker);
    742     VA_END (Marker);
    743     break;
    744 
    745   case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
    746     VA_START (Marker, OpCode);
    747     Status = BootScriptWriteSmbusExecute (Marker);
    748     VA_END (Marker);
    749     break;
    750 
    751   case EFI_BOOT_SCRIPT_STALL_OPCODE:
    752     VA_START (Marker, OpCode);
    753     Status = BootScriptWriteStall (Marker);
    754     VA_END (Marker);
    755 
    756     break;
    757 
    758   case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
    759     VA_START (Marker, OpCode);
    760     Status = BootScriptWriteDispatch (Marker);
    761     VA_END (Marker);
    762     break;
    763 
    764   case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
    765     VA_START (Marker, OpCode);
    766     Status = BootScriptWriteDispatch2 (Marker);
    767     VA_END (Marker);
    768     break;
    769 
    770   case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
    771     VA_START (Marker, OpCode);
    772     Status = BootScriptWriteInformation (Marker);
    773     VA_END (Marker);
    774     break;
    775 
    776   case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
    777     VA_START (Marker, OpCode);
    778     Status = BootScriptWriteMemPoll (Marker);
    779     VA_END (Marker);
    780     break;
    781 
    782   case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
    783     VA_START (Marker, OpCode);
    784     Status = BootScriptWritePciCfg2Write (Marker);
    785     VA_END (Marker);
    786     break;
    787 
    788   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
    789     VA_START (Marker, OpCode);
    790     Status = BootScriptWritePciCfg2ReadWrite (Marker);
    791     VA_END (Marker);
    792     break;
    793 
    794   case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
    795     VA_START (Marker, OpCode);
    796     Status = BootScriptWriteIoPoll (Marker);
    797     VA_END (Marker);
    798     break;
    799 
    800   case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
    801     VA_START (Marker, OpCode);
    802     Status = BootScriptWritePciConfigPoll (Marker);
    803     VA_END (Marker);
    804     break;
    805 
    806   case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
    807     VA_START (Marker, OpCode);
    808     Status = BootScriptWritePciConfig2Poll (Marker);
    809     VA_END (Marker);
    810     break;
    811 
    812   default:
    813     Status = EFI_INVALID_PARAMETER;
    814     break;
    815   }
    816 
    817   if (!EFI_ERROR (Status)) {
    818    Status = S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
    819   }
    820   return Status;
    821 }
    822 /**
    823   Find a label within the boot script table and, if not present, optionally create it.
    824 
    825   If the label Label is already exists in the boot script table, then no new label is created, the
    826   position of the Label is returned in *Position and EFI_SUCCESS is returned.
    827   If the label Label does not already exist and CreateIfNotFound is TRUE, then it will be
    828   created before or after the specified position and EFI_SUCCESS is returned.
    829   If the label Label does not already exist and CreateIfNotFound is FALSE, then
    830   EFI_NOT_FOUND is returned.
    831 
    832   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
    833   @param  BeforeOrAfter         Specifies whether the label is stored before (TRUE) or after (FALSE) the position in
    834                                 the boot script table specified by Position. If Position is NULL or points to
    835                                 NULL then the new label is inserted at the beginning of the table (if TRUE) or end of
    836                                 the table (if FALSE).
    837   @param  CreateIfNotFound      Specifies whether the label will be created if the label does not exists (TRUE) or not
    838                                 (FALSE).
    839   @param  Position              On entry, specifies the position in the boot script table where the label will be inserted,
    840                                 either before or after, depending on BeforeOrAfter. On exit, specifies the position
    841                                 of the inserted label in the boot script table.
    842   @param  Label                 Points to the label which will be inserted in the boot script table.
    843 
    844   @retval EFI_SUCCESS           The label already exists or was inserted.
    845   @retval EFI_INVALID_PARAMETER The Label is NULL or points to an empty string.
    846   @retval EFI_INVALID_PARAMETER The Position is not a valid position in the boot script table.
    847 
    848 **/
    849 EFI_STATUS
    850 EFIAPI
    851 BootScriptLabel (
    852   IN CONST EFI_S3_SAVE_STATE_PROTOCOL           *This,
    853   IN       BOOLEAN                               BeforeOrAfter,
    854   IN       BOOLEAN                               CreateIfNotFound,
    855   IN OUT   EFI_S3_BOOT_SCRIPT_POSITION          *Position OPTIONAL,
    856   IN CONST CHAR8                                *Label
    857   )
    858 {
    859 	return S3BootScriptLabel (BeforeOrAfter, CreateIfNotFound, Position, Label);
    860 }
    861 /**
    862   Compare two positions in the boot script table and return their relative position.
    863 
    864   This function compares two positions in the boot script table and returns their relative positions. If
    865   Position1 is before Position2, then -1 is returned. If Position1 is equal to Position2,
    866   then 0 is returned. If Position1 is after Position2, then 1 is returned.
    867 
    868   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
    869   @param  Position1             The positions in the boot script table to compare
    870   @param  Position2             The positions in the boot script table to compare
    871   @param  RelativePosition      On return, points to the result of the comparison
    872 
    873   @retval EFI_SUCCESS           The operation succeeded.
    874   @retval EFI_INVALID_PARAMETER The Position1 or Position2 is not a valid position in the boot script table.
    875   @retval EFI_INVALID_PARAMETER The RelativePosition is NULL.
    876 
    877 **/
    878 EFI_STATUS
    879 EFIAPI
    880 BootScriptCompare (
    881   IN CONST EFI_S3_SAVE_STATE_PROTOCOL      *This,
    882   IN       EFI_S3_BOOT_SCRIPT_POSITION      Position1,
    883   IN       EFI_S3_BOOT_SCRIPT_POSITION      Position2,
    884   OUT      UINTN                           *RelativePosition
    885   )
    886 {
    887 	return S3BootScriptCompare (Position1, Position2, RelativePosition);
    888 }
    889 /**
    890   This routine is entry point of ScriptSave driver.
    891 
    892   @param  ImageHandle           Handle for this drivers loaded image protocol.
    893   @param  SystemTable           EFI system table.
    894 
    895   @retval EFI_OUT_OF_RESOURCES  No enough resource
    896   @retval EFI_SUCCESS           Succesfully installed the ScriptSave driver.
    897   @retval other                 Errors occured.
    898 
    899 **/
    900 EFI_STATUS
    901 EFIAPI
    902 InitializeSmmS3SaveState (
    903   IN EFI_HANDLE           ImageHandle,
    904   IN EFI_SYSTEM_TABLE     *SystemTable
    905   )
    906 {
    907   EFI_HANDLE   Handle;
    908 
    909 
    910   Handle  = NULL;
    911   return  gSmst->SmmInstallProtocolInterface (
    912                    &Handle,
    913                    &gEfiS3SmmSaveStateProtocolGuid,
    914                    EFI_NATIVE_INTERFACE,
    915                    &mS3SmmSaveState
    916                    );
    917 }
    918