StartPerformanceMeasurement(), EndPerformanceMeasurement(), StartPerformanceMeasurementEx()\r
and EndPerformanceMeasurementEx() are not implemented.\r
\r
- Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2011 - 2018, 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
\r
#include <Protocol/SmmCommunication.h>\r
\r
+#include <Guid/PiSmmCommunicationRegionTable.h>\r
+#include <Library/UefiLib.h>\r
+\r
#define SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof (SMM_PERF_COMMUNICATE))\r
\r
EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;\r
-UINT8 mSmmPerformanceBuffer[SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE];\r
+UINT8 *mSmmPerformanceBuffer;\r
GAUGE_DATA_ENTRY *mGaugeData = NULL;\r
UINTN mGaugeNumberOfEntries = 0;\r
GAUGE_DATA_ENTRY_EX *mGaugeDataEx = NULL;\r
UINTN mGaugeNumberOfEntriesEx = 0;\r
\r
+BOOLEAN mNoSmmPerfHandler = FALSE;\r
+BOOLEAN mNoSmmPerfExHandler = FALSE;\r
+\r
//\r
// The cached Performance Protocol and PerformanceEx Protocol interface.\r
//\r
/**\r
Fills in the end time of a performance measurement.\r
\r
- Looks up the record that matches Handle, Token, Module and Identifier.\r
+ Looks up the record that matches Handle, Token and Module.\r
If the record can not be found then return RETURN_NOT_FOUND.\r
If the record is found and TimeStamp is not zero,\r
then TimeStamp is added to the record as the end time.\r
UINTN\r
EFIAPI\r
GetByPerformanceProtocol (\r
- IN UINTN LogEntryKey, \r
+ IN UINTN LogEntryKey,\r
OUT CONST VOID **Handle,\r
OUT CONST CHAR8 **Token,\r
OUT CONST CHAR8 **Module,\r
On exit, the key of the next performance log entry.\r
\r
@retval !NULL Get all gauge data success.\r
- @retval NULL Get all guage data failed.\r
+ @retval NULL Get all gauge data failed.\r
**/\r
GAUGE_DATA_ENTRY *\r
EFIAPI\r
IN UINTN LogEntryKey\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;\r
- SMM_PERF_COMMUNICATE *SmmPerfCommData;\r
- UINTN CommSize;\r
- UINTN DataSize;\r
+ EFI_STATUS Status;\r
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;\r
+ SMM_PERF_COMMUNICATE *SmmPerfCommData;\r
+ UINTN CommSize;\r
+ UINTN DataSize;\r
+ EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;\r
+ UINT32 Index;\r
+ EFI_MEMORY_DESCRIPTOR *Entry;\r
+ UINT8 *Buffer;\r
+ UINTN Size;\r
+ UINTN NumberOfEntries;\r
+ UINTN EntriesGot;\r
+\r
+ if (mNoSmmPerfHandler) {\r
+ //\r
+ // Not try to get the SMM gauge data again\r
+ // if no SMM Performance handler found.\r
+ //\r
+ return NULL;\r
+ }\r
\r
if (LogEntryKey != 0) {\r
if (mGaugeData != NULL) {\r
}\r
} else {\r
//\r
- // Reget the SMM guage data at the first entry get.\r
+ // Reget the SMM gauge data at the first entry get.\r
//\r
if (mGaugeData != NULL) {\r
FreePool (mGaugeData);\r
return NULL;\r
}\r
\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEdkiiPiSmmCommunicationRegionTableGuid,\r
+ (VOID **) &PiSmmCommunicationRegionTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ ASSERT (PiSmmCommunicationRegionTable != NULL);\r
+ Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
+ Size = 0;\r
+ for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+ if (Entry->Type == EfiConventionalMemory) {\r
+ Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
+ if (Size >= (SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE + sizeof (GAUGE_DATA_ENTRY))) {\r
+ break;\r
+ }\r
+ }\r
+ Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
+ }\r
+ ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);\r
+ mSmmPerformanceBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;\r
+\r
//\r
- // Initialize communicate buffer \r
+ // Initialize communicate buffer\r
//\r
SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER *)mSmmPerformanceBuffer;\r
SmmPerfCommData = (SMM_PERF_COMMUNICATE *)SmmCommBufferHeader->Data;\r
ZeroMem((UINT8*)SmmPerfCommData, sizeof(SMM_PERF_COMMUNICATE));\r
- \r
+\r
CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gSmmPerformanceProtocolGuid);\r
SmmCommBufferHeader->MessageLength = sizeof(SMM_PERF_COMMUNICATE);\r
CommSize = SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
\r
//\r
- // Get totol number of SMM gauge entries\r
+ // Get total number of SMM gauge entries\r
//\r
SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER;\r
Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ mNoSmmPerfHandler = TRUE;\r
+ }\r
if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus) || SmmPerfCommData->NumberOfEntries == 0) {\r
return NULL;\r
}\r
\r
mGaugeNumberOfEntries = SmmPerfCommData->NumberOfEntries;\r
- \r
+\r
+ Buffer = mSmmPerformanceBuffer + SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
+ NumberOfEntries = (Size - SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE) / sizeof (GAUGE_DATA_ENTRY);\r
DataSize = mGaugeNumberOfEntries * sizeof(GAUGE_DATA_ENTRY);\r
mGaugeData = AllocateZeroPool(DataSize);\r
ASSERT (mGaugeData != NULL);\r
- \r
+\r
//\r
// Get all SMM gauge data\r
- // \r
+ //\r
SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;\r
- SmmPerfCommData->LogEntryKey = 0;\r
- SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntries;\r
- SmmPerfCommData->GaugeData = mGaugeData;\r
- Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
- if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
- FreePool (mGaugeData);\r
- mGaugeData = NULL;\r
- mGaugeNumberOfEntries = 0;\r
- }\r
+ SmmPerfCommData->GaugeData = (GAUGE_DATA_ENTRY *) Buffer;\r
+ EntriesGot = 0;\r
+ do {\r
+ SmmPerfCommData->LogEntryKey = EntriesGot;\r
+ if ((mGaugeNumberOfEntries - EntriesGot) >= NumberOfEntries) {\r
+ SmmPerfCommData->NumberOfEntries = NumberOfEntries;\r
+ } else {\r
+ SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntries - EntriesGot;\r
+ }\r
+ Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+ if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
+ FreePool (mGaugeData);\r
+ mGaugeData = NULL;\r
+ mGaugeNumberOfEntries = 0;\r
+ return NULL;\r
+ } else {\r
+ CopyMem (&mGaugeData[EntriesGot], Buffer, SmmPerfCommData->NumberOfEntries * sizeof (GAUGE_DATA_ENTRY));\r
+ }\r
+ EntriesGot += SmmPerfCommData->NumberOfEntries;\r
+ } while (EntriesGot < mGaugeNumberOfEntries);\r
\r
return mGaugeData;\r
}\r
On exit, the key of the next performance log entry.\r
\r
@retval !NULL Get all gauge data success.\r
- @retval NULL Get all guage data failed.\r
+ @retval NULL Get all gauge data failed.\r
**/\r
GAUGE_DATA_ENTRY_EX *\r
EFIAPI\r
IN UINTN LogEntryKey\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;\r
- SMM_PERF_COMMUNICATE_EX *SmmPerfCommData;\r
- UINTN CommSize;\r
- UINTN DataSize;\r
+ EFI_STATUS Status;\r
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;\r
+ SMM_PERF_COMMUNICATE_EX *SmmPerfCommData;\r
+ UINTN CommSize;\r
+ UINTN DataSize;\r
+ EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;\r
+ UINT32 Index;\r
+ EFI_MEMORY_DESCRIPTOR *Entry;\r
+ UINT8 *Buffer;\r
+ UINTN Size;\r
+ UINTN NumberOfEntries;\r
+ UINTN EntriesGot;\r
+\r
+ if (mNoSmmPerfExHandler) {\r
+ //\r
+ // Not try to get the SMM gauge data again\r
+ // if no SMM PerformanceEx handler found.\r
+ //\r
+ return NULL;\r
+ }\r
\r
if (LogEntryKey != 0) {\r
if (mGaugeDataEx != NULL) {\r
}\r
} else {\r
//\r
- // Reget the SMM guage data at the first entry get.\r
+ // Reget the SMM gauge data at the first entry get.\r
//\r
if (mGaugeDataEx != NULL) {\r
FreePool (mGaugeDataEx);\r
return NULL;\r
}\r
\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEdkiiPiSmmCommunicationRegionTableGuid,\r
+ (VOID **) &PiSmmCommunicationRegionTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ ASSERT (PiSmmCommunicationRegionTable != NULL);\r
+ Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
+ Size = 0;\r
+ for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+ if (Entry->Type == EfiConventionalMemory) {\r
+ Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
+ if (Size >= (SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE + sizeof (GAUGE_DATA_ENTRY_EX))) {\r
+ break;\r
+ }\r
+ }\r
+ Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
+ }\r
+ ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);\r
+ mSmmPerformanceBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;\r
//\r
- // Initialize communicate buffer \r
+ // Initialize communicate buffer\r
//\r
SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER *)mSmmPerformanceBuffer;\r
SmmPerfCommData = (SMM_PERF_COMMUNICATE_EX *)SmmCommBufferHeader->Data;\r
ZeroMem((UINT8*)SmmPerfCommData, sizeof(SMM_PERF_COMMUNICATE_EX));\r
- \r
+\r
CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gSmmPerformanceExProtocolGuid);\r
SmmCommBufferHeader->MessageLength = sizeof(SMM_PERF_COMMUNICATE_EX);\r
CommSize = SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
\r
//\r
- // Get totol number of SMM gauge entries\r
+ // Get total number of SMM gauge entries\r
//\r
SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER;\r
Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ mNoSmmPerfExHandler = TRUE;\r
+ }\r
if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus) || SmmPerfCommData->NumberOfEntries == 0) {\r
return NULL;\r
}\r
\r
mGaugeNumberOfEntriesEx = SmmPerfCommData->NumberOfEntries;\r
- \r
+\r
+ Buffer = mSmmPerformanceBuffer + SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
+ NumberOfEntries = (Size - SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE) / sizeof (GAUGE_DATA_ENTRY_EX);\r
DataSize = mGaugeNumberOfEntriesEx * sizeof(GAUGE_DATA_ENTRY_EX);\r
mGaugeDataEx = AllocateZeroPool(DataSize);\r
ASSERT (mGaugeDataEx != NULL);\r
- \r
+\r
//\r
// Get all SMM gauge data\r
- // \r
+ //\r
SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;\r
- SmmPerfCommData->LogEntryKey = 0;\r
- SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntriesEx;\r
- SmmPerfCommData->GaugeDataEx = mGaugeDataEx;\r
- Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
- if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
- FreePool (mGaugeDataEx);\r
- mGaugeDataEx = NULL;\r
- mGaugeNumberOfEntriesEx = 0;\r
- }\r
- \r
+ SmmPerfCommData->GaugeDataEx = (GAUGE_DATA_ENTRY_EX *) Buffer;\r
+ EntriesGot = 0;\r
+ do {\r
+ SmmPerfCommData->LogEntryKey = EntriesGot;\r
+ if ((mGaugeNumberOfEntriesEx - EntriesGot) >= NumberOfEntries) {\r
+ SmmPerfCommData->NumberOfEntries = NumberOfEntries;\r
+ } else {\r
+ SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntriesEx - EntriesGot;\r
+ }\r
+ Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+ if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
+ FreePool (mGaugeDataEx);\r
+ mGaugeDataEx = NULL;\r
+ mGaugeNumberOfEntriesEx = 0;\r
+ return NULL;\r
+ } else {\r
+ CopyMem (&mGaugeDataEx[EntriesGot], Buffer, SmmPerfCommData->NumberOfEntries * sizeof (GAUGE_DATA_ENTRY_EX));\r
+ }\r
+ EntriesGot += SmmPerfCommData->NumberOfEntries;\r
+ } while (EntriesGot < mGaugeNumberOfEntriesEx);\r
+\r
return mGaugeDataEx;\r
}\r
\r
UINTN\r
EFIAPI\r
GetPerformanceMeasurementEx (\r
- IN UINTN LogEntryKey, \r
+ IN UINTN LogEntryKey,\r
OUT CONST VOID **Handle,\r
OUT CONST CHAR8 **Token,\r
OUT CONST CHAR8 **Module,\r
GaugeData = (GAUGE_DATA_ENTRY_EX *) &mGaugeData[LogEntryKey++];\r
*Identifier = 0;\r
} else {\r
- return 0;\r
+ return GetByPerformanceProtocol (\r
+ LogEntryKey,\r
+ Handle,\r
+ Token,\r
+ Module,\r
+ StartTimeStamp,\r
+ EndTimeStamp,\r
+ Identifier\r
+ );\r
}\r
}\r
\r