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)) {