]> git.proxmox.com Git - mirror_edk2.git/blame - PrmPkg/Application/PrmInfo/PrmInfo.c
PrmPkg: Enforce stricter types
[mirror_edk2.git] / PrmPkg / Application / PrmInfo / PrmInfo.c
CommitLineData
4348c72a
MK
1/** @file\r
2 Prints information about the PRM configuration loaded by the system firmware.\r
3\r
4 This application also provides some additional testing features for PRM configuration. For example,\r
5 the application can be used to selectively invoke PRM handlers in the UEFI shell environment to\r
6 provide a quick testing path of the PRM infrastructure on the firmware and the PRM module implementation.\r
7\r
8 This can also be useful to prepare a PRM enabled firmware and PRM modules prior to formal OS support to\r
9 test the PRM code.\r
10\r
11 Copyright (C) Microsoft Corporation. All rights reserved.\r
12 SPDX-License-Identifier: BSD-2-Clause-Patent\r
13\r
14**/\r
15\r
16#include <Guid/ZeroGuid.h>\r
17#include <Library/BaseLib.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/HiiLib.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/PcdLib.h>\r
23#include <Library/PrmContextBufferLib.h>\r
24#include <Library/PrmModuleDiscoveryLib.h>\r
25#include <Library/PrmPeCoffLib.h>\r
26#include <Library/ShellLib.h>\r
27#include <Library/TimerLib.h>\r
28#include <Library/UefiApplicationEntryPoint.h>\r
29#include <Library/UefiBootServicesTableLib.h>\r
30#include <Library/UefiHiiServicesLib.h>\r
31#include <Library/UefiLib.h>\r
32\r
33#include "PrmInfo.h"\r
34\r
35GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringPrmInfoHelpTokenId = STRING_TOKEN (STR_PRMINFO_HELP);\r
36//\r
37// This is the generated String package data for all .UNI files.\r
38// This data array is ready to be used as input of HiiAddPackages() to\r
39// create a packagelist (which contains Form packages, String packages, etc).\r
40//\r
41extern UINT8 PrmInfoStrings[];\r
42\r
43STATIC UINTN mPrmHandlerCount;\r
44STATIC UINTN mPrmModuleCount;\r
45\r
46STATIC EFI_HII_HANDLE mPrmInfoHiiHandle;\r
47STATIC LIST_ENTRY mPrmHandlerList;\r
48\r
49STATIC CONST SHELL_PARAM_ITEM mParamList[] = {\r
50 {L"-l", TypeFlag},\r
51 {L"-t", TypeValue},\r
52 {NULL, TypeMax}\r
53 };\r
54\r
55/**\r
56 Frees all of the nodes in a linked list.\r
57\r
58 @param[in] ListHead A pointer to the head of the list that should be freed.\r
59\r
60 **/\r
61VOID\r
62EFIAPI\r
63FreeList (\r
64 IN LIST_ENTRY *ListHead\r
65 )\r
66{\r
67 LIST_ENTRY *Link;\r
68 LIST_ENTRY *NextLink;\r
69 PRM_HANDLER_CONTEXT_LIST_ENTRY *ListEntry;\r
70\r
71 if (ListHead == NULL) {\r
72 return;\r
73 }\r
74\r
75 Link = GetFirstNode (&mPrmHandlerList);\r
76 while (!IsNull (&mPrmHandlerList, Link)) {\r
77 ListEntry = CR (Link, PRM_HANDLER_CONTEXT_LIST_ENTRY, Link, PRM_HANDLER_CONTEXT_LIST_ENTRY_SIGNATURE);\r
78 NextLink = GetNextNode (&mPrmHandlerList, Link);\r
79\r
80 RemoveEntryList (Link);\r
81 FreePool (ListEntry);\r
82\r
83 Link = NextLink;\r
84 }\r
85}\r
86\r
87/**\r
88 Creates a new PRM Module Image Context linked list entry.\r
89\r
90 @retval PrmHandlerContextListEntry If successful, a pointer a PRM Handler Context linked list entry\r
91 otherwise, NULL is returned.\r
92\r
93**/\r
94PRM_HANDLER_CONTEXT_LIST_ENTRY *\r
95CreateNewPrmHandlerListEntry (\r
96 VOID\r
97 )\r
98{\r
99 PRM_HANDLER_CONTEXT_LIST_ENTRY *PrmHandlerContextListEntry;\r
100\r
101 PrmHandlerContextListEntry = AllocateZeroPool (sizeof (*PrmHandlerContextListEntry));\r
102 if (PrmHandlerContextListEntry == NULL) {\r
103 return NULL;\r
104 }\r
105 PrmHandlerContextListEntry->Signature = PRM_HANDLER_CONTEXT_LIST_ENTRY_SIGNATURE;\r
106\r
107 return PrmHandlerContextListEntry;\r
108}\r
109\r
110/**\r
111 Creates a new PRM Module Image Context linked list entry.\r
112\r
113 @param[in] RuntimeMmioRanges A pointer to an array of PRM module config runtime MMIO ranges.\r
114\r
115**/\r
116VOID\r
117PrintMmioRuntimeRangeInfo (\r
118 IN PRM_RUNTIME_MMIO_RANGES *RuntimeMmioRanges\r
119 )\r
120{\r
121 UINTN RuntimeMmioRangeCount;\r
122 UINTN RuntimeMmioRangeIndex;\r
123\r
124 if (RuntimeMmioRanges == NULL) {\r
125 return;\r
126 }\r
127\r
128 RuntimeMmioRangeCount = (UINTN) RuntimeMmioRanges->Count;\r
129 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_RUNTIME_MMIO_COUNT), mPrmInfoHiiHandle, RuntimeMmioRangeCount);\r
130\r
131 for (RuntimeMmioRangeIndex = 0; RuntimeMmioRangeIndex < RuntimeMmioRangeCount; RuntimeMmioRangeIndex++) {\r
132 ShellPrintHiiEx (\r
133 -1,\r
134 -1,\r
135 NULL,\r
136 STRING_TOKEN (STR_PRMINFO_RUNTIME_MMIO_INFO),\r
137 mPrmInfoHiiHandle,\r
138 RuntimeMmioRangeIndex,\r
139 RuntimeMmioRanges->Range[RuntimeMmioRangeIndex].PhysicalBaseAddress,\r
140 RuntimeMmioRanges->Range[RuntimeMmioRangeIndex].VirtualBaseAddress,\r
141 RuntimeMmioRanges->Range[RuntimeMmioRangeIndex].Length\r
142 );\r
143 }\r
144}\r
145\r
146/**\r
147 Gathers the PRM handler (and by extension module) information discovered on this system.\r
148\r
149 This function must be called to build up the discovered context for other functions in the application. The\r
150 function will optionally print results as determed by the value of the PrintInformation parameter.\r
151\r
152 @param[in] PrintInformation Indicates whether to print information as discovered in the function.\r
153\r
154**/\r
155VOID\r
156GatherPrmHandlerInfo (\r
157 IN BOOLEAN PrintInformation\r
158 )\r
159{\r
160 EFI_STATUS Status;\r
161 UINT16 MajorVersion;\r
162 UINT16 MinorVersion;\r
163 UINT16 HandlerCount;\r
164 UINTN HandlerIndex;\r
165 EFI_PHYSICAL_ADDRESS CurrentHandlerPhysicalAddress;\r
166 EFI_PHYSICAL_ADDRESS CurrentImageAddress;\r
167 PRM_HANDLER_CONTEXT CurrentHandlerContext;\r
168 EFI_GUID *CurrentModuleGuid;\r
169 EFI_IMAGE_EXPORT_DIRECTORY *CurrentImageExportDirectory;\r
170 PRM_CONTEXT_BUFFER *CurrentContextBuffer;\r
171 PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *CurrentExportDescriptorStruct;\r
172 PRM_MODULE_CONTEXT_BUFFERS *CurrentModuleContextBuffers;\r
173 PRM_HANDLER_CONTEXT_LIST_ENTRY *CurrentHandlerContextListEntry;\r
174 PRM_MODULE_IMAGE_CONTEXT *CurrentPrmModuleImageContext;\r
175 PRM_RUNTIME_MMIO_RANGES *CurrentPrmModuleRuntimeMmioRanges;\r
176\r
177 ASSERT (mPrmModuleCount <= mPrmHandlerCount);\r
178\r
179 if (mPrmHandlerCount == 0) {\r
180 return;\r
181 }\r
182\r
183 // Iterate across all PRM modules discovered\r
184 for (\r
185 CurrentPrmModuleImageContext = NULL, Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext);\r
186 !EFI_ERROR (Status);\r
187 Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext)) {\r
188\r
189 CurrentImageAddress = CurrentPrmModuleImageContext->PeCoffImageContext.ImageAddress;\r
190 CurrentImageExportDirectory = CurrentPrmModuleImageContext->ExportDirectory;\r
191 CurrentExportDescriptorStruct = CurrentPrmModuleImageContext->ExportDescriptor;\r
192\r
193 CurrentModuleGuid = &CurrentExportDescriptorStruct->Header.ModuleGuid;\r
194 HandlerCount = CurrentExportDescriptorStruct->Header.NumberPrmHandlers;\r
195\r
196 MajorVersion = 0;\r
197 MinorVersion = 0;\r
198 Status = GetImageVersionInPeCoffImage (\r
199 (VOID *) (UINTN) CurrentImageAddress,\r
200 &CurrentPrmModuleImageContext->PeCoffImageContext,\r
201 &MajorVersion,\r
202 &MinorVersion\r
203 );\r
204 ASSERT_EFI_ERROR (Status);\r
205\r
206 if (PrintInformation) {\r
207 ShellPrintHiiEx (\r
208 -1,\r
209 -1,\r
210 NULL,\r
211 STRING_TOKEN (STR_PRMINFO_MODULE_NAME),\r
212 mPrmInfoHiiHandle,\r
213 (CHAR8 *) ((UINTN) CurrentImageAddress + CurrentImageExportDirectory->Name)\r
214 );\r
215 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MODULE_GUID), mPrmInfoHiiHandle, CurrentModuleGuid);\r
216 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MODULE_VERSION), mPrmInfoHiiHandle, MajorVersion, MinorVersion);\r
217 }\r
218\r
219 // It is currently valid for a PRM module not to use a context buffer\r
220 CurrentPrmModuleRuntimeMmioRanges = NULL;\r
221 Status = GetModuleContextBuffers (\r
222 ByModuleGuid,\r
223 CurrentModuleGuid,\r
e10c7764 224 (CONST PRM_MODULE_CONTEXT_BUFFERS **) &CurrentModuleContextBuffers\r
4348c72a
MK
225 );\r
226 ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);\r
227 if (!EFI_ERROR (Status) && CurrentModuleContextBuffers != NULL) {\r
228 CurrentPrmModuleRuntimeMmioRanges = CurrentModuleContextBuffers->RuntimeMmioRanges;\r
229 }\r
230\r
231 if (PrintInformation) {\r
232 if (CurrentPrmModuleRuntimeMmioRanges != NULL) {\r
233 PrintMmioRuntimeRangeInfo (CurrentPrmModuleRuntimeMmioRanges);\r
234 } else {\r
235 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_MMIO_RANGES), mPrmInfoHiiHandle);\r
236 }\r
237 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);\r
238 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_COUNT), mPrmInfoHiiHandle, HandlerCount);\r
239 }\r
240\r
241 for (HandlerIndex = 0; HandlerIndex < HandlerCount; HandlerIndex++) {\r
242 ZeroMem (&CurrentHandlerContext, sizeof (CurrentHandlerContext));\r
243\r
244 CurrentHandlerContext.ModuleName = (CHAR8 *) ((UINTN) CurrentImageAddress + CurrentImageExportDirectory->Name);\r
245 CurrentHandlerContext.Guid = &CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerGuid;\r
246 CurrentHandlerContext.Name = (CHAR8 *) CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerName;\r
247\r
248 if (PrintInformation) {\r
249 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_NAME), mPrmInfoHiiHandle, CurrentHandlerContext.Name);\r
250 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_GUID), mPrmInfoHiiHandle, CurrentHandlerContext.Guid);\r
251 }\r
252\r
253 Status = GetExportEntryAddress (\r
254 CurrentHandlerContext.Name,\r
255 CurrentImageAddress,\r
256 CurrentImageExportDirectory,\r
257 &CurrentHandlerPhysicalAddress\r
258 );\r
259 ASSERT_EFI_ERROR (Status);\r
260 if (!EFI_ERROR (Status)) {\r
261 CurrentHandlerContext.Handler = (PRM_HANDLER *) (UINTN) CurrentHandlerPhysicalAddress;\r
262\r
263 if (PrintInformation) {\r
264 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_PA), mPrmInfoHiiHandle, CurrentHandlerPhysicalAddress);\r
265 }\r
266 } else {\r
267 if (PrintInformation) {\r
268 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_PA_ERROR), mPrmInfoHiiHandle, Status);\r
269 }\r
270 }\r
271\r
272 Status = GetContextBuffer (\r
273 CurrentHandlerContext.Guid,\r
274 CurrentModuleContextBuffers,\r
e10c7764 275 (CONST PRM_CONTEXT_BUFFER **) &CurrentContextBuffer\r
4348c72a
MK
276 );\r
277 if (!EFI_ERROR (Status)) {\r
278 CurrentHandlerContext.StaticDataBuffer = CurrentContextBuffer->StaticDataBuffer;\r
279 }\r
280\r
281 if (PrintInformation) {\r
282 if (CurrentHandlerContext.StaticDataBuffer != NULL) {\r
283 ShellPrintHiiEx (\r
284 -1,\r
285 -1,\r
286 NULL,\r
287 STRING_TOKEN (STR_PRMINFO_STATIC_DATA_BUFFER),\r
288 mPrmInfoHiiHandle,\r
289 (UINTN) CurrentHandlerContext.StaticDataBuffer\r
290 );\r
291 } else {\r
292 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);\r
293 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_STATIC_BUFFER), mPrmInfoHiiHandle);\r
294 }\r
295 }\r
296\r
297 CurrentHandlerContextListEntry = CreateNewPrmHandlerListEntry ();\r
298 ASSERT (CurrentHandlerContextListEntry != NULL);\r
299 if (CurrentHandlerContextListEntry != NULL) {\r
300 CopyMem (\r
301 &CurrentHandlerContextListEntry->Context,\r
302 &CurrentHandlerContext,\r
303 sizeof (CurrentHandlerContextListEntry->Context)\r
304 );\r
305 InsertTailList (&mPrmHandlerList, &CurrentHandlerContextListEntry->Link);\r
306 }\r
307 }\r
308 }\r
309}\r
310\r
311/**\r
312 Populates the given context buffer so it can be passed to a PRM handler.\r
313\r
314 @param[in] StaticDataBuffer A pointer to the static data buffer that will be referenced in the context\r
315 buffer that is populated. This is an optional pointer that, if not provided,\r
316 by passing NULL will be ignored.\r
317 @param[in] HandlerGuid A pointer to the GUID of the PRM handler.\r
318 @param[in] ContextBuffer A pointer to a caller allocated ContextBuffer structure that will be populated\r
319 by this function.\r
320\r
321 @retval EFI_SUCCESS The given ContextBuffer was populated successfully.\r
322 @retval EFI_INVALID_PARAMETER The HandlerGuid or ContextBuffer actual argument is NULL.\r
323\r
324**/\r
325EFI_STATUS\r
326PopulateContextBuffer (\r
327 IN PRM_DATA_BUFFER *StaticDataBuffer OPTIONAL,\r
328 IN EFI_GUID *HandlerGuid,\r
329 IN PRM_CONTEXT_BUFFER *ContextBuffer\r
330 )\r
331{\r
332 if (HandlerGuid == NULL || ContextBuffer == NULL) {\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
335\r
336 ZeroMem (ContextBuffer, sizeof (*ContextBuffer));\r
337\r
338 ContextBuffer->Signature = PRM_CONTEXT_BUFFER_SIGNATURE;\r
339 ContextBuffer->Version = PRM_CONTEXT_BUFFER_INTERFACE_VERSION;\r
340 CopyGuid (&ContextBuffer->HandlerGuid, HandlerGuid);\r
341\r
342 if (StaticDataBuffer != NULL) {\r
343 ContextBuffer->StaticDataBuffer = StaticDataBuffer;\r
344 }\r
345\r
346 return EFI_SUCCESS;\r
347}\r
348\r
349/**\r
350 Prints a given execution time in the appropriate unit.\r
351\r
352 @param[in] TimeInNanoSec The time to print in unit of nanoseconds.\r
353\r
354**/\r
355VOID\r
356PrintExecutionTime (\r
357 IN UINT64 TimeInNanoSec\r
358 )\r
359{\r
360 UINT64 Sec;\r
361 UINT64 MilliSec;\r
362 UINT64 MicroSec;\r
363 UINT64 NanoSec;\r
364 UINT64 RemainingTime;\r
365\r
366 Sec = 0;\r
367 MilliSec = 0;\r
368 MicroSec = 0;\r
369 NanoSec = 0;\r
370 RemainingTime = TimeInNanoSec;\r
371\r
372 if (RemainingTime > ONE_SECOND) {\r
373 Sec = DivU64x32 (RemainingTime, ONE_SECOND);\r
374 RemainingTime -= MultU64x32 (Sec, ONE_SECOND);\r
375 }\r
376\r
377 if (RemainingTime > ONE_MILLISECOND) {\r
378 MilliSec = DivU64x32 (RemainingTime, ONE_MILLISECOND);\r
379 RemainingTime -= MultU64x32 (MilliSec, ONE_MILLISECOND);\r
380 }\r
381\r
382 if (RemainingTime > ONE_MICROSECOND) {\r
383 MicroSec = DivU64x32 (RemainingTime, ONE_MICROSECOND);\r
384 RemainingTime -= MultU64x32 (MicroSec, ONE_MICROSECOND);\r
385 }\r
386\r
387 if (RemainingTime > 0) {\r
388 NanoSec = RemainingTime;\r
389 }\r
390\r
391 if (Sec > 0) {\r
392 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_SECS), mPrmInfoHiiHandle, Sec, MilliSec, MicroSec, NanoSec);\r
393 } else if (MilliSec > 0) {\r
394 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MILLI_SECS), mPrmInfoHiiHandle, MilliSec, MicroSec, NanoSec);\r
395 } else if (MicroSec > 0) {\r
396 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_USECS), mPrmInfoHiiHandle, MicroSec, NanoSec);\r
397 } else {\r
398 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NANO_SECS), mPrmInfoHiiHandle, NanoSec);\r
399 }\r
400}\r
401\r
402/**\r
403 Executes the PRM handler with the provided GUID.\r
404\r
405 @param[in] HandlerGuid A pointer to the GUID of the PRM handler to execute.\r
406 A zero GUID indicates that all PRM handlers present should be executed.\r
407\r
408 @retval EFI_SUCCESS The PRM handler(s) were executed.\r
409 @retval EFI_INVALID_PARAMETER The HandlerGuid actual argument is NULL.\r
410 @retval EFI_NOT_FOUND The PRM handler could not be found.\r
411\r
412**/\r
413EFI_STATUS\r
414ExecutePrmHandlerByGuid (\r
415 IN EFI_GUID *HandlerGuid\r
416 )\r
417{\r
418 EFI_STATUS Status;\r
419 BOOLEAN ExecuteAllHandlers;\r
420 BOOLEAN HandlerFound;\r
421 UINT64 StartTime;\r
422 UINT64 EndTime;\r
423 PRM_CONTEXT_BUFFER CurrentContextBuffer;\r
424 PRM_HANDLER_CONTEXT *HandlerContext;\r
425 PRM_HANDLER_CONTEXT_LIST_ENTRY *HandlerContextListEntry;\r
426 LIST_ENTRY *Link;\r
427\r
428 Link = NULL;\r
429 HandlerFound = FALSE;\r
430\r
431 if (HandlerGuid == NULL) {\r
432 return EFI_INVALID_PARAMETER;\r
433 }\r
434\r
435 //\r
436 // Zero GUID means execute all discovered handlers\r
437 //\r
438 ExecuteAllHandlers = CompareGuid (HandlerGuid, &gZeroGuid);\r
439\r
440 EFI_LIST_FOR_EACH (Link, &mPrmHandlerList) {\r
441 HandlerContextListEntry = CR (Link, PRM_HANDLER_CONTEXT_LIST_ENTRY, Link, PRM_HANDLER_CONTEXT_LIST_ENTRY_SIGNATURE);\r
442 HandlerContext = &HandlerContextListEntry->Context;\r
443\r
444 if (!ExecuteAllHandlers && !CompareGuid (HandlerGuid, HandlerContext->Guid)) {\r
445 continue;\r
446 }\r
447\r
448 HandlerFound = TRUE;\r
449 Status = PopulateContextBuffer (HandlerContext->StaticDataBuffer, HandlerContext->Guid, &CurrentContextBuffer);\r
450 if (!EFI_ERROR (Status)) {\r
451 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);\r
452 ShellPrintHiiEx (\r
453 -1,\r
454 -1,\r
455 NULL,\r
456 STRING_TOKEN (STR_PRMINFO_MODULE_NAME),\r
457 mPrmInfoHiiHandle,\r
458 HandlerContext->ModuleName\r
459 );\r
460 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_NAME_HL), mPrmInfoHiiHandle, HandlerContext->Name);\r
461 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_GUID), mPrmInfoHiiHandle, HandlerContext->Guid);\r
462\r
463 StartTime = 0;\r
464 EndTime = 0;\r
465 if (PcdGetBool (PcdPrmInfoPrintHandlerExecutionTime)) {\r
466 StartTime = GetPerformanceCounter ();\r
467 }\r
468 Status = HandlerContext->Handler (NULL, &CurrentContextBuffer);\r
469 if (PcdGetBool (PcdPrmInfoPrintHandlerExecutionTime)) {\r
470 EndTime = GetPerformanceCounter ();\r
471 }\r
472\r
473 if (EFI_ERROR (Status)) {\r
474 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_ERR_STATUS), mPrmInfoHiiHandle, Status);\r
475 } else {\r
476 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_SUCC_STATUS), mPrmInfoHiiHandle, Status);\r
477 }\r
478\r
479 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_EXEC_TIME), mPrmInfoHiiHandle);\r
480 if (StartTime == 0 && EndTime == 0) {\r
481 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_UNKNOWN), mPrmInfoHiiHandle);\r
482 } else {\r
483 PrintExecutionTime (GetTimeInNanoSecond (EndTime - StartTime));\r
484 }\r
485 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);\r
486 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);\r
487 } else {\r
488 DEBUG ((\r
489 DEBUG_ERROR,\r
490 "%a - %a: An error occurred creating a context buffer for handler %g\n",\r
491 gEfiCallerBaseName,\r
492 __FUNCTION__,\r
493 HandlerContext->Guid\r
494 ));\r
495 }\r
496\r
497 if (!ExecuteAllHandlers) {\r
498 break;\r
499 }\r
500 }\r
501\r
502 if (!HandlerFound) {\r
503 return EFI_NOT_FOUND;\r
504 }\r
505\r
506 return EFI_SUCCESS;\r
507}\r
508\r
509/**\r
510 Parses the application parameter list and performs the appropriate operations based on the results.\r
511\r
512 @retval EFI_SUCCESS The parameter list was parsed successfully.\r
513 @retval EFI_INVALID_PARAMETER An invalid parameter was given to the application.\r
514 @retval EFI_LOAD_ERROR An error occurred loading the application.\r
515\r
516**/\r
517EFI_STATUS\r
518ParseParameterList (\r
519 VOID\r
520 )\r
521{\r
522 EFI_STATUS Status;\r
e10c7764 523 EFI_STATUS ReturnStatus;\r
4348c72a
MK
524 UINTN ArgumentCount;\r
525 EFI_GUID HandlerGuid;\r
526 BOOLEAN PrintHandlerInfo;\r
527 LIST_ENTRY *Package;\r
528 LIST_ENTRY *TempNode;\r
529 CHAR16 *ProblemParam;\r
530 CONST CHAR16 *HandlerGuidStr;\r
531\r
532 HandlerGuidStr = NULL;\r
533 Package = NULL;\r
534 PrintHandlerInfo = FALSE;\r
535 ReturnStatus = EFI_SUCCESS;\r
536\r
537 InitializeListHead (&mPrmHandlerList);\r
538\r
539 //\r
540 // Basic application parameter validation\r
541 //\r
542 Status = ShellCommandLineParseEx (mParamList, &Package, &ProblemParam, FALSE, FALSE);\r
543 if (EFI_ERROR (Status)) {\r
544 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
545 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_GEN_PROBLEM), mPrmInfoHiiHandle, APPLICATION_NAME, ProblemParam);\r
546 ReturnStatus = EFI_INVALID_PARAMETER;\r
547 FreePool (ProblemParam);\r
548 } else {\r
549 ReturnStatus = EFI_LOAD_ERROR;\r
550 ASSERT (FALSE);\r
551 }\r
552\r
553 goto Done;\r
554 } else if (Package == NULL) {\r
555 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_ARG), mPrmInfoHiiHandle, APPLICATION_NAME);\r
556 ReturnStatus = EFI_INVALID_PARAMETER;\r
557 goto Done;\r
558 }\r
559\r
560 //\r
561 // Get argument count including flags\r
562 //\r
563 for (\r
564 ArgumentCount = 0, TempNode = Package;\r
565 GetNextNode (Package, TempNode) != Package;\r
566 ArgumentCount++, TempNode = GetNextNode (Package, TempNode)\r
567 );\r
568\r
569 if (ArgumentCount == 1) {\r
570 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_ARG), mPrmInfoHiiHandle, APPLICATION_NAME);\r
571 ReturnStatus = EFI_INVALID_PARAMETER;\r
572 goto Done;\r
573 }\r
574\r
575 if (ArgumentCount > 6) {\r
576 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_TOO_MANY), mPrmInfoHiiHandle, APPLICATION_NAME);\r
577 ReturnStatus = EFI_INVALID_PARAMETER;\r
578 goto Done;\r
579 }\r
580\r
581 //\r
582 // Parse the actual arguments provided\r
583 //\r
584 if (ShellCommandLineGetFlag (Package, L"-b")) {\r
585 if (ArgumentCount <= 2) {\r
586 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_PARAM_INV), mPrmInfoHiiHandle, APPLICATION_NAME, L"-b");\r
587 ReturnStatus = EFI_INVALID_PARAMETER;\r
588 goto Done;\r
589 } else {\r
590 ShellSetPageBreakMode (TRUE);\r
591 }\r
592 }\r
593\r
594 if (ShellCommandLineGetFlag (Package, L"-l")) {\r
595 PrintHandlerInfo = TRUE;\r
596 }\r
597\r
598 if (ShellCommandLineGetFlag (Package, L"-t")) {\r
599 HandlerGuidStr = ShellCommandLineGetValue (Package, L"-t");\r
600 if (HandlerGuidStr != NULL) {\r
601 if (StrnCmp (HandlerGuidStr, L"all", StrLen (HandlerGuidStr)) == 0) {\r
602 CopyGuid (&HandlerGuid, &gZeroGuid);\r
603 } else {\r
604 Status = StrToGuid (HandlerGuidStr, &HandlerGuid);\r
605 if (EFI_ERROR (Status) || (HandlerGuidStr[GUID_STRING_LENGTH] != L'\0')) {\r
606 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_GUID_INV), mPrmInfoHiiHandle, APPLICATION_NAME, HandlerGuidStr);\r
607 ReturnStatus = EFI_INVALID_PARAMETER;\r
608 goto Done;\r
609 }\r
610 }\r
611 } else {\r
612 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_VALUE), mPrmInfoHiiHandle, APPLICATION_NAME, L"-t");\r
613 ReturnStatus = EFI_INVALID_PARAMETER;\r
614 goto Done;\r
615 }\r
616 }\r
617\r
618 Status = DiscoverPrmModules (&mPrmModuleCount, &mPrmHandlerCount);\r
619 if (EFI_ERROR (Status)) {\r
620 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_DISCOVERY_FAILED), mPrmInfoHiiHandle, APPLICATION_NAME);\r
621 DEBUG ((\r
622 DEBUG_ERROR,\r
623 "%a - %a: An error occurred during PRM module discovery (%r)\n",\r
624 gEfiCallerBaseName,\r
625 __FUNCTION__,\r
626 Status\r
627 ));\r
628 ReturnStatus = Status;\r
629 goto Done;\r
630 }\r
631\r
632 if (PrintHandlerInfo) {\r
633 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LIST_TITLE), mPrmInfoHiiHandle);\r
634 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MODULES_FOUND), mPrmInfoHiiHandle, mPrmModuleCount);\r
635 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLERS_FOUND), mPrmInfoHiiHandle, mPrmHandlerCount);\r
636 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);\r
637 }\r
638 GatherPrmHandlerInfo (PrintHandlerInfo);\r
639\r
640 if (HandlerGuidStr != NULL) {\r
641 Status = ExecutePrmHandlerByGuid (&HandlerGuid);\r
642 if (Status == EFI_NOT_FOUND) {\r
643 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_NOT_FOUND), mPrmInfoHiiHandle, APPLICATION_NAME, HandlerGuid);\r
644 }\r
645 }\r
646\r
647Done:\r
648 FreeList (&mPrmHandlerList);\r
649\r
650 if (Package != NULL) {\r
651 ShellCommandLineFreeVarList (Package);\r
652 }\r
653\r
654 return ReturnStatus;\r
655}\r
656\r
657/**\r
658 Entry point of this UEFI application.\r
659\r
660 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
661 @param[in] SystemTable A pointer to the EFI System Table.\r
662\r
663 @retval EFI_SUCCESS The entry point is executed successfully.\r
664 @retval other Some error occurs when executing this entry point.\r
665\r
666**/\r
667EFI_STATUS\r
668EFIAPI\r
669UefiMain (\r
670 IN EFI_HANDLE ImageHandle,\r
671 IN EFI_SYSTEM_TABLE *SystemTable\r
672 )\r
673{\r
674 EFI_STATUS Status;\r
675 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
676\r
677 //\r
678 // Retrieve the HII package list from ImageHandle\r
679 //\r
680 Status = gBS->OpenProtocol (\r
681 ImageHandle,\r
682 &gEfiHiiPackageListProtocolGuid,\r
683 (VOID **) &PackageList,\r
684 ImageHandle,\r
685 NULL,\r
686 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
687 );\r
688 if (EFI_ERROR (Status)) {\r
689 return Status;\r
690 }\r
691\r
692 //\r
693 // Publish the HII package list to the HII Database\r
694 //\r
695 Status = gHiiDatabase->NewPackageList (\r
696 gHiiDatabase,\r
697 PackageList,\r
698 NULL,\r
699 &mPrmInfoHiiHandle\r
700 );\r
701 if (EFI_ERROR (Status)) {\r
702 return Status;\r
703 }\r
704\r
705 if (mPrmInfoHiiHandle == NULL) {\r
706 return EFI_SUCCESS;\r
707 }\r
708\r
709 Status = ParseParameterList ();\r
710 if (EFI_ERROR (Status)) {\r
711 DEBUG ((\r
712 DEBUG_ERROR,\r
713 "%a - %a: An error occurred parsing user-provided arguments (%r)\n",\r
714 gEfiCallerBaseName,\r
715 __FUNCTION__,\r
716 Status\r
717 ));\r
718 }\r
719\r
720 if (mPrmInfoHiiHandle != NULL) {\r
721 HiiRemovePackages (mPrmInfoHiiHandle);\r
722 }\r
723\r
724 return EFI_SUCCESS;\r
725}\r