#include <Protocol/ReportStatusCodeHandler.h>\r
#include <Protocol/AcpiTable.h>\r
#include <Protocol/SmmCommunication.h>\r
+#include <Protocol/LockBox.h>\r
+#include <Protocol/Variable.h>\r
\r
#include <Guid/Acpi.h>\r
#include <Guid/FirmwarePerformance.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/HobLib.h>\r
-#include <Library/PcdLib.h>\r
+#include <Library/LockBoxLib.h>\r
+#include <Library/UefiLib.h>\r
\r
//\r
// ACPI table information used to initialize tables.\r
\r
EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;\r
\r
+BOOLEAN mLockBoxReady = FALSE;\r
EFI_EVENT mReadyToBootEvent;\r
EFI_EVENT mLegacyBootEvent;\r
EFI_EVENT mExitBootServicesEvent;\r
EFI_STATUS Status;\r
VOID *Buffer;\r
\r
+ Buffer = NULL;\r
Pages = EFI_SIZE_TO_PAGES (Size);\r
Address = 0xffffffff;\r
\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- Buffer = (VOID *) (UINTN) Address;\r
- ZeroMem (Buffer, Size);\r
+ if (!EFI_ERROR (Status)) {\r
+ Buffer = (VOID *) (UINTN) Address;\r
+ ZeroMem (Buffer, Size);\r
+ }\r
\r
return Buffer;\r
}\r
\r
+/**\r
+ Callback function upon VariableArchProtocol and LockBoxProtocol\r
+ to allocate S3 performance table memory and save the pointer to LockBox.\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
+FpdtAllocateS3PerformanceTableMemory (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *Interface;\r
+ FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
+ UINTN Size;\r
+ EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer;\r
+\r
+ if (mLockBoxReady && (mAcpiS3PerformanceTable != NULL)) {\r
+ //\r
+ // The memory for S3 performance table should have been ready,\r
+ // and the pointer should have been saved to LockBox, just return.\r
+ //\r
+ return;\r
+ }\r
+\r
+ if (!mLockBoxReady) {\r
+ Status = gBS->LocateProtocol (&gEfiLockBoxProtocolGuid, NULL, &Interface);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // LockBox services has been ready.\r
+ //\r
+ mLockBoxReady = TRUE;\r
+ }\r
+ }\r
+\r
+ if (mAcpiS3PerformanceTable == NULL) {\r
+ Status = gBS->LocateProtocol (&gEfiVariableArchProtocolGuid, NULL, &Interface);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Try to allocate the same runtime buffer as last time boot.\r
+ //\r
+ ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));\r
+ Size = sizeof (PerformanceVariable);\r
+ Status = gRT->GetVariable (\r
+ EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
+ &gEfiFirmwarePerformanceGuid,\r
+ NULL,\r
+ &Size,\r
+ &PerformanceVariable\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->AllocatePages (\r
+ AllocateAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)),\r
+ &PerformanceVariable.S3PerformanceTablePointer\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.S3PerformanceTablePointer;\r
+ }\r
+ }\r
+ if (mAcpiS3PerformanceTable == NULL) {\r
+ //\r
+ // Fail to allocate at specified address, continue to allocate at any address.\r
+ //\r
+ mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (sizeof (S3_PERFORMANCE_TABLE));\r
+ }\r
+ DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable));\r
+ if (mAcpiS3PerformanceTable != NULL) {\r
+ CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));\r
+ }\r
+ }\r
+ }\r
+\r
+ if (mLockBoxReady && (mAcpiS3PerformanceTable != NULL)) {\r
+ //\r
+ // If LockBox services has been ready and memory for FPDT S3 performance table has been allocated,\r
+ // save the pointer to LockBox for use in S3 resume.\r
+ //\r
+ S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;\r
+ Status = SaveLockBox (\r
+ &gFirmwarePerformanceS3PointerGuid,\r
+ &S3PerformanceTablePointer,\r
+ sizeof (EFI_PHYSICAL_ADDRESS)\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+}\r
+\r
/**\r
Install ACPI Firmware Performance Data Table (FPDT).\r
\r
{\r
EFI_STATUS Status;\r
EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
- EFI_PHYSICAL_ADDRESS Address;\r
UINTN Size;\r
UINT8 *SmmBootRecordCommBuffer;\r
EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;\r
SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;\r
UINTN CommSize;\r
- UINTN PerformanceRuntimeDataSize;\r
- UINT8 *PerformanceRuntimeData; \r
- UINT8 *PerformanceRuntimeDataHead; \r
+ UINTN BootPerformanceDataSize;\r
+ UINT8 *BootPerformanceData; \r
EFI_SMM_COMMUNICATION_PROTOCOL *Communication;\r
FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
\r
FreePool (SmmBootRecordCommBuffer);\r
\r
//\r
- // Prepare memory for runtime Performance Record. \r
- // Runtime performance records includes two tables S3 performance table and Boot performance table. \r
- // S3 Performance table includes S3Resume and S3Suspend records. \r
+ // Prepare memory for Boot Performance table.\r
// Boot Performance table includes BasicBoot record, and one or more appended Boot Records. \r
//\r
- PerformanceRuntimeData = NULL;\r
- PerformanceRuntimeDataSize = sizeof (S3_PERFORMANCE_TABLE) + sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);\r
+ BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);\r
if (SmmCommData != NULL) {\r
- PerformanceRuntimeDataSize += SmmCommData->BootRecordSize;\r
+ BootPerformanceDataSize += SmmCommData->BootRecordSize;\r
}\r
\r
//\r
&PerformanceVariable\r
);\r
if (!EFI_ERROR (Status)) {\r
- Address = PerformanceVariable.S3PerformanceTablePointer;\r
Status = gBS->AllocatePages (\r
AllocateAddress,\r
EfiReservedMemoryType,\r
- EFI_SIZE_TO_PAGES (PerformanceRuntimeDataSize),\r
- &Address\r
+ EFI_SIZE_TO_PAGES (BootPerformanceDataSize),\r
+ &PerformanceVariable.BootPerformanceTablePointer\r
);\r
if (!EFI_ERROR (Status)) {\r
- PerformanceRuntimeData = (UINT8 *) (UINTN) Address;\r
+ mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer;\r
}\r
}\r
\r
- if (PerformanceRuntimeData == NULL) {\r
+ if (mAcpiBootPerformanceTable == NULL) {\r
//\r
// Fail to allocate at specified address, continue to allocate at any address.\r
//\r
- PerformanceRuntimeData = FpdtAllocateReservedMemoryBelow4G (PerformanceRuntimeDataSize);\r
+ mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize);\r
}\r
- DEBUG ((EFI_D_INFO, "FPDT: Performance Runtime Data address = 0x%x\n", PerformanceRuntimeData));\r
+ DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));\r
\r
- if (PerformanceRuntimeData == NULL) {\r
+ if (mAcpiBootPerformanceTable == NULL) {\r
if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {\r
FreePool (SmmCommData->BootRecordData);\r
}\r
+ if (mAcpiS3PerformanceTable != NULL) {\r
+ FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));\r
+ }\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- \r
- PerformanceRuntimeDataHead = PerformanceRuntimeData;\r
-\r
- if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {\r
- //\r
- // Prepare S3 Performance Table.\r
- //\r
- mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) PerformanceRuntimeData;\r
- CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));\r
- PerformanceRuntimeData = PerformanceRuntimeData + mAcpiS3PerformanceTable->Header.Length;\r
- DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable));\r
- //\r
- // Save S3 Performance Table address to Variable for use in Firmware Performance PEIM.\r
- //\r
- PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;\r
- //\r
- // Update S3 Performance Table Pointer in template.\r
- //\r
- mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) PerformanceVariable.S3PerformanceTablePointer;\r
- } else {\r
- //\r
- // Exclude S3 Performance Table Pointer from FPDT table template.\r
- //\r
- mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);\r
- }\r
\r
//\r
// Prepare Boot Performance Table.\r
//\r
- mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) PerformanceRuntimeData;\r
+ BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable;\r
//\r
// Fill Basic Boot record to Boot Performance Table.\r
//\r
- CopyMem (PerformanceRuntimeData, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));\r
- PerformanceRuntimeData = PerformanceRuntimeData + mAcpiBootPerformanceTable->Header.Length;\r
+ CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));\r
+ BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length;\r
//\r
// Fill Boot records from boot drivers.\r
//\r
- CopyMem (PerformanceRuntimeData, mBootRecordBuffer, mBootRecordSize);\r
+ CopyMem (BootPerformanceData, mBootRecordBuffer, mBootRecordSize);\r
mAcpiBootPerformanceTable->Header.Length += mBootRecordSize;\r
- PerformanceRuntimeData = PerformanceRuntimeData + mBootRecordSize;\r
+ BootPerformanceData = BootPerformanceData + mBootRecordSize;\r
if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {\r
//\r
// Fill Boot records from SMM drivers.\r
//\r
- CopyMem (PerformanceRuntimeData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);\r
+ CopyMem (BootPerformanceData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);\r
FreePool (SmmCommData->BootRecordData);\r
mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize);\r
- PerformanceRuntimeData = PerformanceRuntimeData + SmmCommData->BootRecordSize;\r
+ BootPerformanceData = BootPerformanceData + SmmCommData->BootRecordSize;\r
}\r
//\r
- // Reserve space for boot records after ReadyToBoot.\r
- //\r
- PerformanceRuntimeData = PerformanceRuntimeData + PcdGet32 (PcdExtFpdtBootRecordPadSize);\r
- DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));\r
- //\r
// Save Boot Performance Table address to Variable for use in S4 resume.\r
//\r
PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable;\r
//\r
mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;\r
\r
+ //\r
+ // Save S3 Performance Table address to Variable for use in S4 resume.\r
+ //\r
+ PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;\r
+ //\r
+ // Update S3 Performance Table Pointer in template.\r
+ //\r
+ mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) (UINTN) mAcpiS3PerformanceTable;\r
//\r
// Save Runtime Performance Table pointers to Variable.\r
//\r
Status = gRT->SetVariable (\r
EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
&gEfiFirmwarePerformanceGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
sizeof (PerformanceVariable),\r
&PerformanceVariable\r
);\r
&mFirmwarePerformanceTableTemplateKey\r
);\r
if (EFI_ERROR (Status)) {\r
- FreePool (PerformanceRuntimeDataHead);\r
+ FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize));\r
+ if (mAcpiS3PerformanceTable != NULL) {\r
+ FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));\r
+ }\r
mAcpiBootPerformanceTable = NULL;\r
mAcpiS3PerformanceTable = NULL;\r
return Status;\r
EFI_STATUS Status;\r
EFI_HOB_GUID_TYPE *GuidHob;\r
FIRMWARE_SEC_PERFORMANCE *Performance;\r
+ VOID *Registration;\r
\r
//\r
// Get Report Status Code Handler Protocol.\r
DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));\r
}\r
\r
+ if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {\r
+ //\r
+ // Register callback function upon VariableArchProtocol and LockBoxProtocol\r
+ // to allocate S3 performance table memory and save the pointer to LockBox.\r
+ //\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEfiVariableArchProtocolGuid,\r
+ TPL_CALLBACK,\r
+ FpdtAllocateS3PerformanceTableMemory,\r
+ NULL,\r
+ &Registration\r
+ );\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEfiLockBoxProtocolGuid,\r
+ TPL_CALLBACK,\r
+ FpdtAllocateS3PerformanceTableMemory,\r
+ NULL,\r
+ &Registration\r
+ );\r
+ } else {\r
+ //\r
+ // Exclude S3 Performance Table Pointer from FPDT table template.\r
+ //\r
+ mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r