]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / FirmwarePerformanceDataTableDxe / FirmwarePerformanceDxe.c
CommitLineData
0284e90c
LG
1/** @file\r
2 This module install ACPI Firmware Performance Data Table (FPDT).\r
3\r
4 This module register report status code listener to collect performance data\r
d1102dba 5 for Firmware Basic Boot Performance Record and other boot performance records,\r
1c0cc375 6 and install FPDT to ACPI table.\r
0284e90c 7\r
9e62c230 8 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
0284e90c
LG
9 This program and the accompanying materials\r
10 are licensed and made available under the terms and conditions of the BSD License\r
11 which accompanies this distribution. The full text of the license may be found at\r
12 http://opensource.org/licenses/bsd-license.php\r
13\r
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19#include <PiDxe.h>\r
20\r
0284e90c
LG
21#include <Protocol/ReportStatusCodeHandler.h>\r
22#include <Protocol/AcpiTable.h>\r
db91c620
SZ
23#include <Protocol/LockBox.h>\r
24#include <Protocol/Variable.h>\r
0284e90c
LG
25\r
26#include <Guid/Acpi.h>\r
27#include <Guid/FirmwarePerformance.h>\r
28#include <Guid/EventGroup.h>\r
29#include <Guid/EventLegacyBios.h>\r
30\r
31#include <Library/UefiBootServicesTableLib.h>\r
32#include <Library/UefiRuntimeServicesTableLib.h>\r
33#include <Library/BaseLib.h>\r
34#include <Library/DebugLib.h>\r
65e984cd 35#include <Library/DxeServicesLib.h>\r
0284e90c
LG
36#include <Library/TimerLib.h>\r
37#include <Library/BaseMemoryLib.h>\r
38#include <Library/MemoryAllocationLib.h>\r
39#include <Library/PcdLib.h>\r
40#include <Library/HobLib.h>\r
db91c620
SZ
41#include <Library/LockBoxLib.h>\r
42#include <Library/UefiLib.h>\r
0284e90c 43\r
9e62c230 44#define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))\r
0284e90c
LG
45\r
46EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;\r
47\r
db91c620 48BOOLEAN mLockBoxReady = FALSE;\r
0284e90c
LG
49EFI_EVENT mReadyToBootEvent;\r
50EFI_EVENT mLegacyBootEvent;\r
51EFI_EVENT mExitBootServicesEvent;\r
52UINTN mFirmwarePerformanceTableTemplateKey = 0;\r
40a0f8cb 53BOOLEAN mDxeCoreReportStatusCodeEnable = FALSE;\r
0284e90c 54\r
0284e90c 55BOOT_PERFORMANCE_TABLE *mAcpiBootPerformanceTable = NULL;\r
9e62c230 56BOOT_PERFORMANCE_TABLE *mReceivedAcpiBootPerformanceTable = NULL;\r
0284e90c
LG
57S3_PERFORMANCE_TABLE *mAcpiS3PerformanceTable = NULL;\r
58\r
59FIRMWARE_PERFORMANCE_TABLE mFirmwarePerformanceTableTemplate = {\r
60 {\r
61 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE,\r
62 sizeof (FIRMWARE_PERFORMANCE_TABLE),\r
63 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION, // Revision\r
64 0x00, // Checksum will be updated at runtime\r
65 //\r
e84f07b5 66 // It is expected that these values will be updated at EntryPoint.\r
0284e90c 67 //\r
e84f07b5
SZ
68 {0x00}, // OEM ID is a 6 bytes long field\r
69 0x00, // OEM Table ID(8 bytes long)\r
70 0x00, // OEM Revision\r
71 0x00, // Creator ID\r
72 0x00, // Creator Revision\r
0284e90c
LG
73 },\r
74 //\r
75 // Firmware Basic Boot Performance Table Pointer Record.\r
76 //\r
77 {\r
78 {\r
79 EFI_ACPI_5_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER , // Type\r
80 sizeof (EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD), // Length\r
81 EFI_ACPI_5_0_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER // Revision\r
82 },\r
83 0, // Reserved\r
84 0 // BootPerformanceTablePointer will be updated at runtime.\r
85 },\r
86 //\r
87 // S3 Performance Table Pointer Record.\r
88 //\r
89 {\r
90 {\r
91 EFI_ACPI_5_0_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER, // Type\r
92 sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD), // Length\r
93 EFI_ACPI_5_0_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER // Revision\r
94 },\r
95 0, // Reserved\r
96 0 // S3PerformanceTablePointer will be updated at runtime.\r
97 }\r
98};\r
99\r
100BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate = {\r
101 {\r
102 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE,\r
103 sizeof (BOOT_PERFORMANCE_TABLE)\r
104 },\r
105 {\r
106 {\r
107 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT, // Type\r
108 sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD), // Length\r
109 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT // Revision\r
110 },\r
111 0, // Reserved\r
112 //\r
113 // These values will be updated at runtime.\r
114 //\r
115 0, // ResetEnd\r
116 0, // OsLoaderLoadImageStart\r
117 0, // OsLoaderStartImageStart\r
118 0, // ExitBootServicesEntry\r
119 0 // ExitBootServicesExit\r
120 }\r
121};\r
122\r
123S3_PERFORMANCE_TABLE mS3PerformanceTableTemplate = {\r
124 {\r
125 EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE,\r
126 sizeof (S3_PERFORMANCE_TABLE)\r
127 },\r
128 {\r
129 {\r
130 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME, // Type\r
131 sizeof (EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD), // Length\r
132 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME // Revision\r
133 },\r
134 //\r
135 // These values will be updated by Firmware Performance PEIM.\r
136 //\r
137 0, // ResumeCount\r
138 0, // FullResume\r
139 0 // AverageResume\r
140 },\r
141 {\r
142 {\r
143 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND, // Type\r
144 sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD), // Length\r
145 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND // Revision\r
146 },\r
147 //\r
148 // These values will be updated bye Firmware Performance SMM driver.\r
149 //\r
150 0, // SuspendStart\r
151 0 // SuspendEnd\r
152 }\r
153};\r
154\r
155/**\r
156 This function calculates and updates an UINT8 checksum.\r
157\r
158 @param[in] Buffer Pointer to buffer to checksum\r
159 @param[in] Size Number of bytes to checksum\r
160\r
161**/\r
162VOID\r
163FpdtAcpiTableChecksum (\r
164 IN UINT8 *Buffer,\r
165 IN UINTN Size\r
166 )\r
167{\r
168 UINTN ChecksumOffset;\r
169\r
170 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);\r
171\r
172 //\r
173 // Set checksum to 0 first.\r
174 //\r
175 Buffer[ChecksumOffset] = 0;\r
176\r
177 //\r
178 // Update checksum value.\r
179 //\r
180 Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);\r
181}\r
182\r
db91c620
SZ
183/**\r
184 Callback function upon VariableArchProtocol and LockBoxProtocol\r
185 to allocate S3 performance table memory and save the pointer to LockBox.\r
186\r
187 @param[in] Event Event whose notification function is being invoked.\r
188 @param[in] Context Pointer to the notification function's context.\r
189**/\r
190VOID\r
191EFIAPI\r
192FpdtAllocateS3PerformanceTableMemory (\r
193 IN EFI_EVENT Event,\r
194 IN VOID *Context\r
195 )\r
196{\r
197 EFI_STATUS Status;\r
198 VOID *Interface;\r
199 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
200 UINTN Size;\r
201 EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer;\r
202\r
203 if (mLockBoxReady && (mAcpiS3PerformanceTable != NULL)) {\r
204 //\r
205 // The memory for S3 performance table should have been ready,\r
206 // and the pointer should have been saved to LockBox, just return.\r
207 //\r
208 return;\r
209 }\r
210\r
211 if (!mLockBoxReady) {\r
212 Status = gBS->LocateProtocol (&gEfiLockBoxProtocolGuid, NULL, &Interface);\r
213 if (!EFI_ERROR (Status)) {\r
214 //\r
215 // LockBox services has been ready.\r
216 //\r
217 mLockBoxReady = TRUE;\r
218 }\r
219 }\r
220\r
221 if (mAcpiS3PerformanceTable == NULL) {\r
222 Status = gBS->LocateProtocol (&gEfiVariableArchProtocolGuid, NULL, &Interface);\r
223 if (!EFI_ERROR (Status)) {\r
224 //\r
225 // Try to allocate the same runtime buffer as last time boot.\r
226 //\r
227 ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));\r
228 Size = sizeof (PerformanceVariable);\r
229 Status = gRT->GetVariable (\r
230 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
231 &gEfiFirmwarePerformanceGuid,\r
232 NULL,\r
233 &Size,\r
234 &PerformanceVariable\r
235 );\r
236 if (!EFI_ERROR (Status)) {\r
237 Status = gBS->AllocatePages (\r
238 AllocateAddress,\r
239 EfiReservedMemoryType,\r
240 EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)),\r
241 &PerformanceVariable.S3PerformanceTablePointer\r
242 );\r
243 if (!EFI_ERROR (Status)) {\r
244 mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.S3PerformanceTablePointer;\r
245 }\r
246 }\r
247 if (mAcpiS3PerformanceTable == NULL) {\r
248 //\r
249 // Fail to allocate at specified address, continue to allocate at any address.\r
250 //\r
65e984cd
AB
251 mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) AllocatePeiAccessiblePages (\r
252 EfiReservedMemoryType,\r
253 EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE))\r
254 );\r
db91c620
SZ
255 }\r
256 DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable));\r
257 if (mAcpiS3PerformanceTable != NULL) {\r
258 CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));\r
259 }\r
260 }\r
261 }\r
262\r
263 if (mLockBoxReady && (mAcpiS3PerformanceTable != NULL)) {\r
264 //\r
265 // If LockBox services has been ready and memory for FPDT S3 performance table has been allocated,\r
266 // save the pointer to LockBox for use in S3 resume.\r
267 //\r
268 S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;\r
269 Status = SaveLockBox (\r
270 &gFirmwarePerformanceS3PointerGuid,\r
271 &S3PerformanceTablePointer,\r
272 sizeof (EFI_PHYSICAL_ADDRESS)\r
273 );\r
274 ASSERT_EFI_ERROR (Status);\r
275 }\r
276}\r
277\r
0284e90c
LG
278/**\r
279 Install ACPI Firmware Performance Data Table (FPDT).\r
280\r
281 @return Status code.\r
282\r
283**/\r
284EFI_STATUS\r
285InstallFirmwarePerformanceDataTable (\r
286 VOID\r
287 )\r
288{\r
289 EFI_STATUS Status;\r
290 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
db91c620 291 UINTN BootPerformanceDataSize;\r
1c0cc375 292 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
9e62c230 293 UINTN Size;\r
0284e90c
LG
294\r
295 //\r
296 // Get AcpiTable Protocol.\r
297 //\r
298 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
299 if (EFI_ERROR (Status)) {\r
300 return Status;\r
301 }\r
302\r
9e62c230
DB
303 if (mReceivedAcpiBootPerformanceTable != NULL) {\r
304 mAcpiBootPerformanceTable = mReceivedAcpiBootPerformanceTable;\r
305 mAcpiBootPerformanceTable->BasicBoot.ResetEnd = mBootPerformanceTableTemplate.BasicBoot.ResetEnd;\r
306 } else {\r
1c0cc375 307 //\r
9e62c230
DB
308 // Try to allocate the same runtime buffer as last time boot.\r
309 //\r
310 BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE);\r
311 ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));\r
312 Size = sizeof (PerformanceVariable);\r
313 Status = gRT->GetVariable (\r
314 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
315 &gEfiFirmwarePerformanceGuid,\r
316 NULL,\r
317 &Size,\r
318 &PerformanceVariable\r
319 );\r
d158ba67 320 if (!EFI_ERROR (Status)) {\r
9e62c230
DB
321 Status = gBS->AllocatePages (\r
322 AllocateAddress,\r
323 EfiReservedMemoryType,\r
324 EFI_SIZE_TO_PAGES (BootPerformanceDataSize),\r
325 &PerformanceVariable.BootPerformanceTablePointer\r
326 );\r
327 if (!EFI_ERROR (Status)) {\r
328 mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer;\r
d158ba67 329 }\r
9e62c230
DB
330 }\r
331 if (mAcpiBootPerformanceTable == NULL) {\r
1c0cc375 332 //\r
9e62c230 333 // Fail to allocate at specified address, continue to allocate at any address.\r
1c0cc375 334 //\r
65e984cd
AB
335 mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) AllocatePeiAccessiblePages (\r
336 EfiReservedMemoryType,\r
337 EFI_SIZE_TO_PAGES (BootPerformanceDataSize)\r
338 );\r
1c0cc375 339 }\r
9e62c230
DB
340 DEBUG ((DEBUG_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));\r
341 if (mAcpiBootPerformanceTable == NULL) {\r
342 return EFI_OUT_OF_RESOURCES;\r
db91c620 343 }\r
1c0cc375 344 //\r
9e62c230 345 // Fill Basic Boot record to Boot Performance Table.\r
1c0cc375 346 //\r
9e62c230 347 CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));\r
9cf37b40 348 }\r
9e62c230 349 BootPerformanceDataSize = mAcpiBootPerformanceTable->Header.Length;\r
9cf37b40 350\r
1c0cc375 351 //\r
1c0cc375
LG
352 // Save Boot Performance Table address to Variable for use in S4 resume.\r
353 //\r
354 PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable;\r
355 //\r
356 // Update Boot Performance Table Pointer in template.\r
357 //\r
358 mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;\r
359\r
db91c620
SZ
360 //\r
361 // Save S3 Performance Table address to Variable for use in S4 resume.\r
362 //\r
363 PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;\r
364 //\r
365 // Update S3 Performance Table Pointer in template.\r
366 //\r
367 mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) (UINTN) mAcpiS3PerformanceTable;\r
0284e90c
LG
368 //\r
369 // Save Runtime Performance Table pointers to Variable.\r
9e62c230 370 // Don't check SetVariable return status. It doesn't impact FPDT table generation.\r
fd704cbd
LG
371 //\r
372 gRT->SetVariable (\r
373 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
374 &gEfiFirmwarePerformanceGuid,\r
375 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
376 sizeof (PerformanceVariable),\r
377 &PerformanceVariable\r
378 );\r
0284e90c
LG
379\r
380 //\r
381 // Publish Firmware Performance Data Table.\r
382 //\r
383 FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length);\r
384 Status = AcpiTableProtocol->InstallAcpiTable (\r
385 AcpiTableProtocol,\r
386 &mFirmwarePerformanceTableTemplate,\r
387 mFirmwarePerformanceTableTemplate.Header.Length,\r
388 &mFirmwarePerformanceTableTemplateKey\r
389 );\r
390 if (EFI_ERROR (Status)) {\r
9e62c230
DB
391 if (mAcpiBootPerformanceTable != NULL) {\r
392 FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize));\r
393 }\r
db91c620
SZ
394 if (mAcpiS3PerformanceTable != NULL) {\r
395 FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));\r
396 }\r
0284e90c
LG
397 mAcpiBootPerformanceTable = NULL;\r
398 mAcpiS3PerformanceTable = NULL;\r
399 return Status;\r
400 }\r
0284e90c
LG
401 return EFI_SUCCESS;\r
402}\r
403\r
0284e90c
LG
404/**\r
405 Report status code listener of FPDT. This is used to collect performance data\r
406 for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.\r
407\r
408 @param[in] CodeType Indicates the type of status code being reported.\r
409 @param[in] Value Describes the current status of a hardware or software entity.\r
410 This included information about the class and subclass that is used to\r
411 classify the entity as well as an operation.\r
412 @param[in] Instance The enumeration of a hardware or software entity within\r
413 the system. Valid instance numbers start with 1.\r
414 @param[in] CallerId This optional parameter may be used to identify the caller.\r
415 This parameter allows the status code driver to apply different rules to\r
416 different callers.\r
417 @param[in] Data This optional parameter may be used to pass additional data.\r
418\r
419 @retval EFI_SUCCESS Status code is what we expected.\r
420 @retval EFI_UNSUPPORTED Status code not supported.\r
421\r
422**/\r
423EFI_STATUS\r
424EFIAPI\r
425FpdtStatusCodeListenerDxe (\r
426 IN EFI_STATUS_CODE_TYPE CodeType,\r
427 IN EFI_STATUS_CODE_VALUE Value,\r
428 IN UINT32 Instance,\r
429 IN EFI_GUID *CallerId,\r
430 IN EFI_STATUS_CODE_DATA *Data\r
431 )\r
432{\r
433 EFI_STATUS Status;\r
434\r
435 //\r
436 // Check whether status code is what we are interested in.\r
437 //\r
438 if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {\r
439 return EFI_UNSUPPORTED;\r
440 }\r
d1102dba 441\r
40a0f8cb
LG
442 if (Value == (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT)) {\r
443 //\r
444 // DxeCore ReportStatusCode Enable so that the capability can be supported.\r
445 //\r
446 mDxeCoreReportStatusCodeEnable = TRUE;\r
447 }\r
0284e90c
LG
448\r
449 Status = EFI_SUCCESS;\r
450 if (Value == PcdGet32 (PcdProgressCodeOsLoaderLoad)) {\r
451 //\r
452 // Progress code for OS Loader LoadImage.\r
453 //\r
454 if (mAcpiBootPerformanceTable == NULL) {\r
455 return Status;\r
456 }\r
457\r
458 //\r
459 // Update OS Loader LoadImage Start for UEFI boot.\r
460 //\r
461 mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());\r
462 } else if (Value == PcdGet32 (PcdProgressCodeOsLoaderStart)) {\r
463 //\r
464 // Progress code for OS Loader StartImage.\r
465 //\r
466 if (mAcpiBootPerformanceTable == NULL) {\r
467 return Status;\r
468 }\r
469\r
470 //\r
471 // Update OS Loader StartImage Start for UEFI boot.\r
472 //\r
473 mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());\r
474 } else if (Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) {\r
40a0f8cb
LG
475 //\r
476 // Unregister boot time report status code listener.\r
477 //\r
478 mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);\r
479\r
0284e90c
LG
480 //\r
481 // Progress code for ExitBootServices.\r
482 //\r
483 if (mAcpiBootPerformanceTable == NULL) {\r
484 return Status;\r
485 }\r
486\r
487 //\r
488 // Update ExitBootServicesExit for UEFI boot.\r
489 //\r
490 mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = GetTimeInNanoSecond (GetPerformanceCounter ());\r
522dfbf3
LG
491 } else if (Value == (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT)) {\r
492 if (mAcpiBootPerformanceTable == NULL) {\r
493 //\r
494 // Firmware Performance Data Table not installed, do nothing.\r
495 //\r
496 return Status;\r
497 }\r
498\r
499 //\r
500 // Update Firmware Basic Boot Performance Record for legacy boot.\r
501 //\r
502 mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());\r
503\r
504 //\r
505 // Dump FPDT Boot Performance record.\r
506 //\r
507 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));\r
508 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = 0\n"));\r
509 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));\r
510 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));\r
511 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));\r
9e62c230 512 } else if (Value == (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)) {\r
1c0cc375
LG
513 if (mAcpiBootPerformanceTable == NULL) {\r
514 //\r
9e62c230 515 // ACPI Firmware Performance Data Table not installed yet, install it now.\r
1c0cc375 516 //\r
9e62c230 517 InstallFirmwarePerformanceDataTable ();\r
1c0cc375 518 }\r
9e62c230
DB
519 } else if (Data != NULL && CompareGuid (&Data->Type, &gEdkiiFpdtExtendedFirmwarePerformanceGuid)) {\r
520 //\r
521 // Get the Boot performance table and then install it to ACPI table.\r
522 //\r
523 CopyMem (&mReceivedAcpiBootPerformanceTable, Data + 1, Data->Size);\r
d4ee449d
DB
524 } else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {\r
525 DEBUG ((DEBUG_ERROR, "FpdtStatusCodeListenerDxe: Performance data reported through gEfiFirmwarePerformanceGuid will not be collected by FirmwarePerformanceDataTableDxe\n"));\r
526 Status = EFI_UNSUPPORTED;\r
0284e90c
LG
527 } else {\r
528 //\r
529 // Ignore else progress code.\r
530 //\r
531 Status = EFI_UNSUPPORTED;\r
532 }\r
533\r
534 return Status;\r
535}\r
536\r
40a0f8cb
LG
537\r
538/**\r
539 Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record\r
540 performance data for ExitBootServicesEntry in FPDT.\r
541\r
542 @param[in] Event The Event that is being processed.\r
543 @param[in] Context The Event Context.\r
544\r
545**/\r
546VOID\r
547EFIAPI\r
548FpdtExitBootServicesEventNotify (\r
549 IN EFI_EVENT Event,\r
550 IN VOID *Context\r
551 )\r
552{\r
0b24f2cf 553 if (!mDxeCoreReportStatusCodeEnable) {\r
40a0f8cb 554 //\r
d1102dba 555 // When DxeCore Report Status Code is disabled,\r
40a0f8cb
LG
556 // Unregister boot time report status code listener at ExitBootService Event.\r
557 //\r
558 mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);\r
559 }\r
560\r
561 if (mAcpiBootPerformanceTable == NULL) {\r
562 //\r
563 // Firmware Performance Data Table not installed, do nothing.\r
564 //\r
565 return ;\r
566 }\r
567\r
568 //\r
569 // Update Firmware Basic Boot Performance Record for UEFI boot.\r
570 //\r
571 mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());\r
572\r
573 //\r
574 // Dump FPDT Boot Performance record.\r
575 //\r
576 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));\r
577 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));\r
578 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));\r
579 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));\r
580 //\r
581 // ExitBootServicesExit will be updated later, so don't dump it here.\r
582 //\r
583}\r
584\r
0284e90c
LG
585/**\r
586 The module Entry Point of the Firmware Performance Data Table DXE driver.\r
587\r
588 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
589 @param[in] SystemTable A pointer to the EFI System Table.\r
590\r
591 @retval EFI_SUCCESS The entry point is executed successfully.\r
592 @retval Other Some error occurs when executing this entry point.\r
593\r
594**/\r
595EFI_STATUS\r
596EFIAPI\r
597FirmwarePerformanceDxeEntryPoint (\r
598 IN EFI_HANDLE ImageHandle,\r
599 IN EFI_SYSTEM_TABLE *SystemTable\r
600 )\r
601{\r
602 EFI_STATUS Status;\r
603 EFI_HOB_GUID_TYPE *GuidHob;\r
604 FIRMWARE_SEC_PERFORMANCE *Performance;\r
db91c620 605 VOID *Registration;\r
e84f07b5
SZ
606 UINT64 OemTableId;\r
607\r
608 CopyMem (\r
609 mFirmwarePerformanceTableTemplate.Header.OemId,\r
610 PcdGetPtr (PcdAcpiDefaultOemId),\r
611 sizeof (mFirmwarePerformanceTableTemplate.Header.OemId)\r
612 );\r
613 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
614 CopyMem (&mFirmwarePerformanceTableTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
615 mFirmwarePerformanceTableTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
616 mFirmwarePerformanceTableTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
617 mFirmwarePerformanceTableTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
0284e90c
LG
618\r
619 //\r
620 // Get Report Status Code Handler Protocol.\r
621 //\r
622 Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mRscHandlerProtocol);\r
623 ASSERT_EFI_ERROR (Status);\r
624\r
625 //\r
626 // Register report status code listener for OS Loader load and start.\r
627 //\r
628 Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerDxe, TPL_HIGH_LEVEL);\r
629 ASSERT_EFI_ERROR (Status);\r
630\r
631 //\r
632 // Register the notify function to update FPDT on ExitBootServices Event.\r
633 //\r
634 Status = gBS->CreateEventEx (\r
635 EVT_NOTIFY_SIGNAL,\r
636 TPL_NOTIFY,\r
637 FpdtExitBootServicesEventNotify,\r
638 NULL,\r
639 &gEfiEventExitBootServicesGuid,\r
640 &mExitBootServicesEvent\r
641 );\r
642 ASSERT_EFI_ERROR (Status);\r
643\r
0284e90c
LG
644 //\r
645 // Retrieve GUID HOB data that contains the ResetEnd.\r
646 //\r
647 GuidHob = GetFirstGuidHob (&gEfiFirmwarePerformanceGuid);\r
648 if (GuidHob != NULL) {\r
649 Performance = (FIRMWARE_SEC_PERFORMANCE *) GET_GUID_HOB_DATA (GuidHob);\r
650 mBootPerformanceTableTemplate.BasicBoot.ResetEnd = Performance->ResetEnd;\r
651 } else {\r
652 //\r
653 // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.\r
654 //\r
d3d562b9 655 DEBUG ((DEBUG_WARN, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));\r
0284e90c
LG
656 }\r
657\r
db91c620
SZ
658 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {\r
659 //\r
660 // Register callback function upon VariableArchProtocol and LockBoxProtocol\r
661 // to allocate S3 performance table memory and save the pointer to LockBox.\r
662 //\r
663 EfiCreateProtocolNotifyEvent (\r
664 &gEfiVariableArchProtocolGuid,\r
665 TPL_CALLBACK,\r
666 FpdtAllocateS3PerformanceTableMemory,\r
667 NULL,\r
668 &Registration\r
669 );\r
670 EfiCreateProtocolNotifyEvent (\r
671 &gEfiLockBoxProtocolGuid,\r
672 TPL_CALLBACK,\r
673 FpdtAllocateS3PerformanceTableMemory,\r
674 NULL,\r
675 &Registration\r
676 );\r
677 } else {\r
678 //\r
679 // Exclude S3 Performance Table Pointer from FPDT table template.\r
680 //\r
681 mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);\r
682 }\r
683\r
0284e90c
LG
684 return EFI_SUCCESS;\r
685}\r