/** @file\r
This is an implementation of the AcpiVariable platform field for ECP platform.\r
\r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2018, 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
ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData;\r
EFI_PHYSICAL_ADDRESS VideoOpromAddress;\r
UINT32 VideoOpromSize;\r
- EFI_PHYSICAL_ADDRESS S3DebugBufferAddress; \r
- EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint; \r
+ EFI_PHYSICAL_ADDRESS S3DebugBufferAddress;\r
+ EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint;\r
} ACPI_VARIABLE_SET_COMPATIBILITY;\r
\r
**/\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
GLOBAL_REMOVE_IF_UNREFERENCED\r
ACPI_VARIABLE_SET_COMPATIBILITY *mAcpiVariableSetCompatibility = NULL;\r
\r
/**\r
- Allocate EfiACPIMemoryNVS below 4G memory address.\r
+ Allocate memory below 4G memory address.\r
\r
- This function allocates EfiACPIMemoryNVS below 4G memory address.\r
+ This function allocates memory below 4G memory address.\r
\r
+ @param MemoryType Memory type of memory to allocate.\r
@param Size Size of memory to allocate.\r
- \r
+\r
@return Allocated address for output.\r
\r
**/\r
VOID*\r
-AllocateAcpiNvsMemoryBelow4G (\r
- IN UINTN Size\r
+AllocateMemoryBelow4G (\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Size\r
);\r
\r
/**\r
Hook point for AcpiVariableThunkPlatform for S3Ready.\r
\r
- @param AcpiS3Context ACPI s3 context\r
**/\r
VOID\r
S3ReadyThunkPlatform (\r
- IN ACPI_S3_CONTEXT *AcpiS3Context\r
+ VOID\r
)\r
{\r
EFI_PHYSICAL_ADDRESS AcpiMemoryBase;\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
- AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));\r
+ AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3AcpiReservedMemorySize));\r
ASSERT (AcpiMemoryBase != 0);\r
AcpiMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);\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
);\r
if (!EFI_ERROR (Status)) {\r
//\r
- // On ECP platform, if framework CPU drivers are in use, The compatible version of ACPI variable set \r
- // should be produced by CPU driver. \r
+ // On ECP platform, if framework CPU drivers are in use, The compatible version of ACPI variable set\r
+ // should be produced by CPU driver.\r
//\r
VarSize = sizeof (mAcpiVariableSetCompatibility);\r
Status = gRT->GetVariable (\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
+ // Allocate/initialize the compatible version of Acpi Variable Set since Framework chipset/platform\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 = AllocateAcpiNvsMemoryBelow4G (sizeof(ACPI_VARIABLE_SET_COMPATIBILITY));\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