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 <Protocol/ReportStatusCodeHandler.h>
22 #include <Protocol/AcpiTable.h>
23 #include <Protocol/SmmCommunication.h>
25 #include <Guid/Acpi.h>
26 #include <Guid/FirmwarePerformance.h>
27 #include <Guid/EventGroup.h>
28 #include <Guid/EventLegacyBios.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/UefiRuntimeServicesTableLib.h>
32 #include <Library/BaseLib.h>
33 #include <Library/DebugLib.h>
34 #include <Library/TimerLib.h>
35 #include <Library/BaseMemoryLib.h>
36 #include <Library/MemoryAllocationLib.h>
37 #include <Library/PcdLib.h>
38 #include <Library/HobLib.h>
39 #include <Library/PcdLib.h>
42 // ACPI table information used to initialize tables.
44 #define EFI_ACPI_OEM_ID "INTEL"
45 #define EFI_ACPI_OEM_TABLE_ID 0x2020204F4E414954ULL // "TIANO "
46 #define EFI_ACPI_OEM_REVISION 0x00000001
47 #define EFI_ACPI_CREATOR_ID 0x5446534D // TBD "MSFT"
48 #define EFI_ACPI_CREATOR_REVISION 0x01000013 // TBD
49 #define EXTENSION_RECORD_SIZE 0x10000
50 #define SMM_BOOT_RECORD_COMM_SIZE OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE)
52 EFI_RSC_HANDLER_PROTOCOL
*mRscHandlerProtocol
= NULL
;
54 EFI_EVENT mReadyToBootEvent
;
55 EFI_EVENT mLegacyBootEvent
;
56 EFI_EVENT mExitBootServicesEvent
;
57 UINTN mFirmwarePerformanceTableTemplateKey
= 0;
58 UINT32 mBootRecordSize
= 0;
59 UINT32 mBootRecordMaxSize
= 0;
60 UINT8
*mBootRecordBuffer
= NULL
;
62 BOOT_PERFORMANCE_TABLE
*mAcpiBootPerformanceTable
= NULL
;
63 S3_PERFORMANCE_TABLE
*mAcpiS3PerformanceTable
= NULL
;
65 FIRMWARE_PERFORMANCE_TABLE mFirmwarePerformanceTableTemplate
= {
67 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE
,
68 sizeof (FIRMWARE_PERFORMANCE_TABLE
),
69 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION
, // Revision
70 0x00, // Checksum will be updated at runtime
72 // It is expected that these values will be updated at runtime.
74 EFI_ACPI_OEM_ID
, // OEMID is a 6 bytes long field
75 EFI_ACPI_OEM_TABLE_ID
, // OEM table identification(8 bytes long)
76 EFI_ACPI_OEM_REVISION
, // OEM revision number
77 EFI_ACPI_CREATOR_ID
, // ASL compiler vendor ID
78 EFI_ACPI_CREATOR_REVISION
, // ASL compiler revision number
81 // Firmware Basic Boot Performance Table Pointer Record.
85 EFI_ACPI_5_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER
, // Type
86 sizeof (EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD
), // Length
87 EFI_ACPI_5_0_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER
// Revision
90 0 // BootPerformanceTablePointer will be updated at runtime.
93 // S3 Performance Table Pointer Record.
97 EFI_ACPI_5_0_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER
, // Type
98 sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD
), // Length
99 EFI_ACPI_5_0_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER
// Revision
102 0 // S3PerformanceTablePointer will be updated at runtime.
106 BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate
= {
108 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE
,
109 sizeof (BOOT_PERFORMANCE_TABLE
)
113 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT
, // Type
114 sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD
), // Length
115 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT
// Revision
119 // These values will be updated at runtime.
122 0, // OsLoaderLoadImageStart
123 0, // OsLoaderStartImageStart
124 0, // ExitBootServicesEntry
125 0 // ExitBootServicesExit
129 S3_PERFORMANCE_TABLE mS3PerformanceTableTemplate
= {
131 EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE
,
132 sizeof (S3_PERFORMANCE_TABLE
)
136 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME
, // Type
137 sizeof (EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD
), // Length
138 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME
// Revision
141 // These values will be updated by Firmware Performance PEIM.
149 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND
, // Type
150 sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD
), // Length
151 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND
// Revision
154 // These values will be updated bye Firmware Performance SMM driver.
162 This function calculates and updates an UINT8 checksum.
164 @param[in] Buffer Pointer to buffer to checksum
165 @param[in] Size Number of bytes to checksum
169 FpdtAcpiTableChecksum (
174 UINTN ChecksumOffset
;
176 ChecksumOffset
= OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
, Checksum
);
179 // Set checksum to 0 first.
181 Buffer
[ChecksumOffset
] = 0;
184 // Update checksum value.
186 Buffer
[ChecksumOffset
] = CalculateCheckSum8 (Buffer
, Size
);
190 Allocate EfiReservedMemoryType below 4G memory address.
192 This function allocates EfiReservedMemoryType below 4G memory address.
194 @param[in] Size Size of memory to allocate.
196 @return Allocated address for output.
200 FpdtAllocateReservedMemoryBelow4G (
205 EFI_PHYSICAL_ADDRESS Address
;
209 Pages
= EFI_SIZE_TO_PAGES (Size
);
210 Address
= 0xffffffff;
212 Status
= gBS
->AllocatePages (
214 EfiReservedMemoryType
,
218 ASSERT_EFI_ERROR (Status
);
220 Buffer
= (VOID
*) (UINTN
) Address
;
221 ZeroMem (Buffer
, Size
);
227 Install ACPI Firmware Performance Data Table (FPDT).
233 InstallFirmwarePerformanceDataTable (
238 EFI_ACPI_TABLE_PROTOCOL
*AcpiTableProtocol
;
239 EFI_PHYSICAL_ADDRESS Address
;
241 UINT8 SmmBootRecordCommBuffer
[SMM_BOOT_RECORD_COMM_SIZE
];
242 EFI_SMM_COMMUNICATE_HEADER
*SmmCommBufferHeader
;
243 SMM_BOOT_RECORD_COMMUNICATE
*SmmCommData
;
245 UINTN PerformanceRuntimeDataSize
;
246 UINT8
*PerformanceRuntimeData
;
247 UINT8
*PerformanceRuntimeDataHead
;
248 EFI_SMM_COMMUNICATION_PROTOCOL
*Communication
;
249 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable
;
252 // Get AcpiTable Protocol.
254 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTableProtocol
);
255 if (EFI_ERROR (Status
)) {
260 // Collect boot records from SMM drivers.
263 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &Communication
);
264 if (!EFI_ERROR (Status
)) {
266 // Initialize communicate buffer
268 SmmCommBufferHeader
= (EFI_SMM_COMMUNICATE_HEADER
*)SmmBootRecordCommBuffer
;
269 SmmCommData
= (SMM_BOOT_RECORD_COMMUNICATE
*)SmmCommBufferHeader
->Data
;
270 ZeroMem((UINT8
*)SmmCommData
, sizeof(SMM_BOOT_RECORD_COMMUNICATE
));
272 CopyGuid (&SmmCommBufferHeader
->HeaderGuid
, &gEfiFirmwarePerformanceGuid
);
273 SmmCommBufferHeader
->MessageLength
= sizeof(SMM_BOOT_RECORD_COMMUNICATE
);
274 CommSize
= SMM_BOOT_RECORD_COMM_SIZE
;
277 // Get the size of boot records.
279 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE
;
280 SmmCommData
->BootRecordData
= NULL
;
281 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
282 ASSERT_EFI_ERROR (Status
);
284 if (!EFI_ERROR (SmmCommData
->ReturnStatus
) && SmmCommData
->BootRecordSize
!= 0) {
286 // Get all boot records
288 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA
;
289 SmmCommData
->BootRecordData
= AllocateZeroPool(SmmCommData
->BootRecordSize
);
290 ASSERT (SmmCommData
->BootRecordData
!= NULL
);
292 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
293 ASSERT_EFI_ERROR (Status
);
294 ASSERT_EFI_ERROR(SmmCommData
->ReturnStatus
);
299 // Prepare memory for runtime Performance Record.
300 // Runtime performance records includes two tables S3 performance table and Boot performance table.
301 // S3 Performance table includes S3Resume and S3Suspend records.
302 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
304 PerformanceRuntimeData
= NULL
;
305 PerformanceRuntimeDataSize
= sizeof (S3_PERFORMANCE_TABLE
) + sizeof (BOOT_PERFORMANCE_TABLE
) + mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
306 if (SmmCommData
!= NULL
) {
307 PerformanceRuntimeDataSize
+= SmmCommData
->BootRecordSize
;
311 // Try to allocate the same runtime buffer as last time boot.
313 ZeroMem (&PerformanceVariable
, sizeof (PerformanceVariable
));
314 Size
= sizeof (PerformanceVariable
);
315 Status
= gRT
->GetVariable (
316 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
317 &gEfiFirmwarePerformanceGuid
,
322 if (!EFI_ERROR (Status
)) {
323 Address
= PerformanceVariable
.S3PerformanceTablePointer
;
324 Status
= gBS
->AllocatePages (
326 EfiReservedMemoryType
,
327 EFI_SIZE_TO_PAGES (PerformanceRuntimeDataSize
),
330 if (!EFI_ERROR (Status
)) {
331 PerformanceRuntimeData
= (UINT8
*) (UINTN
) Address
;
335 if (PerformanceRuntimeData
== NULL
) {
337 // Fail to allocate at specified address, continue to allocate at any address.
339 PerformanceRuntimeData
= FpdtAllocateReservedMemoryBelow4G (PerformanceRuntimeDataSize
);
341 DEBUG ((EFI_D_INFO
, "FPDT: Performance Runtime Data address = 0x%x\n", PerformanceRuntimeData
));
343 if (PerformanceRuntimeData
== NULL
) {
344 if (SmmCommData
!= NULL
&& SmmCommData
->BootRecordData
!= NULL
) {
345 FreePool (SmmCommData
->BootRecordData
);
347 return EFI_OUT_OF_RESOURCES
;
350 PerformanceRuntimeDataHead
= PerformanceRuntimeData
;
352 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support
)) {
354 // Prepare S3 Performance Table.
356 mAcpiS3PerformanceTable
= (S3_PERFORMANCE_TABLE
*) PerformanceRuntimeData
;
357 CopyMem (mAcpiS3PerformanceTable
, &mS3PerformanceTableTemplate
, sizeof (mS3PerformanceTableTemplate
));
358 PerformanceRuntimeData
= PerformanceRuntimeData
+ mAcpiS3PerformanceTable
->Header
.Length
;
359 DEBUG ((EFI_D_INFO
, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable
));
361 // Save S3 Performance Table address to Variable for use in Firmware Performance PEIM.
363 PerformanceVariable
.S3PerformanceTablePointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) mAcpiS3PerformanceTable
;
365 // Update S3 Performance Table Pointer in template.
367 mFirmwarePerformanceTableTemplate
.S3PointerRecord
.S3PerformanceTablePointer
= (UINT64
) PerformanceVariable
.S3PerformanceTablePointer
;
370 // Exclude S3 Performance Table Pointer from FPDT table template.
372 mFirmwarePerformanceTableTemplate
.Header
.Length
-= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD
);
376 // Prepare Boot Performance Table.
378 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) PerformanceRuntimeData
;
380 // Fill Basic Boot record to Boot Performance Table.
382 CopyMem (PerformanceRuntimeData
, &mBootPerformanceTableTemplate
, sizeof (mBootPerformanceTableTemplate
));
383 PerformanceRuntimeData
= PerformanceRuntimeData
+ mAcpiBootPerformanceTable
->Header
.Length
;
385 // Fill Boot records from boot drivers.
387 CopyMem (PerformanceRuntimeData
, mBootRecordBuffer
, mBootRecordSize
);
388 mAcpiBootPerformanceTable
->Header
.Length
+= mBootRecordSize
;
389 PerformanceRuntimeData
= PerformanceRuntimeData
+ mBootRecordSize
;
390 if (SmmCommData
!= NULL
&& SmmCommData
->BootRecordData
!= NULL
) {
392 // Fill Boot records from SMM drivers.
394 CopyMem (PerformanceRuntimeData
, SmmCommData
->BootRecordData
, SmmCommData
->BootRecordSize
);
395 FreePool (SmmCommData
->BootRecordData
);
396 mAcpiBootPerformanceTable
->Header
.Length
= (UINT32
) (mAcpiBootPerformanceTable
->Header
.Length
+ SmmCommData
->BootRecordSize
);
397 PerformanceRuntimeData
= PerformanceRuntimeData
+ SmmCommData
->BootRecordSize
;
400 // Reserve space for boot records after ReadyToBoot.
402 PerformanceRuntimeData
= PerformanceRuntimeData
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
403 DEBUG ((EFI_D_INFO
, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable
));
405 // Save Boot Performance Table address to Variable for use in S4 resume.
407 PerformanceVariable
.BootPerformanceTablePointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) mAcpiBootPerformanceTable
;
409 // Update Boot Performance Table Pointer in template.
411 mFirmwarePerformanceTableTemplate
.BootPointerRecord
.BootPerformanceTablePointer
= (UINT64
) (UINTN
) mAcpiBootPerformanceTable
;
414 // Save Runtime Performance Table pointers to Variable.
416 Status
= gRT
->SetVariable (
417 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
418 &gEfiFirmwarePerformanceGuid
,
419 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
420 sizeof (PerformanceVariable
),
423 ASSERT_EFI_ERROR (Status
);
426 // Publish Firmware Performance Data Table.
428 FpdtAcpiTableChecksum ((UINT8
*) &mFirmwarePerformanceTableTemplate
, mFirmwarePerformanceTableTemplate
.Header
.Length
);
429 Status
= AcpiTableProtocol
->InstallAcpiTable (
431 &mFirmwarePerformanceTableTemplate
,
432 mFirmwarePerformanceTableTemplate
.Header
.Length
,
433 &mFirmwarePerformanceTableTemplateKey
435 if (EFI_ERROR (Status
)) {
436 FreePool (PerformanceRuntimeDataHead
);
437 mAcpiBootPerformanceTable
= NULL
;
438 mAcpiS3PerformanceTable
= NULL
;
443 // Free temp Boot record, and update Boot Record to point to Basic Boot performance table.
445 if (mBootRecordBuffer
!= NULL
) {
446 FreePool (mBootRecordBuffer
);
448 mBootRecordBuffer
= (UINT8
*) mAcpiBootPerformanceTable
;
449 mBootRecordSize
= mAcpiBootPerformanceTable
->Header
.Length
;
450 mBootRecordMaxSize
= mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
456 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
457 install the Firmware Performance Data Table.
459 @param[in] Event The Event that is being processed.
460 @param[in] Context The Event Context.
465 FpdtReadyToBootEventNotify (
470 if (mAcpiBootPerformanceTable
== NULL
) {
472 // ACPI Firmware Performance Data Table not installed yet, install it now.
474 InstallFirmwarePerformanceDataTable ();
479 Notify function for event group EFI_EVENT_LEGACY_BOOT_GUID. This is used to
480 record performance data for OsLoaderLoadImageStart in FPDT for legacy boot.
482 @param[in] Event The Event that is being processed.
483 @param[in] Context The Event Context.
488 FpdtLegacyBootEventNotify (
493 if (mAcpiBootPerformanceTable
== NULL
) {
495 // Firmware Performance Data Table not installed, do nothing.
501 // Update Firmware Basic Boot Performance Record for legacy boot.
503 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
= 0;
504 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
505 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
= 0;
506 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesExit
= 0;
509 // Dump FPDT Boot Performance record.
511 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ResetEnd
));
512 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderLoadImageStart = 0\n"));
513 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
));
514 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));
515 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));
519 Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
520 performance data for ExitBootServicesEntry in FPDT.
522 @param[in] Event The Event that is being processed.
523 @param[in] Context The Event Context.
528 FpdtExitBootServicesEventNotify (
533 if (mAcpiBootPerformanceTable
== NULL
) {
535 // Firmware Performance Data Table not installed, do nothing.
541 // Update Firmware Basic Boot Performance Record for UEFI boot.
543 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
= GetTimeInNanoSecond (GetPerformanceCounter ());
546 // Dump FPDT Boot Performance record.
548 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ResetEnd
));
549 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderLoadImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
));
550 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
));
551 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesEntry = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
));
553 // ExitBootServicesExit will be updated later, so don't dump it here.
558 Report status code listener of FPDT. This is used to collect performance data
559 for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.
561 @param[in] CodeType Indicates the type of status code being reported.
562 @param[in] Value Describes the current status of a hardware or software entity.
563 This included information about the class and subclass that is used to
564 classify the entity as well as an operation.
565 @param[in] Instance The enumeration of a hardware or software entity within
566 the system. Valid instance numbers start with 1.
567 @param[in] CallerId This optional parameter may be used to identify the caller.
568 This parameter allows the status code driver to apply different rules to
570 @param[in] Data This optional parameter may be used to pass additional data.
572 @retval EFI_SUCCESS Status code is what we expected.
573 @retval EFI_UNSUPPORTED Status code not supported.
578 FpdtStatusCodeListenerDxe (
579 IN EFI_STATUS_CODE_TYPE CodeType
,
580 IN EFI_STATUS_CODE_VALUE Value
,
582 IN EFI_GUID
*CallerId
,
583 IN EFI_STATUS_CODE_DATA
*Data
589 // Check whether status code is what we are interested in.
591 if ((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) != EFI_PROGRESS_CODE
) {
592 return EFI_UNSUPPORTED
;
595 Status
= EFI_SUCCESS
;
596 if (Value
== PcdGet32 (PcdProgressCodeOsLoaderLoad
)) {
598 // Progress code for OS Loader LoadImage.
600 if (mAcpiBootPerformanceTable
== NULL
) {
605 // Update OS Loader LoadImage Start for UEFI boot.
607 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
608 } else if (Value
== PcdGet32 (PcdProgressCodeOsLoaderStart
)) {
610 // Progress code for OS Loader StartImage.
612 if (mAcpiBootPerformanceTable
== NULL
) {
617 // Update OS Loader StartImage Start for UEFI boot.
619 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
620 } else if (Value
== (EFI_SOFTWARE_EFI_BOOT_SERVICE
| EFI_SW_BS_PC_EXIT_BOOT_SERVICES
)) {
622 // Progress code for ExitBootServices.
624 if (mAcpiBootPerformanceTable
== NULL
) {
629 // Update ExitBootServicesExit for UEFI boot.
631 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesExit
= GetTimeInNanoSecond (GetPerformanceCounter ());
634 // Unregister boot time report status code listener.
636 mRscHandlerProtocol
->Unregister (FpdtStatusCodeListenerDxe
);
637 } else if (Data
!= NULL
&& CompareGuid (&Data
->Type
, &gEfiFirmwarePerformanceGuid
)) {
639 // Append one or more Boot records
641 if (mAcpiBootPerformanceTable
== NULL
) {
643 // Append Boot records before FPDT ACPI table is installed.
645 if (mBootRecordSize
+ Data
->Size
> mBootRecordMaxSize
) {
646 mBootRecordBuffer
= ReallocatePool (mBootRecordSize
, mBootRecordSize
+ Data
->Size
+ EXTENSION_RECORD_SIZE
, mBootRecordBuffer
);
647 ASSERT (mBootRecordBuffer
!= NULL
);
648 mBootRecordMaxSize
= mBootRecordSize
+ Data
->Size
+ EXTENSION_RECORD_SIZE
;
651 // Save boot record into the temp memory space.
653 CopyMem (mBootRecordBuffer
+ mBootRecordSize
, Data
+ 1, Data
->Size
);
654 mBootRecordSize
+= Data
->Size
;
657 // Append Boot records after FPDT ACPI table is installed.
659 if (mBootRecordSize
+ Data
->Size
> mBootRecordMaxSize
) {
661 // No enough space to save boot record.
663 Status
= EFI_OUT_OF_RESOURCES
;
666 // Save boot record into BootPerformance table
668 CopyMem (mBootRecordBuffer
+ mBootRecordSize
, Data
+ 1, Data
->Size
);
669 mBootRecordSize
+= Data
->Size
;
670 mAcpiBootPerformanceTable
->Header
.Length
= mBootRecordSize
;
675 // Ignore else progress code.
677 Status
= EFI_UNSUPPORTED
;
684 The module Entry Point of the Firmware Performance Data Table DXE driver.
686 @param[in] ImageHandle The firmware allocated handle for the EFI image.
687 @param[in] SystemTable A pointer to the EFI System Table.
689 @retval EFI_SUCCESS The entry point is executed successfully.
690 @retval Other Some error occurs when executing this entry point.
695 FirmwarePerformanceDxeEntryPoint (
696 IN EFI_HANDLE ImageHandle
,
697 IN EFI_SYSTEM_TABLE
*SystemTable
701 EFI_HOB_GUID_TYPE
*GuidHob
;
702 FIRMWARE_SEC_PERFORMANCE
*Performance
;
705 // Get Report Status Code Handler Protocol.
707 Status
= gBS
->LocateProtocol (&gEfiRscHandlerProtocolGuid
, NULL
, (VOID
**) &mRscHandlerProtocol
);
708 ASSERT_EFI_ERROR (Status
);
711 // Register report status code listener for OS Loader load and start.
713 Status
= mRscHandlerProtocol
->Register (FpdtStatusCodeListenerDxe
, TPL_HIGH_LEVEL
);
714 ASSERT_EFI_ERROR (Status
);
717 // Register the notify function to update FPDT on ExitBootServices Event.
719 Status
= gBS
->CreateEventEx (
722 FpdtExitBootServicesEventNotify
,
724 &gEfiEventExitBootServicesGuid
,
725 &mExitBootServicesEvent
727 ASSERT_EFI_ERROR (Status
);
730 // Create ready to boot event to install ACPI FPDT table.
732 Status
= gBS
->CreateEventEx (
735 FpdtReadyToBootEventNotify
,
737 &gEfiEventReadyToBootGuid
,
740 ASSERT_EFI_ERROR (Status
);
743 // Create legacy boot event to log OsLoaderStartImageStart for legacy boot.
745 Status
= gBS
->CreateEventEx (
748 FpdtLegacyBootEventNotify
,
750 &gEfiEventLegacyBootGuid
,
753 ASSERT_EFI_ERROR (Status
);
756 // Retrieve GUID HOB data that contains the ResetEnd.
758 GuidHob
= GetFirstGuidHob (&gEfiFirmwarePerformanceGuid
);
759 if (GuidHob
!= NULL
) {
760 Performance
= (FIRMWARE_SEC_PERFORMANCE
*) GET_GUID_HOB_DATA (GuidHob
);
761 mBootPerformanceTableTemplate
.BasicBoot
.ResetEnd
= Performance
->ResetEnd
;
764 // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.
766 DEBUG ((EFI_D_ERROR
, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));