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