]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c
Update Code to pass EBC compiler.
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / FirmwarePerformanceDataTableDxe / FirmwarePerformanceDxe.c
1 /** @file
2 This module install ACPI Firmware Performance Data Table (FPDT).
3
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.
7
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
13
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.
16
17 **/
18
19 #include <PiDxe.h>
20
21 #include <Protocol/ReportStatusCodeHandler.h>
22 #include <Protocol/AcpiTable.h>
23 #include <Protocol/SmmCommunication.h>
24
25 #include <Guid/Acpi.h>
26 #include <Guid/FirmwarePerformance.h>
27 #include <Guid/EventGroup.h>
28 #include <Guid/EventLegacyBios.h>
29
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>
40
41 //
42 // ACPI table information used to initialize tables.
43 //
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)
51
52 EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
53
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;
61
62 BOOT_PERFORMANCE_TABLE *mAcpiBootPerformanceTable = NULL;
63 S3_PERFORMANCE_TABLE *mAcpiS3PerformanceTable = NULL;
64
65 FIRMWARE_PERFORMANCE_TABLE mFirmwarePerformanceTableTemplate = {
66 {
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
71 //
72 // It is expected that these values will be updated at runtime.
73 //
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
79 },
80 //
81 // Firmware Basic Boot Performance Table Pointer Record.
82 //
83 {
84 {
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
88 },
89 0, // Reserved
90 0 // BootPerformanceTablePointer will be updated at runtime.
91 },
92 //
93 // S3 Performance Table Pointer Record.
94 //
95 {
96 {
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
100 },
101 0, // Reserved
102 0 // S3PerformanceTablePointer will be updated at runtime.
103 }
104 };
105
106 BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate = {
107 {
108 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE,
109 sizeof (BOOT_PERFORMANCE_TABLE)
110 },
111 {
112 {
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
116 },
117 0, // Reserved
118 //
119 // These values will be updated at runtime.
120 //
121 0, // ResetEnd
122 0, // OsLoaderLoadImageStart
123 0, // OsLoaderStartImageStart
124 0, // ExitBootServicesEntry
125 0 // ExitBootServicesExit
126 }
127 };
128
129 S3_PERFORMANCE_TABLE mS3PerformanceTableTemplate = {
130 {
131 EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE,
132 sizeof (S3_PERFORMANCE_TABLE)
133 },
134 {
135 {
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
139 },
140 //
141 // These values will be updated by Firmware Performance PEIM.
142 //
143 0, // ResumeCount
144 0, // FullResume
145 0 // AverageResume
146 },
147 {
148 {
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
152 },
153 //
154 // These values will be updated bye Firmware Performance SMM driver.
155 //
156 0, // SuspendStart
157 0 // SuspendEnd
158 }
159 };
160
161 /**
162 This function calculates and updates an UINT8 checksum.
163
164 @param[in] Buffer Pointer to buffer to checksum
165 @param[in] Size Number of bytes to checksum
166
167 **/
168 VOID
169 FpdtAcpiTableChecksum (
170 IN UINT8 *Buffer,
171 IN UINTN Size
172 )
173 {
174 UINTN ChecksumOffset;
175
176 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
177
178 //
179 // Set checksum to 0 first.
180 //
181 Buffer[ChecksumOffset] = 0;
182
183 //
184 // Update checksum value.
185 //
186 Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);
187 }
188
189 /**
190 Allocate EfiReservedMemoryType below 4G memory address.
191
192 This function allocates EfiReservedMemoryType below 4G memory address.
193
194 @param[in] Size Size of memory to allocate.
195
196 @return Allocated address for output.
197
198 **/
199 VOID *
200 FpdtAllocateReservedMemoryBelow4G (
201 IN UINTN Size
202 )
203 {
204 UINTN Pages;
205 EFI_PHYSICAL_ADDRESS Address;
206 EFI_STATUS Status;
207 VOID *Buffer;
208
209 Pages = EFI_SIZE_TO_PAGES (Size);
210 Address = 0xffffffff;
211
212 Status = gBS->AllocatePages (
213 AllocateMaxAddress,
214 EfiReservedMemoryType,
215 Pages,
216 &Address
217 );
218 ASSERT_EFI_ERROR (Status);
219
220 Buffer = (VOID *) (UINTN) Address;
221 ZeroMem (Buffer, Size);
222
223 return Buffer;
224 }
225
226 /**
227 Install ACPI Firmware Performance Data Table (FPDT).
228
229 @return Status code.
230
231 **/
232 EFI_STATUS
233 InstallFirmwarePerformanceDataTable (
234 VOID
235 )
236 {
237 EFI_STATUS Status;
238 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
239 EFI_PHYSICAL_ADDRESS Address;
240 UINTN Size;
241 UINT8 *SmmBootRecordCommBuffer;
242 EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;
243 SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
244 UINTN CommSize;
245 UINTN PerformanceRuntimeDataSize;
246 UINT8 *PerformanceRuntimeData;
247 UINT8 *PerformanceRuntimeDataHead;
248 EFI_SMM_COMMUNICATION_PROTOCOL *Communication;
249 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
250
251 //
252 // Get AcpiTable Protocol.
253 //
254 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
255 if (EFI_ERROR (Status)) {
256 return Status;
257 }
258
259 //
260 // Collect boot records from SMM drivers.
261 //
262 SmmBootRecordCommBuffer = AllocateZeroPool (SMM_BOOT_RECORD_COMM_SIZE);
263 ASSERT (SmmBootRecordCommBuffer != NULL);
264 SmmCommData = NULL;
265 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
266 if (!EFI_ERROR (Status)) {
267 //
268 // Initialize communicate buffer
269 //
270 SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer;
271 SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data;
272 ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE));
273
274 CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
275 SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE);
276 CommSize = SMM_BOOT_RECORD_COMM_SIZE;
277
278 //
279 // Get the size of boot records.
280 //
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);
285
286 if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) {
287 //
288 // Get all boot records
289 //
290 SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA;
291 SmmCommData->BootRecordData = AllocateZeroPool(SmmCommData->BootRecordSize);
292 ASSERT (SmmCommData->BootRecordData != NULL);
293
294 Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
295 ASSERT_EFI_ERROR (Status);
296 ASSERT_EFI_ERROR(SmmCommData->ReturnStatus);
297 }
298 }
299 FreePool (SmmBootRecordCommBuffer);
300
301 //
302 // Prepare memory for runtime Performance Record.
303 // Runtime performance records includes two tables S3 performance table and Boot performance table.
304 // S3 Performance table includes S3Resume and S3Suspend records.
305 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
306 //
307 PerformanceRuntimeData = NULL;
308 PerformanceRuntimeDataSize = sizeof (S3_PERFORMANCE_TABLE) + sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
309 if (SmmCommData != NULL) {
310 PerformanceRuntimeDataSize += SmmCommData->BootRecordSize;
311 }
312
313 //
314 // Try to allocate the same runtime buffer as last time boot.
315 //
316 ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));
317 Size = sizeof (PerformanceVariable);
318 Status = gRT->GetVariable (
319 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
320 &gEfiFirmwarePerformanceGuid,
321 NULL,
322 &Size,
323 &PerformanceVariable
324 );
325 if (!EFI_ERROR (Status)) {
326 Address = PerformanceVariable.S3PerformanceTablePointer;
327 Status = gBS->AllocatePages (
328 AllocateAddress,
329 EfiReservedMemoryType,
330 EFI_SIZE_TO_PAGES (PerformanceRuntimeDataSize),
331 &Address
332 );
333 if (!EFI_ERROR (Status)) {
334 PerformanceRuntimeData = (UINT8 *) (UINTN) Address;
335 }
336 }
337
338 if (PerformanceRuntimeData == NULL) {
339 //
340 // Fail to allocate at specified address, continue to allocate at any address.
341 //
342 PerformanceRuntimeData = FpdtAllocateReservedMemoryBelow4G (PerformanceRuntimeDataSize);
343 }
344 DEBUG ((EFI_D_INFO, "FPDT: Performance Runtime Data address = 0x%x\n", PerformanceRuntimeData));
345
346 if (PerformanceRuntimeData == NULL) {
347 if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
348 FreePool (SmmCommData->BootRecordData);
349 }
350 return EFI_OUT_OF_RESOURCES;
351 }
352
353 PerformanceRuntimeDataHead = PerformanceRuntimeData;
354
355 if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {
356 //
357 // Prepare S3 Performance Table.
358 //
359 mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) PerformanceRuntimeData;
360 CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));
361 PerformanceRuntimeData = PerformanceRuntimeData + mAcpiS3PerformanceTable->Header.Length;
362 DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable));
363 //
364 // Save S3 Performance Table address to Variable for use in Firmware Performance PEIM.
365 //
366 PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;
367 //
368 // Update S3 Performance Table Pointer in template.
369 //
370 mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) PerformanceVariable.S3PerformanceTablePointer;
371 } else {
372 //
373 // Exclude S3 Performance Table Pointer from FPDT table template.
374 //
375 mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);
376 }
377
378 //
379 // Prepare Boot Performance Table.
380 //
381 mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) PerformanceRuntimeData;
382 //
383 // Fill Basic Boot record to Boot Performance Table.
384 //
385 CopyMem (PerformanceRuntimeData, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
386 PerformanceRuntimeData = PerformanceRuntimeData + mAcpiBootPerformanceTable->Header.Length;
387 //
388 // Fill Boot records from boot drivers.
389 //
390 CopyMem (PerformanceRuntimeData, mBootRecordBuffer, mBootRecordSize);
391 mAcpiBootPerformanceTable->Header.Length += mBootRecordSize;
392 PerformanceRuntimeData = PerformanceRuntimeData + mBootRecordSize;
393 if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
394 //
395 // Fill Boot records from SMM drivers.
396 //
397 CopyMem (PerformanceRuntimeData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
398 FreePool (SmmCommData->BootRecordData);
399 mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize);
400 PerformanceRuntimeData = PerformanceRuntimeData + SmmCommData->BootRecordSize;
401 }
402 //
403 // Reserve space for boot records after ReadyToBoot.
404 //
405 PerformanceRuntimeData = PerformanceRuntimeData + PcdGet32 (PcdExtFpdtBootRecordPadSize);
406 DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));
407 //
408 // Save Boot Performance Table address to Variable for use in S4 resume.
409 //
410 PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable;
411 //
412 // Update Boot Performance Table Pointer in template.
413 //
414 mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;
415
416 //
417 // Save Runtime Performance Table pointers to Variable.
418 //
419 Status = gRT->SetVariable (
420 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
421 &gEfiFirmwarePerformanceGuid,
422 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
423 sizeof (PerformanceVariable),
424 &PerformanceVariable
425 );
426 ASSERT_EFI_ERROR (Status);
427
428 //
429 // Publish Firmware Performance Data Table.
430 //
431 FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length);
432 Status = AcpiTableProtocol->InstallAcpiTable (
433 AcpiTableProtocol,
434 &mFirmwarePerformanceTableTemplate,
435 mFirmwarePerformanceTableTemplate.Header.Length,
436 &mFirmwarePerformanceTableTemplateKey
437 );
438 if (EFI_ERROR (Status)) {
439 FreePool (PerformanceRuntimeDataHead);
440 mAcpiBootPerformanceTable = NULL;
441 mAcpiS3PerformanceTable = NULL;
442 return Status;
443 }
444
445 //
446 // Free temp Boot record, and update Boot Record to point to Basic Boot performance table.
447 //
448 if (mBootRecordBuffer != NULL) {
449 FreePool (mBootRecordBuffer);
450 }
451 mBootRecordBuffer = (UINT8 *) mAcpiBootPerformanceTable;
452 mBootRecordSize = mAcpiBootPerformanceTable->Header.Length;
453 mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
454
455 return EFI_SUCCESS;
456 }
457
458 /**
459 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
460 install the Firmware Performance Data Table.
461
462 @param[in] Event The Event that is being processed.
463 @param[in] Context The Event Context.
464
465 **/
466 VOID
467 EFIAPI
468 FpdtReadyToBootEventNotify (
469 IN EFI_EVENT Event,
470 IN VOID *Context
471 )
472 {
473 if (mAcpiBootPerformanceTable == NULL) {
474 //
475 // ACPI Firmware Performance Data Table not installed yet, install it now.
476 //
477 InstallFirmwarePerformanceDataTable ();
478 }
479 }
480
481 /**
482 Notify function for event group EFI_EVENT_LEGACY_BOOT_GUID. This is used to
483 record performance data for OsLoaderLoadImageStart in FPDT for legacy boot.
484
485 @param[in] Event The Event that is being processed.
486 @param[in] Context The Event Context.
487
488 **/
489 VOID
490 EFIAPI
491 FpdtLegacyBootEventNotify (
492 IN EFI_EVENT Event,
493 IN VOID *Context
494 )
495 {
496 if (mAcpiBootPerformanceTable == NULL) {
497 //
498 // Firmware Performance Data Table not installed, do nothing.
499 //
500 return ;
501 }
502
503 //
504 // Update Firmware Basic Boot Performance Record for legacy boot.
505 //
506 mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = 0;
507 mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
508 mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = 0;
509 mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = 0;
510
511 //
512 // Dump FPDT Boot Performance record.
513 //
514 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));
515 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = 0\n"));
516 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));
517 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));
518 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));
519 }
520
521 /**
522 Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
523 performance data for ExitBootServicesEntry in FPDT.
524
525 @param[in] Event The Event that is being processed.
526 @param[in] Context The Event Context.
527
528 **/
529 VOID
530 EFIAPI
531 FpdtExitBootServicesEventNotify (
532 IN EFI_EVENT Event,
533 IN VOID *Context
534 )
535 {
536 if (mAcpiBootPerformanceTable == NULL) {
537 //
538 // Firmware Performance Data Table not installed, do nothing.
539 //
540 return ;
541 }
542
543 //
544 // Update Firmware Basic Boot Performance Record for UEFI boot.
545 //
546 mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());
547
548 //
549 // Dump FPDT Boot Performance record.
550 //
551 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));
552 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));
553 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));
554 DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));
555 //
556 // ExitBootServicesExit will be updated later, so don't dump it here.
557 //
558 }
559
560 /**
561 Report status code listener of FPDT. This is used to collect performance data
562 for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.
563
564 @param[in] CodeType Indicates the type of status code being reported.
565 @param[in] Value Describes the current status of a hardware or software entity.
566 This included information about the class and subclass that is used to
567 classify the entity as well as an operation.
568 @param[in] Instance The enumeration of a hardware or software entity within
569 the system. Valid instance numbers start with 1.
570 @param[in] CallerId This optional parameter may be used to identify the caller.
571 This parameter allows the status code driver to apply different rules to
572 different callers.
573 @param[in] Data This optional parameter may be used to pass additional data.
574
575 @retval EFI_SUCCESS Status code is what we expected.
576 @retval EFI_UNSUPPORTED Status code not supported.
577
578 **/
579 EFI_STATUS
580 EFIAPI
581 FpdtStatusCodeListenerDxe (
582 IN EFI_STATUS_CODE_TYPE CodeType,
583 IN EFI_STATUS_CODE_VALUE Value,
584 IN UINT32 Instance,
585 IN EFI_GUID *CallerId,
586 IN EFI_STATUS_CODE_DATA *Data
587 )
588 {
589 EFI_STATUS Status;
590
591 //
592 // Check whether status code is what we are interested in.
593 //
594 if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {
595 return EFI_UNSUPPORTED;
596 }
597
598 Status = EFI_SUCCESS;
599 if (Value == PcdGet32 (PcdProgressCodeOsLoaderLoad)) {
600 //
601 // Progress code for OS Loader LoadImage.
602 //
603 if (mAcpiBootPerformanceTable == NULL) {
604 return Status;
605 }
606
607 //
608 // Update OS Loader LoadImage Start for UEFI boot.
609 //
610 mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
611 } else if (Value == PcdGet32 (PcdProgressCodeOsLoaderStart)) {
612 //
613 // Progress code for OS Loader StartImage.
614 //
615 if (mAcpiBootPerformanceTable == NULL) {
616 return Status;
617 }
618
619 //
620 // Update OS Loader StartImage Start for UEFI boot.
621 //
622 mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
623 } else if (Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) {
624 //
625 // Progress code for ExitBootServices.
626 //
627 if (mAcpiBootPerformanceTable == NULL) {
628 return Status;
629 }
630
631 //
632 // Update ExitBootServicesExit for UEFI boot.
633 //
634 mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = GetTimeInNanoSecond (GetPerformanceCounter ());
635
636 //
637 // Unregister boot time report status code listener.
638 //
639 mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);
640 } else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
641 //
642 // Append one or more Boot records
643 //
644 if (mAcpiBootPerformanceTable == NULL) {
645 //
646 // Append Boot records before FPDT ACPI table is installed.
647 //
648 if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
649 mBootRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer);
650 ASSERT (mBootRecordBuffer != NULL);
651 mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE;
652 }
653 //
654 // Save boot record into the temp memory space.
655 //
656 CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
657 mBootRecordSize += Data->Size;
658 } else {
659 //
660 // Append Boot records after FPDT ACPI table is installed.
661 //
662 if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
663 //
664 // No enough space to save boot record.
665 //
666 Status = EFI_OUT_OF_RESOURCES;
667 } else {
668 //
669 // Save boot record into BootPerformance table
670 //
671 CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
672 mBootRecordSize += Data->Size;
673 mAcpiBootPerformanceTable->Header.Length = mBootRecordSize;
674 }
675 }
676 } else {
677 //
678 // Ignore else progress code.
679 //
680 Status = EFI_UNSUPPORTED;
681 }
682
683 return Status;
684 }
685
686 /**
687 The module Entry Point of the Firmware Performance Data Table DXE driver.
688
689 @param[in] ImageHandle The firmware allocated handle for the EFI image.
690 @param[in] SystemTable A pointer to the EFI System Table.
691
692 @retval EFI_SUCCESS The entry point is executed successfully.
693 @retval Other Some error occurs when executing this entry point.
694
695 **/
696 EFI_STATUS
697 EFIAPI
698 FirmwarePerformanceDxeEntryPoint (
699 IN EFI_HANDLE ImageHandle,
700 IN EFI_SYSTEM_TABLE *SystemTable
701 )
702 {
703 EFI_STATUS Status;
704 EFI_HOB_GUID_TYPE *GuidHob;
705 FIRMWARE_SEC_PERFORMANCE *Performance;
706
707 //
708 // Get Report Status Code Handler Protocol.
709 //
710 Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mRscHandlerProtocol);
711 ASSERT_EFI_ERROR (Status);
712
713 //
714 // Register report status code listener for OS Loader load and start.
715 //
716 Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerDxe, TPL_HIGH_LEVEL);
717 ASSERT_EFI_ERROR (Status);
718
719 //
720 // Register the notify function to update FPDT on ExitBootServices Event.
721 //
722 Status = gBS->CreateEventEx (
723 EVT_NOTIFY_SIGNAL,
724 TPL_NOTIFY,
725 FpdtExitBootServicesEventNotify,
726 NULL,
727 &gEfiEventExitBootServicesGuid,
728 &mExitBootServicesEvent
729 );
730 ASSERT_EFI_ERROR (Status);
731
732 //
733 // Create ready to boot event to install ACPI FPDT table.
734 //
735 Status = gBS->CreateEventEx (
736 EVT_NOTIFY_SIGNAL,
737 TPL_NOTIFY,
738 FpdtReadyToBootEventNotify,
739 NULL,
740 &gEfiEventReadyToBootGuid,
741 &mReadyToBootEvent
742 );
743 ASSERT_EFI_ERROR (Status);
744
745 //
746 // Create legacy boot event to log OsLoaderStartImageStart for legacy boot.
747 //
748 Status = gBS->CreateEventEx (
749 EVT_NOTIFY_SIGNAL,
750 TPL_NOTIFY,
751 FpdtLegacyBootEventNotify,
752 NULL,
753 &gEfiEventLegacyBootGuid,
754 &mLegacyBootEvent
755 );
756 ASSERT_EFI_ERROR (Status);
757
758 //
759 // Retrieve GUID HOB data that contains the ResetEnd.
760 //
761 GuidHob = GetFirstGuidHob (&gEfiFirmwarePerformanceGuid);
762 if (GuidHob != NULL) {
763 Performance = (FIRMWARE_SEC_PERFORMANCE *) GET_GUID_HOB_DATA (GuidHob);
764 mBootPerformanceTableTemplate.BasicBoot.ResetEnd = Performance->ResetEnd;
765 } else {
766 //
767 // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.
768 //
769 DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));
770 }
771
772 return EFI_SUCCESS;
773 }