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