]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / FirmwarePerformanceDataTablePei / FirmwarePerformancePei.c
CommitLineData
0284e90c
LG
1/** @file\r
2 This module updates S3 Resume Performance Record in ACPI Firmware Performance\r
c1acb0f9 3 Data Table in S3 resume boot mode.\r
0284e90c
LG
4\r
5 This module register report status code listener to collect performance data\r
6 for S3 Resume Performance Record on S3 resume boot path.\r
7\r
2040e6c5 8 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
0284e90c
LG
10\r
11**/\r
12\r
13#include <PiPei.h>\r
14\r
0284e90c 15#include <Ppi/ReportStatusCodeHandler.h>\r
2040e6c5 16#include <Ppi/ReadOnlyVariable2.h>\r
0284e90c
LG
17\r
18#include <Guid/FirmwarePerformance.h>\r
2040e6c5
DB
19#include <Guid/Performance.h>\r
20#include <Guid/ExtendedFirmwarePerformance.h>\r
0284e90c
LG
21\r
22#include <Library/PeiServicesLib.h>\r
23#include <Library/BaseLib.h>\r
24#include <Library/DebugLib.h>\r
25#include <Library/TimerLib.h>\r
26#include <Library/BaseMemoryLib.h>\r
27#include <Library/LockBoxLib.h>\r
0284e90c 28#include <Library/PcdLib.h>\r
2040e6c5 29#include <Library/HobLib.h>\r
0284e90c
LG
30\r
31/**\r
32 Report status code listener for PEI. This is used to record the performance\r
33 data for S3 FullResume in FPDT.\r
34\r
35 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
36 @param[in] CodeType Indicates the type of status code being reported.\r
37 @param[in] Value Describes the current status of a hardware or software entity.\r
38 This included information about the class and subclass that is used to\r
39 classify the entity as well as an operation.\r
40 @param[in] Instance The enumeration of a hardware or software entity within\r
41 the system. Valid instance numbers start with 1.\r
42 @param[in] CallerId This optional parameter may be used to identify the caller.\r
43 This parameter allows the status code driver to apply different rules to\r
44 different callers.\r
45 @param[in] Data This optional parameter may be used to pass additional data.\r
46\r
47 @retval EFI_SUCCESS Status code is what we expected.\r
48 @retval EFI_UNSUPPORTED Status code not supported.\r
49\r
50**/\r
51EFI_STATUS\r
52EFIAPI\r
53FpdtStatusCodeListenerPei (\r
54 IN CONST EFI_PEI_SERVICES **PeiServices,\r
55 IN EFI_STATUS_CODE_TYPE CodeType,\r
56 IN EFI_STATUS_CODE_VALUE Value,\r
57 IN UINT32 Instance,\r
58 IN CONST EFI_GUID *CallerId,\r
59 IN CONST EFI_STATUS_CODE_DATA *Data\r
60 )\r
61{\r
62 EFI_STATUS Status;\r
63 UINT64 CurrentTime;\r
0284e90c 64 UINTN VarSize;\r
db91c620 65 EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer;\r
0284e90c
LG
66 S3_PERFORMANCE_TABLE *AcpiS3PerformanceTable;\r
67 EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD *AcpiS3ResumeRecord;\r
68 UINT64 S3ResumeTotal;\r
69 EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD S3SuspendRecord;\r
70 EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD *AcpiS3SuspendRecord;\r
2040e6c5
DB
71 EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;\r
72 UINT8 *BootPerformanceTable;\r
73 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
74 EFI_HOB_GUID_TYPE *GuidHob;\r
75 FPDT_PEI_EXT_PERF_HEADER *PeiPerformanceLogHeader;\r
76 UINT8 *FirmwarePerformanceData;\r
77 UINT8 *FirmwarePerformanceTablePtr;\r
0284e90c
LG
78\r
79 //\r
80 // Check whether status code is what we are interested in.\r
81 //\r
82 if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) ||\r
c1acb0f9 83 (Value != (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE))) {\r
0284e90c
LG
84 return EFI_UNSUPPORTED;\r
85 }\r
86\r
87 //\r
88 // Retrieve current time as early as possible.\r
89 //\r
90 CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());\r
91\r
0284e90c
LG
92 //\r
93 // Update S3 Resume Performance Record.\r
94 //\r
db91c620
SZ
95 S3PerformanceTablePointer = 0;\r
96 VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
97 Status = RestoreLockBox (&gFirmwarePerformanceS3PointerGuid, &S3PerformanceTablePointer, &VarSize);\r
98 ASSERT_EFI_ERROR (Status);\r
0284e90c 99\r
db91c620 100 AcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) S3PerformanceTablePointer;\r
0284e90c 101 ASSERT (AcpiS3PerformanceTable != NULL);\r
db91c620
SZ
102 if (AcpiS3PerformanceTable->Header.Signature != EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE) {\r
103 DEBUG ((EFI_D_ERROR, "FPDT S3 performance data in ACPI memory get corrupted\n"));\r
104 return EFI_ABORTED;\r
105 }\r
0284e90c
LG
106 AcpiS3ResumeRecord = &AcpiS3PerformanceTable->S3Resume;\r
107 AcpiS3ResumeRecord->FullResume = CurrentTime;\r
108 //\r
109 // Calculate average S3 resume time.\r
110 //\r
111 S3ResumeTotal = MultU64x32 (AcpiS3ResumeRecord->AverageResume, AcpiS3ResumeRecord->ResumeCount);\r
112 AcpiS3ResumeRecord->ResumeCount++;\r
113 AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);\r
114\r
115 DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - ResumeCount = %d\n", AcpiS3ResumeRecord->ResumeCount));\r
116 DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - FullResume = %ld\n", AcpiS3ResumeRecord->FullResume));\r
117 DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - AverageResume = %ld\n", AcpiS3ResumeRecord->AverageResume));\r
118\r
119 //\r
120 // Update S3 Suspend Performance Record.\r
121 //\r
122 AcpiS3SuspendRecord = &AcpiS3PerformanceTable->S3Suspend;\r
123 VarSize = sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD);\r
124 ZeroMem (&S3SuspendRecord, sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD));\r
125 Status = RestoreLockBox (\r
126 &gEfiFirmwarePerformanceGuid,\r
127 &S3SuspendRecord,\r
128 &VarSize\r
129 );\r
130 ASSERT_EFI_ERROR (Status);\r
131\r
132 AcpiS3SuspendRecord->SuspendStart = S3SuspendRecord.SuspendStart;\r
133 AcpiS3SuspendRecord->SuspendEnd = S3SuspendRecord.SuspendEnd;\r
134\r
135 DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendStart = %ld\n", AcpiS3SuspendRecord->SuspendStart));\r
136 DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendEnd = %ld\n", AcpiS3SuspendRecord->SuspendEnd));\r
137\r
2040e6c5
DB
138 Status = PeiServicesLocatePpi (\r
139 &gEfiPeiReadOnlyVariable2PpiGuid,\r
140 0,\r
141 NULL,\r
142 (VOID **) &VariableServices\r
143 );\r
144 ASSERT_EFI_ERROR (Status);\r
145\r
146 //\r
147 // Update S3 boot records into the basic boot performance table.\r
148 //\r
149 VarSize = sizeof (PerformanceVariable);\r
150 Status = VariableServices->GetVariable (\r
151 VariableServices,\r
152 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
153 &gEfiFirmwarePerformanceGuid,\r
154 NULL,\r
155 &VarSize,\r
156 &PerformanceVariable\r
157 );\r
158 if (EFI_ERROR (Status)) {\r
159 return Status;\r
160 }\r
161 BootPerformanceTable = (UINT8*) (UINTN) PerformanceVariable.BootPerformanceTablePointer;\r
162\r
163 //\r
164 // Dump PEI boot records\r
165 //\r
166 FirmwarePerformanceTablePtr = (BootPerformanceTable + sizeof (BOOT_PERFORMANCE_TABLE));\r
167 GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);\r
168 while (GuidHob != NULL) {\r
169 FirmwarePerformanceData = GET_GUID_HOB_DATA (GuidHob);\r
170 PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *) FirmwarePerformanceData;\r
171\r
172 CopyMem (FirmwarePerformanceTablePtr, FirmwarePerformanceData + sizeof (FPDT_PEI_EXT_PERF_HEADER), (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries));\r
173\r
174 GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));\r
175\r
176 FirmwarePerformanceTablePtr += (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries);\r
177 }\r
178\r
179 //\r
180 // Update Table length.\r
181 //\r
182 ((BOOT_PERFORMANCE_TABLE *) BootPerformanceTable)->Header.Length = (UINT32)((UINTN)FirmwarePerformanceTablePtr - (UINTN)BootPerformanceTable);\r
183\r
0284e90c
LG
184 return EFI_SUCCESS;\r
185}\r
186\r
187/**\r
188 Main entry for Firmware Performance Data Table PEIM.\r
189\r
190 This routine is to register report status code listener for FPDT.\r
191\r
192 @param[in] FileHandle Handle of the file being invoked.\r
193 @param[in] PeiServices Pointer to PEI Services table.\r
194\r
195 @retval EFI_SUCCESS Report status code listener is registered successfully.\r
196\r
197**/\r
198EFI_STATUS\r
199EFIAPI\r
200FirmwarePerformancePeiEntryPoint (\r
201 IN EFI_PEI_FILE_HANDLE FileHandle,\r
202 IN CONST EFI_PEI_SERVICES **PeiServices\r
203 )\r
204{\r
205 EFI_STATUS Status;\r
0284e90c 206 EFI_PEI_RSC_HANDLER_PPI *RscHandler;\r
0284e90c 207\r
04f4c2d6 208 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {\r
0284e90c 209 //\r
04f4c2d6 210 // S3 resume - register status code listener for OS wake vector.\r
0284e90c
LG
211 //\r
212 Status = PeiServicesLocatePpi (\r
04f4c2d6 213 &gEfiPeiRscHandlerPpiGuid,\r
0284e90c
LG
214 0,\r
215 NULL,\r
04f4c2d6 216 (VOID **) &RscHandler\r
0284e90c 217 );\r
04f4c2d6
HW
218 ASSERT_EFI_ERROR (Status);\r
219\r
220 Status = RscHandler->Register (FpdtStatusCodeListenerPei);\r
221 ASSERT_EFI_ERROR (Status);\r
222 }\r
223\r
0284e90c
LG
224 return EFI_SUCCESS;\r
225}\r