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