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