/** @file\r
Save the S3 data to S3 boot script. \r
\r
- Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
UINTN mLockBoxLength;\r
\r
EFI_GUID mBootScriptDataGuid = {\r
- 0xaea6b965, 0xdcf5, 0x4311, 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2\r
+ 0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }\r
};\r
\r
EFI_GUID mBootScriptHeaderDataGuid = {\r
- 0x1810ab4a, 0x2314, 0x4df6, 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91\r
+ 0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }\r
+};\r
+\r
+EFI_GUID mBootScriptInformationGuid = {\r
+ 0x2c680508, 0x2b87, 0x46ab, { 0xb9, 0x8a, 0x49, 0xfc, 0x23, 0xf9, 0xf5, 0x95 }\r
};\r
\r
/**\r
//\r
} \r
\r
+/**\r
+ This function return the total size of INFORMATION OPCODE in boot script table.\r
+\r
+ @return InformationBufferSize The total size of INFORMATION OPCODE in boot script table.\r
+**/\r
+UINTN\r
+GetBootScriptInformationBufferSize (\r
+ VOID\r
+ )\r
+{\r
+ UINT8 *S3TableBase;\r
+ UINT8 *Script;\r
+ UINTN TableLength;\r
+ EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;\r
+ EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;\r
+ EFI_BOOT_SCRIPT_INFORMATION Information;\r
+ UINTN InformationBufferSize;\r
+\r
+ InformationBufferSize = 0;\r
+\r
+ S3TableBase = mS3BootScriptTablePtr->TableBase;\r
+ Script = S3TableBase;\r
+ CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));\r
+ TableLength = TableHeader.TableLength;\r
+\r
+ //\r
+ // Go through the ScriptTable\r
+ //\r
+ while ((UINTN) Script < (UINTN) (S3TableBase + TableLength)) {\r
+ CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));\r
+ switch (ScriptHeader.OpCode) {\r
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:\r
+ CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(Information));\r
+ InformationBufferSize += Information.InformationLength;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ Script = Script + ScriptHeader.Length;\r
+ }\r
+\r
+ return InformationBufferSize;\r
+}\r
+\r
+/**\r
+ This function fix INFORMATION OPCODE in boot script table.\r
+ Originally, the Information buffer is pointer to EfiRuntimeServicesCode,\r
+ EfiRuntimeServicesData, or EfiACPIMemoryNVS. They are seperated.\r
+ Now, in order to save it to LockBox, we allocate a big EfiACPIMemoryNVS,\r
+ and fix the pointer for INFORMATION opcode InformationBuffer.\r
+\r
+ @param InformationBuffer The address of new Information buffer.\r
+ @param InformationBufferSize The size of new Information buffer.\r
+**/\r
+VOID\r
+FixBootScriptInformation (\r
+ IN VOID *InformationBuffer,\r
+ IN UINTN InformationBufferSize\r
+ )\r
+{\r
+ UINT8 *S3TableBase;\r
+ UINT8 *Script;\r
+ UINTN TableLength;\r
+ EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;\r
+ EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;\r
+ EFI_BOOT_SCRIPT_INFORMATION Information;\r
+ UINTN FixedInformationBufferSize;\r
+\r
+ FixedInformationBufferSize = 0;\r
+\r
+ S3TableBase = mS3BootScriptTablePtr->TableBase;\r
+ Script = S3TableBase;\r
+ CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));\r
+ TableLength = TableHeader.TableLength;\r
+\r
+ //\r
+ // Go through the ScriptTable\r
+ //\r
+ while ((UINTN) Script < (UINTN) (S3TableBase + TableLength)) {\r
+ CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));\r
+ switch (ScriptHeader.OpCode) {\r
+ case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:\r
+ CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(Information));\r
+\r
+ CopyMem (\r
+ (VOID *)((UINTN)InformationBuffer + FixedInformationBufferSize),\r
+ (VOID *)(UINTN)Information.Information,\r
+ Information.InformationLength\r
+ );\r
+ gBS->FreePool ((VOID *)(UINTN)Information.Information);\r
+ Information.Information = (EFI_PHYSICAL_ADDRESS)((UINTN)InformationBuffer + FixedInformationBufferSize);\r
+\r
+ CopyMem ((VOID*)Script, (VOID*)&Information, sizeof(Information));\r
+\r
+ FixedInformationBufferSize += Information.InformationLength;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ Script = Script + ScriptHeader.Length;\r
+ }\r
+\r
+ ASSERT (FixedInformationBufferSize == InformationBufferSize);\r
+\r
+ return ;\r
+}\r
+\r
/**\r
This function save boot script data to LockBox.\r
1. BootSriptPrivate data, BootScript data - Image and DispatchContext are handled by platform.\r
VOID\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS InformationBuffer;\r
+ UINTN InformationBufferSize;\r
+\r
+ //\r
+ // We need save BootScriptInformation to LockBox, because it is in\r
+ // EfiRuntimeServicesCode, EfiRuntimeServicesData, or EfiACPIMemoryNVS.\r
+ // \r
+ //\r
+ InformationBufferSize = GetBootScriptInformationBufferSize ();\r
+ if (InformationBufferSize != 0) {\r
+ InformationBuffer = 0xFFFFFFFF;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES(InformationBufferSize),\r
+ &InformationBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Fix BootScript information pointer\r
+ //\r
+ FixBootScriptInformation ((VOID *)(UINTN)InformationBuffer, InformationBufferSize);\r
+\r
+ //\r
+ // Save BootScript information to lockbox\r
+ //\r
+ Status = SaveLockBox (\r
+ &mBootScriptInformationGuid,\r
+ (VOID *)(UINTN)InformationBuffer,\r
+ InformationBufferSize\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = SetLockBoxAttributes (&mBootScriptInformationGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
//\r
// mS3BootScriptTablePtr->TableLength does not include EFI_BOOT_SCRIPT_TERMINATE, because we need add entry at runtime.\r
// Save all info here, just in case that no one will add boot script entry in SMM.\r
// Here we do not count the reserved memory for runtime script table.\r
PageNumber = (UINT16)(mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber)); \r
TableLength = mS3BootScriptTablePtr->TableLength;\r
- if ((UINT32)(PageNumber * EFI_PAGE_SIZE) < (TableLength + EntryLength)) {\r
+ if ((UINT32)(PageNumber * EFI_PAGE_SIZE) < (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {\r
// \r
// The buffer is too small to hold the table, Reallocate the buffer\r
//\r
RETURN_STATUS Status;\r
UINT8 Length;\r
UINT8 *Script;\r
- EFI_PHYSICAL_ADDRESS Buffer;\r
+ VOID *Buffer;\r
EFI_BOOT_SCRIPT_INFORMATION ScriptInformation;\r
\r
if (mS3BootScriptTablePtr->AtRuntime) {\r
}\r
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION));\r
\r
- Buffer = 0xFFFFFFFF;\r
- Status = gBS->AllocatePages (\r
- AllocateMaxAddress,\r
- EfiACPIMemoryNVS,\r
- EFI_SIZE_TO_PAGES(InformationLength),\r
+ //\r
+ // Use BootServicesData to hold the data, just in case caller free it.\r
+ // It will be copied into ACPINvs later.\r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData,\r
+ InformationLength,\r
&Buffer\r
);\r
if (EFI_ERROR (Status)) {\r
EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;\r
UINT32 LabelLength;\r
//\r
- // Assume Label is not NULL\r
+ // Check NULL Label\r
+ //\r
+ if (Label == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Check empty Label\r
//\r
- if (Label == NULL) {\r
+ if (Label[0] == '\0') {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r