This module install ACPI Firmware Performance Data Table (FPDT).\r
\r
This module register report status code listener to collect performance data\r
- for Firmware Basic Boot Performance Record and install FPDT to ACPI table.\r
+ for Firmware Basic Boot Performance Record and other boot performance records,\r
+ and install FPDT to ACPI table.\r
\r
- Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <PiDxe.h>\r
\r
-#include <IndustryStandard/Acpi50.h>\r
-\r
#include <Protocol/ReportStatusCodeHandler.h>\r
#include <Protocol/AcpiTable.h>\r
+#include <Protocol/LockBox.h>\r
+#include <Protocol/Variable.h>\r
+#include <Protocol/VariablePolicy.h>\r
\r
#include <Guid/Acpi.h>\r
#include <Guid/FirmwarePerformance.h>\r
-#include <Guid/EventGroup.h>\r
-#include <Guid/EventLegacyBios.h>\r
\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/DebugLib.h>\r
+#include <Library/DxeServicesLib.h>\r
#include <Library/TimerLib.h>\r
#include <Library/BaseMemoryLib.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
+#include <Library/VariablePolicyHelperLib.h>\r
+#include <Library/PerformanceLib.h>\r
\r
-//\r
-// ACPI table information used to initialize tables.\r
-//\r
-#define EFI_ACPI_OEM_ID "INTEL"\r
-#define EFI_ACPI_OEM_TABLE_ID 0x2020204F4E414954ULL // "TIANO "\r
-#define EFI_ACPI_OEM_REVISION 0x00000001\r
-#define EFI_ACPI_CREATOR_ID 0x5446534D // TBD "MSFT"\r
-#define EFI_ACPI_CREATOR_REVISION 0x01000013 // TBD\r
+#define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))\r
\r
-EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;\r
+EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;\r
\r
-EFI_EVENT mReadyToBootEvent;\r
-EFI_EVENT mLegacyBootEvent;\r
-EFI_EVENT mExitBootServicesEvent;\r
-UINTN mFirmwarePerformanceTableTemplateKey = 0;\r
+BOOLEAN mLockBoxReady = FALSE;\r
+EFI_EVENT mReadyToBootEvent;\r
+EFI_EVENT mLegacyBootEvent;\r
+static EFI_EVENT mExitBootServicesEvent;\r
+UINTN mFirmwarePerformanceTableTemplateKey = 0;\r
+BOOLEAN mDxeCoreReportStatusCodeEnable = FALSE;\r
\r
-FIRMWARE_PERFORMANCE_RUNTIME_DATA *mPerformanceRuntimeData = NULL;\r
-BOOT_PERFORMANCE_TABLE *mAcpiBootPerformanceTable = NULL;\r
-S3_PERFORMANCE_TABLE *mAcpiS3PerformanceTable = NULL;\r
+BOOT_PERFORMANCE_TABLE *mAcpiBootPerformanceTable = NULL;\r
+BOOT_PERFORMANCE_TABLE *mReceivedAcpiBootPerformanceTable = NULL;\r
+S3_PERFORMANCE_TABLE *mAcpiS3PerformanceTable = NULL;\r
\r
FIRMWARE_PERFORMANCE_TABLE mFirmwarePerformanceTableTemplate = {\r
{\r
EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE,\r
sizeof (FIRMWARE_PERFORMANCE_TABLE),\r
- EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION, // Revision\r
- 0x00, // Checksum will be updated at runtime\r
+ EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION, // Revision\r
+ 0x00, // Checksum will be updated at runtime\r
//\r
- // It is expected that these values will be updated at runtime.\r
+ // It is expected that these values will be updated at EntryPoint.\r
//\r
- EFI_ACPI_OEM_ID, // OEMID is a 6 bytes long field\r
- EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long)\r
- EFI_ACPI_OEM_REVISION, // OEM revision number\r
- EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID\r
- EFI_ACPI_CREATOR_REVISION, // ASL compiler revision number\r
+ { 0x00 }, // OEM ID is a 6 bytes long field\r
+ 0x00, // OEM Table ID(8 bytes long)\r
+ 0x00, // OEM Revision\r
+ 0x00, // Creator ID\r
+ 0x00, // Creator Revision\r
},\r
//\r
// Firmware Basic Boot Performance Table Pointer Record.\r
//\r
{\r
{\r
- EFI_ACPI_5_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER , // Type\r
+ EFI_ACPI_5_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER, // Type\r
sizeof (EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD), // Length\r
EFI_ACPI_5_0_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER // Revision\r
},\r
}\r
};\r
\r
-BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate = {\r
+BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate = {\r
{\r
EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE,\r
sizeof (BOOT_PERFORMANCE_TABLE)\r
}\r
};\r
\r
-S3_PERFORMANCE_TABLE mS3PerformanceTableTemplate = {\r
+S3_PERFORMANCE_TABLE mS3PerformanceTableTemplate = {\r
{\r
EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE,\r
sizeof (S3_PERFORMANCE_TABLE)\r
**/\r
VOID\r
FpdtAcpiTableChecksum (\r
- IN UINT8 *Buffer,\r
- IN UINTN Size\r
+ IN UINT8 *Buffer,\r
+ IN UINTN Size\r
)\r
{\r
- UINTN ChecksumOffset;\r
+ UINTN ChecksumOffset;\r
\r
ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);\r
\r
}\r
\r
/**\r
- Allocate EfiReservedMemoryType below 4G memory address.\r
-\r
- This function allocates EfiReservedMemoryType below 4G memory address.\r
-\r
- @param[in] Size Size of memory to allocate.\r
-\r
- @return Allocated address for output.\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
-FpdtAllocateReservedMemoryBelow4G (\r
- IN UINTN Size\r
+VOID\r
+EFIAPI\r
+FpdtAllocateS3PerformanceTableMemory (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
- UINTN Pages;\r
- EFI_PHYSICAL_ADDRESS Address;\r
- EFI_STATUS Status;\r
- VOID *Buffer;\r
-\r
- Pages = EFI_SIZE_TO_PAGES (Size);\r
- Address = 0xffffffff;\r
-\r
- Status = gBS->AllocatePages (\r
- AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
- Pages,\r
- &Address\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ EFI_STATUS Status;\r
+ VOID *Interface;\r
+ FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
+ UINTN Size;\r
+ EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer;\r
\r
- Buffer = (VOID *) (UINTN) Address;\r
- ZeroMem (Buffer, Size);\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
- return Buffer;\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
+\r
+ if (mAcpiS3PerformanceTable == NULL) {\r
+ //\r
+ // Fail to allocate at specified address, continue to allocate at any address.\r
+ //\r
+ mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *)AllocatePeiAccessiblePages (\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE))\r
+ );\r
+ }\r
+\r
+ DEBUG ((DEBUG_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
VOID\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
- FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
- EFI_PHYSICAL_ADDRESS Address;\r
- UINTN Size;\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
+ UINTN BootPerformanceDataSize;\r
+ FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
+ UINTN Size;\r
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicyProtocol;\r
\r
//\r
// Get AcpiTable Protocol.\r
//\r
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
//\r
- // Prepare memory for runtime Performance Record.\r
+ // Get VariablePolicy Protocol.\r
//\r
- mPerformanceRuntimeData = NULL;\r
- ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));\r
- //\r
- // Try to allocate the same runtime buffer as last time boot.\r
- //\r
- Size = sizeof (FIRMWARE_PERFORMANCE_VARIABLE);\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
- Address = PerformanceVariable.BootPerformanceTablePointer;\r
- Status = gBS->AllocatePages (\r
- AllocateAddress,\r
- EfiReservedMemoryType,\r
- EFI_SIZE_TO_PAGES (sizeof (FIRMWARE_PERFORMANCE_RUNTIME_DATA)),\r
- &Address\r
+ Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicyProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (mReceivedAcpiBootPerformanceTable != NULL) {\r
+ mAcpiBootPerformanceTable = mReceivedAcpiBootPerformanceTable;\r
+ mAcpiBootPerformanceTable->BasicBoot.ResetEnd = mBootPerformanceTableTemplate.BasicBoot.ResetEnd;\r
+ } else {\r
+ //\r
+ // Try to allocate the same runtime buffer as last time boot.\r
+ //\r
+ BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE);\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
- mPerformanceRuntimeData = (FIRMWARE_PERFORMANCE_RUNTIME_DATA *) (UINTN) Address;\r
+ Status = gBS->AllocatePages (\r
+ AllocateAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (BootPerformanceDataSize),\r
+ &PerformanceVariable.BootPerformanceTablePointer\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *)(UINTN)PerformanceVariable.BootPerformanceTablePointer;\r
+ }\r
+ }\r
+\r
+ if (mAcpiBootPerformanceTable == NULL) {\r
+ //\r
+ // Fail to allocate at specified address, continue to allocate at any address.\r
+ //\r
+ mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *)AllocatePeiAccessiblePages (\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (BootPerformanceDataSize)\r
+ );\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));\r
+ if (mAcpiBootPerformanceTable == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
- }\r
\r
- if (mPerformanceRuntimeData == NULL) {\r
//\r
- // Fail to allocate at specified address, continue to allocate at any address.\r
+ // Fill Basic Boot record to Boot Performance Table.\r
//\r
- mPerformanceRuntimeData = FpdtAllocateReservedMemoryBelow4G (sizeof (FIRMWARE_PERFORMANCE_RUNTIME_DATA));\r
+ CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));\r
}\r
- DEBUG ((EFI_D_INFO, "FPDT: Performance Runtime Data address = 0x%x\n", mPerformanceRuntimeData));\r
\r
- if (mPerformanceRuntimeData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ BootPerformanceDataSize = mAcpiBootPerformanceTable->Header.Length;\r
\r
- //\r
- // Prepare Boot Performance Table.\r
- //\r
- mAcpiBootPerformanceTable = &mPerformanceRuntimeData->BootPerformance;\r
- CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));\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
+ PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS)(UINTN)mAcpiBootPerformanceTable;\r
//\r
// Update Boot Performance Table Pointer in template.\r
//\r
- mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;\r
-\r
- if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {\r
- //\r
- // Prepare S3 Performance Table.\r
- //\r
- mAcpiS3PerformanceTable = &mPerformanceRuntimeData->S3Performance;\r
- CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));\r
- DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable));\r
-\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
- //\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_SUSPEND_RECORD);\r
- }\r
+ mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64)(UINTN)mAcpiBootPerformanceTable;\r
\r
//\r
- // Save Runtime Performance Table pointers to Variable.\r
+ // Save S3 Performance Table address to Variable for use in S4 resume.\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
- sizeof (FIRMWARE_PERFORMANCE_VARIABLE),\r
- &PerformanceVariable\r
- );\r
- ASSERT_EFI_ERROR (Status);\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
+ // Don't check SetVariable return status. It doesn't impact FPDT table generation.\r
+ //\r
+ gRT->SetVariable (\r
+ EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
+ &gEfiFirmwarePerformanceGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (PerformanceVariable),\r
+ &PerformanceVariable\r
+ );\r
+\r
+ //\r
+ // Lock the variable which stores the Performance Table pointers.\r
+ //\r
+ Status = RegisterBasicVariablePolicy (\r
+ VariablePolicyProtocol,\r
+ &gEfiFirmwarePerformanceGuid,\r
+ EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
+ VARIABLE_POLICY_NO_MIN_SIZE,\r
+ VARIABLE_POLICY_NO_MAX_SIZE,\r
+ VARIABLE_POLICY_NO_MUST_ATTR,\r
+ VARIABLE_POLICY_NO_CANT_ATTR,\r
+ VARIABLE_POLICY_TYPE_LOCK_NOW\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[FirmwarePerformanceDxe] Error when lock variable %s, Status = %r\n", EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
\r
//\r
// Publish Firmware Performance Data Table.\r
//\r
- FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length);\r
+ FpdtAcpiTableChecksum ((UINT8 *)&mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length);\r
Status = AcpiTableProtocol->InstallAcpiTable (\r
AcpiTableProtocol,\r
&mFirmwarePerformanceTableTemplate,\r
&mFirmwarePerformanceTableTemplateKey\r
);\r
if (EFI_ERROR (Status)) {\r
- FreePool (mPerformanceRuntimeData);\r
+ if (mAcpiBootPerformanceTable != NULL) {\r
+ FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize));\r
+ }\r
+\r
+ if (mAcpiS3PerformanceTable != NULL) {\r
+ FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));\r
+ }\r
+\r
mAcpiBootPerformanceTable = NULL;\r
- mAcpiS3PerformanceTable = NULL;\r
+ mAcpiS3PerformanceTable = NULL;\r
return Status;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to\r
- install the Firmware Performance Data Table.\r
-\r
- @param[in] Event The Event that is being processed.\r
- @param[in] Context The Event Context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-FpdtReadyToBootEventNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- if (mAcpiBootPerformanceTable == NULL) {\r
- //\r
- // ACPI Firmware Performance Data Table not installed yet, install it now.\r
- //\r
- InstallFirmwarePerformanceDataTable ();\r
- }\r
-}\r
-\r
-/**\r
- Notify function for event group EFI_EVENT_LEGACY_BOOT_GUID. This is used to\r
- record performance data for OsLoaderLoadImageStart in FPDT for legacy boot.\r
-\r
- @param[in] Event The Event that is being processed.\r
- @param[in] Context The Event Context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-FpdtLegacyBootEventNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- if (mAcpiBootPerformanceTable == NULL) {\r
- //\r
- // Firmware Performance Data Table not installed, do nothing.\r
- //\r
- return ;\r
- }\r
-\r
- //\r
- // Update Firmware Basic Boot Performance Record for legacy boot.\r
- //\r
- mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = 0;\r
- mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());\r
- mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = 0;\r
- mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = 0;\r
-\r
- //\r
- // Dump FPDT Boot Performance record.\r
- //\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = 0\n"));\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));\r
-}\r
-\r
-/**\r
- Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record\r
- performance data for ExitBootServicesEntry in FPDT.\r
-\r
- @param[in] Event The Event that is being processed.\r
- @param[in] Context The Event Context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-FpdtExitBootServicesEventNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- if (mAcpiBootPerformanceTable == NULL) {\r
- //\r
- // Firmware Performance Data Table not installed, do nothing.\r
- //\r
- return ;\r
- }\r
-\r
- //\r
- // Update Firmware Basic Boot Performance Record for UEFI boot.\r
- //\r
- mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());\r
-\r
- //\r
- // Dump FPDT Boot Performance record.\r
- //\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));\r
- DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));\r
- //\r
- // ExitBootServicesExit will be updated later, so don't dump it here.\r
- //\r
-}\r
-\r
/**\r
Report status code listener of FPDT. This is used to collect performance data\r
for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.\r
EFI_STATUS\r
EFIAPI\r
FpdtStatusCodeListenerDxe (\r
- IN EFI_STATUS_CODE_TYPE CodeType,\r
- IN EFI_STATUS_CODE_VALUE Value,\r
- IN UINT32 Instance,\r
- IN EFI_GUID *CallerId,\r
- IN EFI_STATUS_CODE_DATA *Data\r
+ IN EFI_STATUS_CODE_TYPE CodeType,\r
+ IN EFI_STATUS_CODE_VALUE Value,\r
+ IN UINT32 Instance,\r
+ IN EFI_GUID *CallerId,\r
+ IN EFI_STATUS_CODE_DATA *Data\r
)\r
{\r
EFI_STATUS Status;\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ if (Value == (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT)) {\r
+ //\r
+ // DxeCore ReportStatusCode Enable so that the capability can be supported.\r
+ //\r
+ mDxeCoreReportStatusCodeEnable = TRUE;\r
+ }\r
+\r
Status = EFI_SUCCESS;\r
if (Value == PcdGet32 (PcdProgressCodeOsLoaderLoad)) {\r
//\r
//\r
mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());\r
} else if (Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) {\r
+ //\r
+ // Unregister boot time report status code listener.\r
+ //\r
+ mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);\r
+\r
//\r
// Progress code for ExitBootServices.\r
//\r
// Update ExitBootServicesExit for UEFI boot.\r
//\r
mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = GetTimeInNanoSecond (GetPerformanceCounter ());\r
+ } else if (Value == (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT)) {\r
+ if (mAcpiBootPerformanceTable == NULL) {\r
+ //\r
+ // Firmware Performance Data Table not installed, do nothing.\r
+ //\r
+ return Status;\r
+ }\r
\r
//\r
- // Unregister boot time report status code listener.\r
+ // Update Firmware Basic Boot Performance Record for legacy boot.\r
//\r
- mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);\r
+ mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());\r
+\r
+ //\r
+ // Dump FPDT Boot Performance record.\r
+ //\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = 0\n"));\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));\r
+ } else if ((Data != NULL) && CompareGuid (&Data->Type, &gEdkiiFpdtExtendedFirmwarePerformanceGuid)) {\r
+ //\r
+ // Get the Boot performance table and then install it to ACPI table.\r
+ //\r
+ CopyMem (&mReceivedAcpiBootPerformanceTable, Data + 1, Data->Size);\r
+ InstallFirmwarePerformanceDataTable ();\r
+ } else if ((Data != NULL) && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {\r
+ DEBUG ((DEBUG_ERROR, "FpdtStatusCodeListenerDxe: Performance data reported through gEfiFirmwarePerformanceGuid will not be collected by FirmwarePerformanceDataTableDxe\n"));\r
+ Status = EFI_UNSUPPORTED;\r
} else {\r
//\r
// Ignore else progress code.\r
return Status;\r
}\r
\r
+/**\r
+ Notify function for event EndOfDxe.\r
+\r
+ This is used to install ACPI Firmware Performance Data Table for basic boot records.\r
+\r
+ @param[in] Event The Event that is being processed.\r
+ @param[in] Context The Event Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FpdtEndOfDxeEventNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // When performance is enabled, the FPDT will be installed when DxeCorePerformanceLib report the data to FimwarePerformanceDxe.\r
+ // This is used to install the FPDT for the basic boot recods when performance infrastructure is not enabled.\r
+ //\r
+ if ((PcdGet8 (PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0) {\r
+ return;\r
+ }\r
+\r
+ ASSERT (mReceivedAcpiBootPerformanceTable == NULL);\r
+ InstallFirmwarePerformanceDataTable ();\r
+}\r
+\r
+/**\r
+ Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record\r
+ performance data for ExitBootServicesEntry in FPDT.\r
+\r
+ @param[in] Event The Event that is being processed.\r
+ @param[in] Context The Event Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FpdtExitBootServicesEventNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ if (!mDxeCoreReportStatusCodeEnable) {\r
+ //\r
+ // When DxeCore Report Status Code is disabled,\r
+ // Unregister boot time report status code listener at ExitBootService Event.\r
+ //\r
+ mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);\r
+ }\r
+\r
+ if (mAcpiBootPerformanceTable == NULL) {\r
+ //\r
+ // Firmware Performance Data Table not installed, do nothing.\r
+ //\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Update Firmware Basic Boot Performance Record for UEFI boot.\r
+ //\r
+ mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());\r
+\r
+ //\r
+ // Dump FPDT Boot Performance record.\r
+ //\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));\r
+ DEBUG ((DEBUG_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));\r
+ //\r
+ // ExitBootServicesExit will be updated later, so don't dump it here.\r
+ //\r
+}\r
+\r
/**\r
The module Entry Point of the Firmware Performance Data Table DXE driver.\r
\r
EFI_STATUS\r
EFIAPI\r
FirmwarePerformanceDxeEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_HOB_GUID_TYPE *GuidHob;\r
- FIRMWARE_SEC_PERFORMANCE *Performance;\r
+ EFI_STATUS Status;\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+ FIRMWARE_SEC_PERFORMANCE *Performance;\r
+ VOID *Registration;\r
+ UINT64 OemTableId;\r
+ EFI_EVENT EndOfDxeEvent;\r
+\r
+ CopyMem (\r
+ mFirmwarePerformanceTableTemplate.Header.OemId,\r
+ PcdGetPtr (PcdAcpiDefaultOemId),\r
+ sizeof (mFirmwarePerformanceTableTemplate.Header.OemId)\r
+ );\r
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+ CopyMem (&mFirmwarePerformanceTableTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+ mFirmwarePerformanceTableTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+ mFirmwarePerformanceTableTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+ mFirmwarePerformanceTableTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
\r
//\r
// Get Report Status Code Handler Protocol.\r
//\r
- Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mRscHandlerProtocol);\r
+ Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **)&mRscHandlerProtocol);\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Register the notify function to update FPDT on ExitBootServices Event.\r
- //\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- FpdtExitBootServicesEventNotify,\r
- NULL,\r
- &gEfiEventExitBootServicesGuid,\r
- &mExitBootServicesEvent\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Create ready to boot event to install ACPI FPDT table.\r
+ // Register the notify function to install FPDT at EndOfDxe.\r
//\r
Status = gBS->CreateEventEx (\r
EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
- FpdtReadyToBootEventNotify,\r
+ FpdtEndOfDxeEventNotify,\r
NULL,\r
- &gEfiEventReadyToBootGuid,\r
- &mReadyToBootEvent\r
+ &gEfiEndOfDxeEventGroupGuid,\r
+ &EndOfDxeEvent\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Create legacy boot event to log OsLoaderStartImageStart for legacy boot.\r
+ // Register the notify function to update FPDT on ExitBootServices Event.\r
//\r
Status = gBS->CreateEventEx (\r
EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
- FpdtLegacyBootEventNotify,\r
+ FpdtExitBootServicesEventNotify,\r
NULL,\r
- &gEfiEventLegacyBootGuid,\r
- &mLegacyBootEvent\r
+ &gEfiEventExitBootServicesGuid,\r
+ &mExitBootServicesEvent\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
GuidHob = GetFirstGuidHob (&gEfiFirmwarePerformanceGuid);\r
if (GuidHob != NULL) {\r
- Performance = (FIRMWARE_SEC_PERFORMANCE *) GET_GUID_HOB_DATA (GuidHob);\r
+ Performance = (FIRMWARE_SEC_PERFORMANCE *)GET_GUID_HOB_DATA (GuidHob);\r
mBootPerformanceTableTemplate.BasicBoot.ResetEnd = Performance->ResetEnd;\r
} else {\r
//\r
// SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.\r
//\r
- DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));\r
+ DEBUG ((DEBUG_WARN, "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