2 This module install ACPI Firmware Performance Data Table (FPDT).
4 This module register report status code listener to collect performance data
5 for Firmware Basic Boot Performance Record and other boot performance records,
6 and install FPDT to ACPI table.
8 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include <IndustryStandard/Acpi50.h>
23 #include <Protocol/ReportStatusCodeHandler.h>
24 #include <Protocol/AcpiTable.h>
25 #include <Protocol/SmmCommunication.h>
27 #include <Guid/Acpi.h>
28 #include <Guid/FirmwarePerformance.h>
29 #include <Guid/EventGroup.h>
30 #include <Guid/EventLegacyBios.h>
32 #include <Library/UefiBootServicesTableLib.h>
33 #include <Library/UefiRuntimeServicesTableLib.h>
34 #include <Library/BaseLib.h>
35 #include <Library/DebugLib.h>
36 #include <Library/TimerLib.h>
37 #include <Library/BaseMemoryLib.h>
38 #include <Library/MemoryAllocationLib.h>
39 #include <Library/PcdLib.h>
40 #include <Library/HobLib.h>
41 #include <Library/PcdLib.h>
44 // ACPI table information used to initialize tables.
46 #define EFI_ACPI_OEM_ID "INTEL"
47 #define EFI_ACPI_OEM_TABLE_ID 0x2020204F4E414954ULL // "TIANO "
48 #define EFI_ACPI_OEM_REVISION 0x00000001
49 #define EFI_ACPI_CREATOR_ID 0x5446534D // TBD "MSFT"
50 #define EFI_ACPI_CREATOR_REVISION 0x01000013 // TBD
51 #define EXTENSION_RECORD_SIZE 0x10000
52 #define SMM_BOOT_RECORD_COMM_SIZE OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE)
54 EFI_RSC_HANDLER_PROTOCOL
*mRscHandlerProtocol
= NULL
;
56 EFI_EVENT mReadyToBootEvent
;
57 EFI_EVENT mLegacyBootEvent
;
58 EFI_EVENT mExitBootServicesEvent
;
59 UINTN mFirmwarePerformanceTableTemplateKey
= 0;
60 UINT32 mBootRecordSize
= 0;
61 UINT32 mBootRecordMaxSize
= 0;
62 UINT8
*mBootRecordBuffer
= NULL
;
64 BOOT_PERFORMANCE_TABLE
*mAcpiBootPerformanceTable
= NULL
;
65 S3_PERFORMANCE_TABLE
*mAcpiS3PerformanceTable
= NULL
;
67 FIRMWARE_PERFORMANCE_TABLE mFirmwarePerformanceTableTemplate
= {
69 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE
,
70 sizeof (FIRMWARE_PERFORMANCE_TABLE
),
71 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION
, // Revision
72 0x00, // Checksum will be updated at runtime
74 // It is expected that these values will be updated at runtime.
76 EFI_ACPI_OEM_ID
, // OEMID is a 6 bytes long field
77 EFI_ACPI_OEM_TABLE_ID
, // OEM table identification(8 bytes long)
78 EFI_ACPI_OEM_REVISION
, // OEM revision number
79 EFI_ACPI_CREATOR_ID
, // ASL compiler vendor ID
80 EFI_ACPI_CREATOR_REVISION
, // ASL compiler revision number
83 // Firmware Basic Boot Performance Table Pointer Record.
87 EFI_ACPI_5_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER
, // Type
88 sizeof (EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD
), // Length
89 EFI_ACPI_5_0_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER
// Revision
92 0 // BootPerformanceTablePointer will be updated at runtime.
95 // S3 Performance Table Pointer Record.
99 EFI_ACPI_5_0_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER
, // Type
100 sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD
), // Length
101 EFI_ACPI_5_0_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER
// Revision
104 0 // S3PerformanceTablePointer will be updated at runtime.
108 BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate
= {
110 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE
,
111 sizeof (BOOT_PERFORMANCE_TABLE
)
115 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT
, // Type
116 sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD
), // Length
117 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT
// Revision
121 // These values will be updated at runtime.
124 0, // OsLoaderLoadImageStart
125 0, // OsLoaderStartImageStart
126 0, // ExitBootServicesEntry
127 0 // ExitBootServicesExit
131 S3_PERFORMANCE_TABLE mS3PerformanceTableTemplate
= {
133 EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE
,
134 sizeof (S3_PERFORMANCE_TABLE
)
138 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME
, // Type
139 sizeof (EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD
), // Length
140 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME
// Revision
143 // These values will be updated by Firmware Performance PEIM.
151 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND
, // Type
152 sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD
), // Length
153 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND
// Revision
156 // These values will be updated bye Firmware Performance SMM driver.
164 This function calculates and updates an UINT8 checksum.
166 @param[in] Buffer Pointer to buffer to checksum
167 @param[in] Size Number of bytes to checksum
171 FpdtAcpiTableChecksum (
176 UINTN ChecksumOffset
;
178 ChecksumOffset
= OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
, Checksum
);
181 // Set checksum to 0 first.
183 Buffer
[ChecksumOffset
] = 0;
186 // Update checksum value.
188 Buffer
[ChecksumOffset
] = CalculateCheckSum8 (Buffer
, Size
);
192 Allocate EfiReservedMemoryType below 4G memory address.
194 This function allocates EfiReservedMemoryType below 4G memory address.
196 @param[in] Size Size of memory to allocate.
198 @return Allocated address for output.
202 FpdtAllocateReservedMemoryBelow4G (
207 EFI_PHYSICAL_ADDRESS Address
;
211 Pages
= EFI_SIZE_TO_PAGES (Size
);
212 Address
= 0xffffffff;
214 Status
= gBS
->AllocatePages (
216 EfiReservedMemoryType
,
220 ASSERT_EFI_ERROR (Status
);
222 Buffer
= (VOID
*) (UINTN
) Address
;
223 ZeroMem (Buffer
, Size
);
229 Install ACPI Firmware Performance Data Table (FPDT).
235 InstallFirmwarePerformanceDataTable (
240 EFI_ACPI_TABLE_PROTOCOL
*AcpiTableProtocol
;
241 EFI_PHYSICAL_ADDRESS Address
;
243 UINT8 SmmBootRecordCommBuffer
[SMM_BOOT_RECORD_COMM_SIZE
];
244 EFI_SMM_COMMUNICATE_HEADER
*SmmCommBufferHeader
;
245 SMM_BOOT_RECORD_COMMUNICATE
*SmmCommData
;
247 UINTN PerformanceRuntimeDataSize
;
248 UINT8
*PerformanceRuntimeData
;
249 UINT8
*PerformanceRuntimeDataHead
;
250 EFI_SMM_COMMUNICATION_PROTOCOL
*Communication
;
251 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable
;
254 // Get AcpiTable Protocol.
256 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTableProtocol
);
257 if (EFI_ERROR (Status
)) {
262 // Collect boot records from SMM drivers.
265 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &Communication
);
266 if (!EFI_ERROR (Status
)) {
268 // Initialize communicate buffer
270 SmmCommBufferHeader
= (EFI_SMM_COMMUNICATE_HEADER
*)SmmBootRecordCommBuffer
;
271 SmmCommData
= (SMM_BOOT_RECORD_COMMUNICATE
*)SmmCommBufferHeader
->Data
;
272 ZeroMem((UINT8
*)SmmCommData
, sizeof(SMM_BOOT_RECORD_COMMUNICATE
));
274 CopyGuid (&SmmCommBufferHeader
->HeaderGuid
, &gEfiFirmwarePerformanceGuid
);
275 SmmCommBufferHeader
->MessageLength
= sizeof(SMM_BOOT_RECORD_COMMUNICATE
);
276 CommSize
= SMM_BOOT_RECORD_COMM_SIZE
;
279 // Get the size of boot records.
281 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE
;
282 SmmCommData
->BootRecordData
= NULL
;
283 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
284 ASSERT_EFI_ERROR (Status
);
286 if (!EFI_ERROR (SmmCommData
->ReturnStatus
) && SmmCommData
->BootRecordSize
!= 0) {
288 // Get all boot records
290 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA
;
291 SmmCommData
->BootRecordData
= AllocateZeroPool(SmmCommData
->BootRecordSize
);
292 ASSERT (SmmCommData
->BootRecordData
!= NULL
);
294 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
295 ASSERT_EFI_ERROR (Status
);
296 ASSERT_EFI_ERROR(SmmCommData
->ReturnStatus
);
301 // Prepare memory for runtime Performance Record.
302 // Runtime performance records includes two tables S3 performance table and Boot performance table.
303 // S3 Performance table includes S3Resume and S3Suspend records.
304 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
306 PerformanceRuntimeData
= NULL
;
307 PerformanceRuntimeDataSize
= sizeof (S3_PERFORMANCE_TABLE
) + sizeof (BOOT_PERFORMANCE_TABLE
) + mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
308 if (SmmCommData
!= NULL
) {
309 PerformanceRuntimeDataSize
+= SmmCommData
->BootRecordSize
;
313 // Try to allocate the same runtime buffer as last time boot.
315 ZeroMem (&PerformanceVariable
, sizeof (PerformanceVariable
));
316 Size
= sizeof (PerformanceVariable
);
317 Status
= gRT
->GetVariable (
318 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
319 &gEfiFirmwarePerformanceGuid
,
324 if (!EFI_ERROR (Status
)) {
325 Address
= PerformanceVariable
.S3PerformanceTablePointer
;
326 Status
= gBS
->AllocatePages (
328 EfiReservedMemoryType
,
329 EFI_SIZE_TO_PAGES (PerformanceRuntimeDataSize
),
332 if (!EFI_ERROR (Status
)) {
333 PerformanceRuntimeData
= (UINT8
*) (UINTN
) Address
;
337 if (PerformanceRuntimeData
== NULL
) {
339 // Fail to allocate at specified address, continue to allocate at any address.
341 PerformanceRuntimeData
= FpdtAllocateReservedMemoryBelow4G (PerformanceRuntimeDataSize
);
343 DEBUG ((EFI_D_INFO
, "FPDT: Performance Runtime Data address = 0x%x\n", PerformanceRuntimeData
));
345 if (PerformanceRuntimeData
== NULL
) {
346 if (SmmCommData
!= NULL
&& SmmCommData
->BootRecordData
!= NULL
) {
347 FreePool (SmmCommData
->BootRecordData
);
349 return EFI_OUT_OF_RESOURCES
;
352 PerformanceRuntimeDataHead
= PerformanceRuntimeData
;
354 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support
)) {
356 // Prepare S3 Performance Table.
358 mAcpiS3PerformanceTable
= (S3_PERFORMANCE_TABLE
*) PerformanceRuntimeData
;
359 CopyMem (mAcpiS3PerformanceTable
, &mS3PerformanceTableTemplate
, sizeof (mS3PerformanceTableTemplate
));
360 PerformanceRuntimeData
= PerformanceRuntimeData
+ mAcpiS3PerformanceTable
->Header
.Length
;
361 DEBUG ((EFI_D_INFO
, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable
));
363 // Save S3 Performance Table address to Variable for use in Firmware Performance PEIM.
365 PerformanceVariable
.S3PerformanceTablePointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) mAcpiS3PerformanceTable
;
367 // Update S3 Performance Table Pointer in template.
369 mFirmwarePerformanceTableTemplate
.S3PointerRecord
.S3PerformanceTablePointer
= (UINT64
) PerformanceVariable
.S3PerformanceTablePointer
;
372 // Exclude S3 Performance Table Pointer from FPDT table template.
374 mFirmwarePerformanceTableTemplate
.Header
.Length
-= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD
);
378 // Prepare Boot Performance Table.
380 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) PerformanceRuntimeData
;
382 // Fill Basic Boot record to Boot Performance Table.
384 CopyMem (PerformanceRuntimeData
, &mBootPerformanceTableTemplate
, sizeof (mBootPerformanceTableTemplate
));
385 PerformanceRuntimeData
= PerformanceRuntimeData
+ mAcpiBootPerformanceTable
->Header
.Length
;
387 // Fill Boot records from boot drivers.
389 CopyMem (PerformanceRuntimeData
, mBootRecordBuffer
, mBootRecordSize
);
390 mAcpiBootPerformanceTable
->Header
.Length
+= mBootRecordSize
;
391 PerformanceRuntimeData
= PerformanceRuntimeData
+ mBootRecordSize
;
392 if (SmmCommData
!= NULL
&& SmmCommData
->BootRecordData
!= NULL
) {
394 // Fill Boot records from SMM drivers.
396 CopyMem (PerformanceRuntimeData
, SmmCommData
->BootRecordData
, SmmCommData
->BootRecordSize
);
397 FreePool (SmmCommData
->BootRecordData
);
398 mAcpiBootPerformanceTable
->Header
.Length
= (UINT32
) (mAcpiBootPerformanceTable
->Header
.Length
+ SmmCommData
->BootRecordSize
);
399 PerformanceRuntimeData
= PerformanceRuntimeData
+ SmmCommData
->BootRecordSize
;
402 // Reserve space for boot records after ReadyToBoot.
404 PerformanceRuntimeData
= PerformanceRuntimeData
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
405 DEBUG ((EFI_D_INFO
, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable
));
407 // Save Boot Performance Table address to Variable for use in S4 resume.
409 PerformanceVariable
.BootPerformanceTablePointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) mAcpiBootPerformanceTable
;
411 // Update Boot Performance Table Pointer in template.
413 mFirmwarePerformanceTableTemplate
.BootPointerRecord
.BootPerformanceTablePointer
= (UINT64
) (UINTN
) mAcpiBootPerformanceTable
;
416 // Save Runtime Performance Table pointers to Variable.
418 Status
= gRT
->SetVariable (
419 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
420 &gEfiFirmwarePerformanceGuid
,
421 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
422 sizeof (PerformanceVariable
),
425 ASSERT_EFI_ERROR (Status
);
428 // Publish Firmware Performance Data Table.
430 FpdtAcpiTableChecksum ((UINT8
*) &mFirmwarePerformanceTableTemplate
, mFirmwarePerformanceTableTemplate
.Header
.Length
);
431 Status
= AcpiTableProtocol
->InstallAcpiTable (
433 &mFirmwarePerformanceTableTemplate
,
434 mFirmwarePerformanceTableTemplate
.Header
.Length
,
435 &mFirmwarePerformanceTableTemplateKey
437 if (EFI_ERROR (Status
)) {
438 FreePool (PerformanceRuntimeDataHead
);
439 mAcpiBootPerformanceTable
= NULL
;
440 mAcpiS3PerformanceTable
= NULL
;
445 // Free temp Boot record, and update Boot Record to point to Basic Boot performance table.
447 if (mBootRecordBuffer
!= NULL
) {
448 FreePool (mBootRecordBuffer
);
450 mBootRecordBuffer
= (UINT8
*) mAcpiBootPerformanceTable
;
451 mBootRecordSize
= mAcpiBootPerformanceTable
->Header
.Length
;
452 mBootRecordMaxSize
= mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
458 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
459 install the Firmware Performance Data Table.
461 @param[in] Event The Event that is being processed.
462 @param[in] Context The Event Context.
467 FpdtReadyToBootEventNotify (
472 if (mAcpiBootPerformanceTable
== NULL
) {
474 // ACPI Firmware Performance Data Table not installed yet, install it now.
476 InstallFirmwarePerformanceDataTable ();
481 Notify function for event group EFI_EVENT_LEGACY_BOOT_GUID. This is used to
482 record performance data for OsLoaderLoadImageStart in FPDT for legacy boot.
484 @param[in] Event The Event that is being processed.
485 @param[in] Context The Event Context.
490 FpdtLegacyBootEventNotify (
495 if (mAcpiBootPerformanceTable
== NULL
) {
497 // Firmware Performance Data Table not installed, do nothing.
503 // Update Firmware Basic Boot Performance Record for legacy boot.
505 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
= 0;
506 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
507 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
= 0;
508 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesExit
= 0;
511 // Dump FPDT Boot Performance record.
513 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ResetEnd
));
514 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderLoadImageStart = 0\n"));
515 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
));
516 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));
517 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));
521 Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
522 performance data for ExitBootServicesEntry in FPDT.
524 @param[in] Event The Event that is being processed.
525 @param[in] Context The Event Context.
530 FpdtExitBootServicesEventNotify (
535 if (mAcpiBootPerformanceTable
== NULL
) {
537 // Firmware Performance Data Table not installed, do nothing.
543 // Update Firmware Basic Boot Performance Record for UEFI boot.
545 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
= GetTimeInNanoSecond (GetPerformanceCounter ());
548 // Dump FPDT Boot Performance record.
550 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ResetEnd
));
551 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderLoadImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
));
552 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
));
553 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesEntry = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
));
555 // ExitBootServicesExit will be updated later, so don't dump it here.
560 Report status code listener of FPDT. This is used to collect performance data
561 for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.
563 @param[in] CodeType Indicates the type of status code being reported.
564 @param[in] Value Describes the current status of a hardware or software entity.
565 This included information about the class and subclass that is used to
566 classify the entity as well as an operation.
567 @param[in] Instance The enumeration of a hardware or software entity within
568 the system. Valid instance numbers start with 1.
569 @param[in] CallerId This optional parameter may be used to identify the caller.
570 This parameter allows the status code driver to apply different rules to
572 @param[in] Data This optional parameter may be used to pass additional data.
574 @retval EFI_SUCCESS Status code is what we expected.
575 @retval EFI_UNSUPPORTED Status code not supported.
580 FpdtStatusCodeListenerDxe (
581 IN EFI_STATUS_CODE_TYPE CodeType
,
582 IN EFI_STATUS_CODE_VALUE Value
,
584 IN EFI_GUID
*CallerId
,
585 IN EFI_STATUS_CODE_DATA
*Data
591 // Check whether status code is what we are interested in.
593 if ((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) != EFI_PROGRESS_CODE
) {
594 return EFI_UNSUPPORTED
;
597 Status
= EFI_SUCCESS
;
598 if (Value
== PcdGet32 (PcdProgressCodeOsLoaderLoad
)) {
600 // Progress code for OS Loader LoadImage.
602 if (mAcpiBootPerformanceTable
== NULL
) {
607 // Update OS Loader LoadImage Start for UEFI boot.
609 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
610 } else if (Value
== PcdGet32 (PcdProgressCodeOsLoaderStart
)) {
612 // Progress code for OS Loader StartImage.
614 if (mAcpiBootPerformanceTable
== NULL
) {
619 // Update OS Loader StartImage Start for UEFI boot.
621 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
622 } else if (Value
== (EFI_SOFTWARE_EFI_BOOT_SERVICE
| EFI_SW_BS_PC_EXIT_BOOT_SERVICES
)) {
624 // Progress code for ExitBootServices.
626 if (mAcpiBootPerformanceTable
== NULL
) {
631 // Update ExitBootServicesExit for UEFI boot.
633 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesExit
= GetTimeInNanoSecond (GetPerformanceCounter ());
636 // Unregister boot time report status code listener.
638 mRscHandlerProtocol
->Unregister (FpdtStatusCodeListenerDxe
);
639 } else if (Data
!= NULL
&& CompareGuid (&Data
->Type
, &gEfiFirmwarePerformanceGuid
)) {
641 // Append one or more Boot records
643 if (mAcpiBootPerformanceTable
== NULL
) {
645 // Append Boot records before FPDT ACPI table is installed.
647 if (mBootRecordSize
+ Data
->Size
> mBootRecordMaxSize
) {
648 mBootRecordBuffer
= ReallocatePool (mBootRecordSize
, mBootRecordSize
+ Data
->Size
+ EXTENSION_RECORD_SIZE
, mBootRecordBuffer
);
649 ASSERT (mBootRecordBuffer
!= NULL
);
650 mBootRecordMaxSize
= mBootRecordSize
+ Data
->Size
+ EXTENSION_RECORD_SIZE
;
653 // Save boot record into the temp memory space.
655 CopyMem (mBootRecordBuffer
+ mBootRecordSize
, Data
+ 1, Data
->Size
);
656 mBootRecordSize
+= Data
->Size
;
659 // Append Boot records after FPDT ACPI table is installed.
661 if (mBootRecordSize
+ Data
->Size
> mBootRecordMaxSize
) {
663 // No enough space to save boot record.
665 Status
= EFI_OUT_OF_RESOURCES
;
668 // Save boot record into BootPerformance table
670 CopyMem (mBootRecordBuffer
+ mBootRecordSize
, Data
+ 1, Data
->Size
);
671 mBootRecordSize
+= Data
->Size
;
672 mAcpiBootPerformanceTable
->Header
.Length
= mBootRecordSize
;
677 // Ignore else progress code.
679 Status
= EFI_UNSUPPORTED
;
686 The module Entry Point of the Firmware Performance Data Table DXE driver.
688 @param[in] ImageHandle The firmware allocated handle for the EFI image.
689 @param[in] SystemTable A pointer to the EFI System Table.
691 @retval EFI_SUCCESS The entry point is executed successfully.
692 @retval Other Some error occurs when executing this entry point.
697 FirmwarePerformanceDxeEntryPoint (
698 IN EFI_HANDLE ImageHandle
,
699 IN EFI_SYSTEM_TABLE
*SystemTable
703 EFI_HOB_GUID_TYPE
*GuidHob
;
704 FIRMWARE_SEC_PERFORMANCE
*Performance
;
707 // Get Report Status Code Handler Protocol.
709 Status
= gBS
->LocateProtocol (&gEfiRscHandlerProtocolGuid
, NULL
, (VOID
**) &mRscHandlerProtocol
);
710 ASSERT_EFI_ERROR (Status
);
713 // Register report status code listener for OS Loader load and start.
715 Status
= mRscHandlerProtocol
->Register (FpdtStatusCodeListenerDxe
, TPL_HIGH_LEVEL
);
716 ASSERT_EFI_ERROR (Status
);
719 // Register the notify function to update FPDT on ExitBootServices Event.
721 Status
= gBS
->CreateEventEx (
724 FpdtExitBootServicesEventNotify
,
726 &gEfiEventExitBootServicesGuid
,
727 &mExitBootServicesEvent
729 ASSERT_EFI_ERROR (Status
);
732 // Create ready to boot event to install ACPI FPDT table.
734 Status
= gBS
->CreateEventEx (
737 FpdtReadyToBootEventNotify
,
739 &gEfiEventReadyToBootGuid
,
742 ASSERT_EFI_ERROR (Status
);
745 // Create legacy boot event to log OsLoaderStartImageStart for legacy boot.
747 Status
= gBS
->CreateEventEx (
750 FpdtLegacyBootEventNotify
,
752 &gEfiEventLegacyBootGuid
,
755 ASSERT_EFI_ERROR (Status
);
758 // Retrieve GUID HOB data that contains the ResetEnd.
760 GuidHob
= GetFirstGuidHob (&gEfiFirmwarePerformanceGuid
);
761 if (GuidHob
!= NULL
) {
762 Performance
= (FIRMWARE_SEC_PERFORMANCE
*) GET_GUID_HOB_DATA (GuidHob
);
763 mBootPerformanceTableTemplate
.BasicBoot
.ResetEnd
= Performance
->ResetEnd
;
766 // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.
768 DEBUG ((EFI_D_ERROR
, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));