]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[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 return EFI_UNSUPPORTED;
85 }
86
87 //
88 // Retrieve current time as early as possible.
89 //
90 CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());
91
92 //
93 // Update S3 Resume Performance Record.
94 //
95 S3PerformanceTablePointer = 0;
96 VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
97 Status = RestoreLockBox (&gFirmwarePerformanceS3PointerGuid, &S3PerformanceTablePointer, &VarSize);
98 ASSERT_EFI_ERROR (Status);
99
100 AcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) S3PerformanceTablePointer;
101 ASSERT (AcpiS3PerformanceTable != NULL);
102 if (AcpiS3PerformanceTable->Header.Signature != EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE) {
103 DEBUG ((EFI_D_ERROR, "FPDT S3 performance data in ACPI memory get corrupted\n"));
104 return EFI_ABORTED;
105 }
106 AcpiS3ResumeRecord = &AcpiS3PerformanceTable->S3Resume;
107 AcpiS3ResumeRecord->FullResume = CurrentTime;
108 //
109 // Calculate average S3 resume time.
110 //
111 S3ResumeTotal = MultU64x32 (AcpiS3ResumeRecord->AverageResume, AcpiS3ResumeRecord->ResumeCount);
112 AcpiS3ResumeRecord->ResumeCount++;
113 AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);
114
115 DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - ResumeCount = %d\n", AcpiS3ResumeRecord->ResumeCount));
116 DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - FullResume = %ld\n", AcpiS3ResumeRecord->FullResume));
117 DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - AverageResume = %ld\n", AcpiS3ResumeRecord->AverageResume));
118
119 //
120 // Update S3 Suspend Performance Record.
121 //
122 AcpiS3SuspendRecord = &AcpiS3PerformanceTable->S3Suspend;
123 VarSize = sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD);
124 ZeroMem (&S3SuspendRecord, sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD));
125 Status = RestoreLockBox (
126 &gEfiFirmwarePerformanceGuid,
127 &S3SuspendRecord,
128 &VarSize
129 );
130 ASSERT_EFI_ERROR (Status);
131
132 AcpiS3SuspendRecord->SuspendStart = S3SuspendRecord.SuspendStart;
133 AcpiS3SuspendRecord->SuspendEnd = S3SuspendRecord.SuspendEnd;
134
135 DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendStart = %ld\n", AcpiS3SuspendRecord->SuspendStart));
136 DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendEnd = %ld\n", AcpiS3SuspendRecord->SuspendEnd));
137
138 Status = PeiServicesLocatePpi (
139 &gEfiPeiReadOnlyVariable2PpiGuid,
140 0,
141 NULL,
142 (VOID **) &VariableServices
143 );
144 ASSERT_EFI_ERROR (Status);
145
146 //
147 // Update S3 boot records into the basic boot performance table.
148 //
149 VarSize = sizeof (PerformanceVariable);
150 Status = VariableServices->GetVariable (
151 VariableServices,
152 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
153 &gEfiFirmwarePerformanceGuid,
154 NULL,
155 &VarSize,
156 &PerformanceVariable
157 );
158 if (EFI_ERROR (Status)) {
159 return Status;
160 }
161 BootPerformanceTable = (UINT8*) (UINTN) PerformanceVariable.BootPerformanceTablePointer;
162
163 //
164 // Dump PEI boot records
165 //
166 FirmwarePerformanceTablePtr = (BootPerformanceTable + sizeof (BOOT_PERFORMANCE_TABLE));
167 GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);
168 while (GuidHob != NULL) {
169 FirmwarePerformanceData = GET_GUID_HOB_DATA (GuidHob);
170 PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *) FirmwarePerformanceData;
171
172 CopyMem (FirmwarePerformanceTablePtr, FirmwarePerformanceData + sizeof (FPDT_PEI_EXT_PERF_HEADER), (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries));
173
174 GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
175
176 FirmwarePerformanceTablePtr += (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries);
177 }
178
179 //
180 // Update Table length.
181 //
182 ((BOOT_PERFORMANCE_TABLE *) BootPerformanceTable)->Header.Length = (UINT32)((UINTN)FirmwarePerformanceTablePtr - (UINTN)BootPerformanceTable);
183
184 return EFI_SUCCESS;
185 }
186
187 /**
188 Main entry for Firmware Performance Data Table PEIM.
189
190 This routine is to register report status code listener for FPDT.
191
192 @param[in] FileHandle Handle of the file being invoked.
193 @param[in] PeiServices Pointer to PEI Services table.
194
195 @retval EFI_SUCCESS Report status code listener is registered successfully.
196
197 **/
198 EFI_STATUS
199 EFIAPI
200 FirmwarePerformancePeiEntryPoint (
201 IN EFI_PEI_FILE_HANDLE FileHandle,
202 IN CONST EFI_PEI_SERVICES **PeiServices
203 )
204 {
205 EFI_STATUS Status;
206 EFI_PEI_RSC_HANDLER_PPI *RscHandler;
207
208 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {
209 //
210 // S3 resume - register status code listener for OS wake vector.
211 //
212 Status = PeiServicesLocatePpi (
213 &gEfiPeiRscHandlerPpiGuid,
214 0,
215 NULL,
216 (VOID **) &RscHandler
217 );
218 ASSERT_EFI_ERROR (Status);
219
220 Status = RscHandler->Register (FpdtStatusCodeListenerPei);
221 ASSERT_EFI_ERROR (Status);
222 }
223
224 return EFI_SUCCESS;
225 }