EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c

Go to the documentation of this file.
00001 
00016 #include "InternalBootScriptLib.h"
00017 
00041 SCRIPT_TABLE_PRIVATE_DATA        *mS3BootScriptTablePtr;
00042 EFI_EVENT                        mEnterRuntimeEvent;
00043 //
00044 // Allocate local copy in SMM because we can not use mS3BootScriptTablePtr when we AtRuntime in InSmm.
00045 //
00046 SCRIPT_TABLE_PRIVATE_DATA        mS3BootScriptTable;
00047 UINTN                            mLockBoxLength;
00048 
00049 EFI_GUID                         mBootScriptDataGuid = {
00050   0xaea6b965, 0xdcf5, 0x4311, 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2
00051 };
00052 
00053 EFI_GUID                         mBootScriptHeaderDataGuid = {
00054   0x1810ab4a, 0x2314, 0x4df6, 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91
00055 };
00056 
00063 UINT8*
00064 S3BootScriptInternalCloseTable (
00065   VOID
00066   )
00067 {
00068   UINT8                          *S3TableBase;
00069   EFI_BOOT_SCRIPT_TERMINATE      ScriptTerminate;
00070   EFI_BOOT_SCRIPT_TABLE_HEADER   *ScriptTableInfo;
00071   S3TableBase = mS3BootScriptTablePtr->TableBase;
00072   
00073   if (S3TableBase == NULL) {
00074     //
00075     // the table is not exist
00076     //
00077     return S3TableBase;
00078   }
00079   //
00080   // Append the termination entry.
00081   //
00082   ScriptTerminate.OpCode  = S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE;
00083   ScriptTerminate.Length  = (UINT8) sizeof (EFI_BOOT_SCRIPT_TERMINATE);
00084   CopyMem (mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength, &ScriptTerminate, sizeof (EFI_BOOT_SCRIPT_TERMINATE));
00085   //
00086   // fill the table length
00087   //
00088   ScriptTableInfo                = (EFI_BOOT_SCRIPT_TABLE_HEADER*)(mS3BootScriptTablePtr->TableBase);
00089   ScriptTableInfo->TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
00090   
00091  
00092   
00093   return S3TableBase;
00094   //
00095   // NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to 
00096   // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE). Because 
00097   // maybe in runtime, we still need add entries into the table, and the runtime entry should be
00098   // added start before this TERMINATE node.
00099   //
00100 }  
00101 
00109 VOID
00110 SaveBootScriptDataToLockBox (
00111   VOID
00112   )
00113 {
00114   EFI_STATUS Status;
00115   //
00116   // mS3BootScriptTablePtr->TableLength does not include EFI_BOOT_SCRIPT_TERMINATE, because we need add entry at runtime.
00117   // Save all info here, just in case that no one will add boot script entry in SMM.
00118   //
00119   Status = SaveLockBox (
00120              &mBootScriptDataGuid,
00121              (VOID *)mS3BootScriptTablePtr->TableBase,
00122              mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE)
00123              );
00124   ASSERT_EFI_ERROR (Status);
00125 
00126   Status = SetLockBoxAttributes (&mBootScriptDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
00127   ASSERT_EFI_ERROR (Status);
00128 
00129   //
00130   // Just need save TableBase.
00131   // Do not update other field because they will NOT be used in S3.
00132   //
00133   Status = SaveLockBox (
00134              &mBootScriptHeaderDataGuid,
00135              (VOID *)&mS3BootScriptTablePtr->TableBase,
00136              sizeof(mS3BootScriptTablePtr->TableBase)
00137              );
00138   ASSERT_EFI_ERROR (Status);
00139 
00140   Status = SetLockBoxAttributes (&mBootScriptHeaderDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
00141   ASSERT_EFI_ERROR (Status);
00142 }
00143 
00151 VOID
00152 EFIAPI
00153 S3BootScriptEventCallBack (
00154   IN EFI_EVENT  Event,
00155   IN VOID       *Context
00156   )
00157 {
00158   EFI_STATUS   Status;
00159   VOID         *Interface;
00160 
00161   //
00162   // Try to locate it because EfiCreateProtocolNotifyEvent will trigger it once when registration.
00163   // Just return if it is not found.
00164   //
00165   Status = gBS->LocateProtocol (
00166                   &gEfiDxeSmmReadyToLockProtocolGuid,
00167                   NULL,
00168                   &Interface
00169                   );
00170   if (EFI_ERROR (Status)) {
00171     return ;
00172   }
00173 
00174   //
00175   // Here we should tell the library that we are enter into runtime phase. and 
00176   // the memory page number occupied by the table should not grow anymore.
00177   //
00178   if (!mS3BootScriptTablePtr->AtRuntime) {
00179     //
00180     // In boot time, we need not write the terminate node when adding a node to boot scipt table
00181     // or else, that will impact the performance. However, in runtime, we should append terminate
00182     // node on every add to boot script table
00183     //
00184     S3BootScriptInternalCloseTable ();
00185     mS3BootScriptTablePtr->AtRuntime = TRUE;
00186 
00187     //
00188     // Save BootScript data to lockbox
00189     //
00190     SaveBootScriptDataToLockBox ();
00191   }
00192 } 
00203 EFI_STATUS
00204 EFIAPI
00205 S3BootScriptSmmEventCallBack (
00206   IN CONST EFI_GUID  *Protocol,
00207   IN VOID            *Interface,
00208   IN EFI_HANDLE      Handle
00209   )
00210 {
00211   //
00212   // Check if it is already done
00213   //
00214   if (mS3BootScriptTablePtr == &mS3BootScriptTable) {
00215     return EFI_SUCCESS;
00216   }
00217 
00218   //
00219   // Last chance to call-out, just make sure AtRuntime is set
00220   //
00221   S3BootScriptEventCallBack (NULL, NULL);
00222 
00223   //
00224   // Save a local copy
00225   //
00226   CopyMem (&mS3BootScriptTable, mS3BootScriptTablePtr, sizeof(*mS3BootScriptTablePtr));
00227   //
00228   // We should not use ACPINvs copy, because it is not safe.
00229   //
00230   mS3BootScriptTablePtr = &mS3BootScriptTable;
00231 
00232   //
00233   // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.
00234   // InSmm will only be checked if AtRuntime is TRUE.
00235   //
00236   mS3BootScriptTablePtr->InSmm = TRUE;
00237 
00238   //
00239   // Record LockBoxLength
00240   //
00241   mLockBoxLength = mS3BootScriptTable.TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE);
00242 
00243   return EFI_SUCCESS;
00244 }
00245 
00257 RETURN_STATUS
00258 EFIAPI
00259 S3BootScriptLibInitialize (
00260   IN EFI_HANDLE           ImageHandle,
00261   IN EFI_SYSTEM_TABLE     *SystemTable
00262   )
00263 {
00264   EFI_STATUS                      Status;
00265   SCRIPT_TABLE_PRIVATE_DATA      *S3TablePtr;
00266   VOID                           *Registration;
00267   EFI_SMM_BASE2_PROTOCOL         *SmmBase2;
00268   BOOLEAN                        InSmm;
00269   EFI_SMM_SYSTEM_TABLE2          *Smst;
00270   EFI_PHYSICAL_ADDRESS           Buffer;
00271 
00272   S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateDataPtr);
00273   //
00274   // The Boot script private data is not be initialized. create it
00275   //
00276   if (S3TablePtr == 0) {
00277     Buffer = SIZE_4GB - 1;
00278     Status = gBS->AllocatePages (
00279                     AllocateMaxAddress,
00280                     EfiACPIMemoryNVS,
00281                     EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)),
00282                     &Buffer
00283                     );
00284     if (EFI_ERROR (Status)) {
00285       return RETURN_OUT_OF_RESOURCES;
00286     }
00287     S3TablePtr = (VOID *) (UINTN) Buffer;
00288 
00289     PcdSet64 (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr); 
00290     ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));  
00291     //
00292     // create event to notify the library system enter the runtime phase
00293     //
00294     mEnterRuntimeEvent = EfiCreateProtocolNotifyEvent  (
00295                           &gEfiDxeSmmReadyToLockProtocolGuid,
00296                           TPL_CALLBACK,
00297                           S3BootScriptEventCallBack,
00298                           NULL,
00299                           &Registration
00300                           );
00301     ASSERT (mEnterRuntimeEvent != NULL);
00302   } 
00303   mS3BootScriptTablePtr = S3TablePtr;
00304 
00305   //
00306   // Get InSmm, we need to register SmmReadyToLock if this library is linked to SMM driver.
00307   //
00308   Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID**) &SmmBase2);
00309   if (EFI_ERROR (Status)) {
00310     return RETURN_SUCCESS;
00311   }
00312   Status = SmmBase2->InSmm (SmmBase2, &InSmm);
00313   if (EFI_ERROR (Status)) {
00314     return RETURN_SUCCESS;
00315   }
00316   if (!InSmm) {
00317     return RETURN_SUCCESS;
00318   }
00319   //
00320   // Good, we are in SMM
00321   //
00322   Status = SmmBase2->GetSmstLocation (SmmBase2, &Smst);
00323   if (EFI_ERROR (Status)) {
00324     return RETURN_SUCCESS;
00325   }
00326 
00327   //
00328   // Then register event after lock
00329   //
00330   Registration = NULL;
00331   Status = Smst->SmmRegisterProtocolNotify (
00332                    &gEfiSmmReadyToLockProtocolGuid,
00333                    S3BootScriptSmmEventCallBack,
00334                    &Registration
00335                    );
00336   ASSERT_EFI_ERROR (Status);
00337 
00338   return RETURN_SUCCESS;
00339 }
00350 UINT8*
00351 S3BootScriptGetBootTimeEntryAddAddress (
00352   UINT8  EntryLength
00353   )
00354 {
00355    EFI_PHYSICAL_ADDRESS              S3TableBase;
00356    EFI_PHYSICAL_ADDRESS              NewS3TableBase;
00357    UINT8                            *NewEntryPtr;
00358    UINT32                            TableLength;
00359    UINT16                            PageNumber;
00360    EFI_STATUS                        Status;
00361    EFI_BOOT_SCRIPT_TABLE_HEADER      *ScriptTableInfo;
00362    
00363    S3TableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(mS3BootScriptTablePtr->TableBase);
00364    if (S3TableBase == 0) {
00365      // The table is not exist. This is the first to add entry. 
00366      // Allocate ACPI script table space under 4G memory. We need it to save
00367      // some settings done by CSM, which runs after normal script table closed
00368      //
00369      S3TableBase = 0xffffffff;
00370      Status = gBS->AllocatePages (
00371                   AllocateMaxAddress,
00372                   EfiACPIMemoryNVS,
00373                   2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),
00374                   (EFI_PHYSICAL_ADDRESS*)&S3TableBase
00375                   );
00376      
00377      if (EFI_ERROR(Status)) {
00378        ASSERT_EFI_ERROR (Status);
00379        return 0;
00380      }
00381      //
00382      // Fill Table Header
00383      //
00384      ScriptTableInfo              = (EFI_BOOT_SCRIPT_TABLE_HEADER*)(UINTN)S3TableBase;
00385      ScriptTableInfo->OpCode      = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;
00386      ScriptTableInfo->Length      = (UINT8) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
00387      ScriptTableInfo->TableLength = 0;   // will be calculate at CloseTable
00388      mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
00389      mS3BootScriptTablePtr->TableBase = (UINT8*)(UINTN)S3TableBase;
00390      mS3BootScriptTablePtr->TableMemoryPageNumber = (UINT16)(2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));
00391    }
00392      
00393    // Here we do not count the reserved memory for runtime script table.
00394    PageNumber   = (UINT16)(mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));   
00395    TableLength =  mS3BootScriptTablePtr->TableLength;
00396    if ((UINT32)(PageNumber * EFI_PAGE_SIZE) < (TableLength + EntryLength)) {
00397      // 
00398      // The buffer is too small to hold the table, Reallocate the buffer
00399      //
00400      NewS3TableBase = 0xffffffff;
00401      Status = gBS->AllocatePages (
00402                   AllocateMaxAddress,
00403                   EfiACPIMemoryNVS,
00404                   2 + PageNumber + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),
00405                   (EFI_PHYSICAL_ADDRESS*)&NewS3TableBase
00406                   );
00407    
00408      if (EFI_ERROR(Status)) {
00409        ASSERT_EFI_ERROR (Status);
00410        return 0;
00411      }
00412      
00413      CopyMem ((VOID*)(UINTN)NewS3TableBase, (VOID*)(UINTN)S3TableBase, TableLength);
00414      gBS->FreePages (S3TableBase, mS3BootScriptTablePtr->TableMemoryPageNumber);
00415          
00416      mS3BootScriptTablePtr->TableBase = (UINT8*)(UINTN)NewS3TableBase;
00417      mS3BootScriptTablePtr->TableMemoryPageNumber =  (UINT16) (2 + PageNumber + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber)); 
00418    }
00419    //
00420    // calculate the the start address for the new entry. 
00421    //
00422    NewEntryPtr = mS3BootScriptTablePtr->TableBase + TableLength;
00423    
00424    //
00425    // update the table lenghth
00426    //
00427    mS3BootScriptTablePtr->TableLength =  TableLength + EntryLength;
00428    
00429    //
00430    // In the boot time, we will not append the termination entry to the boot script
00431    // table until the callers think there is no boot time data that should be added and 
00432    // it is caller's responsibility to explicit call the CloseTable. 
00433    //
00434    //
00435   
00436    return NewEntryPtr;    
00437 }
00446 UINT8*
00447 S3BootScriptGetRuntimeEntryAddAddress (
00448   UINT8  EntryLength
00449   )
00450 {
00451    UINT8     *NewEntryPtr;
00452    
00453    NewEntryPtr = NULL;   
00454    //
00455    // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node. 
00456    //
00457    if (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE) <= EFI_PAGES_TO_SIZE((UINT32)(mS3BootScriptTablePtr->TableMemoryPageNumber))) {
00458      NewEntryPtr = mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength;   
00459      mS3BootScriptTablePtr->TableLength = mS3BootScriptTablePtr->TableLength + EntryLength;
00460      //
00461      // Append a terminate node on every insert
00462      //
00463      S3BootScriptInternalCloseTable ();
00464    }
00465    return (UINT8*)NewEntryPtr;    
00466 }
00474 UINT8* 
00475 S3BootScriptGetEntryAddAddress (
00476   UINT8  EntryLength
00477   )
00478 {
00479   UINT8*                         NewEntryPtr;
00480   EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;
00481   EFI_STATUS                     Status;
00482 
00483   if (mS3BootScriptTablePtr->AtRuntime) {
00484     //
00485     // We need check InSmm when AtRuntime, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
00486     //
00487     if (!mS3BootScriptTablePtr->InSmm) {
00488       //
00489       // Add DEBUG ERROR, so that we can find it at boot time.
00490       // Do not use ASSERT, because we may have test invoke this interface.
00491       //
00492       DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script after ReadyToLock!!!\n"));
00493       return NULL;
00494     }
00495 
00496     //
00497     // NOTE: OS will restore ACPINvs data. After S3, the table length in mS3BootScriptTable (SMM) is different with
00498     // table length in BootScriptTable header (ACPINvs).
00499     // So here we need sync them. We choose ACPINvs table length, because we want to override the boot script saved
00500     // in SMM every time.
00501     //
00502     ASSERT (mS3BootScriptTablePtr == &mS3BootScriptTable);
00503     CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
00504     if (mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE) != TableHeader.TableLength) {
00505       //
00506       // Restore it to use original value
00507       //
00508       RestoreLockBox (&mBootScriptDataGuid, NULL, NULL);
00509       //
00510       // Copy it again to get original value
00511       // NOTE: We should NOT use TableHeader.TableLength, because it is already updated to be whole length.
00512       //
00513       mS3BootScriptTablePtr->TableLength = (UINT32)(mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE));
00514     }
00515 
00516     NewEntryPtr  = S3BootScriptGetRuntimeEntryAddAddress (EntryLength);
00517     //
00518     // Now the length field is updated, need sync to lockbox.
00519     // So in S3 resume, the data can be restored correctly.
00520     //
00521     CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
00522     Status = UpdateLockBox (
00523                &mBootScriptDataGuid,
00524                OFFSET_OF(EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),
00525                &TableHeader.TableLength,
00526                sizeof(TableHeader.TableLength)
00527                );
00528     ASSERT_EFI_ERROR (Status);
00529   } else {   
00530     NewEntryPtr  = S3BootScriptGetBootTimeEntryAddAddress (EntryLength);
00531   }  
00532   return NewEntryPtr;
00533   
00534 }  
00535 
00539 VOID
00540 SyncBootScript (
00541   VOID
00542   )
00543 {
00544   EFI_STATUS  Status;
00545 
00546   if (!mS3BootScriptTablePtr->AtRuntime || !mS3BootScriptTablePtr->InSmm) {
00547     return ;
00548   }
00549   //
00550   // Update Terminate
00551   // So in S3 resume, the data can be restored correctly.
00552   //
00553   Status = UpdateLockBox (
00554              &mBootScriptDataGuid,
00555              mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE),
00556              (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE)),
00557              sizeof(EFI_BOOT_SCRIPT_TERMINATE)
00558              );
00559   ASSERT_EFI_ERROR (Status);
00560 }
00561 
00587 UINT8*
00588 EFIAPI
00589 S3BootScriptCloseTable (
00590   VOID
00591   )
00592 {
00593   UINT8                          *S3TableBase;
00594   UINT32                          TableLength;
00595   UINT8                          *Buffer;
00596   EFI_STATUS                      Status;
00597   EFI_BOOT_SCRIPT_TABLE_HEADER      *ScriptTableInfo;
00598   
00599   S3TableBase =    mS3BootScriptTablePtr->TableBase;    
00600   if (S3TableBase == 0) {
00601     return 0; 
00602   }
00603   //
00604   // Append the termination record the S3 boot script table
00605   //
00606   S3BootScriptInternalCloseTable();
00607   TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
00608   //
00609   // Allocate the buffer and copy the boot script to the buffer. 
00610   //
00611   Status = gBS->AllocatePool (
00612                   EfiBootServicesData,
00613                   (UINTN)TableLength,
00614                   (VOID **) &Buffer
00615                   );
00616   if (EFI_ERROR (Status)) {
00617         return 0; 
00618   }
00619   CopyMem (Buffer, S3TableBase, TableLength);
00620   
00621   //
00622   // Destroy the table maintained by the library so that the next write operation 
00623   // will write the record to the first entry of the table.
00624   //
00625   // Fill the table header.
00626   ScriptTableInfo                    = (EFI_BOOT_SCRIPT_TABLE_HEADER*)S3TableBase;
00627   ScriptTableInfo->OpCode      = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;
00628   ScriptTableInfo->Length      = (UINT8) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
00629   ScriptTableInfo->TableLength = 0;   // will be calculate at close the table
00630   
00631   mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
00632   return Buffer;
00633 }
00645 RETURN_STATUS
00646 EFIAPI
00647 S3BootScriptSaveIoWrite (
00648   IN  S3_BOOT_SCRIPT_LIB_WIDTH          Width,
00649   IN  UINT64                            Address,
00650   IN  UINTN                             Count,
00651   IN  VOID                              *Buffer
00652   )
00653 
00654 {
00655   UINT8                     Length;
00656   UINT8                    *Script;
00657   UINT8                     WidthInByte;
00658   EFI_BOOT_SCRIPT_IO_WRITE  ScriptIoWrite;
00659 
00660   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
00661   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_WRITE) + (WidthInByte * Count));
00662   
00663   Script = S3BootScriptGetEntryAddAddress (Length);
00664   if (Script == NULL) {
00665     return RETURN_OUT_OF_RESOURCES;
00666   }
00667   //
00668   // save script data
00669   //
00670   ScriptIoWrite.OpCode  = EFI_BOOT_SCRIPT_IO_WRITE_OPCODE;
00671   ScriptIoWrite.Length  = Length;
00672   ScriptIoWrite.Width   = Width;
00673   ScriptIoWrite.Address = Address;
00674   ScriptIoWrite.Count   = (UINT32) Count;
00675   CopyMem ((VOID*)Script, (VOID*)&ScriptIoWrite, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));
00676   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)), Buffer, WidthInByte * Count);
00677 
00678   SyncBootScript ();
00679 
00680   return RETURN_SUCCESS;
00681 }
00682 
00694 RETURN_STATUS
00695 EFIAPI
00696 S3BootScriptSaveIoReadWrite (
00697   IN  S3_BOOT_SCRIPT_LIB_WIDTH         Width,
00698   IN  UINT64                           Address,
00699   IN  VOID                            *Data,
00700   IN  VOID                            *DataMask
00701   )
00702 {
00703   UINT8                 Length;
00704   UINT8                *Script;
00705   UINT8                 WidthInByte;
00706   EFI_BOOT_SCRIPT_IO_READ_WRITE  ScriptIoReadWrite;
00707 
00708   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
00709   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + (WidthInByte * 2));
00710   
00711   Script = S3BootScriptGetEntryAddAddress (Length);
00712   if (Script == NULL) {
00713     return RETURN_OUT_OF_RESOURCES;
00714   }
00715   //
00716   // Build script data
00717   //
00718   ScriptIoReadWrite.OpCode  = EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE;
00719   ScriptIoReadWrite.Length  = Length;
00720   ScriptIoReadWrite.Width   = Width;
00721   ScriptIoReadWrite.Address = Address;
00722   
00723   CopyMem ((VOID*)Script, (VOID*)&ScriptIoReadWrite, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));
00724   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE)), Data, WidthInByte);
00725   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
00726 
00727   SyncBootScript ();
00728 
00729   return RETURN_SUCCESS;
00730 }
00742 RETURN_STATUS
00743 EFIAPI
00744 S3BootScriptSaveMemWrite (
00745   IN  S3_BOOT_SCRIPT_LIB_WIDTH          Width,
00746   IN  UINT64                            Address,
00747   IN  UINTN                             Count,
00748   IN  VOID                              *Buffer
00749   )
00750 {
00751   UINT8                 Length;
00752   UINT8                *Script;
00753   UINT8                 WidthInByte;
00754   EFI_BOOT_SCRIPT_MEM_WRITE  ScriptMemWrite;
00755   
00756   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
00757   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_WRITE) + (WidthInByte * Count));
00758   
00759   Script = S3BootScriptGetEntryAddAddress (Length);
00760   if (Script == NULL) {
00761     return RETURN_OUT_OF_RESOURCES;
00762   }  
00763   //
00764   // Build script data
00765   //
00766   ScriptMemWrite.OpCode   = EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE;
00767   ScriptMemWrite.Length   = Length;
00768   ScriptMemWrite.Width    = Width;
00769   ScriptMemWrite.Address  = Address;
00770   ScriptMemWrite.Count    = (UINT32) Count;
00771   
00772   CopyMem ((VOID*)Script, (VOID*)&ScriptMemWrite, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));
00773   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)), Buffer, WidthInByte * Count);
00774   
00775   SyncBootScript ();
00776 
00777   return RETURN_SUCCESS;
00778 }
00790 RETURN_STATUS
00791 EFIAPI
00792 S3BootScriptSaveMemReadWrite (
00793   IN  S3_BOOT_SCRIPT_LIB_WIDTH          Width,
00794   IN  UINT64                            Address,
00795   IN  VOID                              *Data,
00796   IN  VOID                              *DataMask
00797   )
00798 {
00799   UINT8                 Length;
00800   UINT8                *Script;
00801   UINT8                 WidthInByte;
00802   EFI_BOOT_SCRIPT_MEM_READ_WRITE  ScriptMemReadWrite;
00803  
00804   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
00805   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + (WidthInByte * 2));
00806   
00807   Script = S3BootScriptGetEntryAddAddress (Length);
00808   if (Script == NULL) {
00809     return RETURN_OUT_OF_RESOURCES;
00810   } 
00811   //
00812   // Build script data
00813   //    
00814   ScriptMemReadWrite.OpCode   = EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE;
00815   ScriptMemReadWrite.Length   = Length;
00816   ScriptMemReadWrite.Width    = Width;
00817   ScriptMemReadWrite.Address  = Address;
00818   
00819   CopyMem ((VOID*)Script, (VOID*)&ScriptMemReadWrite , sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE));
00820   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE)), Data, WidthInByte);
00821   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
00822 
00823   SyncBootScript ();
00824 
00825   return RETURN_SUCCESS;
00826 }
00838 RETURN_STATUS
00839 EFIAPI
00840 S3BootScriptSavePciCfgWrite (
00841   IN  S3_BOOT_SCRIPT_LIB_WIDTH         Width,
00842   IN  UINT64                           Address,
00843   IN  UINTN                            Count,
00844   IN  VOID                            *Buffer
00845   )
00846 {
00847   UINT8                 Length;
00848   UINT8                *Script;
00849   UINT8                 WidthInByte;
00850   EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE  ScriptPciWrite;
00851 
00852   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
00853   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count));
00854   
00855   Script = S3BootScriptGetEntryAddAddress (Length);
00856   if (Script == NULL) {
00857     return RETURN_OUT_OF_RESOURCES;
00858   } 
00859   //
00860   // Build script data
00861   //
00862   ScriptPciWrite.OpCode   = EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE;
00863   ScriptPciWrite.Length   = Length;
00864   ScriptPciWrite.Width    = Width;
00865   ScriptPciWrite.Address  = Address;
00866   ScriptPciWrite.Count    = (UINT32) Count;
00867   
00868   CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite,  sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
00869   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)), Buffer, WidthInByte * Count);
00870   
00871   SyncBootScript ();
00872 
00873   return RETURN_SUCCESS;
00874 }
00886 RETURN_STATUS
00887 EFIAPI
00888 S3BootScriptSavePciCfgReadWrite (
00889   IN  S3_BOOT_SCRIPT_LIB_WIDTH          Width,
00890   IN  UINT64                            Address,
00891   IN  VOID                              *Data,
00892   IN  VOID                              *DataMask
00893   )
00894 {
00895   UINT8                 Length;
00896   UINT8                *Script;
00897   UINT8                 WidthInByte;
00898   EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE  ScriptPciReadWrite;
00899 
00900   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
00901   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + (WidthInByte * 2));
00902   
00903   Script = S3BootScriptGetEntryAddAddress (Length);
00904   if (Script == NULL) {
00905     return RETURN_OUT_OF_RESOURCES;
00906   }  
00907   //
00908   // Build script data
00909   // 
00910   ScriptPciReadWrite.OpCode   = EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE;
00911   ScriptPciReadWrite.Length   = Length;
00912   ScriptPciReadWrite.Width    = Width;
00913   ScriptPciReadWrite.Address  = Address;
00914   
00915   CopyMem ((VOID*)Script, (VOID*)&ScriptPciReadWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
00916   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE)), Data, WidthInByte);
00917   CopyMem (
00918     (VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + WidthInByte),
00919     DataMask,
00920     WidthInByte
00921     );
00922 
00923   SyncBootScript ();
00924 
00925   return RETURN_SUCCESS;
00926 }
00939 RETURN_STATUS
00940 EFIAPI
00941 S3BootScriptSavePciCfg2Write (
00942   IN S3_BOOT_SCRIPT_LIB_WIDTH        Width,
00943   IN UINT16                          Segment,
00944   IN UINT64                          Address,
00945   IN UINTN                           Count,
00946   IN VOID                           *Buffer
00947   )
00948 {
00949   UINT8                 Length;
00950   UINT8                *Script;
00951   UINT8                 WidthInByte;
00952   EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE  ScriptPciWrite2;
00953   
00954   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
00955   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE) + (WidthInByte * Count));
00956   
00957   Script = S3BootScriptGetEntryAddAddress (Length);
00958   if (Script == NULL) {
00959     return RETURN_OUT_OF_RESOURCES;
00960   }  
00961   //
00962   // Build script data
00963   //
00964   ScriptPciWrite2.OpCode   = EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE;
00965   ScriptPciWrite2.Length   = Length;
00966   ScriptPciWrite2.Width    = Width;
00967   ScriptPciWrite2.Address  = Address;
00968   ScriptPciWrite2.Segment  = Segment;
00969   ScriptPciWrite2.Count    = (UINT32)Count;
00970   
00971   CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
00972   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)), Buffer, WidthInByte * Count);
00973 
00974   SyncBootScript ();
00975 
00976   return RETURN_SUCCESS;
00977 }
00990 RETURN_STATUS
00991 EFIAPI
00992 S3BootScriptSavePciCfg2ReadWrite (
00993   IN S3_BOOT_SCRIPT_LIB_WIDTH        Width,
00994   IN UINT16                          Segment,
00995   IN UINT64                          Address,
00996   IN VOID                           *Data,
00997   IN VOID                           *DataMask
00998   )
00999 {
01000   UINT8                 Length;
01001   UINT8                *Script;
01002   UINT8                 WidthInByte;
01003   EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE  ScriptPciReadWrite2;
01004   
01005   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
01006   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + (WidthInByte * 2));
01007   
01008   Script = S3BootScriptGetEntryAddAddress (Length);
01009   if (Script == NULL) {
01010     return RETURN_OUT_OF_RESOURCES;
01011   }  
01012   //
01013   // Build script data
01014   //
01015   ScriptPciReadWrite2.OpCode   = EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE;
01016   ScriptPciReadWrite2.Length   = Length;
01017   ScriptPciReadWrite2.Width    = Width;
01018   ScriptPciReadWrite2.Segment  = Segment;
01019   ScriptPciReadWrite2.Address  = Address;
01020   
01021   CopyMem ((VOID*)Script, (VOID*)&ScriptPciReadWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
01022   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE)), Data, WidthInByte);
01023   CopyMem (
01024     (VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + WidthInByte),
01025     DataMask,
01026     WidthInByte
01027     );
01028   
01029   SyncBootScript ();
01030 
01031   return RETURN_SUCCESS;
01032 }
01045 RETURN_STATUS
01046 EFIAPI
01047 S3BootScriptSaveSmbusExecute (
01048   IN  UINTN                             SmBusAddress, 
01049   IN  EFI_SMBUS_OPERATION               Operation,
01050   IN  UINTN                             *Length,
01051   IN  VOID                              *Buffer
01052   )
01053 {
01054   UINT8                 DataSize;
01055   UINT8                *Script;
01056   EFI_BOOT_SCRIPT_SMBUS_EXECUTE  ScriptSmbusExecute;
01057 
01058   DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + (*Length));
01059   
01060   Script = S3BootScriptGetEntryAddAddress (DataSize);
01061   if (Script == NULL) {
01062     return RETURN_OUT_OF_RESOURCES;
01063   }
01064   //
01065   // Build script data
01066   //
01067   ScriptSmbusExecute.OpCode       = EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE;
01068   ScriptSmbusExecute.Length       = DataSize;
01069   ScriptSmbusExecute.SmBusAddress = (UINT64) SmBusAddress;
01070   ScriptSmbusExecute.Operation    = Operation;
01071   ScriptSmbusExecute.DataSize     = (UINT32) *Length;
01072 
01073   CopyMem ((VOID*)Script, (VOID*)&ScriptSmbusExecute, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE));
01074   CopyMem (
01075     (VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)),
01076     Buffer,
01077     (*Length)
01078     );
01079 
01080   SyncBootScript ();
01081 
01082   return RETURN_SUCCESS;
01083 }
01092 RETURN_STATUS
01093 EFIAPI
01094 S3BootScriptSaveStall (
01095   IN  UINTN                             Duration
01096   )
01097 {
01098   UINT8                 Length;
01099   UINT8                *Script;
01100   EFI_BOOT_SCRIPT_STALL  ScriptStall;
01101 
01102   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_STALL));
01103   
01104   Script = S3BootScriptGetEntryAddAddress (Length);
01105   if (Script == NULL) {
01106     return RETURN_OUT_OF_RESOURCES;
01107   }  
01108   //
01109   // Build script data
01110   //
01111   ScriptStall.OpCode    = EFI_BOOT_SCRIPT_STALL_OPCODE;
01112   ScriptStall.Length    = Length;
01113   ScriptStall.Duration  = Duration;
01114   
01115   CopyMem ((VOID*)Script, (VOID*)&ScriptStall, sizeof (EFI_BOOT_SCRIPT_STALL));
01116   
01117   SyncBootScript ();
01118 
01119   return RETURN_SUCCESS;
01120 }
01130 RETURN_STATUS
01131 EFIAPI
01132 S3BootScriptSaveDispatch2 (
01133   IN  VOID                      *EntryPoint,
01134   IN  VOID                      *Context
01135   )
01136 {
01137   UINT8                 Length;
01138   UINT8                 *Script;
01139   EFI_BOOT_SCRIPT_DISPATCH_2  ScriptDispatch2;
01140   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));
01141   
01142   Script = S3BootScriptGetEntryAddAddress (Length);
01143   if (Script == NULL) {
01144     return RETURN_OUT_OF_RESOURCES;
01145   }  
01146   //
01147   // Build script data
01148   //
01149   ScriptDispatch2.OpCode     = EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE;
01150   ScriptDispatch2.Length     = Length;
01151   ScriptDispatch2.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
01152   ScriptDispatch2.Context =   (EFI_PHYSICAL_ADDRESS)(UINTN)Context;
01153   
01154   CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch2, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));
01155   
01156   SyncBootScript ();
01157 
01158   return RETURN_SUCCESS;
01159 
01160 }
01176 RETURN_STATUS
01177 EFIAPI
01178 S3BootScriptSaveMemPoll (
01179   IN  S3_BOOT_SCRIPT_LIB_WIDTH          Width,
01180   IN  UINT64                            Address,
01181   IN  VOID                              *BitMask,
01182   IN  VOID                              *BitValue,
01183   IN  UINTN                             Duration,
01184   IN  UINTN                             LoopTimes
01185   )
01186 {
01187   UINT8                 Length;
01188   UINT8                *Script;
01189   UINT8                 WidthInByte; 
01190   EFI_BOOT_SCRIPT_MEM_POLL      ScriptMemPoll; 
01191 
01192   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
01193   
01194   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + (WidthInByte * 2));
01195   
01196   Script = S3BootScriptGetEntryAddAddress (Length);
01197   if (Script == NULL) {
01198     return RETURN_OUT_OF_RESOURCES;
01199   }
01200   //
01201   // Build script data
01202   //
01203   ScriptMemPoll.OpCode   = EFI_BOOT_SCRIPT_MEM_POLL_OPCODE;
01204   ScriptMemPoll.Length   = Length;
01205   ScriptMemPoll.Width    = Width;  
01206   ScriptMemPoll.Address  = Address;
01207   ScriptMemPoll.Duration = Duration;
01208   ScriptMemPoll.LoopTimes = LoopTimes;
01209 
01210   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL)), BitValue, WidthInByte);
01211   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + WidthInByte), BitMask, WidthInByte);
01212   CopyMem ((VOID*)Script, (VOID*)&ScriptMemPoll, sizeof (EFI_BOOT_SCRIPT_MEM_POLL)); 
01213 
01214   SyncBootScript ();
01215 
01216   return RETURN_SUCCESS;
01217 }
01230 RETURN_STATUS
01231 EFIAPI
01232 S3BootScriptSaveInformation (
01233   IN  UINT32                                InformationLength, 
01234   IN  VOID                                 *Information
01235   )
01236 {
01237   RETURN_STATUS         Status;
01238   UINT8                 Length;
01239   UINT8                 *Script;
01240   EFI_PHYSICAL_ADDRESS  Buffer;
01241   EFI_BOOT_SCRIPT_INFORMATION  ScriptInformation;
01242 
01243   if (mS3BootScriptTablePtr->AtRuntime) {
01244     return RETURN_UNSUPPORTED;
01245   }
01246   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION));
01247   
01248   Buffer = 0xFFFFFFFF;
01249   Status = gBS->AllocatePages (
01250                   AllocateMaxAddress,
01251                   EfiACPIMemoryNVS,
01252                   EFI_SIZE_TO_PAGES(InformationLength),
01253                   &Buffer
01254                   );
01255   if (EFI_ERROR (Status)) {
01256     return RETURN_OUT_OF_RESOURCES;
01257   }
01258   
01259   Script = S3BootScriptGetEntryAddAddress (Length);
01260   if (Script == NULL) {
01261     return RETURN_OUT_OF_RESOURCES;
01262   }
01263   //
01264   // Build script data
01265   //
01266   ScriptInformation.OpCode     = EFI_BOOT_SCRIPT_INFORMATION_OPCODE;
01267   ScriptInformation.Length     = Length;
01268 
01269 
01270   ScriptInformation.InformationLength = InformationLength;  
01271 
01272   CopyMem ((VOID *)(UINTN)Buffer, Information,(UINTN) InformationLength);  
01273   ScriptInformation.Information = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer;
01274   
01275   CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));  
01276   return RETURN_SUCCESS;
01277 
01278 }
01289 RETURN_STATUS
01290 EFIAPI
01291 S3BootScriptSaveInformationAsciiString (
01292   IN  CONST CHAR8               *String
01293   )
01294 {
01295   return S3BootScriptSaveInformation (      
01296            (UINT32) AsciiStrLen (String) + 1, 
01297            (VOID*) String
01298            );
01299 }
01308 RETURN_STATUS
01309 EFIAPI
01310 S3BootScriptSaveDispatch (
01311   IN  VOID                              *EntryPoint
01312   )
01313 {
01314   UINT8                 Length;
01315   UINT8                *Script;
01316   EFI_BOOT_SCRIPT_DISPATCH  ScriptDispatch;
01317   
01318   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH));
01319   
01320   Script = S3BootScriptGetEntryAddAddress (Length);
01321   if (Script == NULL) {
01322     return RETURN_OUT_OF_RESOURCES;
01323   }  
01324   //
01325   // Build script data
01326   //
01327   ScriptDispatch.OpCode     = EFI_BOOT_SCRIPT_DISPATCH_OPCODE;
01328   ScriptDispatch.Length     = Length;
01329   ScriptDispatch.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
01330   
01331   CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch, sizeof (EFI_BOOT_SCRIPT_DISPATCH)); 
01332   
01333   SyncBootScript ();
01334 
01335   return RETURN_SUCCESS;
01336 
01337 }
01354 RETURN_STATUS
01355 EFIAPI
01356 S3BootScriptSaveIoPoll (
01357   IN S3_BOOT_SCRIPT_LIB_WIDTH       Width,
01358   IN UINT64                     Address,
01359   IN VOID                      *Data,
01360   IN VOID                      *DataMask, 
01361   IN UINT64                     Delay   
01362   )
01363 {
01364   UINT8                 WidthInByte;  
01365   UINT8                *Script;
01366   UINT8                 Length;
01367   EFI_BOOT_SCRIPT_IO_POLL  ScriptIoPoll;
01368   
01369 
01370   WidthInByte = (UINT8) (0x01 << (Width & 0x03));  
01371   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));
01372  
01373   Script = S3BootScriptGetEntryAddAddress (Length);
01374   if (Script == NULL) {
01375     return RETURN_OUT_OF_RESOURCES;
01376   } 
01377   //
01378   // Build script data
01379   //
01380   ScriptIoPoll.OpCode   = EFI_BOOT_SCRIPT_IO_POLL_OPCODE;
01381   ScriptIoPoll.Length   = (UINT8) (sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));
01382   ScriptIoPoll.Width    = Width;  
01383   ScriptIoPoll.Address  = Address;
01384   ScriptIoPoll.Delay    = Delay;
01385 
01386   CopyMem ((VOID*)Script, (VOID*)&ScriptIoPoll, sizeof (EFI_BOOT_SCRIPT_IO_POLL));  
01387   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL)), Data, WidthInByte);
01388   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL) + WidthInByte), DataMask, WidthInByte);
01389   
01390   SyncBootScript ();
01391 
01392   return RETURN_SUCCESS;
01393 }
01394 
01411 RETURN_STATUS
01412 EFIAPI
01413 S3BootScriptSavePciPoll (
01414    IN S3_BOOT_SCRIPT_LIB_WIDTH   Width,
01415    IN UINT64                     Address,
01416    IN VOID                      *Data,
01417    IN VOID                      *DataMask,
01418    IN UINT64                     Delay
01419 )
01420 {
01421   UINT8                   *Script;
01422   UINT8                    WidthInByte;  
01423   UINT8                    Length;
01424   EFI_BOOT_SCRIPT_PCI_CONFIG_POLL  ScriptPciPoll;
01425 
01426   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
01427   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));
01428   
01429   Script = S3BootScriptGetEntryAddAddress (Length);
01430   if (Script == NULL) {
01431     return RETURN_OUT_OF_RESOURCES;
01432   }
01433   //
01434   // Build script data
01435   //
01436   ScriptPciPoll.OpCode   = EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE;
01437   ScriptPciPoll.Length   = (UINT8) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));
01438   ScriptPciPoll.Width    = Width;  
01439   ScriptPciPoll.Address  = Address;
01440   ScriptPciPoll.Delay    = Delay;
01441 
01442   CopyMem ((VOID*)Script, (VOID*)&ScriptPciPoll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
01443   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL)), Data, WidthInByte);
01444   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + WidthInByte), DataMask, WidthInByte);
01445   
01446   SyncBootScript ();
01447 
01448   return RETURN_SUCCESS;
01449 }
01469 RETURN_STATUS
01470 EFIAPI
01471 S3BootScriptSavePci2Poll (
01472    IN S3_BOOT_SCRIPT_LIB_WIDTH      Width,
01473    IN UINT16                        Segment,
01474    IN UINT64                        Address,
01475    IN VOID                         *Data,
01476    IN VOID                         *DataMask,
01477   IN UINT64                         Delay
01478 )
01479 {
01480   UINT8                    WidthInByte;  
01481   UINT8                   *Script;
01482   UINT8                    Length;
01483   EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL  ScriptPci2Poll;
01484   
01485   WidthInByte = (UINT8) (0x01 << (Width & 0x03));
01486   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));
01487   
01488   Script = S3BootScriptGetEntryAddAddress (Length);
01489   if (Script == NULL) {
01490     return RETURN_OUT_OF_RESOURCES;
01491   } 
01492   //
01493   // Build script data
01494   //
01495   ScriptPci2Poll.OpCode   = EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE;
01496   ScriptPci2Poll.Length   = (UINT8) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));
01497   ScriptPci2Poll.Width    = Width; 
01498   ScriptPci2Poll.Segment  = Segment;
01499   ScriptPci2Poll.Address  = Address;
01500   ScriptPci2Poll.Delay    = Delay;
01501 
01502   CopyMem ((VOID*)Script, (VOID*)&ScriptPci2Poll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
01503   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL)), Data, WidthInByte);
01504   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + WidthInByte), DataMask, WidthInByte);
01505   
01506   SyncBootScript ();
01507 
01508   return RETURN_SUCCESS;
01509 }
01520 VOID
01521 S3BootScriptCalculateInsertAddress (
01522   IN  UINT8     EntryLength,
01523   IN  VOID     *Position OPTIONAL,
01524   IN  BOOLEAN   BeforeOrAfter OPTIONAL,
01525   OUT UINT8   **Script   
01526   )
01527 {
01528    UINTN                            TableLength;
01529    UINT8                            *S3TableBase;
01530    UINTN                            PositionOffset; 
01531    EFI_BOOT_SCRIPT_COMMON_HEADER     ScriptHeader;
01532    //
01533    // The entry inserting to table is already added to the end of the table
01534    //
01535    TableLength =  mS3BootScriptTablePtr->TableLength - EntryLength;
01536    S3TableBase = mS3BootScriptTablePtr->TableBase ;
01537    // 
01538    // calculate the Position offset
01539    //
01540    if (Position != NULL) {
01541      PositionOffset = (UINTN) ((UINT8 *)Position - S3TableBase);
01542    
01543      //
01544      // If the BeforeOrAfter is FALSE, that means to insert the node right after the node.
01545      //
01546      if (!BeforeOrAfter) {
01547         CopyMem ((VOID*)&ScriptHeader, Position, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));  
01548         PositionOffset += (ScriptHeader.Length);
01549      }
01550      //     
01551      // Insert the node before the adjusted Position
01552      //
01553      CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset);  
01554      //
01555      // calculate the the start address for the new entry. 
01556      //
01557      *Script = S3TableBase + PositionOffset;
01558        
01559    } else {
01560      if (!BeforeOrAfter) {
01561        //
01562        //  Insert the node to the end of the table
01563        //
01564        *Script = S3TableBase + TableLength; 
01565      } else {
01566        // 
01567        // Insert the node to the beginning of the table
01568        //
01569        PositionOffset = (UINTN) sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);
01570        CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset); 
01571        *Script = S3TableBase + PositionOffset; 
01572      }
01573    }       
01574 }
01590 RETURN_STATUS
01591 EFIAPI
01592 S3BootScriptMoveLastOpcode (
01593   IN     BOOLEAN                        BeforeOrAfter,
01594   IN OUT VOID                         **Position OPTIONAL
01595 )
01596 {
01597   UINT8*                Script;
01598   VOID                  *TempPosition;  
01599   UINTN                 StartAddress;
01600   UINT32                TableLength;
01601   EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
01602   BOOLEAN               ValidatePosition;
01603   UINT8*                LastOpcode;
01604   UINT8                 TempBootScriptEntry[BOOT_SCRIPT_NODE_MAX_LENGTH];
01605   
01606   ValidatePosition = FALSE;
01607   TempPosition = (Position == NULL) ? NULL:(*Position);
01608   Script = mS3BootScriptTablePtr->TableBase;
01609   if (Script == 0) {    
01610     return EFI_OUT_OF_RESOURCES;
01611   }
01612   StartAddress  = (UINTN) Script;
01613   TableLength   = mS3BootScriptTablePtr->TableLength;
01614   Script        = Script + sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);
01615   LastOpcode    = Script;
01616   //
01617   // Find the last boot Script Entry which is not the terminate node
01618   //
01619   while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {    
01620     CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));   
01621     if (TempPosition != NULL && TempPosition == Script) {
01622       //
01623       // If the position is specified, the position must be pointed to a boot script entry start address. 
01624       //
01625       ValidatePosition = TRUE;
01626     }
01627     if (ScriptHeader.OpCode != S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE) {
01628       LastOpcode = Script;
01629     } 
01630     Script  = Script + ScriptHeader.Length;
01631   }
01632   //
01633   // If the position is specified, but not the start of a boot script entry, it is a invalid input
01634   //
01635   if (TempPosition != NULL && !ValidatePosition) {
01636     return RETURN_INVALID_PARAMETER;
01637   }
01638   
01639   CopyMem ((VOID*)&ScriptHeader, LastOpcode, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER)); 
01640   
01641   CopyMem((VOID*)TempBootScriptEntry, LastOpcode, ScriptHeader.Length); 
01642   //
01643   // Find the right position to write the node in
01644   //
01645   S3BootScriptCalculateInsertAddress (
01646     ScriptHeader.Length,
01647     TempPosition,
01648     BeforeOrAfter,
01649     &Script   
01650   );
01651   //
01652   // Copy the node to Boot script table
01653   //
01654   CopyMem((VOID*)Script, (VOID*)TempBootScriptEntry, ScriptHeader.Length); 
01655   //
01656   // return out the Position
01657   //
01658   if (Position != NULL) {
01659     *Position = Script;
01660   }
01661   return RETURN_SUCCESS;
01662 }
01681 RETURN_STATUS
01682 EFIAPI
01683 S3BootScriptLabelInternal (
01684   IN        BOOLEAN                        BeforeOrAfter,
01685   IN OUT    VOID                         **Position OPTIONAL, 
01686   IN        UINT32                         InformationLength, 
01687   IN CONST  CHAR8                          *Information
01688   )
01689 {
01690   UINT8                 Length;
01691   UINT8                 *Script;
01692   VOID                  *Buffer;
01693   EFI_BOOT_SCRIPT_INFORMATION  ScriptInformation;
01694  
01695   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);
01696   
01697   Script = S3BootScriptGetEntryAddAddress (Length);
01698   if (Script == NULL) {
01699     return RETURN_OUT_OF_RESOURCES;
01700   }
01701   Buffer =  Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
01702   //
01703   // Build script data
01704   //
01705   ScriptInformation.OpCode     = S3_BOOT_SCRIPT_LIB_LABEL_OPCODE;
01706   ScriptInformation.Length     = Length;
01707 
01708 
01709   ScriptInformation.InformationLength = InformationLength;  
01710 
01711   AsciiStrnCpy (Buffer, Information,(UINTN) InformationLength);  
01712   ScriptInformation.Information = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer;
01713   
01714   CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));  
01715   
01716   return S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
01717 
01718 }
01741 RETURN_STATUS
01742 EFIAPI 
01743 S3BootScriptLabel (
01744   IN       BOOLEAN                      BeforeOrAfter,
01745   IN       BOOLEAN                      CreateIfNotFound,
01746   IN OUT   VOID                       **Position OPTIONAL,
01747   IN CONST CHAR8                       *Label
01748   )
01749 {
01750   UINT8*                Script;
01751   UINTN                 StartAddress;
01752   UINT32                TableLength;
01753   EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
01754   EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;
01755   UINT32                         LabelLength;
01756   //
01757   // Assume Label is not NULL
01758   //
01759  if (Label == NULL) {
01760     return EFI_INVALID_PARAMETER;
01761   }
01762   
01763   //
01764   // Check that the script is initialized without adding an entry to the script.
01765   // The code must search for the label first befor it knows if a new entry needs
01766   // to be added.
01767   //
01768   Script = S3BootScriptGetEntryAddAddress (0);
01769   if (Script == NULL) {
01770     return RETURN_OUT_OF_RESOURCES;
01771   }
01772   
01773   //
01774   // Check the header and search for existing label.
01775   // 
01776   Script = mS3BootScriptTablePtr->TableBase;
01777   CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
01778   if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
01779     return EFI_INVALID_PARAMETER;
01780   }
01781   StartAddress  = (UINTN) Script;
01782   TableLength   = mS3BootScriptTablePtr->TableLength;
01783   Script    =     Script + TableHeader.Length;
01784   while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
01785     
01786     CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));   
01787     if (ScriptHeader.OpCode == S3_BOOT_SCRIPT_LIB_LABEL_OPCODE) {
01788       if (AsciiStrCmp ((CHAR8 *)(UINTN)(Script+sizeof(EFI_BOOT_SCRIPT_INFORMATION)), Label) == 0) {
01789         (*Position) = Script; 
01790         return EFI_SUCCESS;
01791       }
01792     } 
01793     Script  = Script + ScriptHeader.Length;
01794   }
01795   if (CreateIfNotFound) {
01796     LabelLength = (UINT32)AsciiStrSize(Label);
01797     return S3BootScriptLabelInternal (BeforeOrAfter,Position, LabelLength, Label);     
01798   } else {
01799     return EFI_NOT_FOUND;
01800   }   
01801 }
01802 
01817 RETURN_STATUS
01818 EFIAPI 
01819 S3BootScriptCompare (
01820   IN  UINT8                       *Position1,
01821   IN  UINT8                       *Position2,
01822   OUT UINTN                       *RelativePosition
01823   )
01824 {
01825   UINT8*                    Script;
01826   UINT32                    TableLength; 
01827 
01828   Script = mS3BootScriptTablePtr->TableBase;
01829   if (Script == NULL) {
01830     return EFI_OUT_OF_RESOURCES;
01831   }
01832   if (RelativePosition == NULL) {
01833     return EFI_INVALID_PARAMETER;
01834   }
01835   TableLength = ((EFI_BOOT_SCRIPT_TABLE_HEADER*)Script)->TableLength;
01836   //
01837   // If in boot time, TableLength does not include the termination node. so add it up 
01838   //
01839   if (!mS3BootScriptTablePtr->AtRuntime) {
01840     TableLength += sizeof(EFI_BOOT_SCRIPT_TERMINATE);
01841   }
01842   if (Position1 < Script || Position1 > Script+TableLength) {
01843     return EFI_INVALID_PARAMETER;
01844   }
01845   if (Position2 < Script || Position2 > Script+TableLength) {
01846     return EFI_INVALID_PARAMETER;
01847   }
01848   *RelativePosition = (Position1 < Position2)?-1:((Position1 == Position2)?0:1);
01849   
01850   return EFI_SUCCESS;
01851 }
01852 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines