Dp.c 34 KB

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