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