diff --git a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
index 5a93549271..766396d1d1 100644
--- a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
+++ b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
@@ -1,7 +1,7 @@
/** @file
Interpret and execute the S3 data in S3 boot script.
- Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -1199,8 +1199,18 @@ BootScriptExecuteInformation (
)
{
- UINT8 Index;
- for (Index = 0; Index < 10; Index++);
+ UINT32 Index;
+ EFI_BOOT_SCRIPT_INFORMATION Information;
+
+ CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(Information));
+
+ DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN)Information.Information));
+
+ DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
+ for (Index = 0; Index < Information.InformationLength; Index++) {
+ DEBUG ((EFI_D_INFO, "%02x ", *(UINT8 *)(UINTN)(Information.Information + Index)));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
}
/**
calculate the mask value for 'and' and 'or' operation
diff --git a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
index aa20d6d302..0ebfdbb1b6 100644
--- a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
+++ b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
@@ -54,6 +54,10 @@ EFI_GUID mBootScriptHeaderDataGuid = {
0x1810ab4a, 0x2314, 0x4df6, 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91
};
+EFI_GUID mBootScriptInformationGuid = {
+ 0x2c680508, 0x2b87, 0x46ab, 0xb9, 0x8a, 0x49, 0xfc, 0x23, 0xf9, 0xf5, 0x95
+};
+
/**
This is an internal function to add a terminate node the entry, recalculate the table
length and fill into the table.
@@ -99,6 +103,113 @@ S3BootScriptInternalCloseTable (
//
}
+/**
+ This function return the total size of INFORMATION OPCODE in boot script table.
+
+ @return InformationBufferSize The total size of INFORMATION OPCODE in boot script table.
+**/
+UINTN
+GetBootScriptInformationBufferSize (
+ VOID
+ )
+{
+ UINT8 *S3TableBase;
+ UINT8 *Script;
+ UINTN TableLength;
+ EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
+ EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
+ EFI_BOOT_SCRIPT_INFORMATION Information;
+ UINTN InformationBufferSize;
+
+ InformationBufferSize = 0;
+
+ S3TableBase = mS3BootScriptTablePtr->TableBase;
+ Script = S3TableBase;
+ CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
+ TableLength = TableHeader.TableLength;
+
+ //
+ // Go through the ScriptTable
+ //
+ while ((UINTN) Script < (UINTN) (S3TableBase + TableLength)) {
+ CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
+ switch (ScriptHeader.OpCode) {
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
+ CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(Information));
+ InformationBufferSize += Information.InformationLength;
+ break;
+ default:
+ break;
+ }
+ Script = Script + ScriptHeader.Length;
+ }
+
+ return InformationBufferSize;
+}
+
+/**
+ This function fix INFORMATION OPCODE in boot script table.
+ Originally, the Information buffer is pointer to EfiRuntimeServicesCode,
+ EfiRuntimeServicesData, or EfiACPIMemoryNVS. They are seperated.
+ Now, in order to save it to LockBox, we allocate a big EfiACPIMemoryNVS,
+ and fix the pointer for INFORMATION opcode InformationBuffer.
+
+ @param InformationBuffer The address of new Information buffer.
+ @param InformationBufferSize The size of new Information buffer.
+**/
+VOID
+FixBootScriptInformation (
+ IN VOID *InformationBuffer,
+ IN UINTN InformationBufferSize
+ )
+{
+ UINT8 *S3TableBase;
+ UINT8 *Script;
+ UINTN TableLength;
+ EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
+ EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
+ EFI_BOOT_SCRIPT_INFORMATION Information;
+ UINTN FixedInformationBufferSize;
+
+ FixedInformationBufferSize = 0;
+
+ S3TableBase = mS3BootScriptTablePtr->TableBase;
+ Script = S3TableBase;
+ CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
+ TableLength = TableHeader.TableLength;
+
+ //
+ // Go through the ScriptTable
+ //
+ while ((UINTN) Script < (UINTN) (S3TableBase + TableLength)) {
+ CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
+ switch (ScriptHeader.OpCode) {
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
+ CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(Information));
+
+ CopyMem (
+ (VOID *)((UINTN)InformationBuffer + FixedInformationBufferSize),
+ (VOID *)(UINTN)Information.Information,
+ Information.InformationLength
+ );
+ gBS->FreePool ((VOID *)(UINTN)Information.Information);
+ Information.Information = (EFI_PHYSICAL_ADDRESS)((UINTN)InformationBuffer + FixedInformationBufferSize);
+
+ CopyMem ((VOID*)Script, (VOID*)&Information, sizeof(Information));
+
+ FixedInformationBufferSize += Information.InformationLength;
+ break;
+ default:
+ break;
+ }
+ Script = Script + ScriptHeader.Length;
+ }
+
+ ASSERT (FixedInformationBufferSize == InformationBufferSize);
+
+ return ;
+}
+
/**
This function save boot script data to LockBox.
1. BootSriptPrivate data, BootScript data - Image and DispatchContext are handled by platform.
@@ -111,7 +222,45 @@ SaveBootScriptDataToLockBox (
VOID
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS InformationBuffer;
+ UINTN InformationBufferSize;
+
+ //
+ // We need save BootScriptInformation to LockBox, because it is in
+ // EfiRuntimeServicesCode, EfiRuntimeServicesData, or EfiACPIMemoryNVS.
+ //
+ //
+ InformationBufferSize = GetBootScriptInformationBufferSize ();
+ if (InformationBufferSize != 0) {
+ InformationBuffer = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES(InformationBufferSize),
+ &InformationBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Fix BootScript information pointer
+ //
+ FixBootScriptInformation ((VOID *)(UINTN)InformationBuffer, InformationBufferSize);
+
+ //
+ // Save BootScript information to lockbox
+ //
+ Status = SaveLockBox (
+ &mBootScriptInformationGuid,
+ (VOID *)(UINTN)InformationBuffer,
+ InformationBufferSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SetLockBoxAttributes (&mBootScriptInformationGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+ }
+
//
// mS3BootScriptTablePtr->TableLength does not include EFI_BOOT_SCRIPT_TERMINATE, because we need add entry at runtime.
// Save all info here, just in case that no one will add boot script entry in SMM.
@@ -1237,7 +1386,7 @@ S3BootScriptSaveInformation (
RETURN_STATUS Status;
UINT8 Length;
UINT8 *Script;
- EFI_PHYSICAL_ADDRESS Buffer;
+ VOID *Buffer;
EFI_BOOT_SCRIPT_INFORMATION ScriptInformation;
if (mS3BootScriptTablePtr->AtRuntime) {
@@ -1245,11 +1394,13 @@ S3BootScriptSaveInformation (
}
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION));
- Buffer = 0xFFFFFFFF;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiACPIMemoryNVS,
- EFI_SIZE_TO_PAGES(InformationLength),
+ //
+ // Use BootServicesData to hold the data, just in case caller free it.
+ // It will be copied into ACPINvs later.
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ InformationLength,
&Buffer
);
if (EFI_ERROR (Status)) {