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