2 This module updates S3 Resume Performance Record in ACPI Firmware Performance
3 Data Table in S3 resume boot mode.
5 This module register report status code listener to collect performance data
6 for S3 Resume Performance Record on S3 resume boot path.
8 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
15 #include <Ppi/ReportStatusCodeHandler.h>
16 #include <Ppi/ReadOnlyVariable2.h>
18 #include <Guid/FirmwarePerformance.h>
19 #include <Guid/Performance.h>
20 #include <Guid/ExtendedFirmwarePerformance.h>
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>
32 Report status code listener for PEI. This is used to record the performance
33 data for S3 FullResume in FPDT.
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
45 @param[in] Data This optional parameter may be used to pass additional data.
47 @retval EFI_SUCCESS Status code is what we expected.
48 @retval EFI_UNSUPPORTED Status code not supported.
53 FpdtStatusCodeListenerPei (
54 IN CONST EFI_PEI_SERVICES
**PeiServices
,
55 IN EFI_STATUS_CODE_TYPE CodeType
,
56 IN EFI_STATUS_CODE_VALUE Value
,
58 IN CONST EFI_GUID
*CallerId
,
59 IN CONST EFI_STATUS_CODE_DATA
*Data
65 EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer
;
66 S3_PERFORMANCE_TABLE
*AcpiS3PerformanceTable
;
67 EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD
*AcpiS3ResumeRecord
;
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
;
80 // Check whether status code is what we are interested in.
82 if (((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) != EFI_PROGRESS_CODE
) ||
83 (Value
!= (EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_PC_OS_WAKE
)))
85 return EFI_UNSUPPORTED
;
89 // Retrieve current time as early as possible.
91 CurrentTime
= GetTimeInNanoSecond (GetPerformanceCounter ());
94 // Update S3 Resume Performance Record.
96 S3PerformanceTablePointer
= 0;
97 VarSize
= sizeof (EFI_PHYSICAL_ADDRESS
);
98 Status
= RestoreLockBox (&gFirmwarePerformanceS3PointerGuid
, &S3PerformanceTablePointer
, &VarSize
);
99 ASSERT_EFI_ERROR (Status
);
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"));
108 AcpiS3ResumeRecord
= &AcpiS3PerformanceTable
->S3Resume
;
109 AcpiS3ResumeRecord
->FullResume
= CurrentTime
;
111 // Calculate average S3 resume time.
113 S3ResumeTotal
= MultU64x32 (AcpiS3ResumeRecord
->AverageResume
, AcpiS3ResumeRecord
->ResumeCount
);
114 AcpiS3ResumeRecord
->ResumeCount
++;
115 AcpiS3ResumeRecord
->AverageResume
= DivU64x32 (S3ResumeTotal
+ AcpiS3ResumeRecord
->FullResume
, AcpiS3ResumeRecord
->ResumeCount
);
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
));
122 // Update S3 Suspend Performance Record.
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
,
132 ASSERT_EFI_ERROR (Status
);
134 AcpiS3SuspendRecord
->SuspendStart
= S3SuspendRecord
.SuspendStart
;
135 AcpiS3SuspendRecord
->SuspendEnd
= S3SuspendRecord
.SuspendEnd
;
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
));
140 Status
= PeiServicesLocatePpi (
141 &gEfiPeiReadOnlyVariable2PpiGuid
,
144 (VOID
**)&VariableServices
146 ASSERT_EFI_ERROR (Status
);
149 // Update S3 boot records into the basic boot performance table.
151 VarSize
= sizeof (PerformanceVariable
);
152 Status
= VariableServices
->GetVariable (
154 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
155 &gEfiFirmwarePerformanceGuid
,
160 if (EFI_ERROR (Status
)) {
164 BootPerformanceTable
= (UINT8
*)(UINTN
)PerformanceVariable
.BootPerformanceTablePointer
;
167 // Dump PEI boot records
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
;
175 CopyMem (FirmwarePerformanceTablePtr
, FirmwarePerformanceData
+ sizeof (FPDT_PEI_EXT_PERF_HEADER
), (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
));
177 GuidHob
= GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid
, GET_NEXT_HOB (GuidHob
));
179 FirmwarePerformanceTablePtr
+= (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
);
183 // Update Table length.
185 ((BOOT_PERFORMANCE_TABLE
*)BootPerformanceTable
)->Header
.Length
= (UINT32
)((UINTN
)FirmwarePerformanceTablePtr
- (UINTN
)BootPerformanceTable
);
191 Main entry for Firmware Performance Data Table PEIM.
193 This routine is to register report status code listener for FPDT.
195 @param[in] FileHandle Handle of the file being invoked.
196 @param[in] PeiServices Pointer to PEI Services table.
198 @retval EFI_SUCCESS Report status code listener is registered successfully.
203 FirmwarePerformancePeiEntryPoint (
204 IN EFI_PEI_FILE_HANDLE FileHandle
,
205 IN CONST EFI_PEI_SERVICES
**PeiServices
209 EFI_PEI_RSC_HANDLER_PPI
*RscHandler
;
211 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support
)) {
213 // S3 resume - register status code listener for OS wake vector.
215 Status
= PeiServicesLocatePpi (
216 &gEfiPeiRscHandlerPpiGuid
,
221 ASSERT_EFI_ERROR (Status
);
223 Status
= RscHandler
->Register (FpdtStatusCodeListenerPei
);
224 ASSERT_EFI_ERROR (Status
);