/** @file\r
This is an implementation of the AcpiVariable platform field for ECP platform.\r
\r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2014, 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
#include <Library/HobLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
#include <Protocol/FrameworkMpService.h>\r
+#include <Protocol/VariableLock.h>\r
#include <Guid/AcpiVariableCompatibility.h>\r
#include <Guid/AcpiS3Context.h>\r
\r
\r
DEBUG ((EFI_D_INFO, "S3ReadyThunkPlatform\n"));\r
\r
+ if (mAcpiVariableSetCompatibility == NULL) {\r
+ return;\r
+ }\r
+\r
//\r
// Allocate ACPI reserved memory under 4G\r
//\r
return ;\r
}\r
\r
+/**\r
+ Register callback function upon VariableLockProtocol\r
+ to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it.\r
+\r
+ @param[in] Event Event whose notification function is being invoked.\r
+ @param[in] Context Pointer to the notification function's context.\r
+**/\r
+VOID\r
+EFIAPI\r
+VariableLockAcpiGlobalVariable (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
+ //\r
+ // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists\r
+ //\r
+ Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = VariableLock->RequestToLock (VariableLock, ACPI_GLOBAL_VARIABLE, &gEfiAcpiVariableCompatiblityGuid);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+}\r
+\r
/**\r
Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.\r
**/\r
EFI_STATUS Status;\r
FRAMEWORK_EFI_MP_SERVICES_PROTOCOL *FrameworkMpService;\r
UINTN VarSize;\r
+ VOID *Registration;\r
\r
Status = gBS->LocateProtocol (\r
&gFrameworkEfiMpServiceProtocolGuid,\r
&VarSize,\r
&mAcpiVariableSetCompatibility\r
);\r
- ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status) || (VarSize != sizeof (mAcpiVariableSetCompatibility))) {\r
+ DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility was not saved by CPU driver correctly. OS S3 may fail!\n"));\r
+ mAcpiVariableSetCompatibility = NULL;\r
+ }\r
} else {\r
//\r
// Allocate/initialize the compatible version of Acpi Variable Set since Framework chipset/platform \r
- // driver need this variable\r
+ // driver need this variable. ACPI_GLOBAL_VARIABLE variable is not used in runtime phase,\r
+ // so RT attribute is not needed for it.\r
//\r
mAcpiVariableSetCompatibility = AllocateMemoryBelow4G (EfiACPIMemoryNVS, sizeof(ACPI_VARIABLE_SET_COMPATIBILITY));\r
Status = gRT->SetVariable (\r
ACPI_GLOBAL_VARIABLE,\r
&gEfiAcpiVariableCompatiblityGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
sizeof(mAcpiVariableSetCompatibility),\r
&mAcpiVariableSetCompatibility\r
);\r
- ASSERT_EFI_ERROR (Status);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Register callback function upon VariableLockProtocol\r
+ // to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it.\r
+ //\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEdkiiVariableLockProtocolGuid,\r
+ TPL_CALLBACK,\r
+ VariableLockAcpiGlobalVariable,\r
+ NULL,\r
+ &Registration\r
+ );\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility cannot be saved: %r. OS S3 may fail!\n", Status));\r
+ gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiVariableSetCompatibility,\r
+ EFI_SIZE_TO_PAGES (sizeof (ACPI_VARIABLE_SET_COMPATIBILITY))\r
+ );\r
+ mAcpiVariableSetCompatibility = NULL;\r
+ }\r
}\r
\r
DEBUG((EFI_D_INFO, "AcpiVariableSetCompatibility is 0x%8x\n", mAcpiVariableSetCompatibility));\r