mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 19:23:54 +01:00 
			
		
		
		
	REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			499 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			499 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This is the code for Boot Script Executer module.
 | |
| 
 | |
|   This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
 | |
|   in the entry point. The functionality is to interpret and restore the S3 boot script
 | |
| 
 | |
| Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
| Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 | |
| 
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "ScriptExecute.h"
 | |
| 
 | |
| EFI_GUID  mBootScriptExecutorImageGuid = {
 | |
|   0x9a8d3433, 0x9fe8, 0x42b6, { 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b }
 | |
| };
 | |
| 
 | |
| BOOLEAN  mPage1GSupport  = FALSE;
 | |
| UINT64   mAddressEncMask = 0;
 | |
| 
 | |
| /**
 | |
|   Entry function of Boot script exector. This function will be executed in
 | |
|   S3 boot path.
 | |
|   This function should not return, because it is invoked by switch stack.
 | |
| 
 | |
|   @param  AcpiS3Context    a pointer to a structure of ACPI_S3_CONTEXT
 | |
|   @param  PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER - OS waking vector not found
 | |
|   @retval EFI_UNSUPPORTED - something wrong when we resume to OS
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| S3BootScriptExecutorEntryFunction (
 | |
|   IN ACPI_S3_CONTEXT      *AcpiS3Context,
 | |
|   IN PEI_S3_RESUME_STATE  *PeiS3ResumeState
 | |
|   )
 | |
| {
 | |
|   EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;
 | |
|   EFI_STATUS                                    Status;
 | |
|   UINTN                                         TempStackTop;
 | |
|   UINTN                                         TempStack[0x10];
 | |
|   UINTN                                         AsmTransferControl16Address;
 | |
|   IA32_DESCRIPTOR                               IdtDescriptor;
 | |
| 
 | |
|   //
 | |
|   // Disable interrupt of Debug timer, since new IDT table cannot handle it.
 | |
|   //
 | |
|   SaveAndSetDebugTimerInterrupt (FALSE);
 | |
| 
 | |
|   AsmReadIdtr (&IdtDescriptor);
 | |
|   //
 | |
|   // Restore IDT for debug
 | |
|   //
 | |
|   SetIdtEntry (AcpiS3Context);
 | |
| 
 | |
|   //
 | |
|   // Initialize Debug Agent to support source level debug in S3 path, it will disable interrupt and Debug Timer.
 | |
|   //
 | |
|   InitializeDebugAgent (DEBUG_AGENT_INIT_S3, (VOID *)&IdtDescriptor, NULL);
 | |
| 
 | |
|   //
 | |
|   // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL
 | |
|   // for that parameter.
 | |
|   //
 | |
|   Status = S3BootScriptExecute ();
 | |
| 
 | |
|   //
 | |
|   // If invalid script table or opcode in S3 boot script table.
 | |
|   //
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     CpuDeadLoop ();
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   AsmWbinvd ();
 | |
| 
 | |
|   //
 | |
|   // Get ACPI Table Address
 | |
|   //
 | |
|   Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)((UINTN)(AcpiS3Context->AcpiFacsTable));
 | |
| 
 | |
|   //
 | |
|   // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.
 | |
|   //
 | |
|   if (PeiS3ResumeState != 0) {
 | |
|     //
 | |
|     // Need report status back to S3ResumePeim.
 | |
|     // If boot script execution is failed, S3ResumePeim wil report the error status code.
 | |
|     //
 | |
|     PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status;
 | |
|     if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
 | |
|       //
 | |
|       // X64 S3 Resume
 | |
|       //
 | |
|       DEBUG ((DEBUG_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));
 | |
|       PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl32;
 | |
| 
 | |
|       if ((Facs != NULL) &&
 | |
|           (Facs->Signature == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) &&
 | |
|           (Facs->FirmwareWakingVector != 0))
 | |
|       {
 | |
|         //
 | |
|         // more step needed - because relative address is handled differently between X64 and IA32.
 | |
|         //
 | |
|         AsmTransferControl16Address = (UINTN)AsmTransferControl16;
 | |
|         AsmFixAddress16             = (UINT32)AsmTransferControl16Address;
 | |
|         AsmJmpAddr32                = (UINT32)((Facs->FirmwareWakingVector & 0xF) | ((Facs->FirmwareWakingVector & 0xFFFF0) << 12));
 | |
|       }
 | |
| 
 | |
|       AsmDisablePaging64 (
 | |
|         PeiS3ResumeState->ReturnCs,
 | |
|         (UINT32)PeiS3ResumeState->ReturnEntryPoint,
 | |
|         (UINT32)(UINTN)AcpiS3Context,
 | |
|         (UINT32)(UINTN)PeiS3ResumeState,
 | |
|         (UINT32)PeiS3ResumeState->ReturnStackPointer
 | |
|         );
 | |
|     } else {
 | |
|       //
 | |
|       // IA32 S3 Resume
 | |
|       //
 | |
|       DEBUG ((DEBUG_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
 | |
|       PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl;
 | |
| 
 | |
|       SwitchStack (
 | |
|         (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,
 | |
|         (VOID *)(UINTN)AcpiS3Context,
 | |
|         (VOID *)(UINTN)PeiS3ResumeState,
 | |
|         (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Never run to here
 | |
|     //
 | |
|     CpuDeadLoop ();
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // S3ResumePeim does not provide a way to jump back to itself, so resume to OS here directly
 | |
|   //
 | |
|   if (Facs->XFirmwareWakingVector != 0) {
 | |
|     //
 | |
|     // Switch to native waking vector
 | |
|     //
 | |
|     TempStackTop = (UINTN)&TempStack + sizeof (TempStack);
 | |
|     if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
 | |
|         ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
 | |
|         ((Facs->OspmFlags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0))
 | |
|     {
 | |
|       //
 | |
|       // X64 long mode waking vector
 | |
|       //
 | |
|       DEBUG ((DEBUG_INFO, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
 | |
|       if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
 | |
|         SwitchStack (
 | |
|           (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
 | |
|           NULL,
 | |
|           NULL,
 | |
|           (VOID *)(UINTN)TempStackTop
 | |
|           );
 | |
|       } else {
 | |
|         // Unsupported for 32bit DXE, 64bit OS vector
 | |
|         DEBUG ((DEBUG_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));
 | |
|         ASSERT (FALSE);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // IA32 protected mode waking vector (Page disabled)
 | |
|       //
 | |
|       DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
 | |
|       if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
 | |
|         AsmDisablePaging64 (
 | |
|           0x10,
 | |
|           (UINT32)Facs->XFirmwareWakingVector,
 | |
|           0,
 | |
|           0,
 | |
|           (UINT32)TempStackTop
 | |
|           );
 | |
|       } else {
 | |
|         SwitchStack (
 | |
|           (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
 | |
|           NULL,
 | |
|           NULL,
 | |
|           (VOID *)(UINTN)TempStackTop
 | |
|           );
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // 16bit Realmode waking vector
 | |
|     //
 | |
|     DEBUG ((DEBUG_INFO, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));
 | |
|     AsmTransferControl (Facs->FirmwareWakingVector, 0x0);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Never run to here
 | |
|   //
 | |
|   CpuDeadLoop ();
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Register image to memory profile.
 | |
| 
 | |
|   @param FileName       File name of the image.
 | |
|   @param ImageBase      Image base address.
 | |
|   @param ImageSize      Image size.
 | |
|   @param FileType       File type of the image.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| RegisterMemoryProfileImage (
 | |
|   IN EFI_GUID          *FileName,
 | |
|   IN PHYSICAL_ADDRESS  ImageBase,
 | |
|   IN UINT64            ImageSize,
 | |
|   IN EFI_FV_FILETYPE   FileType
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                         Status;
 | |
|   EDKII_MEMORY_PROFILE_PROTOCOL      *ProfileProtocol;
 | |
|   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FilePath;
 | |
|   UINT8                              TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
 | |
| 
 | |
|   if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {
 | |
|     FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
 | |
|     Status   = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **)&ProfileProtocol);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       EfiInitializeFwVolDevicepathNode (FilePath, FileName);
 | |
|       SetDevicePathEndNode (FilePath + 1);
 | |
| 
 | |
|       Status = ProfileProtocol->RegisterImage (
 | |
|                                   ProfileProtocol,
 | |
|                                   (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
 | |
|                                   ImageBase,
 | |
|                                   ImageSize,
 | |
|                                   FileType
 | |
|                                   );
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This is the Event notification function to reload BootScriptExecutor image
 | |
|   to RESERVED mem and save it to LockBox.
 | |
| 
 | |
|   @param    Event   Pointer to this event
 | |
|   @param    Context Event handler private data
 | |
|  **/
 | |
| VOID
 | |
| EFIAPI
 | |
| ReadyToLockEventNotify (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                       Status;
 | |
|   VOID                             *Interface;
 | |
|   UINT8                            *Buffer;
 | |
|   UINTN                            BufferSize;
 | |
|   EFI_HANDLE                       NewImageHandle;
 | |
|   UINTN                            Pages;
 | |
|   EFI_PHYSICAL_ADDRESS             FfsBuffer;
 | |
|   PE_COFF_LOADER_IMAGE_CONTEXT     ImageContext;
 | |
|   EFI_GCD_MEMORY_SPACE_DESCRIPTOR  MemDesc;
 | |
| 
 | |
|   Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // A workaround: Here we install a dummy handle
 | |
|   //
 | |
|   NewImageHandle = NULL;
 | |
|   Status         = gBS->InstallProtocolInterface (
 | |
|                           &NewImageHandle,
 | |
|                           &gEfiCallerIdGuid,
 | |
|                           EFI_NATIVE_INTERFACE,
 | |
|                           NULL
 | |
|                           );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Reload BootScriptExecutor image itself to RESERVED mem
 | |
|   //
 | |
|   Status = GetSectionFromAnyFv (
 | |
|              &gEfiCallerIdGuid,
 | |
|              EFI_SECTION_PE32,
 | |
|              0,
 | |
|              (VOID **)&Buffer,
 | |
|              &BufferSize
 | |
|              );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   ImageContext.Handle    = Buffer;
 | |
|   ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
 | |
|   //
 | |
|   // Get information about the image being loaded
 | |
|   //
 | |
|   Status = PeCoffLoaderGetImageInfo (&ImageContext);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
 | |
|     Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
 | |
|   } else {
 | |
|     Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
 | |
|   }
 | |
| 
 | |
|   FfsBuffer = 0xFFFFFFFF;
 | |
|   Status    = gBS->AllocatePages (
 | |
|                      AllocateMaxAddress,
 | |
|                      EfiReservedMemoryType,
 | |
|                      Pages,
 | |
|                      &FfsBuffer
 | |
|                      );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Make sure that the buffer can be used to store code.
 | |
|   //
 | |
|   Status = gDS->GetMemorySpaceDescriptor (FfsBuffer, &MemDesc);
 | |
|   if (!EFI_ERROR (Status) && ((MemDesc.Attributes & EFI_MEMORY_XP) != 0)) {
 | |
|     gDS->SetMemorySpaceAttributes (
 | |
|            FfsBuffer,
 | |
|            EFI_PAGES_TO_SIZE (Pages),
 | |
|            MemDesc.Attributes & (~EFI_MEMORY_XP)
 | |
|            );
 | |
|   }
 | |
| 
 | |
|   ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
 | |
|   //
 | |
|   // Align buffer on section boundary
 | |
|   //
 | |
|   ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
 | |
|   ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
 | |
|   //
 | |
|   // Load the image to our new buffer
 | |
|   //
 | |
|   Status = PeCoffLoaderLoadImage (&ImageContext);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Relocate the image in our new buffer
 | |
|   //
 | |
|   Status = PeCoffLoaderRelocateImage (&ImageContext);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
 | |
|   //
 | |
|   gBS->FreePool (Buffer);
 | |
| 
 | |
|   //
 | |
|   // Flush the instruction cache so the image data is written before we execute it
 | |
|   //
 | |
|   InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
 | |
| 
 | |
|   RegisterMemoryProfileImage (
 | |
|     &gEfiCallerIdGuid,
 | |
|     ImageContext.ImageAddress,
 | |
|     ImageContext.ImageSize,
 | |
|     EFI_FV_FILETYPE_DRIVER
 | |
|     );
 | |
| 
 | |
|   Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Additional step for BootScript integrity
 | |
|   // Save BootScriptExecutor image
 | |
|   //
 | |
|   Status = SaveLockBox (
 | |
|              &mBootScriptExecutorImageGuid,
 | |
|              (VOID *)(UINTN)ImageContext.ImageAddress,
 | |
|              (UINTN)ImageContext.ImageSize
 | |
|              );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   gBS->CloseEvent (Event);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Entrypoint of Boot script exector driver, this function will be executed in
 | |
|   normal boot phase and invoked by DXE dispatch.
 | |
| 
 | |
|   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
 | |
|   @param[in] SystemTable    A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS       The entry point is executed successfully.
 | |
|   @retval other             Some error occurs when executing this entry point.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| BootScriptExecutorEntryPoint (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   UINTN                          BufferSize;
 | |
|   UINTN                          Pages;
 | |
|   BOOT_SCRIPT_EXECUTOR_VARIABLE  *EfiBootScriptExecutorVariable;
 | |
|   EFI_PHYSICAL_ADDRESS           BootScriptExecutorBuffer;
 | |
|   EFI_STATUS                     Status;
 | |
|   VOID                           *DevicePath;
 | |
|   EFI_EVENT                      ReadyToLockEvent;
 | |
|   VOID                           *Registration;
 | |
|   UINT32                         RegEax;
 | |
|   UINT32                         RegEdx;
 | |
| 
 | |
|   if (!PcdGetBool (PcdAcpiS3Enable)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Make sure AddressEncMask is contained to smallest supported address field.
 | |
|   //
 | |
|   mAddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
 | |
| 
 | |
|   //
 | |
|   // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
 | |
|   // point is loaded by DXE code which is the first time loaded. or else, it is already
 | |
|   // be reloaded be itself.This is a work-around
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Create ReadyToLock event to reload BootScriptExecutor image
 | |
|     // to RESERVED mem and save it to LockBox.
 | |
|     //
 | |
|     ReadyToLockEvent = EfiCreateProtocolNotifyEvent (
 | |
|                          &gEfiDxeSmmReadyToLockProtocolGuid,
 | |
|                          TPL_NOTIFY,
 | |
|                          ReadyToLockEventNotify,
 | |
|                          NULL,
 | |
|                          &Registration
 | |
|                          );
 | |
|     ASSERT (ReadyToLockEvent != NULL);
 | |
|   } else {
 | |
|     //
 | |
|     // the entry point is invoked after reloading. following code only run in RESERVED mem
 | |
|     //
 | |
|     if (PcdGetBool (PcdUse1GPageTable)) {
 | |
|       AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
 | |
|       if (RegEax >= 0x80000001) {
 | |
|         AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
 | |
|         if ((RegEdx & BIT26) != 0) {
 | |
|           mPage1GSupport = TRUE;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
 | |
| 
 | |
|     BootScriptExecutorBuffer = 0xFFFFFFFF;
 | |
|     Pages                    = EFI_SIZE_TO_PAGES (BufferSize);
 | |
|     Status                   = gBS->AllocatePages (
 | |
|                                       AllocateMaxAddress,
 | |
|                                       EfiReservedMemoryType,
 | |
|                                       Pages,
 | |
|                                       &BootScriptExecutorBuffer
 | |
|                                       );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     EfiBootScriptExecutorVariable                               = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;
 | |
|     EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN)S3BootScriptExecutorEntryFunction;
 | |
| 
 | |
|     Status = SaveLockBox (
 | |
|                &gEfiBootScriptExecutorVariableGuid,
 | |
|                &BootScriptExecutorBuffer,
 | |
|                sizeof (BootScriptExecutorBuffer)
 | |
|                );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     //
 | |
|     // Additional step for BootScript integrity
 | |
|     // Save BootScriptExecutor context
 | |
|     //
 | |
|     Status = SaveLockBox (
 | |
|                &gEfiBootScriptExecutorContextGuid,
 | |
|                EfiBootScriptExecutorVariable,
 | |
|                sizeof (*EfiBootScriptExecutorVariable)
 | |
|                );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |