]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
8363b0e4ed5ceae5acbaabb687a6cd63fefba5d3
[mirror_edk2.git] / MdeModulePkg / Library / DxeCorePerformanceLib / DxeCorePerformanceLib.c
1 /** @file
2 Performance library instance mainly used by DxeCore.
3
4 This library provides the performance measurement interfaces and initializes performance
5 logging for DXE phase. It first initializes its private global data structure for
6 performance logging and saves the performance GUIDed HOB passed from PEI phase.
7 It initializes DXE phase performance logging by publishing the Performance and PerformanceEx Protocol,
8 which are consumed by DxePerformanceLib to logging performance data in DXE phase.
9
10 This library is mainly used by DxeCore to start performance logging to ensure that
11 Performance Protocol is installed at the very beginning of DXE phase.
12
13 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
14 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
15 This program and the accompanying materials
16 are licensed and made available under the terms and conditions of the BSD License
17 which accompanies this distribution. The full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
19
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
21 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22
23 **/
24
25
26 #include "DxeCorePerformanceLibInternal.h"
27
28 //
29 // Data for FPDT performance records.
30 //
31 #define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))
32 #define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
33 #define FIRMWARE_RECORD_BUFFER 0x10000
34 #define CACHE_HANDLE_GUID_COUNT 0x800
35
36 BOOT_PERFORMANCE_TABLE *mAcpiBootPerformanceTable = NULL;
37 BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate = {
38 {
39 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE,
40 sizeof (BOOT_PERFORMANCE_TABLE)
41 },
42 {
43 {
44 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT, // Type
45 sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD), // Length
46 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT // Revision
47 },
48 0, // Reserved
49 //
50 // These values will be updated at runtime.
51 //
52 0, // ResetEnd
53 0, // OsLoaderLoadImageStart
54 0, // OsLoaderStartImageStart
55 0, // ExitBootServicesEntry
56 0 // ExitBootServicesExit
57 }
58 };
59
60 typedef struct {
61 EFI_HANDLE Handle;
62 CHAR8 NameString[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
63 EFI_GUID ModuleGuid;
64 } HANDLE_GUID_MAP;
65
66 HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];
67 UINTN mCachePairCount = 0;
68
69 UINT32 mLoadImageCount = 0;
70 UINT32 mPerformanceLength = 0;
71 UINT32 mMaxPerformanceLength = 0;
72 UINT32 mBootRecordSize = 0;
73 UINT32 mBootRecordMaxSize = 0;
74
75 BOOLEAN mFpdtBufferIsReported = FALSE;
76 BOOLEAN mLackSpaceIsReported = FALSE;
77 CHAR8 *mPlatformLanguage = NULL;
78 UINT8 *mPerformancePointer = NULL;
79 UINT8 *mBootRecordBuffer = NULL;
80 BOOLEAN mLockInsertRecord = FALSE;
81
82 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevicePathToText = NULL;
83
84 //
85 // Interfaces for Performance Protocol.
86 //
87 PERFORMANCE_PROTOCOL mPerformanceInterface = {
88 StartGauge,
89 EndGauge,
90 GetGauge
91 };
92
93 //
94 // Interfaces for PerformanceEx Protocol.
95 //
96 PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {
97 StartGaugeEx,
98 EndGaugeEx,
99 GetGaugeEx
100 };
101
102 PERFORMANCE_PROPERTY mPerformanceProperty;
103
104 /**
105 Check whether the Token is a known one which is uesed by core.
106
107 @param Token Pointer to a Null-terminated ASCII string
108
109 @retval TRUE Is a known one used by core.
110 @retval FALSE Not a known one.
111
112 **/
113 BOOLEAN
114 IsKnownTokens (
115 IN CONST CHAR8 *Token
116 )
117 {
118 if (AsciiStrCmp (Token, SEC_TOK) == 0 ||
119 AsciiStrCmp (Token, PEI_TOK) == 0 ||
120 AsciiStrCmp (Token, DXE_TOK) == 0 ||
121 AsciiStrCmp (Token, BDS_TOK) == 0 ||
122 AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0 ||
123 AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0 ||
124 AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0 ||
125 AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0 ||
126 AsciiStrCmp (Token, START_IMAGE_TOK) == 0 ||
127 AsciiStrCmp (Token, PEIM_TOK) == 0) {
128 return TRUE;
129 } else {
130 return FALSE;
131 }
132 }
133
134 /**
135 Check whether the ID is a known one which map to the known Token.
136
137 @param Identifier 32-bit identifier.
138
139 @retval TRUE Is a known one used by core.
140 @retval FALSE Not a known one.
141
142 **/
143 BOOLEAN
144 IsKnownID (
145 IN UINT32 Identifier
146 )
147 {
148 if (Identifier == MODULE_START_ID ||
149 Identifier == MODULE_END_ID ||
150 Identifier == MODULE_LOADIMAGE_START_ID ||
151 Identifier == MODULE_LOADIMAGE_END_ID ||
152 Identifier == MODULE_DB_START_ID ||
153 Identifier == MODULE_DB_END_ID ||
154 Identifier == MODULE_DB_SUPPORT_START_ID ||
155 Identifier == MODULE_DB_SUPPORT_END_ID ||
156 Identifier == MODULE_DB_STOP_START_ID ||
157 Identifier == MODULE_DB_STOP_END_ID) {
158 return TRUE;
159 } else {
160 return FALSE;
161 }
162 }
163
164 /**
165 Allocate EfiReservedMemoryType below 4G memory address.
166
167 This function allocates EfiReservedMemoryType below 4G memory address.
168
169 @param[in] Size Size of memory to allocate.
170
171 @return Allocated address for output.
172
173 **/
174 VOID *
175 FpdtAllocateReservedMemoryBelow4G (
176 IN UINTN Size
177 )
178 {
179 UINTN Pages;
180 EFI_PHYSICAL_ADDRESS Address;
181 EFI_STATUS Status;
182 VOID *Buffer;
183
184 Buffer = NULL;
185 Pages = EFI_SIZE_TO_PAGES (Size);
186 Address = 0xffffffff;
187
188 Status = gBS->AllocatePages (
189 AllocateMaxAddress,
190 EfiReservedMemoryType,
191 Pages,
192 &Address
193 );
194 ASSERT_EFI_ERROR (Status);
195
196 if (!EFI_ERROR (Status)) {
197 Buffer = (VOID *) (UINTN) Address;
198 ZeroMem (Buffer, Size);
199 }
200
201 return Buffer;
202 }
203
204 /**
205 Allocate buffer for Boot Performance table.
206
207 @return Status code.
208
209 **/
210 EFI_STATUS
211 AllocateBootPerformanceTable (
212 )
213 {
214 EFI_STATUS Status;
215 UINTN Size;
216 UINT8 *SmmBootRecordCommBuffer;
217 EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;
218 SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
219 UINTN CommSize;
220 UINTN BootPerformanceDataSize;
221 UINT8 *BootPerformanceData;
222 EFI_SMM_COMMUNICATION_PROTOCOL *Communication;
223 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
224 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *SmmCommRegionTable;
225 EFI_MEMORY_DESCRIPTOR *SmmCommMemRegion;
226 UINTN Index;
227 VOID *SmmBootRecordData;
228 UINTN SmmBootRecordDataSize;
229 UINTN ReservedMemSize;
230
231 //
232 // Collect boot records from SMM drivers.
233 //
234 SmmBootRecordCommBuffer = NULL;
235 SmmCommData = NULL;
236 SmmBootRecordData = NULL;
237 SmmBootRecordDataSize = 0;
238 ReservedMemSize = 0;
239 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
240 if (!EFI_ERROR (Status)) {
241 //
242 // Initialize communicate buffer
243 // Get the prepared Reserved Memory Range
244 //
245 Status = EfiGetSystemConfigurationTable (
246 &gEdkiiPiSmmCommunicationRegionTableGuid,
247 (VOID **) &SmmCommRegionTable
248 );
249 if (!EFI_ERROR (Status)) {
250 ASSERT (SmmCommRegionTable != NULL);
251 SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) (SmmCommRegionTable + 1);
252 for (Index = 0; Index < SmmCommRegionTable->NumberOfEntries; Index ++) {
253 if (SmmCommMemRegion->Type == EfiConventionalMemory) {
254 break;
255 }
256 SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) SmmCommMemRegion + SmmCommRegionTable->DescriptorSize);
257 }
258 ASSERT (Index < SmmCommRegionTable->NumberOfEntries);
259 ASSERT (SmmCommMemRegion->PhysicalStart > 0);
260 ASSERT (SmmCommMemRegion->NumberOfPages > 0);
261 ReservedMemSize = (UINTN) SmmCommMemRegion->NumberOfPages * EFI_PAGE_SIZE;
262
263 //
264 // Check enough reserved memory space
265 //
266 if (ReservedMemSize > SMM_BOOT_RECORD_COMM_SIZE) {
267 SmmBootRecordCommBuffer = (VOID *) (UINTN) SmmCommMemRegion->PhysicalStart;
268 SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer;
269 SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data;
270 ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE));
271
272 CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
273 SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE);
274 CommSize = SMM_BOOT_RECORD_COMM_SIZE;
275
276 //
277 // Get the size of boot records.
278 //
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);
283
284 if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) {
285 //
286 // Get all boot records
287 //
288 SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET;
289 SmmBootRecordDataSize = SmmCommData->BootRecordSize;
290 SmmBootRecordData = AllocateZeroPool(SmmBootRecordDataSize);
291 ASSERT (SmmBootRecordData != NULL);
292 SmmCommData->BootRecordOffset = 0;
293 SmmCommData->BootRecordData = (VOID *) ((UINTN) SmmCommMemRegion->PhysicalStart + SMM_BOOT_RECORD_COMM_SIZE);
294 SmmCommData->BootRecordSize = ReservedMemSize - SMM_BOOT_RECORD_COMM_SIZE;
295 while (SmmCommData->BootRecordOffset < SmmBootRecordDataSize) {
296 Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
297 ASSERT_EFI_ERROR (Status);
298 ASSERT_EFI_ERROR(SmmCommData->ReturnStatus);
299 if (SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize > SmmBootRecordDataSize) {
300 CopyMem ((UINT8 *) SmmBootRecordData + SmmCommData->BootRecordOffset, SmmCommData->BootRecordData, SmmBootRecordDataSize - SmmCommData->BootRecordOffset);
301 } else {
302 CopyMem ((UINT8 *) SmmBootRecordData + SmmCommData->BootRecordOffset, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
303 }
304 SmmCommData->BootRecordOffset = SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize;
305 }
306 }
307 }
308 }
309 }
310
311 //
312 // Prepare memory for Boot Performance table.
313 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
314 //
315 BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mPerformanceLength + PcdGet32 (PcdExtFpdtBootRecordPadSize);
316 if (SmmCommData != NULL) {
317 BootPerformanceDataSize += SmmBootRecordDataSize;
318 }
319
320 //
321 // Try to allocate the same runtime buffer as last time boot.
322 //
323 ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));
324 Size = sizeof (PerformanceVariable);
325 Status = gRT->GetVariable (
326 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
327 &gEfiFirmwarePerformanceGuid,
328 NULL,
329 &Size,
330 &PerformanceVariable
331 );
332 if (!EFI_ERROR (Status)) {
333 Status = gBS->AllocatePages (
334 AllocateAddress,
335 EfiReservedMemoryType,
336 EFI_SIZE_TO_PAGES (BootPerformanceDataSize),
337 &PerformanceVariable.BootPerformanceTablePointer
338 );
339 if (!EFI_ERROR (Status)) {
340 mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer;
341 }
342 }
343
344 if (mAcpiBootPerformanceTable == NULL) {
345 //
346 // Fail to allocate at specified address, continue to allocate at any address.
347 //
348 mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize);
349 }
350 DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));
351
352 if (mAcpiBootPerformanceTable == NULL) {
353 if (SmmCommData != NULL && SmmBootRecordData != NULL) {
354 FreePool (SmmBootRecordData);
355 }
356 return EFI_OUT_OF_RESOURCES;
357 }
358
359 //
360 // Prepare Boot Performance Table.
361 //
362 BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable;
363 //
364 // Fill Basic Boot record to Boot Performance Table.
365 //
366 CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
367 BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length;
368 //
369 // Fill Boot records from boot drivers.
370 //
371 if (mPerformancePointer != NULL) {
372 CopyMem (BootPerformanceData, mPerformancePointer, mPerformanceLength);
373 mAcpiBootPerformanceTable->Header.Length += mPerformanceLength;
374 BootPerformanceData = BootPerformanceData + mPerformanceLength;
375 FreePool (mPerformancePointer);
376 mPerformancePointer = NULL;
377 mPerformanceLength = 0;
378 mMaxPerformanceLength = 0;
379 }
380 if (SmmCommData != NULL && SmmBootRecordData != NULL) {
381 //
382 // Fill Boot records from SMM drivers.
383 //
384 CopyMem (BootPerformanceData, SmmBootRecordData, SmmBootRecordDataSize);
385 FreePool (SmmBootRecordData);
386 mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmBootRecordDataSize);
387 BootPerformanceData = BootPerformanceData + SmmBootRecordDataSize;
388 }
389
390 mBootRecordBuffer = (UINT8 *) mAcpiBootPerformanceTable;
391 mBootRecordSize = mAcpiBootPerformanceTable->Header.Length;
392 mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
393
394 return EFI_SUCCESS;
395 }
396
397 /**
398 Get a human readable module name and module guid for the given image handle.
399 If module name can't be found, "" string will return.
400 If module guid can't be found, Zero Guid will return.
401
402 @param Handle Image handle or Controller handle.
403 @param NameString The ascii string will be filled into it. If not found, null string will return.
404 @param BufferSize Size of the input NameString buffer.
405 @param ModuleGuid Point to the guid buffer to store the got module guid value.
406
407 @retval EFI_SUCCESS Successfully get module name and guid.
408 @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.
409 @retval other value Module Name can't be got.
410 **/
411 EFI_STATUS
412 GetModuleInfoFromHandle (
413 IN EFI_HANDLE Handle,
414 OUT CHAR8 *NameString,
415 IN UINTN BufferSize,
416 OUT EFI_GUID *ModuleGuid OPTIONAL
417 )
418 {
419 EFI_STATUS Status;
420 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
421 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
422 CHAR8 *PdbFileName;
423 EFI_GUID *TempGuid;
424 UINTN StartIndex;
425 UINTN Index;
426 INTN Count;
427 BOOLEAN ModuleGuidIsGet;
428 UINTN StringSize;
429 CHAR16 *StringPtr;
430 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
431 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
432
433 if (NameString == NULL || BufferSize == 0) {
434 return EFI_INVALID_PARAMETER;
435 }
436 //
437 // Try to get the ModuleGuid and name string form the caached array.
438 //
439 if (mCachePairCount > 0) {
440 for (Count = mCachePairCount -1; Count >= 0; Count--) {
441 if (Handle == mCacheHandleGuidTable[Count].Handle) {
442 CopyGuid (ModuleGuid, &mCacheHandleGuidTable[Count].ModuleGuid);
443 AsciiStrCpyS (NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, mCacheHandleGuidTable[Count].NameString);
444 return EFI_SUCCESS;
445 }
446 }
447 }
448
449 Status = EFI_INVALID_PARAMETER;
450 LoadedImage = NULL;
451 ModuleGuidIsGet = FALSE;
452
453 //
454 // Initialize GUID as zero value.
455 //
456 TempGuid = &gZeroGuid;
457 //
458 // Initialize it as "" string.
459 //
460 NameString[0] = 0;
461
462 if (Handle != NULL) {
463 //
464 // Try Handle as ImageHandle.
465 //
466 Status = gBS->HandleProtocol (
467 Handle,
468 &gEfiLoadedImageProtocolGuid,
469 (VOID**) &LoadedImage
470 );
471
472 if (EFI_ERROR (Status)) {
473 //
474 // Try Handle as Controller Handle
475 //
476 Status = gBS->OpenProtocol (
477 Handle,
478 &gEfiDriverBindingProtocolGuid,
479 (VOID **) &DriverBinding,
480 NULL,
481 NULL,
482 EFI_OPEN_PROTOCOL_GET_PROTOCOL
483 );
484 if (!EFI_ERROR (Status)) {
485 //
486 // Get Image protocol from ImageHandle
487 //
488 Status = gBS->HandleProtocol (
489 DriverBinding->ImageHandle,
490 &gEfiLoadedImageProtocolGuid,
491 (VOID**) &LoadedImage
492 );
493 }
494 }
495 }
496
497 if (!EFI_ERROR (Status) && LoadedImage != NULL) {
498 //
499 // Get Module Guid from DevicePath.
500 //
501 if (LoadedImage->FilePath != NULL &&
502 LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH &&
503 LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP
504 ) {
505 //
506 // Determine GUID associated with module logging performance
507 //
508 ModuleGuidIsGet = TRUE;
509 FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LoadedImage->FilePath;
510 TempGuid = &FvFilePath->FvFileName;
511 }
512
513 //
514 // Method 1 Get Module Name from PDB string.
515 //
516 PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
517 if (PdbFileName != NULL && BufferSize > 0) {
518 StartIndex = 0;
519 for (Index = 0; PdbFileName[Index] != 0; Index++) {
520 if ((PdbFileName[Index] == '\\') || (PdbFileName[Index] == '/')) {
521 StartIndex = Index + 1;
522 }
523 }
524 //
525 // Copy the PDB file name to our temporary string.
526 // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
527 //
528 for (Index = 0; Index < BufferSize - 1; Index++) {
529 NameString[Index] = PdbFileName[Index + StartIndex];
530 if (NameString[Index] == 0 || NameString[Index] == '.') {
531 NameString[Index] = 0;
532 break;
533 }
534 }
535
536 if (Index == BufferSize - 1) {
537 NameString[Index] = 0;
538 }
539 //
540 // Module Name is got.
541 //
542 goto Done;
543 }
544 }
545
546 //
547 // Method 2: Get the name string from ComponentName2 protocol
548 //
549 Status = gBS->HandleProtocol (
550 Handle,
551 &gEfiComponentName2ProtocolGuid,
552 (VOID **) &ComponentName2
553 );
554 if (!EFI_ERROR (Status)) {
555 //
556 // Get the current platform language setting
557 //
558 if (mPlatformLanguage == NULL) {
559 GetEfiGlobalVariable2 (L"PlatformLang", (VOID **) &mPlatformLanguage, NULL);
560 }
561 if (mPlatformLanguage != NULL) {
562 Status = ComponentName2->GetDriverName (
563 ComponentName2,
564 mPlatformLanguage != NULL ? mPlatformLanguage : "en-US",
565 &StringPtr
566 );
567 if (!EFI_ERROR (Status)) {
568 for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {
569 NameString[Index] = (CHAR8) StringPtr[Index];
570 }
571 NameString[Index] = 0;
572 //
573 // Module Name is got.
574 //
575 goto Done;
576 }
577 }
578 }
579
580 if (ModuleGuidIsGet) {
581 //
582 // Method 3 Try to get the image's FFS UI section by image GUID
583 //
584 StringPtr = NULL;
585 StringSize = 0;
586 Status = GetSectionFromAnyFv (
587 TempGuid,
588 EFI_SECTION_USER_INTERFACE,
589 0,
590 (VOID **) &StringPtr,
591 &StringSize
592 );
593
594 if (!EFI_ERROR (Status)) {
595 //
596 // Method 3. Get the name string from FFS UI section
597 //
598 for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {
599 NameString[Index] = (CHAR8) StringPtr[Index];
600 }
601 NameString[Index] = 0;
602 FreePool (StringPtr);
603 }
604 }
605
606 Done:
607 //
608 // Copy Module Guid
609 //
610 if (ModuleGuid != NULL) {
611 CopyGuid (ModuleGuid, TempGuid);
612 if (IsZeroGuid(TempGuid) && (Handle != NULL) && !ModuleGuidIsGet) {
613 // Handle is GUID
614 CopyGuid (ModuleGuid, (EFI_GUID *) Handle);
615 }
616 }
617
618 //
619 // Cache the Handle and Guid pairs.
620 //
621 if (mCachePairCount < CACHE_HANDLE_GUID_COUNT) {
622 mCacheHandleGuidTable[mCachePairCount].Handle = Handle;
623 CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, ModuleGuid);
624 AsciiStrCpyS (mCacheHandleGuidTable[mCachePairCount].NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, NameString);
625 mCachePairCount ++;
626 }
627
628 return Status;
629 }
630
631 /**
632 Get the FPDT record info.
633
634 @param IsStart TRUE if the performance log is start log.
635 @param Handle Pointer to environment specific context used
636 to identify the component being measured.
637 @param Token Pointer to a Null-terminated ASCII string
638 that identifies the component being measured.
639 @param Module Pointer to a Null-terminated ASCII string
640 that identifies the module being measured.
641 @param RecordInfo On return, pointer to the info of the record.
642 @param UseModuleName Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
643 Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.
644
645 @retval EFI_SUCCESS Get record info successfully.
646 @retval EFI_UNSUPPORTED No matched FPDT record.
647
648 **/
649 EFI_STATUS
650 GetFpdtRecordInfo (
651 IN BOOLEAN IsStart,
652 IN CONST VOID *Handle,
653 IN CONST CHAR8 *Token,
654 IN CONST CHAR8 *Module,
655 OUT FPDT_BASIC_RECORD_INFO *RecordInfo,
656 IN OUT BOOLEAN *UseModuleName
657 )
658 {
659 UINT16 RecordType;
660 UINTN StringSize;
661
662 RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
663
664 //
665 // Token to Type and Id.
666 //
667 if (Token != NULL) {
668 if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) { // "StartImage:"
669 *UseModuleName = TRUE;
670 RecordType = FPDT_GUID_EVENT_TYPE;
671 if (IsStart) {
672 RecordInfo->ProgressID = MODULE_START_ID;
673 } else {
674 RecordInfo->ProgressID = MODULE_END_ID;
675 }
676 } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
677 *UseModuleName = TRUE;
678 RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
679 if (IsStart) {
680 RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;
681 } else {
682 RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;
683 }
684 } else if (AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0) { // "DB:Start:"
685 *UseModuleName = TRUE;
686 if (IsStart) {
687 RecordInfo->ProgressID = MODULE_DB_START_ID;
688 RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
689 } else {
690 RecordInfo->ProgressID = MODULE_DB_END_ID;
691 RecordType = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
692 }
693 } else if (AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0) { // "DB:Support:"
694 *UseModuleName = TRUE;
695 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
696 return RETURN_UNSUPPORTED;
697 }
698 RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
699 if (IsStart) {
700 RecordInfo->ProgressID = MODULE_DB_SUPPORT_START_ID;
701 } else {
702 RecordInfo->ProgressID = MODULE_DB_SUPPORT_END_ID;
703 }
704 } else if (AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0) { // "DB:Stop:"
705 *UseModuleName = TRUE;
706 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
707 return RETURN_UNSUPPORTED;
708 }
709 RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
710 if (IsStart) {
711 RecordInfo->ProgressID = MODULE_DB_STOP_START_ID;
712 } else {
713 RecordInfo->ProgressID = MODULE_DB_STOP_END_ID;
714 }
715 } else if (AsciiStrCmp (Token, PEI_TOK) == 0 || // "PEI"
716 AsciiStrCmp (Token, DXE_TOK) == 0 || // "DXE"
717 AsciiStrCmp (Token, BDS_TOK) == 0) { // "BDS"
718 if (IsStart) {
719 RecordInfo->ProgressID = PERF_CROSSMODULE_START_ID;
720 } else {
721 RecordInfo->ProgressID = PERF_CROSSMODULE_END_ID;
722 }
723 } else { // Pref used in Modules.
724 if (IsStart) {
725 RecordInfo->ProgressID = PERF_INMODULE_START_ID;
726 } else {
727 RecordInfo->ProgressID = PERF_INMODULE_END_ID;
728 }
729 }
730 } else if (Handle!= NULL || Module != NULL) { // Pref used in Modules.
731 if (IsStart) {
732 RecordInfo->ProgressID = PERF_INMODULE_START_ID;
733 } else {
734 RecordInfo->ProgressID = PERF_INMODULE_END_ID;
735 }
736 } else {
737 return EFI_UNSUPPORTED;
738 }
739
740 //
741 // Get Record size baesed on the record type.
742 // When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.
743 //
744 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
745 RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
746 RecordInfo->RecordSize = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
747 } else {
748 switch (RecordType) {
749 case FPDT_GUID_EVENT_TYPE:
750 RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);
751 break;
752
753 case FPDT_DYNAMIC_STRING_EVENT_TYPE:
754 if (*UseModuleName) {
755 StringSize = STRING_SIZE;
756 } else if (Token != NULL) {
757 StringSize = AsciiStrSize (Token);
758 } else if (Module != NULL) {
759 StringSize = AsciiStrSize (Module);
760 } else {
761 StringSize = STRING_SIZE;
762 }
763 if (StringSize > STRING_SIZE) {
764 StringSize = STRING_SIZE;
765 }
766 RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);
767 break;
768
769 case FPDT_GUID_QWORD_EVENT_TYPE:
770 RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
771 break;
772
773 case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
774 RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD);
775 break;
776
777 default:
778 //
779 // Record is unsupported yet, return EFI_UNSUPPORTED
780 //
781 return EFI_UNSUPPORTED;
782 }
783 }
784
785 RecordInfo->Type = RecordType;
786 return EFI_SUCCESS;
787 }
788
789 /**
790 Add performance log to FPDT boot record table.
791
792 @param IsStart TRUE if the performance log is start log.
793 @param Handle Pointer to environment specific context used
794 to identify the component being measured.
795 @param Token Pointer to a Null-terminated ASCII string
796 that identifies the component being measured.
797 @param Module Pointer to a Null-terminated ASCII string
798 that identifies the module being measured.
799 @param Ticker 64-bit time stamp.
800 @param Identifier 32-bit identifier. If the value is 0, the created record
801 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
802
803 @retval EFI_SUCCESS Add FPDT boot record.
804 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
805 @retval EFI_UNSUPPORTED No matched FPDT record.
806
807 **/
808 EFI_STATUS
809 InsertFpdtMeasurement (
810 IN BOOLEAN IsStart,
811 IN CONST VOID *Handle, OPTIONAL
812 IN CONST CHAR8 *Token, OPTIONAL
813 IN CONST CHAR8 *Module, OPTIONAL
814 IN UINT64 Ticker,
815 IN UINT32 Identifier
816 )
817 {
818 EFI_GUID ModuleGuid;
819 CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
820 EFI_STATUS Status;
821 FPDT_RECORD_PTR FpdtRecordPtr;
822 FPDT_BASIC_RECORD_INFO RecordInfo;
823 UINT64 TimeStamp;
824 UINTN DestMax;
825 UINTN StrLength;
826 CONST CHAR8 *StringPtr;
827 BOOLEAN UseModuleName;
828
829 StringPtr = NULL;
830 UseModuleName = FALSE;
831 ZeroMem (ModuleName, sizeof (ModuleName));
832
833 if (mLockInsertRecord) {
834 return EFI_UNSUPPORTED;
835 }
836
837 mLockInsertRecord = TRUE;
838
839 //
840 // Get record info (type, size, ProgressID and Module Guid).
841 //
842 Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);
843 if (EFI_ERROR (Status)) {
844 mLockInsertRecord = FALSE;
845 return Status;
846 }
847
848 //
849 // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
850 // !!! Note: If the Pref is not the known Token used in the core but have same
851 // ID with the core Token, this case will not be supported.
852 // And in currtnt usage mode, for the unkown ID, there is a general rule:
853 // If it is start pref: the lower 4 bits of the ID should be 0.
854 // If it is end pref: the lower 4 bits of the ID should not be 0.
855 // If input ID doesn't follow the rule, we will adjust it.
856 //
857 if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
858 mLockInsertRecord = FALSE;
859 return EFI_UNSUPPORTED;
860 } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
861 if (IsStart && ((Identifier & 0x000F) != 0)) {
862 Identifier &= 0xFFF0;
863 } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
864 Identifier += 1;
865 }
866 RecordInfo.ProgressID = (UINT16)Identifier;
867 }
868
869 if (mFpdtBufferIsReported) {
870 //
871 // Append Boot records to the boot performance table.
872 //
873 if (mBootRecordSize + RecordInfo.RecordSize > mBootRecordMaxSize) {
874 if (!mLackSpaceIsReported) {
875 DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));
876 mLackSpaceIsReported = TRUE;
877 }
878 mLockInsertRecord = FALSE;
879 return EFI_OUT_OF_RESOURCES;
880 } else {
881 //
882 // Save boot record into BootPerformance table
883 //
884 FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mBootRecordSize);
885 mBootRecordSize += RecordInfo.RecordSize;
886 mAcpiBootPerformanceTable->Header.Length += RecordInfo.RecordSize;
887 }
888 } else {
889 //
890 // Check if pre-allocated buffer is full
891 //
892 if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
893 mPerformancePointer = ReallocatePool (
894 mPerformanceLength,
895 mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,
896 mPerformancePointer
897 );
898
899 if (mPerformancePointer == NULL) {
900 mLockInsertRecord = FALSE;
901 return EFI_OUT_OF_RESOURCES;
902 }
903 mMaxPerformanceLength = mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;
904 }
905 //
906 // Covert buffer to FPDT Ptr Union type.
907 //
908 FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mPerformanceLength);
909 mPerformanceLength += RecordInfo.RecordSize;
910 }
911
912 //
913 // Get the TimeStamp.
914 //
915 if (Ticker == 0) {
916 Ticker = GetPerformanceCounter ();
917 TimeStamp = GetTimeInNanoSecond (Ticker);
918 } else if (Ticker == 1) {
919 TimeStamp = 0;
920 } else {
921 TimeStamp = GetTimeInNanoSecond (Ticker);
922 }
923
924 //
925 // Get the ModuleName and ModuleGuid form the handle.
926 //
927 GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);
928
929 //
930 // Fill in the record information.
931 //
932 switch (RecordInfo.Type) {
933 case FPDT_GUID_EVENT_TYPE:
934 FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
935 FpdtRecordPtr.GuidEvent->Header.Length = RecordInfo.RecordSize;
936 FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
937 FpdtRecordPtr.GuidEvent->ProgressID = RecordInfo.ProgressID;
938 FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
939 CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
940 break;
941
942 case FPDT_DYNAMIC_STRING_EVENT_TYPE:
943 FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
944 FpdtRecordPtr.DynamicStringEvent->Header.Length = RecordInfo.RecordSize;
945 FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
946 FpdtRecordPtr.DynamicStringEvent->ProgressID = RecordInfo.ProgressID;
947 FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
948 CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
949
950 if (UseModuleName) {
951 StringPtr = ModuleName;
952 } else if (Token != NULL) {
953 StringPtr = Token;
954 } else if (Module != NULL) {
955 StringPtr = Module;
956 } else if (ModuleName != NULL) {
957 StringPtr = ModuleName;
958 }
959 if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
960 StrLength = AsciiStrLen (StringPtr);
961 DestMax = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
962 if (StrLength >= DestMax) {
963 StrLength = DestMax -1;
964 }
965 AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
966 } else {
967 AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
968 }
969 break;
970
971 case FPDT_GUID_QWORD_EVENT_TYPE:
972 FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
973 FpdtRecordPtr.GuidQwordEvent->Header.Length = RecordInfo.RecordSize;
974 FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
975 FpdtRecordPtr.GuidQwordEvent->ProgressID = RecordInfo.ProgressID;
976 FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
977 CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
978 if ((MODULE_LOADIMAGE_START_ID == RecordInfo.ProgressID) && AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) {
979 mLoadImageCount++;
980 FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;
981 }
982 break;
983
984 case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
985 FpdtRecordPtr.GuidQwordStringEvent->Header.Type = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
986 FpdtRecordPtr.GuidQwordStringEvent->Header.Length = RecordInfo.RecordSize;
987 FpdtRecordPtr.GuidQwordStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
988 FpdtRecordPtr.GuidQwordStringEvent->ProgressID = RecordInfo.ProgressID;
989 FpdtRecordPtr.GuidQwordStringEvent->Timestamp = TimeStamp;
990 CopyMem (&FpdtRecordPtr.GuidQwordStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordStringEvent->Guid));
991 break;
992
993 default:
994 //
995 // Record is not supported in current DXE phase, return EFI_ABORTED
996 //
997 mLockInsertRecord = FALSE;
998 return EFI_UNSUPPORTED;
999 }
1000
1001 mLockInsertRecord = FALSE;
1002 return EFI_SUCCESS;
1003 }
1004
1005 /**
1006 Dumps all the PEI performance.
1007
1008 @param HobStart A pointer to a Guid.
1009
1010 This internal function dumps all the PEI performance log to the DXE performance gauge array.
1011 It retrieves the optional GUID HOB for PEI performance and then saves the performance data
1012 to DXE performance data structures.
1013
1014 **/
1015 VOID
1016 InternalGetPeiPerformance (
1017 VOID *HobStart
1018 )
1019 {
1020 UINT8 *FirmwarePerformanceHob;
1021 FPDT_PEI_EXT_PERF_HEADER *PeiPerformanceLogHeader;
1022 UINT8 *EventRec;
1023 EFI_HOB_GUID_TYPE *GuidHob;
1024
1025 GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, HobStart);
1026 while (GuidHob != NULL) {
1027 FirmwarePerformanceHob = GET_GUID_HOB_DATA (GuidHob);
1028 PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)FirmwarePerformanceHob;
1029
1030 if (mPerformanceLength + PeiPerformanceLogHeader->SizeOfAllEntries > mMaxPerformanceLength) {
1031 mPerformancePointer = ReallocatePool (
1032 mPerformanceLength,
1033 mPerformanceLength +
1034 (UINTN)PeiPerformanceLogHeader->SizeOfAllEntries +
1035 FIRMWARE_RECORD_BUFFER,
1036 mPerformancePointer
1037 );
1038 ASSERT (mPerformancePointer != NULL);
1039 mMaxPerformanceLength = mPerformanceLength +
1040 (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries) +
1041 FIRMWARE_RECORD_BUFFER;
1042 }
1043
1044 EventRec = mPerformancePointer + mPerformanceLength;
1045 CopyMem (EventRec, FirmwarePerformanceHob + sizeof (FPDT_PEI_EXT_PERF_HEADER), (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries));
1046 //
1047 // Update the used buffer size.
1048 //
1049 mPerformanceLength += (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries);
1050 mLoadImageCount += PeiPerformanceLogHeader->LoadImageCount;
1051
1052 //
1053 // Get next performance guid hob
1054 //
1055 GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
1056 }
1057 }
1058
1059 /**
1060 Report Boot Perforamnce table address as report status code.
1061
1062 @param Event The event of notify protocol.
1063 @param Context Notify event context.
1064
1065 **/
1066 VOID
1067 EFIAPI
1068 ReportFpdtRecordBuffer (
1069 IN EFI_EVENT Event,
1070 IN VOID *Context
1071 )
1072 {
1073 EFI_STATUS Status;
1074 UINT64 BPDTAddr;
1075
1076 if (!mFpdtBufferIsReported) {
1077 Status = AllocateBootPerformanceTable ();
1078 if (!EFI_ERROR(Status)) {
1079 BPDTAddr = (UINT64)(UINTN)mAcpiBootPerformanceTable;
1080 REPORT_STATUS_CODE_EX (
1081 EFI_PROGRESS_CODE,
1082 EFI_SOFTWARE_DXE_BS_DRIVER,
1083 0,
1084 NULL,
1085 &gEdkiiFpdtExtendedFirmwarePerformanceGuid,
1086 &BPDTAddr,
1087 sizeof (UINT64)
1088 );
1089 }
1090 //
1091 // Set FPDT report state to TRUE.
1092 //
1093 mFpdtBufferIsReported = TRUE;
1094 }
1095 }
1096
1097 /**
1098 Adds a record at the end of the performance measurement log
1099 that records the start time of a performance measurement.
1100
1101 Adds a record to the end of the performance measurement log
1102 that contains the Handle, Token, Module and Identifier.
1103 The end time of the new record must be set to zero.
1104 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1105 If TimeStamp is zero, the start time in the record is filled in with the value
1106 read from the current time stamp.
1107
1108 @param Handle Pointer to environment specific context used
1109 to identify the component being measured.
1110 @param Token Pointer to a Null-terminated ASCII string
1111 that identifies the component being measured.
1112 @param Module Pointer to a Null-terminated ASCII string
1113 that identifies the module being measured.
1114 @param TimeStamp 64-bit time stamp.
1115 @param Identifier 32-bit identifier. If the value is 0, the created record
1116 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
1117
1118 @retval EFI_SUCCESS The data was read correctly from the device.
1119 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1120
1121 **/
1122 EFI_STATUS
1123 EFIAPI
1124 StartGaugeEx (
1125 IN CONST VOID *Handle, OPTIONAL
1126 IN CONST CHAR8 *Token, OPTIONAL
1127 IN CONST CHAR8 *Module, OPTIONAL
1128 IN UINT64 TimeStamp,
1129 IN UINT32 Identifier
1130 )
1131 {
1132 return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
1133 }
1134
1135 /**
1136 Searches the performance measurement log from the beginning of the log
1137 for the first matching record that contains a zero end time and fills in a valid end time.
1138
1139 Searches the performance measurement log from the beginning of the log
1140 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1141 If the record can not be found then return EFI_NOT_FOUND.
1142 If the record is found and TimeStamp is not zero,
1143 then the end time in the record is filled in with the value specified by TimeStamp.
1144 If the record is found and TimeStamp is zero, then the end time in the matching record
1145 is filled in with the current time stamp value.
1146
1147 @param Handle Pointer to environment specific context used
1148 to identify the component being measured.
1149 @param Token Pointer to a Null-terminated ASCII string
1150 that identifies the component being measured.
1151 @param Module Pointer to a Null-terminated ASCII string
1152 that identifies the module being measured.
1153 @param TimeStamp 64-bit time stamp.
1154 @param Identifier 32-bit identifier. If the value is 0, the found record
1155 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
1156
1157 @retval EFI_SUCCESS The end of the measurement was recorded.
1158 @retval EFI_NOT_FOUND The specified measurement record could not be found.
1159
1160 **/
1161 EFI_STATUS
1162 EFIAPI
1163 EndGaugeEx (
1164 IN CONST VOID *Handle, OPTIONAL
1165 IN CONST CHAR8 *Token, OPTIONAL
1166 IN CONST CHAR8 *Module, OPTIONAL
1167 IN UINT64 TimeStamp,
1168 IN UINT32 Identifier
1169 )
1170 {
1171 return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
1172 }
1173
1174 /**
1175 Retrieves a previously logged performance measurement.
1176 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
1177 and then assign the Identifier with 0.
1178
1179 !!! Not support!!!
1180
1181 Retrieves the performance log entry from the performance log specified by LogEntryKey.
1182 If it stands for a valid entry, then EFI_SUCCESS is returned and
1183 GaugeDataEntryEx stores the pointer to that entry.
1184
1185 @param LogEntryKey The key for the previous performance measurement log entry.
1186 If 0, then the first performance measurement log entry is retrieved.
1187 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey
1188 if the retrieval is successful.
1189
1190 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.
1191 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
1192 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
1193 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.
1194
1195 **/
1196 EFI_STATUS
1197 EFIAPI
1198 GetGaugeEx (
1199 IN UINTN LogEntryKey,
1200 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx
1201 )
1202 {
1203 return EFI_UNSUPPORTED;
1204 }
1205
1206 /**
1207 Adds a record at the end of the performance measurement log
1208 that records the start time of a performance measurement.
1209
1210 Adds a record to the end of the performance measurement log
1211 that contains the Handle, Token, and Module.
1212 The end time of the new record must be set to zero.
1213 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1214 If TimeStamp is zero, the start time in the record is filled in with the value
1215 read from the current time stamp.
1216
1217 @param Handle Pointer to environment specific context used
1218 to identify the component being measured.
1219 @param Token Pointer to a Null-terminated ASCII string
1220 that identifies the component being measured.
1221 @param Module Pointer to a Null-terminated ASCII string
1222 that identifies the module being measured.
1223 @param TimeStamp 64-bit time stamp.
1224
1225 @retval EFI_SUCCESS The data was read correctly from the device.
1226 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1227
1228 **/
1229 EFI_STATUS
1230 EFIAPI
1231 StartGauge (
1232 IN CONST VOID *Handle, OPTIONAL
1233 IN CONST CHAR8 *Token, OPTIONAL
1234 IN CONST CHAR8 *Module, OPTIONAL
1235 IN UINT64 TimeStamp
1236 )
1237 {
1238 return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);
1239 }
1240
1241 /**
1242 Searches the performance measurement log from the beginning of the log
1243 for the first matching record that contains a zero end time and fills in a valid end time.
1244
1245 Searches the performance measurement log from the beginning of the log
1246 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1247 If the record can not be found then return EFI_NOT_FOUND.
1248 If the record is found and TimeStamp is not zero,
1249 then the end time in the record is filled in with the value specified by TimeStamp.
1250 If the record is found and TimeStamp is zero, then the end time in the matching record
1251 is filled in with the current time stamp value.
1252
1253 @param Handle Pointer to environment specific context used
1254 to identify the component being measured.
1255 @param Token Pointer to a Null-terminated ASCII string
1256 that identifies the component being measured.
1257 @param Module Pointer to a Null-terminated ASCII string
1258 that identifies the module being measured.
1259 @param TimeStamp 64-bit time stamp.
1260
1261 @retval EFI_SUCCESS The end of the measurement was recorded.
1262 @retval EFI_NOT_FOUND The specified measurement record could not be found.
1263
1264 **/
1265 EFI_STATUS
1266 EFIAPI
1267 EndGauge (
1268 IN CONST VOID *Handle, OPTIONAL
1269 IN CONST CHAR8 *Token, OPTIONAL
1270 IN CONST CHAR8 *Module, OPTIONAL
1271 IN UINT64 TimeStamp
1272 )
1273 {
1274 return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);
1275 }
1276
1277 /**
1278 Retrieves a previously logged performance measurement.
1279 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
1280 and then eliminate the Identifier.
1281
1282 !!! Not support!!!
1283
1284 Retrieves the performance log entry from the performance log specified by LogEntryKey.
1285 If it stands for a valid entry, then EFI_SUCCESS is returned and
1286 GaugeDataEntry stores the pointer to that entry.
1287
1288 @param LogEntryKey The key for the previous performance measurement log entry.
1289 If 0, then the first performance measurement log entry is retrieved.
1290 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
1291 if the retrieval is successful.
1292
1293 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.
1294 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
1295 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
1296 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
1297
1298 **/
1299 EFI_STATUS
1300 EFIAPI
1301 GetGauge (
1302 IN UINTN LogEntryKey,
1303 OUT GAUGE_DATA_ENTRY **GaugeDataEntry
1304 )
1305 {
1306 return EFI_UNSUPPORTED;
1307 }
1308
1309
1310 /**
1311 The constructor function initializes Performance infrastructure for DXE phase.
1312
1313 The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance
1314 and merges PEI performance data to DXE performance log.
1315 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
1316
1317 @param ImageHandle The firmware allocated handle for the EFI image.
1318 @param SystemTable A pointer to the EFI System Table.
1319
1320 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
1321
1322 **/
1323 EFI_STATUS
1324 EFIAPI
1325 DxeCorePerformanceLibConstructor (
1326 IN EFI_HANDLE ImageHandle,
1327 IN EFI_SYSTEM_TABLE *SystemTable
1328 )
1329 {
1330 EFI_STATUS Status;
1331 EFI_HANDLE Handle;
1332 EFI_EVENT ReadyToBootEvent;
1333 PERFORMANCE_PROPERTY *PerformanceProperty;
1334
1335 if (!PerformanceMeasurementEnabled ()) {
1336 //
1337 // Do not initialize performance infrastructure if not required.
1338 //
1339 return EFI_SUCCESS;
1340 }
1341
1342 //
1343 // Dump normal PEI performance records
1344 //
1345 InternalGetPeiPerformance (GetHobList());
1346
1347 //
1348 // Install the protocol interfaces for DXE performance library instance.
1349 //
1350 Handle = NULL;
1351 Status = gBS->InstallMultipleProtocolInterfaces (
1352 &Handle,
1353 &gPerformanceProtocolGuid,
1354 &mPerformanceInterface,
1355 &gPerformanceExProtocolGuid,
1356 &mPerformanceExInterface,
1357 NULL
1358 );
1359 ASSERT_EFI_ERROR (Status);
1360
1361 //
1362 // Register ReadyToBoot event to report StatusCode data
1363 //
1364 Status = gBS->CreateEventEx (
1365 EVT_NOTIFY_SIGNAL,
1366 TPL_CALLBACK,
1367 ReportFpdtRecordBuffer,
1368 NULL,
1369 &gEfiEventReadyToBootGuid,
1370 &ReadyToBootEvent
1371 );
1372
1373 ASSERT_EFI_ERROR (Status);
1374
1375 Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty);
1376 if (EFI_ERROR (Status)) {
1377 //
1378 // Install configuration table for performance property.
1379 //
1380 mPerformanceProperty.Revision = PERFORMANCE_PROPERTY_REVISION;
1381 mPerformanceProperty.Reserved = 0;
1382 mPerformanceProperty.Frequency = GetPerformanceCounterProperties (
1383 &mPerformanceProperty.TimerStartValue,
1384 &mPerformanceProperty.TimerEndValue
1385 );
1386 Status = gBS->InstallConfigurationTable (&gPerformanceProtocolGuid, &mPerformanceProperty);
1387 ASSERT_EFI_ERROR (Status);
1388 }
1389
1390 return EFI_SUCCESS;
1391 }
1392
1393 /**
1394 Adds a record at the end of the performance measurement log
1395 that records the start time of a performance measurement.
1396
1397 Adds a record to the end of the performance measurement log
1398 that contains the Handle, Token, Module and Identifier.
1399 The end time of the new record must be set to zero.
1400 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1401 If TimeStamp is zero, the start time in the record is filled in with the value
1402 read from the current time stamp.
1403
1404 @param Handle Pointer to environment specific context used
1405 to identify the component being measured.
1406 @param Token Pointer to a Null-terminated ASCII string
1407 that identifies the component being measured.
1408 @param Module Pointer to a Null-terminated ASCII string
1409 that identifies the module being measured.
1410 @param TimeStamp 64-bit time stamp.
1411 @param Identifier 32-bit identifier. If the value is 0, the created record
1412 is same as the one created by StartPerformanceMeasurement.
1413
1414 @retval RETURN_SUCCESS The start of the measurement was recorded.
1415 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1416
1417 **/
1418 RETURN_STATUS
1419 EFIAPI
1420 StartPerformanceMeasurementEx (
1421 IN CONST VOID *Handle, OPTIONAL
1422 IN CONST CHAR8 *Token, OPTIONAL
1423 IN CONST CHAR8 *Module, OPTIONAL
1424 IN UINT64 TimeStamp,
1425 IN UINT32 Identifier
1426 )
1427 {
1428 return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
1429 }
1430
1431 /**
1432 Searches the performance measurement log from the beginning of the log
1433 for the first matching record that contains a zero end time and fills in a valid end time.
1434
1435 Searches the performance measurement log from the beginning of the log
1436 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1437 If the record can not be found then return RETURN_NOT_FOUND.
1438 If the record is found and TimeStamp is not zero,
1439 then the end time in the record is filled in with the value specified by TimeStamp.
1440 If the record is found and TimeStamp is zero, then the end time in the matching record
1441 is filled in with the current time stamp value.
1442
1443 @param Handle Pointer to environment specific context used
1444 to identify the component being measured.
1445 @param Token Pointer to a Null-terminated ASCII string
1446 that identifies the component being measured.
1447 @param Module Pointer to a Null-terminated ASCII string
1448 that identifies the module being measured.
1449 @param TimeStamp 64-bit time stamp.
1450 @param Identifier 32-bit identifier. If the value is 0, the found record
1451 is same as the one found by EndPerformanceMeasurement.
1452
1453 @retval RETURN_SUCCESS The end of the measurement was recorded.
1454 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1455
1456 **/
1457 RETURN_STATUS
1458 EFIAPI
1459 EndPerformanceMeasurementEx (
1460 IN CONST VOID *Handle, OPTIONAL
1461 IN CONST CHAR8 *Token, OPTIONAL
1462 IN CONST CHAR8 *Module, OPTIONAL
1463 IN UINT64 TimeStamp,
1464 IN UINT32 Identifier
1465 )
1466 {
1467 return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
1468 }
1469
1470 /**
1471 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1472 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
1473 and then assign the Identifier with 0.
1474
1475 !!! Not support!!!
1476
1477 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1478 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1479 and the key for the second entry in the log is returned. If the performance log is empty,
1480 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1481 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1482 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1483 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1484 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1485 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1486 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
1487 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1488 If Handle is NULL, then ASSERT().
1489 If Token is NULL, then ASSERT().
1490 If Module is NULL, then ASSERT().
1491 If StartTimeStamp is NULL, then ASSERT().
1492 If EndTimeStamp is NULL, then ASSERT().
1493 If Identifier is NULL, then ASSERT().
1494
1495 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1496 0, then the first performance measurement log entry is retrieved.
1497 On exit, the key of the next performance log entry.
1498 @param Handle Pointer to environment specific context used to identify the component
1499 being measured.
1500 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1501 being measured.
1502 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1503 being measured.
1504 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1505 was started.
1506 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1507 was ended.
1508 @param Identifier Pointer to the 32-bit identifier that was recorded when the measurement
1509 was ended.
1510
1511 @return The key for the next performance log entry (in general case).
1512
1513 **/
1514 UINTN
1515 EFIAPI
1516 GetPerformanceMeasurementEx (
1517 IN UINTN LogEntryKey,
1518 OUT CONST VOID **Handle,
1519 OUT CONST CHAR8 **Token,
1520 OUT CONST CHAR8 **Module,
1521 OUT UINT64 *StartTimeStamp,
1522 OUT UINT64 *EndTimeStamp,
1523 OUT UINT32 *Identifier
1524 )
1525 {
1526 return 0;
1527 }
1528
1529 /**
1530 Adds a record at the end of the performance measurement log
1531 that records the start time of a performance measurement.
1532
1533 Adds a record to the end of the performance measurement log
1534 that contains the Handle, Token, and Module.
1535 The end time of the new record must be set to zero.
1536 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1537 If TimeStamp is zero, the start time in the record is filled in with the value
1538 read from the current time stamp.
1539
1540 @param Handle Pointer to environment specific context used
1541 to identify the component being measured.
1542 @param Token Pointer to a Null-terminated ASCII string
1543 that identifies the component being measured.
1544 @param Module Pointer to a Null-terminated ASCII string
1545 that identifies the module being measured.
1546 @param TimeStamp 64-bit time stamp.
1547
1548 @retval RETURN_SUCCESS The start of the measurement was recorded.
1549 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1550
1551 **/
1552 RETURN_STATUS
1553 EFIAPI
1554 StartPerformanceMeasurement (
1555 IN CONST VOID *Handle, OPTIONAL
1556 IN CONST CHAR8 *Token, OPTIONAL
1557 IN CONST CHAR8 *Module, OPTIONAL
1558 IN UINT64 TimeStamp
1559 )
1560 {
1561 return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, 0);
1562 }
1563
1564 /**
1565 Searches the performance measurement log from the beginning of the log
1566 for the first matching record that contains a zero end time and fills in a valid end time.
1567
1568 Searches the performance measurement log from the beginning of the log
1569 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1570 If the record can not be found then return RETURN_NOT_FOUND.
1571 If the record is found and TimeStamp is not zero,
1572 then the end time in the record is filled in with the value specified by TimeStamp.
1573 If the record is found and TimeStamp is zero, then the end time in the matching record
1574 is filled in with the current time stamp value.
1575
1576 @param Handle Pointer to environment specific context used
1577 to identify the component being measured.
1578 @param Token Pointer to a Null-terminated ASCII string
1579 that identifies the component being measured.
1580 @param Module Pointer to a Null-terminated ASCII string
1581 that identifies the module being measured.
1582 @param TimeStamp 64-bit time stamp.
1583
1584 @retval RETURN_SUCCESS The end of the measurement was recorded.
1585 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1586
1587 **/
1588 RETURN_STATUS
1589 EFIAPI
1590 EndPerformanceMeasurement (
1591 IN CONST VOID *Handle, OPTIONAL
1592 IN CONST CHAR8 *Token, OPTIONAL
1593 IN CONST CHAR8 *Module, OPTIONAL
1594 IN UINT64 TimeStamp
1595 )
1596 {
1597 return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, 0);
1598 }
1599
1600 /**
1601 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1602 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1603 and then eliminate the Identifier.
1604
1605 !!! Not support!!!
1606
1607 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1608 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1609 and the key for the second entry in the log is returned. If the performance log is empty,
1610 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1611 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1612 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1613 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1614 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1615 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1616 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1617 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1618 If Handle is NULL, then ASSERT().
1619 If Token is NULL, then ASSERT().
1620 If Module is NULL, then ASSERT().
1621 If StartTimeStamp is NULL, then ASSERT().
1622 If EndTimeStamp is NULL, then ASSERT().
1623
1624 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1625 0, then the first performance measurement log entry is retrieved.
1626 On exit, the key of the next performance log entry.
1627 @param Handle Pointer to environment specific context used to identify the component
1628 being measured.
1629 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1630 being measured.
1631 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1632 being measured.
1633 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1634 was started.
1635 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1636 was ended.
1637
1638 @return The key for the next performance log entry (in general case).
1639
1640 **/
1641 UINTN
1642 EFIAPI
1643 GetPerformanceMeasurement (
1644 IN UINTN LogEntryKey,
1645 OUT CONST VOID **Handle,
1646 OUT CONST CHAR8 **Token,
1647 OUT CONST CHAR8 **Module,
1648 OUT UINT64 *StartTimeStamp,
1649 OUT UINT64 *EndTimeStamp
1650 )
1651 {
1652 return 0;
1653 }
1654
1655 /**
1656 Returns TRUE if the performance measurement macros are enabled.
1657
1658 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1659 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1660
1661 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1662 PcdPerformanceLibraryPropertyMask is set.
1663 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1664 PcdPerformanceLibraryPropertyMask is clear.
1665
1666 **/
1667 BOOLEAN
1668 EFIAPI
1669 PerformanceMeasurementEnabled (
1670 VOID
1671 )
1672 {
1673 return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
1674 }