]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c
SecurityPkg: Apply uncrustify changes
[mirror_edk2.git] / ShellPkg / DynamicCommand / DpDynamicCommand / Dp.c
CommitLineData
d41bc92c 1/** @file\r
2 Shell command for Displaying Performance Metrics.\r
3\r
4 The Dp command reads performance data and presents it in several\r
5 different formats depending upon the needs of the user. Both\r
6 Trace and Measured Profiling information is processed and presented.\r
7\r
8 Dp uses the "PerformanceLib" to read the measurement records.\r
9 The "TimerLib" provides information about the timer, such as frequency,\r
10 beginning, and ending counter values.\r
11 Measurement records contain identifying information (Handle, Token, Module)\r
12 and start and end time values.\r
13 Dp uses this information to group records in different ways. It also uses\r
14 timer information to calculate elapsed time for each measurement.\r
ba0014b9 15\r
115eae65 16 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.\r
196ccda0 17 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
56ba3746 18 SPDX-License-Identifier: BSD-2-Clause-Patent\r
d41bc92c 19**/\r
20\r
d41bc92c 21#include "Dp.h"\r
22#include "Literals.h"\r
23#include "DpInternal.h"\r
24\r
115eae65
DB
25#pragma pack(1)\r
26\r
27typedef struct {\r
28 EFI_ACPI_DESCRIPTION_HEADER Header;\r
29 UINT32 Entry;\r
30} RSDT_TABLE;\r
31\r
32typedef struct {\r
33 EFI_ACPI_DESCRIPTION_HEADER Header;\r
34 UINT64 Entry;\r
35} XSDT_TABLE;\r
36\r
37#pragma pack()\r
38\r
c44501b3 39EFI_HII_HANDLE mDpHiiHandle;\r
92034c4c 40\r
115eae65
DB
41typedef struct {\r
42 EFI_HANDLE Handle;\r
43 EFI_GUID ModuleGuid;\r
44} HANDLE_GUID_MAP;\r
45\r
46HANDLE_GUID_MAP *mCacheHandleGuidTable;\r
47UINTN mCachePairCount = 0;\r
48\r
d41bc92c 49//\r
50/// Module-Global Variables\r
51///@{\r
52CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];\r
53CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];\r
54UINT64 mInterestThreshold;\r
55BOOLEAN mShowId = FALSE;\r
115eae65
DB
56UINT8 *mBootPerformanceTable;\r
57UINTN mBootPerformanceTableSize;\r
58BOOLEAN mPeiPhase = FALSE;\r
59BOOLEAN mDxePhase = FALSE;\r
d41bc92c 60\r
61PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO.\r
115eae65
DB
62MEASUREMENT_RECORD *mMeasurementList = NULL;\r
63UINTN mMeasurementNum = 0;\r
d41bc92c 64\r
65/// Items for which to gather cumulative statistics.\r
66PERF_CUM_DATA CumData[] = {\r
67 PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),\r
68 PERF_INIT_CUM_DATA (START_IMAGE_TOK),\r
69 PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),\r
05aba7e3
DB
70 PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK),\r
71 PERF_INIT_CUM_DATA (DRIVERBINDING_STOP_TOK)\r
d41bc92c 72};\r
73\r
74/// Number of items for which we are gathering cumulative statistics.\r
75UINT32 const NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);\r
76\r
77STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
78 {L"-v", TypeFlag}, // -v Verbose Mode\r
79 {L"-A", TypeFlag}, // -A All, Cooked\r
80 {L"-R", TypeFlag}, // -R RAW All\r
81 {L"-s", TypeFlag}, // -s Summary\r
d41bc92c 82 {L"-x", TypeFlag}, // -x eXclude Cumulative Items\r
83 {L"-i", TypeFlag}, // -i Display Identifier\r
a06795c6 84 {L"-c", TypeValue}, // -c Display cumulative data.\r
d41bc92c 85 {L"-n", TypeValue}, // -n # Number of records to display for A and R\r
86 {L"-t", TypeValue}, // -t # Threshold of interest\r
87 {NULL, TypeMax}\r
88 };\r
89\r
90///@}\r
91\r
92/**\r
93 Display the trailing Verbose information.\r
94**/\r
95VOID\r
96DumpStatistics( void )\r
97{\r
98 EFI_STRING StringPtr;\r
99 EFI_STRING StringPtrUnknown;\r
92034c4c
RN
100 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);\r
101 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
102 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
d41bc92c 103 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);\r
92034c4c
RN
104 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), mDpHiiHandle, SummaryData.NumTrace);\r
105 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), mDpHiiHandle, SummaryData.NumIncomplete);\r
106 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), mDpHiiHandle, SummaryData.NumSummary);\r
107 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), mDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);\r
108 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), mDpHiiHandle, SummaryData.NumPEIMs);\r
109 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), mDpHiiHandle, SummaryData.NumGlobal);\r
d41bc92c 110 SHELL_FREE_NON_NULL (StringPtr);\r
111 SHELL_FREE_NON_NULL (StringPtrUnknown);\r
112}\r
113\r
115eae65
DB
114/**\r
115 Get Boot performance table form Acpi table.\r
116\r
117**/\r
118EFI_STATUS\r
119GetBootPerformanceTable (\r
120 )\r
121{\r
115eae65
DB
122 FIRMWARE_PERFORMANCE_TABLE *FirmwarePerformanceTable;\r
123\r
cb6fe7bb
SZ
124 FirmwarePerformanceTable = (FIRMWARE_PERFORMANCE_TABLE *) EfiLocateFirstAcpiTable (\r
125 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE\r
126 );\r
115eae65 127 if (FirmwarePerformanceTable == NULL) {\r
4109d0d7 128 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GET_ACPI_FPDT_FAIL), mDpHiiHandle);\r
115eae65
DB
129 return EFI_NOT_FOUND;\r
130 }\r
131\r
132 mBootPerformanceTable = (UINT8*) (UINTN)FirmwarePerformanceTable->BootPointerRecord.BootPerformanceTablePointer;\r
133 mBootPerformanceTableSize = ((BOOT_PERFORMANCE_TABLE *) mBootPerformanceTable)->Header.Length;\r
134\r
135 return EFI_SUCCESS;\r
136}\r
137\r
138/**\r
139 Get Handle form Module Guid.\r
140\r
141 @param ModuleGuid Module Guid.\r
142 @param Handle The handle to be returned.\r
143\r
144**/\r
145VOID\r
146GetHandleFormModuleGuid (\r
147 IN EFI_GUID *ModuleGuid,\r
148 IN OUT EFI_HANDLE *Handle\r
149 )\r
150{\r
151 UINTN Index;\r
152\r
153 if (IsZeroGuid (ModuleGuid)) {\r
154 *Handle = NULL;\r
155 }\r
156 //\r
f16bd394 157 // Try to get the Handle from the cached array.\r
115eae65
DB
158 //\r
159 for (Index = 0; Index < mCachePairCount; Index++) {\r
160 if (CompareGuid (ModuleGuid, &mCacheHandleGuidTable[Index].ModuleGuid)) {\r
161 *Handle = mCacheHandleGuidTable[Index].Handle;\r
162 break;\r
163 }\r
164 }\r
165 if (Index >= mCachePairCount) {\r
166 *Handle = NULL;\r
167 }\r
168}\r
169\r
170/**\r
171Cache the GUID and handle mapping pairs. In order to save time for searching.\r
172\r
173**/\r
174EFI_STATUS\r
175BuildCachedGuidHandleTable (\r
176 VOID\r
177 )\r
178{\r
179 EFI_STATUS Status;\r
180 EFI_HANDLE *HandleBuffer;\r
181 UINTN HandleCount;\r
182 UINTN Index;\r
183 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
184 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
185 EFI_GUID *TempGuid;\r
186 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
187\r
188 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);\r
189 if (EFI_ERROR (Status)) {\r
190 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);\r
191 return Status;\r
192 }\r
193\r
194 mCacheHandleGuidTable = AllocateZeroPool (HandleCount * sizeof (HANDLE_GUID_MAP));\r
195 if (mCacheHandleGuidTable == NULL) {\r
196 return EFI_OUT_OF_RESOURCES;\r
197 }\r
198\r
199 for (Index = 0; Index < HandleCount; Index++) {\r
200 //\r
201 // Try Handle as ImageHandle.\r
202 //\r
203 Status = gBS->HandleProtocol (\r
204 HandleBuffer[Index],\r
205 &gEfiLoadedImageProtocolGuid,\r
206 (VOID**) &LoadedImage\r
207 );\r
208 if (EFI_ERROR (Status)) {\r
209 //\r
210 // Try Handle as Controller Handle\r
211 //\r
212 Status = gBS->OpenProtocol (\r
213 HandleBuffer[Index],\r
214 &gEfiDriverBindingProtocolGuid,\r
215 (VOID **) &DriverBinding,\r
216 NULL,\r
217 NULL,\r
218 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
219 );\r
220 if (!EFI_ERROR (Status)) {\r
221 //\r
222 // Get Image protocol from ImageHandle\r
223 //\r
224 Status = gBS->HandleProtocol (\r
225 DriverBinding->ImageHandle,\r
226 &gEfiLoadedImageProtocolGuid,\r
227 (VOID**) &LoadedImage\r
228 );\r
229 }\r
230 }\r
231\r
232 if (!EFI_ERROR (Status) && LoadedImage != NULL) {\r
233 //\r
234 // Get Module Guid from DevicePath.\r
235 //\r
236 if (LoadedImage->FilePath != NULL &&\r
237 LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH &&\r
238 LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP\r
239 ) {\r
240 FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LoadedImage->FilePath;\r
241 TempGuid = &FvFilePath->FvFileName;\r
242\r
243 mCacheHandleGuidTable[mCachePairCount].Handle = HandleBuffer[Index];\r
244 CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, TempGuid);\r
245 mCachePairCount ++;\r
246 }\r
247 }\r
248 }\r
249 if (HandleBuffer != NULL) {\r
250 FreePool (HandleBuffer);\r
251 HandleBuffer = NULL;\r
252 }\r
37d533da 253 return EFI_SUCCESS;\r
115eae65
DB
254}\r
255\r
256/**\r
257 Get Measurement form Fpdt records.\r
258\r
259 @param RecordHeader Pointer to the start record.\r
260 @param IsStart Is start record or End record.\r
261 @param Measurement Pointer to the measurement which need to be filled.\r
262\r
263**/\r
264VOID\r
265GetMeasurementInfo (\r
266 IN EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader,\r
267 IN BOOLEAN IsStart,\r
268 IN OUT MEASUREMENT_RECORD *Measurement\r
269 )\r
270{\r
271 VOID *ModuleGuid;\r
272 EFI_HANDLE StartHandle;\r
273\r
274 switch (RecordHeader->Type) {\r
275 case FPDT_GUID_EVENT_TYPE:\r
276 ModuleGuid = &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid);\r
277 Measurement->Identifier = ((UINT32)((FPDT_GUID_EVENT_RECORD *)RecordHeader)->ProgressID);\r
278 if (IsStart) {\r
279 Measurement->StartTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp;\r
280 } else {\r
281 Measurement->EndTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp;\r
282 }\r
283 switch (Measurement->Identifier) {\r
284 case MODULE_START_ID:\r
285 case MODULE_END_ID:\r
286 if (mPeiPhase) {\r
287 Measurement->Token = ALit_PEIM;\r
288 Measurement->Module = ALit_PEIM;\r
289 } else if (mDxePhase) {\r
290 Measurement->Token = ALit_START_IMAGE;\r
291 Measurement->Module = ALit_START_IMAGE;\r
292 }\r
293 break;\r
294 default:\r
295 ASSERT(FALSE);\r
296 }\r
297\r
f45dd2dd
BD
298 if (Measurement->Token != NULL && AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {\r
299 Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);\r
115eae65
DB
300 } else {\r
301 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
f45dd2dd
BD
302 Measurement->Handle = StartHandle;\r
303 //\r
304 // When no perf entry to record the PEI and DXE phase,\r
305 // For start image, we need detect the PEIM and non PEIM here.\r
306 //\r
307 if (Measurement->Token == NULL) {\r
308 if (StartHandle == NULL && !IsZeroGuid (ModuleGuid)) {\r
309 Measurement->Token = ALit_PEIM;\r
310 Measurement->Module = ALit_PEIM;\r
311 Measurement->Handle = ModuleGuid;\r
312 } else {\r
313 Measurement->Token = ALit_START_IMAGE;\r
314 Measurement->Module = ALit_START_IMAGE;\r
315 }\r
316 }\r
115eae65
DB
317 }\r
318 break;\r
319\r
320 case FPDT_DYNAMIC_STRING_EVENT_TYPE:\r
321 ModuleGuid = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);\r
322 Measurement->Identifier = ((UINT32)((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);\r
323 if (IsStart) {\r
324 Measurement->StartTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
325 } else {\r
326 Measurement->EndTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
327 }\r
328 switch (Measurement->Identifier) {\r
329 case MODULE_START_ID:\r
330 case MODULE_END_ID:\r
331 if (mPeiPhase) {\r
332 Measurement->Token = ALit_PEIM;\r
333 } else if (mDxePhase) {\r
334 Measurement->Token = ALit_START_IMAGE;\r
335 }\r
336 break;\r
337\r
338 case MODULE_LOADIMAGE_START_ID:\r
339 case MODULE_LOADIMAGE_END_ID:\r
340 Measurement->Token = ALit_LOAD_IMAGE;\r
341 break;\r
342\r
343 case MODULE_DB_START_ID:\r
344 case MODULE_DB_END_ID:\r
345 Measurement->Token = ALit_DB_START;\r
346 break;\r
347\r
348 case MODULE_DB_SUPPORT_START_ID:\r
349 case MODULE_DB_SUPPORT_END_ID:\r
350 Measurement->Token = ALit_DB_SUPPORT;\r
351 break;\r
352\r
353 case MODULE_DB_STOP_START_ID:\r
354 case MODULE_DB_STOP_END_ID:\r
355 Measurement->Token = ALit_DB_STOP;\r
356 break;\r
357\r
358 default:\r
359 Measurement->Token = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;\r
360 break;\r
361 }\r
362\r
363 Measurement->Module = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;\r
364\r
f45dd2dd 365 if (Measurement->Token != NULL && AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {\r
115eae65
DB
366 Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);\r
367 } else {\r
368 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
369 Measurement->Handle = StartHandle;\r
f45dd2dd
BD
370 //\r
371 // When no perf entry to record the PEI and DXE phase,\r
372 // For start image, we need detect the PEIM and non PEIM here.\r
373 //\r
374 if (Measurement->Token == NULL && (Measurement->Identifier == MODULE_START_ID || Measurement->Identifier == MODULE_END_ID)) {\r
375 if (StartHandle == NULL && !IsZeroGuid (ModuleGuid)) {\r
376 Measurement->Token = ALit_PEIM;\r
377 Measurement->Handle = ModuleGuid;\r
378 } else {\r
379 Measurement->Token = ALit_START_IMAGE;\r
380 }\r
381 }\r
115eae65
DB
382 }\r
383 break;\r
384\r
385 case FPDT_GUID_QWORD_EVENT_TYPE:\r
386 ModuleGuid = &(((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Guid);\r
387 Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->ProgressID);\r
388 if (IsStart) {\r
389 Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp;\r
390 } else {\r
391 Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp;\r
392 }\r
393 switch (Measurement->Identifier) {\r
394 case MODULE_DB_START_ID:\r
395 Measurement->Token = ALit_DB_START;\r
396 Measurement->Module = ALit_DB_START;\r
397 break;\r
398\r
399 case MODULE_DB_SUPPORT_START_ID:\r
400 case MODULE_DB_SUPPORT_END_ID:\r
401 Measurement->Token = ALit_DB_SUPPORT;\r
402 Measurement->Module = ALit_DB_SUPPORT;\r
403 break;\r
404\r
405 case MODULE_DB_STOP_START_ID:\r
406 case MODULE_DB_STOP_END_ID:\r
407 Measurement->Token = ALit_DB_STOP;\r
408 Measurement->Module = ALit_DB_STOP;\r
409 break;\r
410\r
411 case MODULE_LOADIMAGE_START_ID:\r
412 case MODULE_LOADIMAGE_END_ID:\r
413 Measurement->Token = ALit_LOAD_IMAGE;\r
414 Measurement->Module = ALit_LOAD_IMAGE;\r
415 break;\r
416\r
417 default:\r
418 ASSERT(FALSE);\r
419 }\r
420 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
421 Measurement->Handle = StartHandle;\r
422 break;\r
423\r
424 case FPDT_GUID_QWORD_STRING_EVENT_TYPE:\r
425 ModuleGuid = &(((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Guid);\r
426 Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);\r
427 if (IsStart) {\r
428 Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD*)RecordHeader)->Timestamp;\r
429 } else {\r
430 Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
431 }\r
432 //\r
433 // Currently only "DB:Start:" end record with FPDT_GUID_QWORD_STRING_EVENT_TYPE.\r
434 //\r
435 switch (Measurement->Identifier) {\r
436 case MODULE_DB_END_ID:\r
437 Measurement->Token = ALit_DB_START;\r
438 Measurement->Module = ALit_DB_START;\r
439 break;\r
440 default:\r
441 ASSERT(FALSE);\r
442 }\r
443 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
444 Measurement->Handle = StartHandle;\r
445 break;\r
446\r
f45dd2dd
BD
447 case FPDT_DUAL_GUID_STRING_EVENT_TYPE:\r
448 ModuleGuid = &(((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Guid1);\r
449 Measurement->Identifier = ((UINT32)((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);\r
450 if (IsStart) {\r
451 Measurement->StartTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
452 } else {\r
453 Measurement->EndTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
454 }\r
455 Measurement->Token = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String;\r
456 Measurement->Module = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String;\r
457 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
458 Measurement->Handle = StartHandle;\r
459 break;\r
460\r
115eae65
DB
461 default:\r
462 break;\r
463 }\r
464}\r
465\r
466/**\r
467 Search the start measurement in the mMeasurementList for the end measurement.\r
468\r
469 @param EndMeasureMent Measurement for end record.\r
470\r
471**/\r
472VOID\r
473SearchMeasurement (\r
474 IN MEASUREMENT_RECORD *EndMeasureMent\r
475 )\r
476{\r
477 INTN Index;\r
478\r
479 for (Index = mMeasurementNum - 1; Index >= 0; Index--) {\r
480 if (AsciiStrCmp (EndMeasureMent->Token, ALit_PEIM) == 0) {\r
481 if (mMeasurementList[Index].EndTimeStamp == 0 && EndMeasureMent->Handle!= NULL && mMeasurementList[Index].Handle != NULL&&\r
482 CompareGuid(mMeasurementList[Index].Handle, EndMeasureMent->Handle) &&\r
483 (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&\r
484 (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) {\r
485 mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;\r
486 break;\r
487 }\r
f45dd2dd
BD
488 } else if (EndMeasureMent->Identifier == PERF_CROSSMODULE_END_ID) {\r
489 if (mMeasurementList[Index].EndTimeStamp == 0 &&\r
490 (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&\r
491 (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0) &&\r
492 mMeasurementList[Index].Identifier == PERF_CROSSMODULE_START_ID) {\r
493 mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;\r
494 break;\r
495 }\r
115eae65
DB
496 } else {\r
497 if (mMeasurementList[Index].EndTimeStamp == 0 && mMeasurementList[Index].Handle == EndMeasureMent->Handle &&\r
498 (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&\r
499 (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) {\r
500 mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;\r
501 break;\r
502 }\r
503 }\r
504 }\r
505}\r
506\r
507/**\r
508 Generate the measure record array.\r
509\r
510**/\r
511EFI_STATUS\r
512BuildMeasurementList (\r
513 )\r
514{\r
515 EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader;\r
516 UINT8 *PerformanceTablePtr;\r
517 UINT16 StartProgressId;\r
518 UINTN TableLength;\r
519 UINT8 *StartRecordEvent;\r
520 MEASUREMENT_RECORD MeasureMent;\r
521\r
522 mMeasurementList = AllocateZeroPool (mBootPerformanceTableSize);\r
523 if (mMeasurementList == NULL) {\r
524 return EFI_OUT_OF_RESOURCES;\r
525 }\r
526\r
527 TableLength = sizeof (BOOT_PERFORMANCE_TABLE);\r
528 PerformanceTablePtr = (mBootPerformanceTable + TableLength);\r
529\r
530 while (TableLength < mBootPerformanceTableSize) {\r
531 RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER*) PerformanceTablePtr;\r
532 StartRecordEvent = (UINT8 *)RecordHeader;\r
533 StartProgressId = ((FPDT_GUID_EVENT_RECORD *)StartRecordEvent)->ProgressID;\r
534\r
535 //\r
f45dd2dd 536 // If the record with ProgressId 0, the record doesn't appear in pairs. The timestamp in the record is the EndTimeStamp, its StartTimeStamp is 0.\r
115eae65
DB
537 // If the record is the start record, fill the info to the measurement in the mMeasurementList.\r
538 // If the record is the end record, find the related start measurement in the mMeasurementList and fill the EndTimeStamp.\r
539 //\r
f45dd2dd
BD
540 if (StartProgressId == 0) {\r
541 GetMeasurementInfo (RecordHeader, FALSE, &(mMeasurementList[mMeasurementNum]));\r
542 mMeasurementNum ++;\r
543 } else if (((StartProgressId >= PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x000F) == 0)) ||\r
115eae65
DB
544 (StartProgressId < PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x0001) != 0)))) {\r
545 //\r
546 // Since PEIM and StartImage has same Type and ID when PCD PcdEdkiiFpdtStringRecordEnableOnly = FALSE\r
547 // So we need to identify these two kinds of record through different phase.\r
548 //\r
f45dd2dd
BD
549 if(StartProgressId == PERF_CROSSMODULE_START_ID ){\r
550 if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_PEI) == 0) {\r
551 mPeiPhase = TRUE;\r
552 } else if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_DXE) == 0) {\r
553 mDxePhase = TRUE;\r
554 mPeiPhase = FALSE;\r
555 }\r
115eae65
DB
556 }\r
557 // Get measurement info form the start record to the mMeasurementList.\r
558 GetMeasurementInfo (RecordHeader, TRUE, &(mMeasurementList[mMeasurementNum]));\r
559 mMeasurementNum ++;\r
560 } else {\r
f45dd2dd 561 ZeroMem(&MeasureMent, sizeof(MEASUREMENT_RECORD));\r
115eae65
DB
562 GetMeasurementInfo (RecordHeader, FALSE, &MeasureMent);\r
563 SearchMeasurement (&MeasureMent);\r
564 }\r
565 TableLength += RecordHeader->Length;\r
566 PerformanceTablePtr += RecordHeader->Length;\r
567 }\r
568 return EFI_SUCCESS;\r
569}\r
570\r
303ec9bc
CS
571/**\r
572 Initialize the cumulative data.\r
573\r
574**/\r
575VOID\r
576InitCumulativeData (\r
577 VOID\r
578 )\r
579{\r
580 UINTN Index;\r
581\r
582 for (Index = 0; Index < NumCum; ++Index) {\r
583 CumData[Index].Count = 0;\r
584 CumData[Index].MinDur = PERF_MAXDUR;\r
585 CumData[Index].MaxDur = 0;\r
586 CumData[Index].Duration = 0;\r
587 }\r
588}\r
589\r
d25cf17c
DB
590/**\r
591 Initialize the Summary data.\r
592\r
593**/\r
594VOID\r
595InitSummaryData (\r
596 VOID\r
597 )\r
598{\r
599 SummaryData.NumTrace = 0;\r
d25cf17c
DB
600 SummaryData.NumIncomplete = 0;\r
601 SummaryData.NumSummary = 0;\r
602 SummaryData.NumHandles = 0;\r
603 SummaryData.NumPEIMs = 0;\r
604 SummaryData.NumGlobal = 0;\r
605}\r
606\r
303ec9bc 607/**\r
d41bc92c 608 Dump performance data.\r
ba0014b9 609\r
d41bc92c 610 @param[in] ImageHandle The image handle.\r
611 @param[in] SystemTable The system table.\r
ba0014b9 612\r
196ccda0
CS
613 @retval SHELL_SUCCESS Command completed successfully.\r
614 @retval SHELL_INVALID_PARAMETER Command usage error.\r
615 @retval SHELL_ABORTED The user aborts the operation.\r
616 @retval value Unknown error.\r
d41bc92c 617**/\r
618SHELL_STATUS\r
92034c4c 619RunDp (\r
d41bc92c 620 IN EFI_HANDLE ImageHandle,\r
621 IN EFI_SYSTEM_TABLE *SystemTable\r
622 )\r
623{\r
624 LIST_ENTRY *ParamPackage;\r
625 CONST CHAR16 *CmdLineArg;\r
626 EFI_STATUS Status;\r
627\r
ef224032 628 PERFORMANCE_PROPERTY *PerformanceProperty;\r
d41bc92c 629 UINTN Number2Display;\r
630\r
a9b4ff8d
ED
631 EFI_STRING StringPtr;\r
632 BOOLEAN SummaryMode;\r
633 BOOLEAN VerboseMode;\r
634 BOOLEAN AllMode;\r
635 BOOLEAN RawMode;\r
a9b4ff8d 636 BOOLEAN ExcludeMode;\r
a06795c6
CS
637 BOOLEAN CumulativeMode;\r
638 CONST CHAR16 *CustomCumulativeToken;\r
639 PERF_CUM_DATA *CustomCumulativeData;\r
46213c8e 640 UINTN NameSize;\r
196ccda0 641 SHELL_STATUS ShellStatus;\r
115eae65 642 TIMER_INFO TimerInfo;\r
728f8950 643 UINT64 Intermediate;\r
a9b4ff8d
ED
644\r
645 StringPtr = NULL;\r
646 SummaryMode = FALSE;\r
647 VerboseMode = FALSE;\r
648 AllMode = FALSE;\r
649 RawMode = FALSE;\r
a9b4ff8d 650 ExcludeMode = FALSE;\r
a06795c6
CS
651 CumulativeMode = FALSE;\r
652 CustomCumulativeData = NULL;\r
196ccda0 653 ShellStatus = SHELL_SUCCESS;\r
d41bc92c 654\r
d41bc92c 655 //\r
656 // initialize the shell lib (we must be in non-auto-init...)\r
657 //\r
658 Status = ShellInitialize();\r
659 ASSERT_EFI_ERROR(Status);\r
660\r
d41bc92c 661 //\r
662 // Process Command Line arguments\r
663 //\r
664 Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);\r
665 if (EFI_ERROR(Status)) {\r
92034c4c 666 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), mDpHiiHandle);\r
d41bc92c 667 return SHELL_INVALID_PARAMETER;\r
728f8950
DB
668 } else if (ShellCommandLineGetCount(ParamPackage) > 1){\r
669 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_MANY), mDpHiiHandle);\r
670 return SHELL_INVALID_PARAMETER;\r
d41bc92c 671 }\r
672\r
673 //\r
674 // Boolean options\r
675 //\r
676 VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");\r
677 SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));\r
678 AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");\r
679 RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");\r
d41bc92c 680 ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");\r
681 mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");\r
a06795c6 682 CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");\r
d41bc92c 683\r
728f8950
DB
684 if (AllMode && RawMode) {\r
685 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CONFLICT_ARG), mDpHiiHandle, L"-A", L"-R");\r
686 return SHELL_INVALID_PARAMETER;\r
687 }\r
688\r
d41bc92c 689 // Options with Values\r
728f8950
DB
690 if (ShellCommandLineGetFlag (ParamPackage, L"-n")) {\r
691 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");\r
692 if (CmdLineArg == NULL) {\r
693 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle);\r
694 return SHELL_INVALID_PARAMETER;\r
695 } else {\r
696 if (!(RawMode || AllMode)) {\r
697 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_NO_RAW_ALL), mDpHiiHandle);\r
698 return SHELL_INVALID_PARAMETER;\r
699 }\r
700 Status = ShellConvertStringToUint64(CmdLineArg, &Intermediate, FALSE, TRUE);\r
701 if (EFI_ERROR (Status)) {\r
702 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-n");\r
703 return SHELL_INVALID_PARAMETER;\r
704 } else {\r
705 Number2Display = (UINTN)Intermediate;\r
706 if (Number2Display == 0 || Number2Display > MAXIMUM_DISPLAYCOUNT) {\r
707 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_RANGE), mDpHiiHandle, L"-n", 0, MAXIMUM_DISPLAYCOUNT);\r
708 return SHELL_INVALID_PARAMETER;\r
709 }\r
710 }\r
d41bc92c 711 }\r
728f8950
DB
712 } else {\r
713 Number2Display = DEFAULT_DISPLAYCOUNT;\r
d41bc92c 714 }\r
715\r
728f8950
DB
716 if (ShellCommandLineGetFlag (ParamPackage, L"-t")) {\r
717 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");\r
718 if (CmdLineArg == NULL) {\r
719 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle);\r
720 return SHELL_INVALID_PARAMETER;\r
721 } else {\r
722 Status = ShellConvertStringToUint64(CmdLineArg, &Intermediate, FALSE, TRUE);\r
723 if (EFI_ERROR (Status)) {\r
724 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-t");\r
725 return SHELL_INVALID_PARAMETER;\r
726 } else {\r
727 mInterestThreshold = Intermediate;\r
728 }\r
729 }\r
d41bc92c 730 } else {\r
728f8950 731 mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us\r
d41bc92c 732 }\r
733\r
728f8950
DB
734 if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {\r
735 CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");\r
736 if (CustomCumulativeToken == NULL) {\r
737 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle);\r
738 return SHELL_INVALID_PARAMETER;\r
739 } else {\r
740 CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));\r
741 if (CustomCumulativeData == NULL) {\r
742 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
743 goto Done;\r
744 }\r
745 CustomCumulativeData->MinDur = PERF_MAXDUR;\r
746 CustomCumulativeData->MaxDur = 0;\r
747 CustomCumulativeData->Count = 0;\r
748 CustomCumulativeData->Duration = 0;\r
749 NameSize = StrLen (CustomCumulativeToken) + 1;\r
750 CustomCumulativeData->Name = AllocateZeroPool (NameSize);\r
751 if (CustomCumulativeData->Name == NULL) {\r
752 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
753 goto Done;\r
754 }\r
755 UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize);\r
756 }\r
757 }\r
d41bc92c 758\r
37d533da
DB
759 //\r
760 // DP dump performance data by parsing FPDT table in ACPI table.\r
761 // Folloing 3 steps are to get the measurement form the FPDT table.\r
762 //\r
763\r
764 //\r
765 //1. Get FPDT from ACPI table.\r
766 //\r
767 Status = GetBootPerformanceTable ();\r
768 if (EFI_ERROR (Status)) {\r
769 ShellStatus = Status;\r
770 goto Done;\r
771 }\r
772\r
773 //\r
774 //2. Cache the ModuleGuid and hanlde mapping table.\r
775 //\r
776 Status = BuildCachedGuidHandleTable();\r
777 if (EFI_ERROR (Status)) {\r
778 ShellStatus = Status;\r
779 goto Done;\r
780 }\r
781\r
782 //\r
783 //3. Build the measurement array form the FPDT records.\r
784 //\r
785 Status = BuildMeasurementList ();\r
786 if (EFI_ERROR (Status)) {\r
787 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
788 goto Done;\r
789 }\r
790\r
303ec9bc
CS
791 //\r
792 // Initialize the pre-defined cumulative data.\r
793 //\r
794 InitCumulativeData ();\r
795\r
d25cf17c
DB
796 //\r
797 // Initialize the Summary data.\r
798 //\r
799 InitSummaryData ();\r
800\r
d41bc92c 801 //\r
802 // Timer specific processing\r
803 //\r
804 // Get the Performance counter characteristics:\r
805 // Freq = Frequency in Hz\r
806 // StartCount = Value loaded into the counter when it starts counting\r
807 // EndCount = Value counter counts to before it needs to be reset\r
808 //\r
37322be5 809 Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty);\r
24c6962d 810 if (EFI_ERROR (Status) || (PerformanceProperty == NULL)) {\r
92034c4c 811 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND), mDpHiiHandle);\r
ef224032
SZ
812 goto Done;\r
813 }\r
d41bc92c 814\r
ef224032 815 TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000);\r
115eae65
DB
816 TimerInfo.StartCount = 0;\r
817 TimerInfo.EndCount = 0xFFFF;\r
818 TimerInfo.CountUp = TRUE;\r
d41bc92c 819\r
820 //\r
821 // Print header\r
822 //\r
823 // print DP's build version\r
92034c4c 824 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), mDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);\r
d41bc92c 825\r
826 // print performance timer characteristics\r
92034c4c 827 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), mDpHiiHandle, TimerInfo.Frequency);\r
d41bc92c 828\r
829 if (VerboseMode && !RawMode) {\r
92034c4c 830 StringPtr = HiiGetString (mDpHiiHandle,\r
d41bc92c 831 (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);\r
832 ASSERT (StringPtr != NULL);\r
833 // Print Timer count range and direction\r
92034c4c 834 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), mDpHiiHandle,\r
d41bc92c 835 StringPtr,\r
836 TimerInfo.StartCount,\r
837 TimerInfo.EndCount\r
838 );\r
92034c4c 839 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mDpHiiHandle, mInterestThreshold);\r
d41bc92c 840 }\r
841\r
842/****************************************************************************\r
843**** Print Sections based on command line options\r
844****\r
845**** Option modes have the following priority:\r
846**** v Verbose -- Valid in combination with any other options\r
847**** t Threshold -- Modifies All, Raw, and Cooked output\r
848**** Default is 0 for All and Raw mode\r
849**** Default is DEFAULT_THRESHOLD for "Cooked" mode\r
850**** n Number2Display Used by All and Raw mode. Otherwise ignored.\r
851**** A All -- R and S options are ignored\r
852**** R Raw -- S option is ignored\r
853**** s Summary -- Modifies "Cooked" output only\r
854**** Cooked (Default)\r
d41bc92c 855****************************************************************************/\r
a06795c6 856 GatherStatistics (CustomCumulativeData);\r
ba0014b9 857 if (CumulativeMode) {\r
a06795c6
CS
858 ProcessCumulative (CustomCumulativeData);\r
859 } else if (AllMode) {\r
5a56c049
DB
860 Status = DumpAllTrace( Number2Display, ExcludeMode);\r
861 if (Status == EFI_ABORTED) {\r
862 ShellStatus = SHELL_ABORTED;\r
863 goto Done;\r
864 }\r
865 } else if (RawMode) {\r
866 Status = DumpRawTrace( Number2Display, ExcludeMode);\r
867 if (Status == EFI_ABORTED) {\r
868 ShellStatus = SHELL_ABORTED;\r
869 goto Done;\r
870 }\r
871 } else {\r
872 //------------- Begin Cooked Mode Processing\r
873 ProcessPhases ();\r
874 if ( ! SummaryMode) {\r
875 Status = ProcessHandles ( ExcludeMode);\r
196ccda0
CS
876 if (Status == EFI_ABORTED) {\r
877 ShellStatus = SHELL_ABORTED;\r
878 goto Done;\r
879 }\r
5a56c049
DB
880\r
881 Status = ProcessPeims ();\r
196ccda0
CS
882 if (Status == EFI_ABORTED) {\r
883 ShellStatus = SHELL_ABORTED;\r
884 goto Done;\r
885 }\r
5a56c049
DB
886\r
887 Status = ProcessGlobal ();\r
888 if (Status == EFI_ABORTED) {\r
889 ShellStatus = SHELL_ABORTED;\r
890 goto Done;\r
d41bc92c 891 }\r
5a56c049
DB
892\r
893 ProcessCumulative (NULL);\r
d41bc92c 894 }\r
895 } //------------- End of Cooked Mode Processing\r
896 if ( VerboseMode || SummaryMode) {\r
897 DumpStatistics();\r
898 }\r
899\r
196ccda0 900Done:\r
3751a092
CS
901 if (ParamPackage != NULL) {\r
902 ShellCommandLineFreeVarList (ParamPackage);\r
903 }\r
d41bc92c 904 SHELL_FREE_NON_NULL (StringPtr);\r
a06795c6
CS
905 if (CustomCumulativeData != NULL) {\r
906 SHELL_FREE_NON_NULL (CustomCumulativeData->Name);\r
907 }\r
908 SHELL_FREE_NON_NULL (CustomCumulativeData);\r
d41bc92c 909\r
115eae65
DB
910 SHELL_FREE_NON_NULL (mMeasurementList);\r
911\r
912 SHELL_FREE_NON_NULL (mCacheHandleGuidTable);\r
913\r
914 mMeasurementNum = 0;\r
915 mCachePairCount = 0;\r
196ccda0 916 return ShellStatus;\r
d41bc92c 917}\r
92034c4c
RN
918\r
919\r
920/**\r
f16bd394 921 Retrieve HII package list from ImageHandle and publish to HII database.\r
92034c4c
RN
922\r
923 @param ImageHandle The image handle of the process.\r
924\r
925 @return HII handle.\r
926**/\r
c44501b3 927EFI_HII_HANDLE\r
92034c4c
RN
928InitializeHiiPackage (\r
929 EFI_HANDLE ImageHandle\r
930 )\r
931{\r
932 EFI_STATUS Status;\r
933 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
c44501b3 934 EFI_HII_HANDLE HiiHandle;\r
92034c4c
RN
935\r
936 //\r
937 // Retrieve HII package list from ImageHandle\r
938 //\r
939 Status = gBS->OpenProtocol (\r
940 ImageHandle,\r
941 &gEfiHiiPackageListProtocolGuid,\r
942 (VOID **)&PackageList,\r
943 ImageHandle,\r
944 NULL,\r
945 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
946 );\r
947 ASSERT_EFI_ERROR (Status);\r
948 if (EFI_ERROR (Status)) {\r
949 return NULL;\r
950 }\r
951\r
952 //\r
953 // Publish HII package list to HII Database.\r
954 //\r
955 Status = gHiiDatabase->NewPackageList (\r
956 gHiiDatabase,\r
957 PackageList,\r
958 NULL,\r
959 &HiiHandle\r
960 );\r
961 ASSERT_EFI_ERROR (Status);\r
962 if (EFI_ERROR (Status)) {\r
963 return NULL;\r
964 }\r
965 return HiiHandle;\r
966}\r