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 - 2013, 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>
24 #include <Protocol/LockBox.h>
25 #include <Protocol/Variable.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/LockBoxLib.h>
42 #include <Library/UefiLib.h>
44 #define EXTENSION_RECORD_SIZE 0x10000
45 #define SMM_BOOT_RECORD_COMM_SIZE OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE)
47 EFI_RSC_HANDLER_PROTOCOL
*mRscHandlerProtocol
= NULL
;
49 BOOLEAN mLockBoxReady
= FALSE
;
50 EFI_EVENT mReadyToBootEvent
;
51 EFI_EVENT mLegacyBootEvent
;
52 EFI_EVENT mExitBootServicesEvent
;
53 UINTN mFirmwarePerformanceTableTemplateKey
= 0;
54 UINT32 mBootRecordSize
= 0;
55 UINT32 mBootRecordMaxSize
= 0;
56 UINT8
*mBootRecordBuffer
= NULL
;
58 BOOT_PERFORMANCE_TABLE
*mAcpiBootPerformanceTable
= NULL
;
59 S3_PERFORMANCE_TABLE
*mAcpiS3PerformanceTable
= NULL
;
61 FIRMWARE_PERFORMANCE_TABLE mFirmwarePerformanceTableTemplate
= {
63 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE
,
64 sizeof (FIRMWARE_PERFORMANCE_TABLE
),
65 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION
, // Revision
66 0x00, // Checksum will be updated at runtime
68 // It is expected that these values will be updated at EntryPoint.
70 {0x00}, // OEM ID is a 6 bytes long field
71 0x00, // OEM Table ID(8 bytes long)
74 0x00, // Creator Revision
77 // Firmware Basic Boot Performance Table Pointer Record.
81 EFI_ACPI_5_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER
, // Type
82 sizeof (EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD
), // Length
83 EFI_ACPI_5_0_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER
// Revision
86 0 // BootPerformanceTablePointer will be updated at runtime.
89 // S3 Performance Table Pointer Record.
93 EFI_ACPI_5_0_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER
, // Type
94 sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD
), // Length
95 EFI_ACPI_5_0_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER
// Revision
98 0 // S3PerformanceTablePointer will be updated at runtime.
102 BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate
= {
104 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE
,
105 sizeof (BOOT_PERFORMANCE_TABLE
)
109 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT
, // Type
110 sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD
), // Length
111 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT
// Revision
115 // These values will be updated at runtime.
118 0, // OsLoaderLoadImageStart
119 0, // OsLoaderStartImageStart
120 0, // ExitBootServicesEntry
121 0 // ExitBootServicesExit
125 S3_PERFORMANCE_TABLE mS3PerformanceTableTemplate
= {
127 EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE
,
128 sizeof (S3_PERFORMANCE_TABLE
)
132 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME
, // Type
133 sizeof (EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD
), // Length
134 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME
// Revision
137 // These values will be updated by Firmware Performance PEIM.
145 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND
, // Type
146 sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD
), // Length
147 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND
// Revision
150 // These values will be updated bye Firmware Performance SMM driver.
158 This function calculates and updates an UINT8 checksum.
160 @param[in] Buffer Pointer to buffer to checksum
161 @param[in] Size Number of bytes to checksum
165 FpdtAcpiTableChecksum (
170 UINTN ChecksumOffset
;
172 ChecksumOffset
= OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
, Checksum
);
175 // Set checksum to 0 first.
177 Buffer
[ChecksumOffset
] = 0;
180 // Update checksum value.
182 Buffer
[ChecksumOffset
] = CalculateCheckSum8 (Buffer
, Size
);
186 Allocate EfiReservedMemoryType below 4G memory address.
188 This function allocates EfiReservedMemoryType below 4G memory address.
190 @param[in] Size Size of memory to allocate.
192 @return Allocated address for output.
196 FpdtAllocateReservedMemoryBelow4G (
201 EFI_PHYSICAL_ADDRESS Address
;
206 Pages
= EFI_SIZE_TO_PAGES (Size
);
207 Address
= 0xffffffff;
209 Status
= gBS
->AllocatePages (
211 EfiReservedMemoryType
,
215 ASSERT_EFI_ERROR (Status
);
217 if (!EFI_ERROR (Status
)) {
218 Buffer
= (VOID
*) (UINTN
) Address
;
219 ZeroMem (Buffer
, Size
);
226 Callback function upon VariableArchProtocol and LockBoxProtocol
227 to allocate S3 performance table memory and save the pointer to LockBox.
229 @param[in] Event Event whose notification function is being invoked.
230 @param[in] Context Pointer to the notification function's context.
234 FpdtAllocateS3PerformanceTableMemory (
241 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable
;
243 EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer
;
245 if (mLockBoxReady
&& (mAcpiS3PerformanceTable
!= NULL
)) {
247 // The memory for S3 performance table should have been ready,
248 // and the pointer should have been saved to LockBox, just return.
253 if (!mLockBoxReady
) {
254 Status
= gBS
->LocateProtocol (&gEfiLockBoxProtocolGuid
, NULL
, &Interface
);
255 if (!EFI_ERROR (Status
)) {
257 // LockBox services has been ready.
259 mLockBoxReady
= TRUE
;
263 if (mAcpiS3PerformanceTable
== NULL
) {
264 Status
= gBS
->LocateProtocol (&gEfiVariableArchProtocolGuid
, NULL
, &Interface
);
265 if (!EFI_ERROR (Status
)) {
267 // Try to allocate the same runtime buffer as last time boot.
269 ZeroMem (&PerformanceVariable
, sizeof (PerformanceVariable
));
270 Size
= sizeof (PerformanceVariable
);
271 Status
= gRT
->GetVariable (
272 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
273 &gEfiFirmwarePerformanceGuid
,
278 if (!EFI_ERROR (Status
)) {
279 Status
= gBS
->AllocatePages (
281 EfiReservedMemoryType
,
282 EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE
)),
283 &PerformanceVariable
.S3PerformanceTablePointer
285 if (!EFI_ERROR (Status
)) {
286 mAcpiS3PerformanceTable
= (S3_PERFORMANCE_TABLE
*) (UINTN
) PerformanceVariable
.S3PerformanceTablePointer
;
289 if (mAcpiS3PerformanceTable
== NULL
) {
291 // Fail to allocate at specified address, continue to allocate at any address.
293 mAcpiS3PerformanceTable
= (S3_PERFORMANCE_TABLE
*) FpdtAllocateReservedMemoryBelow4G (sizeof (S3_PERFORMANCE_TABLE
));
295 DEBUG ((EFI_D_INFO
, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable
));
296 if (mAcpiS3PerformanceTable
!= NULL
) {
297 CopyMem (mAcpiS3PerformanceTable
, &mS3PerformanceTableTemplate
, sizeof (mS3PerformanceTableTemplate
));
302 if (mLockBoxReady
&& (mAcpiS3PerformanceTable
!= NULL
)) {
304 // If LockBox services has been ready and memory for FPDT S3 performance table has been allocated,
305 // save the pointer to LockBox for use in S3 resume.
307 S3PerformanceTablePointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) mAcpiS3PerformanceTable
;
308 Status
= SaveLockBox (
309 &gFirmwarePerformanceS3PointerGuid
,
310 &S3PerformanceTablePointer
,
311 sizeof (EFI_PHYSICAL_ADDRESS
)
313 ASSERT_EFI_ERROR (Status
);
318 Install ACPI Firmware Performance Data Table (FPDT).
324 InstallFirmwarePerformanceDataTable (
329 EFI_ACPI_TABLE_PROTOCOL
*AcpiTableProtocol
;
331 UINT8
*SmmBootRecordCommBuffer
;
332 EFI_SMM_COMMUNICATE_HEADER
*SmmCommBufferHeader
;
333 SMM_BOOT_RECORD_COMMUNICATE
*SmmCommData
;
335 UINTN BootPerformanceDataSize
;
336 UINT8
*BootPerformanceData
;
337 EFI_SMM_COMMUNICATION_PROTOCOL
*Communication
;
338 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable
;
341 // Get AcpiTable Protocol.
343 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTableProtocol
);
344 if (EFI_ERROR (Status
)) {
349 // Collect boot records from SMM drivers.
351 SmmBootRecordCommBuffer
= NULL
;
353 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &Communication
);
354 if (!EFI_ERROR (Status
)) {
356 // Initialize communicate buffer
358 SmmBootRecordCommBuffer
= AllocateZeroPool (SMM_BOOT_RECORD_COMM_SIZE
);
359 ASSERT (SmmBootRecordCommBuffer
!= NULL
);
360 SmmCommBufferHeader
= (EFI_SMM_COMMUNICATE_HEADER
*)SmmBootRecordCommBuffer
;
361 SmmCommData
= (SMM_BOOT_RECORD_COMMUNICATE
*)SmmCommBufferHeader
->Data
;
362 ZeroMem((UINT8
*)SmmCommData
, sizeof(SMM_BOOT_RECORD_COMMUNICATE
));
364 CopyGuid (&SmmCommBufferHeader
->HeaderGuid
, &gEfiFirmwarePerformanceGuid
);
365 SmmCommBufferHeader
->MessageLength
= sizeof(SMM_BOOT_RECORD_COMMUNICATE
);
366 CommSize
= SMM_BOOT_RECORD_COMM_SIZE
;
369 // Get the size of boot records.
371 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE
;
372 SmmCommData
->BootRecordData
= NULL
;
373 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
374 ASSERT_EFI_ERROR (Status
);
376 if (!EFI_ERROR (SmmCommData
->ReturnStatus
) && SmmCommData
->BootRecordSize
!= 0) {
378 // Get all boot records
380 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA
;
381 SmmCommData
->BootRecordData
= AllocateZeroPool(SmmCommData
->BootRecordSize
);
382 ASSERT (SmmCommData
->BootRecordData
!= NULL
);
384 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
385 ASSERT_EFI_ERROR (Status
);
386 ASSERT_EFI_ERROR(SmmCommData
->ReturnStatus
);
391 // Prepare memory for Boot Performance table.
392 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
394 BootPerformanceDataSize
= sizeof (BOOT_PERFORMANCE_TABLE
) + mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
395 if (SmmCommData
!= NULL
) {
396 BootPerformanceDataSize
+= SmmCommData
->BootRecordSize
;
400 // Try to allocate the same runtime buffer as last time boot.
402 ZeroMem (&PerformanceVariable
, sizeof (PerformanceVariable
));
403 Size
= sizeof (PerformanceVariable
);
404 Status
= gRT
->GetVariable (
405 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
406 &gEfiFirmwarePerformanceGuid
,
411 if (!EFI_ERROR (Status
)) {
412 Status
= gBS
->AllocatePages (
414 EfiReservedMemoryType
,
415 EFI_SIZE_TO_PAGES (BootPerformanceDataSize
),
416 &PerformanceVariable
.BootPerformanceTablePointer
418 if (!EFI_ERROR (Status
)) {
419 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) (UINTN
) PerformanceVariable
.BootPerformanceTablePointer
;
423 if (mAcpiBootPerformanceTable
== NULL
) {
425 // Fail to allocate at specified address, continue to allocate at any address.
427 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize
);
429 DEBUG ((EFI_D_INFO
, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable
));
431 if (mAcpiBootPerformanceTable
== NULL
) {
432 if (SmmCommData
!= NULL
&& SmmCommData
->BootRecordData
!= NULL
) {
433 FreePool (SmmCommData
->BootRecordData
);
435 if (SmmBootRecordCommBuffer
!= NULL
) {
436 FreePool (SmmBootRecordCommBuffer
);
438 if (mAcpiS3PerformanceTable
!= NULL
) {
439 FreePages (mAcpiS3PerformanceTable
, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE
)));
441 return EFI_OUT_OF_RESOURCES
;
445 // Prepare Boot Performance Table.
447 BootPerformanceData
= (UINT8
*) mAcpiBootPerformanceTable
;
449 // Fill Basic Boot record to Boot Performance Table.
451 CopyMem (mAcpiBootPerformanceTable
, &mBootPerformanceTableTemplate
, sizeof (mBootPerformanceTableTemplate
));
452 BootPerformanceData
= BootPerformanceData
+ mAcpiBootPerformanceTable
->Header
.Length
;
454 // Fill Boot records from boot drivers.
456 CopyMem (BootPerformanceData
, mBootRecordBuffer
, mBootRecordSize
);
457 mAcpiBootPerformanceTable
->Header
.Length
+= mBootRecordSize
;
458 BootPerformanceData
= BootPerformanceData
+ mBootRecordSize
;
459 if (SmmCommData
!= NULL
&& SmmCommData
->BootRecordData
!= NULL
) {
461 // Fill Boot records from SMM drivers.
463 CopyMem (BootPerformanceData
, SmmCommData
->BootRecordData
, SmmCommData
->BootRecordSize
);
464 FreePool (SmmCommData
->BootRecordData
);
465 mAcpiBootPerformanceTable
->Header
.Length
= (UINT32
) (mAcpiBootPerformanceTable
->Header
.Length
+ SmmCommData
->BootRecordSize
);
466 BootPerformanceData
= BootPerformanceData
+ SmmCommData
->BootRecordSize
;
468 if (SmmBootRecordCommBuffer
!= NULL
) {
469 FreePool (SmmBootRecordCommBuffer
);
473 // Save Boot Performance Table address to Variable for use in S4 resume.
475 PerformanceVariable
.BootPerformanceTablePointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) mAcpiBootPerformanceTable
;
477 // Update Boot Performance Table Pointer in template.
479 mFirmwarePerformanceTableTemplate
.BootPointerRecord
.BootPerformanceTablePointer
= (UINT64
) (UINTN
) mAcpiBootPerformanceTable
;
482 // Save S3 Performance Table address to Variable for use in S4 resume.
484 PerformanceVariable
.S3PerformanceTablePointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) mAcpiS3PerformanceTable
;
486 // Update S3 Performance Table Pointer in template.
488 mFirmwarePerformanceTableTemplate
.S3PointerRecord
.S3PerformanceTablePointer
= (UINT64
) (UINTN
) mAcpiS3PerformanceTable
;
490 // Save Runtime Performance Table pointers to Variable.
492 Status
= gRT
->SetVariable (
493 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
494 &gEfiFirmwarePerformanceGuid
,
495 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
496 sizeof (PerformanceVariable
),
499 ASSERT_EFI_ERROR (Status
);
502 // Publish Firmware Performance Data Table.
504 FpdtAcpiTableChecksum ((UINT8
*) &mFirmwarePerformanceTableTemplate
, mFirmwarePerformanceTableTemplate
.Header
.Length
);
505 Status
= AcpiTableProtocol
->InstallAcpiTable (
507 &mFirmwarePerformanceTableTemplate
,
508 mFirmwarePerformanceTableTemplate
.Header
.Length
,
509 &mFirmwarePerformanceTableTemplateKey
511 if (EFI_ERROR (Status
)) {
512 FreePages (mAcpiBootPerformanceTable
, EFI_SIZE_TO_PAGES (BootPerformanceDataSize
));
513 if (mAcpiS3PerformanceTable
!= NULL
) {
514 FreePages (mAcpiS3PerformanceTable
, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE
)));
516 mAcpiBootPerformanceTable
= NULL
;
517 mAcpiS3PerformanceTable
= NULL
;
522 // Free temp Boot record, and update Boot Record to point to Basic Boot performance table.
524 if (mBootRecordBuffer
!= NULL
) {
525 FreePool (mBootRecordBuffer
);
527 mBootRecordBuffer
= (UINT8
*) mAcpiBootPerformanceTable
;
528 mBootRecordSize
= mAcpiBootPerformanceTable
->Header
.Length
;
529 mBootRecordMaxSize
= mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
535 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
536 install the Firmware Performance Data Table.
538 @param[in] Event The Event that is being processed.
539 @param[in] Context The Event Context.
544 FpdtReadyToBootEventNotify (
549 if (mAcpiBootPerformanceTable
== NULL
) {
551 // ACPI Firmware Performance Data Table not installed yet, install it now.
553 InstallFirmwarePerformanceDataTable ();
558 Notify function for event group EFI_EVENT_LEGACY_BOOT_GUID. This is used to
559 record performance data for OsLoaderLoadImageStart in FPDT for legacy boot.
561 @param[in] Event The Event that is being processed.
562 @param[in] Context The Event Context.
567 FpdtLegacyBootEventNotify (
572 if (mAcpiBootPerformanceTable
== NULL
) {
574 // Firmware Performance Data Table not installed, do nothing.
580 // Update Firmware Basic Boot Performance Record for legacy boot.
582 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
= 0;
583 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
584 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
= 0;
585 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesExit
= 0;
588 // Dump FPDT Boot Performance record.
590 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ResetEnd
));
591 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderLoadImageStart = 0\n"));
592 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
));
593 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));
594 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));
598 Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
599 performance data for ExitBootServicesEntry in FPDT.
601 @param[in] Event The Event that is being processed.
602 @param[in] Context The Event Context.
607 FpdtExitBootServicesEventNotify (
612 if (mAcpiBootPerformanceTable
== NULL
) {
614 // Firmware Performance Data Table not installed, do nothing.
620 // Update Firmware Basic Boot Performance Record for UEFI boot.
622 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
= GetTimeInNanoSecond (GetPerformanceCounter ());
625 // Dump FPDT Boot Performance record.
627 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ResetEnd
));
628 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderLoadImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
));
629 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
));
630 DEBUG ((EFI_D_INFO
, "FPDT: Boot Performance - ExitBootServicesEntry = %ld\n", mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesEntry
));
632 // ExitBootServicesExit will be updated later, so don't dump it here.
637 Report status code listener of FPDT. This is used to collect performance data
638 for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.
640 @param[in] CodeType Indicates the type of status code being reported.
641 @param[in] Value Describes the current status of a hardware or software entity.
642 This included information about the class and subclass that is used to
643 classify the entity as well as an operation.
644 @param[in] Instance The enumeration of a hardware or software entity within
645 the system. Valid instance numbers start with 1.
646 @param[in] CallerId This optional parameter may be used to identify the caller.
647 This parameter allows the status code driver to apply different rules to
649 @param[in] Data This optional parameter may be used to pass additional data.
651 @retval EFI_SUCCESS Status code is what we expected.
652 @retval EFI_UNSUPPORTED Status code not supported.
657 FpdtStatusCodeListenerDxe (
658 IN EFI_STATUS_CODE_TYPE CodeType
,
659 IN EFI_STATUS_CODE_VALUE Value
,
661 IN EFI_GUID
*CallerId
,
662 IN EFI_STATUS_CODE_DATA
*Data
668 // Check whether status code is what we are interested in.
670 if ((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) != EFI_PROGRESS_CODE
) {
671 return EFI_UNSUPPORTED
;
674 Status
= EFI_SUCCESS
;
675 if (Value
== PcdGet32 (PcdProgressCodeOsLoaderLoad
)) {
677 // Progress code for OS Loader LoadImage.
679 if (mAcpiBootPerformanceTable
== NULL
) {
684 // Update OS Loader LoadImage Start for UEFI boot.
686 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderLoadImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
687 } else if (Value
== PcdGet32 (PcdProgressCodeOsLoaderStart
)) {
689 // Progress code for OS Loader StartImage.
691 if (mAcpiBootPerformanceTable
== NULL
) {
696 // Update OS Loader StartImage Start for UEFI boot.
698 mAcpiBootPerformanceTable
->BasicBoot
.OsLoaderStartImageStart
= GetTimeInNanoSecond (GetPerformanceCounter ());
699 } else if (Value
== (EFI_SOFTWARE_EFI_BOOT_SERVICE
| EFI_SW_BS_PC_EXIT_BOOT_SERVICES
)) {
701 // Progress code for ExitBootServices.
703 if (mAcpiBootPerformanceTable
== NULL
) {
708 // Update ExitBootServicesExit for UEFI boot.
710 mAcpiBootPerformanceTable
->BasicBoot
.ExitBootServicesExit
= GetTimeInNanoSecond (GetPerformanceCounter ());
713 // Unregister boot time report status code listener.
715 mRscHandlerProtocol
->Unregister (FpdtStatusCodeListenerDxe
);
716 } else if (Data
!= NULL
&& CompareGuid (&Data
->Type
, &gEfiFirmwarePerformanceGuid
)) {
718 // Append one or more Boot records
720 if (mAcpiBootPerformanceTable
== NULL
) {
722 // Append Boot records before FPDT ACPI table is installed.
724 if (mBootRecordSize
+ Data
->Size
> mBootRecordMaxSize
) {
725 mBootRecordBuffer
= ReallocatePool (mBootRecordSize
, mBootRecordSize
+ Data
->Size
+ EXTENSION_RECORD_SIZE
, mBootRecordBuffer
);
726 ASSERT (mBootRecordBuffer
!= NULL
);
727 mBootRecordMaxSize
= mBootRecordSize
+ Data
->Size
+ EXTENSION_RECORD_SIZE
;
730 // Save boot record into the temp memory space.
732 CopyMem (mBootRecordBuffer
+ mBootRecordSize
, Data
+ 1, Data
->Size
);
733 mBootRecordSize
+= Data
->Size
;
736 // Append Boot records after FPDT ACPI table is installed.
738 if (mBootRecordSize
+ Data
->Size
> mBootRecordMaxSize
) {
740 // No enough space to save boot record.
742 Status
= EFI_OUT_OF_RESOURCES
;
745 // Save boot record into BootPerformance table
747 CopyMem (mBootRecordBuffer
+ mBootRecordSize
, Data
+ 1, Data
->Size
);
748 mBootRecordSize
+= Data
->Size
;
749 mAcpiBootPerformanceTable
->Header
.Length
= mBootRecordSize
;
754 // Ignore else progress code.
756 Status
= EFI_UNSUPPORTED
;
763 The module Entry Point of the Firmware Performance Data Table DXE driver.
765 @param[in] ImageHandle The firmware allocated handle for the EFI image.
766 @param[in] SystemTable A pointer to the EFI System Table.
768 @retval EFI_SUCCESS The entry point is executed successfully.
769 @retval Other Some error occurs when executing this entry point.
774 FirmwarePerformanceDxeEntryPoint (
775 IN EFI_HANDLE ImageHandle
,
776 IN EFI_SYSTEM_TABLE
*SystemTable
780 EFI_HOB_GUID_TYPE
*GuidHob
;
781 FIRMWARE_SEC_PERFORMANCE
*Performance
;
786 mFirmwarePerformanceTableTemplate
.Header
.OemId
,
787 PcdGetPtr (PcdAcpiDefaultOemId
),
788 sizeof (mFirmwarePerformanceTableTemplate
.Header
.OemId
)
790 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
791 CopyMem (&mFirmwarePerformanceTableTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
792 mFirmwarePerformanceTableTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
793 mFirmwarePerformanceTableTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
794 mFirmwarePerformanceTableTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
797 // Get Report Status Code Handler Protocol.
799 Status
= gBS
->LocateProtocol (&gEfiRscHandlerProtocolGuid
, NULL
, (VOID
**) &mRscHandlerProtocol
);
800 ASSERT_EFI_ERROR (Status
);
803 // Register report status code listener for OS Loader load and start.
805 Status
= mRscHandlerProtocol
->Register (FpdtStatusCodeListenerDxe
, TPL_HIGH_LEVEL
);
806 ASSERT_EFI_ERROR (Status
);
809 // Register the notify function to update FPDT on ExitBootServices Event.
811 Status
= gBS
->CreateEventEx (
814 FpdtExitBootServicesEventNotify
,
816 &gEfiEventExitBootServicesGuid
,
817 &mExitBootServicesEvent
819 ASSERT_EFI_ERROR (Status
);
822 // Create ready to boot event to install ACPI FPDT table.
824 Status
= gBS
->CreateEventEx (
827 FpdtReadyToBootEventNotify
,
829 &gEfiEventReadyToBootGuid
,
832 ASSERT_EFI_ERROR (Status
);
835 // Create legacy boot event to log OsLoaderStartImageStart for legacy boot.
837 Status
= gBS
->CreateEventEx (
840 FpdtLegacyBootEventNotify
,
842 &gEfiEventLegacyBootGuid
,
845 ASSERT_EFI_ERROR (Status
);
848 // Retrieve GUID HOB data that contains the ResetEnd.
850 GuidHob
= GetFirstGuidHob (&gEfiFirmwarePerformanceGuid
);
851 if (GuidHob
!= NULL
) {
852 Performance
= (FIRMWARE_SEC_PERFORMANCE
*) GET_GUID_HOB_DATA (GuidHob
);
853 mBootPerformanceTableTemplate
.BasicBoot
.ResetEnd
= Performance
->ResetEnd
;
856 // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.
858 DEBUG ((EFI_D_ERROR
, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));
861 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support
)) {
863 // Register callback function upon VariableArchProtocol and LockBoxProtocol
864 // to allocate S3 performance table memory and save the pointer to LockBox.
866 EfiCreateProtocolNotifyEvent (
867 &gEfiVariableArchProtocolGuid
,
869 FpdtAllocateS3PerformanceTableMemory
,
873 EfiCreateProtocolNotifyEvent (
874 &gEfiLockBoxProtocolGuid
,
876 FpdtAllocateS3PerformanceTableMemory
,
882 // Exclude S3 Performance Table Pointer from FPDT table template.
884 mFirmwarePerformanceTableTemplate
.Header
.Length
-= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD
);