]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
MdeModulePkg/DumpDynPcd: Add application to dump dynamic PCD settings
[mirror_edk2.git] / MdeModulePkg / Application / DumpDynPcd / DumpDynPcd.c
CommitLineData
a642e2b4
SZ
1/** @file\r
2 A shell application to dump dynamic PCD settings.\r
3\r
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include <Uefi.h>\r
10#include <PiDxe.h>\r
11#include <Library/BaseLib.h>\r
12#include <Library/DebugLib.h>\r
13#include <Library/MemoryAllocationLib.h>\r
14#include <Library/UefiBootServicesTableLib.h>\r
15#include <Library/UefiLib.h>\r
16\r
17\r
18#include <Protocol/UnicodeCollation.h>\r
19#include <Protocol/PiPcd.h>\r
20#include <Protocol/Pcd.h>\r
21#include <Protocol/PiPcdInfo.h>\r
22#include <Protocol/PcdInfo.h>\r
23#include <Protocol/ShellParameters.h>\r
24#include <Protocol/Shell.h>\r
25\r
26\r
27//\r
28// String token ID of help message text.\r
29// Shell supports to find help message in the resource section of an application image if\r
30// .MAN file is not found. This global variable is added to make build tool recognizes\r
31// that the help string is consumed by user and then build tool will add the string into\r
32// the resource section. Thus the application can use '-?' option to show help message in\r
33// Shell.\r
34//\r
35GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStrDumpDynPcdHelpTokenId = STRING_TOKEN (STR_DUMP_DYN_PCD_HELP_INFORMATION);\r
36\r
37#define MAJOR_VERSION 1\r
38#define MINOR_VERSION 0\r
39\r
40static EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
41static EFI_PCD_PROTOCOL *mPiPcd = NULL;\r
42static PCD_PROTOCOL *mPcd = NULL;\r
43static EFI_GET_PCD_INFO_PROTOCOL *mPiPcdInfo = NULL;\r
44static GET_PCD_INFO_PROTOCOL *mPcdInfo = NULL;\r
45static CHAR16 *mTempPcdNameBuffer = NULL;\r
46static UINTN mTempPcdNameBufferSize = 0;\r
47\r
48static CONST CHAR8 mHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};\r
49\r
50static UINTN Argc;\r
51static CHAR16 **Argv;\r
52\r
53\r
54/**\r
55\r
56 This function parse application ARG.\r
57\r
58 @return Status\r
59**/\r
60static\r
61EFI_STATUS\r
62GetArg (\r
63 VOID\r
64 )\r
65{\r
66 EFI_STATUS Status;\r
67 EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;\r
68\r
69 Status = gBS->HandleProtocol (\r
70 gImageHandle,\r
71 &gEfiShellParametersProtocolGuid,\r
72 (VOID**)&ShellParameters\r
73 );\r
74 if (EFI_ERROR(Status)) {\r
75 return Status;\r
76 }\r
77\r
78 Argc = ShellParameters->Argc;\r
79 Argv = ShellParameters->Argv;\r
80 return EFI_SUCCESS;\r
81}\r
82\r
83/**\r
84 Display current version.\r
85**/\r
86static\r
87VOID\r
88ShowVersion (\r
89 )\r
90{\r
91 Print (L"DumpDynPcd Version %d.%02d\n", MAJOR_VERSION, MINOR_VERSION);\r
92}\r
93\r
94/**\r
95 Display Usage and Help information.\r
96**/\r
97static\r
98VOID\r
99ShowHelp (\r
100 )\r
101{\r
102 Print (L"Dump dynamic[ex] PCD info.\n");\r
103 Print (L"\n");\r
104 Print (L"DumpDynPcd [PcdName]\n");\r
105 Print (L"\n");\r
106 Print (L" PcdName Specifies the name of PCD.\n");\r
107 Print (L" A literal[or partial] name or a pattern as specified in\n");\r
108 Print (L" the MetaiMatch() function of the EFI_UNICODE_COLLATION2_PROCOOL.\n");\r
109 Print (L" If it is absent, dump all PCDs' info.\n");\r
110 Print (L"The PCD data is printed as hexadecimal dump.\n");\r
111}\r
112\r
113/**\r
114 Dump some hexadecimal data to the screen.\r
115\r
116 @param[in] Indent How many spaces to indent the output.\r
117 @param[in] Offset The offset of the printing.\r
118 @param[in] DataSize The size in bytes of UserData.\r
119 @param[in] UserData The data to print out.\r
120**/\r
121static\r
122VOID\r
123DumpHex (\r
124 IN UINTN Indent,\r
125 IN UINTN Offset,\r
126 IN UINTN DataSize,\r
127 IN VOID *UserData\r
128 )\r
129{\r
130 UINT8 *Data;\r
131\r
132 CHAR8 Val[50];\r
133\r
134 CHAR8 Str[20];\r
135\r
136 UINT8 TempByte;\r
137 UINTN Size;\r
138 UINTN Index;\r
139\r
140 Data = UserData;\r
141 while (DataSize != 0) {\r
142 Size = 16;\r
143 if (Size > DataSize) {\r
144 Size = DataSize;\r
145 }\r
146\r
147 for (Index = 0; Index < Size; Index += 1) {\r
148 TempByte = Data[Index];\r
149 Val[Index * 3 + 0] = mHex[TempByte >> 4];\r
150 Val[Index * 3 + 1] = mHex[TempByte & 0xF];\r
151 Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' ');\r
152 Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);\r
153 }\r
154\r
155 Val[Index * 3] = 0;\r
156 Str[Index] = 0;\r
157 Print (L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);\r
158\r
159 Data += Size;\r
160 Offset += Size;\r
161 DataSize -= Size;\r
162 }\r
163}\r
164\r
165\r
166/**\r
167 Safely append with automatic string resizing given length of Destination and\r
168 desired length of copy from Source.\r
169\r
170 append the first D characters of Source to the end of Destination, where D is\r
171 the lesser of Count and the StrLen() of Source. If appending those D characters\r
172 will fit within Destination (whose Size is given as CurrentSize) and\r
173 still leave room for a NULL terminator, then those characters are appended,\r
174 starting at the original terminating NULL of Destination, and a new terminating\r
175 NULL is appended.\r
176\r
177 If appending D characters onto Destination will result in a overflow of the size\r
178 given in CurrentSize the string will be grown such that the copy can be performed\r
179 and CurrentSize will be updated to the new size.\r
180\r
181 If Source is NULL, there is nothing to append, just return the current buffer in\r
182 Destination.\r
183\r
184 if Destination is NULL, then ASSERT()\r
185 if Destination's current length (including NULL terminator) is already more then\r
186 CurrentSize, then ASSERT()\r
187\r
188 @param[in, out] Destination The String to append onto\r
189 @param[in, out] CurrentSize on call the number of bytes in Destination. On\r
190 return possibly the new size (still in bytes). if NULL\r
191 then allocate whatever is needed.\r
192 @param[in] Source The String to append from\r
193\r
194 @return Destination return the resultant string.\r
195**/\r
196static\r
197CHAR16*\r
198InternalStrnCatGrow (\r
199 IN OUT CHAR16 **Destination,\r
200 IN OUT UINTN *CurrentSize,\r
201 IN CONST CHAR16 *Source\r
202 )\r
203{\r
204 UINTN DestinationStartSize;\r
205 UINTN NewSize;\r
206 UINTN SourceLen;\r
207\r
208 SourceLen = StrLen(Source);\r
209\r
210 //\r
211 // ASSERTs\r
212 //\r
213 ASSERT(Destination != NULL);\r
214\r
215 //\r
216 // If there's nothing to do then just return Destination\r
217 //\r
218 if (Source == NULL) {\r
219 return (*Destination);\r
220 }\r
221\r
222 //\r
223 // allow for un-initialized pointers, based on size being 0\r
224 //\r
225 if (CurrentSize != NULL && *CurrentSize == 0) {\r
226 *Destination = NULL;\r
227 }\r
228\r
229 //\r
230 // allow for NULL pointers address as Destination\r
231 //\r
232 if (*Destination != NULL) {\r
233 ASSERT(CurrentSize != 0);\r
234 DestinationStartSize = StrSize(*Destination);\r
235 ASSERT(DestinationStartSize <= *CurrentSize);\r
236 } else {\r
237 DestinationStartSize = 0;\r
238 }\r
239\r
240 //\r
241 // Test and grow if required\r
242 //\r
243 if (CurrentSize != NULL) {\r
244 NewSize = *CurrentSize;\r
245 if (NewSize < DestinationStartSize + (SourceLen * sizeof(CHAR16))) {\r
246 while (NewSize < (DestinationStartSize + (SourceLen*sizeof(CHAR16)))) {\r
247 NewSize += 2 * SourceLen * sizeof(CHAR16);\r
248 }\r
249 *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
250 *CurrentSize = NewSize;\r
251 }\r
252 } else {\r
253 NewSize = (SourceLen + 1)*sizeof(CHAR16);\r
254 *Destination = AllocateZeroPool(NewSize);\r
255 }\r
256\r
257 //\r
258 // Now use standard StrnCat on a big enough buffer\r
259 //\r
260 if (*Destination == NULL) {\r
261 return (NULL);\r
262 }\r
263\r
264 StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, SourceLen);\r
265 return *Destination;\r
266}\r
267\r
268/**\r
269 Get PCD type string based on input PCD type.\r
270\r
271 @param[in] TokenSpace PCD Token Space.\r
272 @param[in] PcdType The input PCD type.\r
273\r
274 @return Pointer to PCD type string.\r
275**/\r
276static\r
277CHAR16 *\r
278GetPcdTypeString (\r
279 IN CONST EFI_GUID *TokenSpace,\r
280 IN EFI_PCD_TYPE PcdType\r
281 )\r
282{\r
283 UINTN BufLen;\r
284 CHAR16 *RetString;\r
285\r
286 BufLen = 0;\r
287 RetString = NULL;\r
288\r
289 switch (PcdType) {\r
290 case EFI_PCD_TYPE_8:\r
291 InternalStrnCatGrow (&RetString, &BufLen, L"UINT8");\r
292 break;\r
293 case EFI_PCD_TYPE_16:\r
294 InternalStrnCatGrow (&RetString, &BufLen, L"UINT16");\r
295 break;\r
296 case EFI_PCD_TYPE_32:\r
297 InternalStrnCatGrow (&RetString, &BufLen, L"UINT32");\r
298 break;\r
299 case EFI_PCD_TYPE_64:\r
300 InternalStrnCatGrow (&RetString, &BufLen, L"UINT64");\r
301 break;\r
302 case EFI_PCD_TYPE_BOOL:\r
303 InternalStrnCatGrow (&RetString, &BufLen, L"BOOLEAN");\r
304 break;\r
305 case EFI_PCD_TYPE_PTR:\r
306 InternalStrnCatGrow (&RetString, &BufLen, L"POINTER");\r
307 break;\r
308 default:\r
309 InternalStrnCatGrow (&RetString, &BufLen, L"UNKNOWN");\r
310 break;\r
311 }\r
312\r
313 if (TokenSpace == NULL) {\r
314 InternalStrnCatGrow (&RetString, &BufLen, L":DYNAMIC");\r
315 } else {\r
316 InternalStrnCatGrow (&RetString, &BufLen, L":DYNAMICEX");\r
317 }\r
318\r
319 return RetString;\r
320}\r
321\r
322/**\r
323 Dump PCD info.\r
324\r
325 @param[in] TokenSpace PCD Token Space.\r
326 @param[in] TokenNumber PCD Token Number.\r
327 @param[in] PcdInfo Pointer to PCD info.\r
328**/\r
329static\r
330VOID\r
331DumpPcdInfo (\r
332 IN CONST EFI_GUID *TokenSpace,\r
333 IN UINTN TokenNumber,\r
334 IN EFI_PCD_INFO *PcdInfo\r
335 )\r
336{\r
337 CHAR16 *RetString;\r
338 UINT8 Uint8;\r
339 UINT16 Uint16;\r
340 UINT32 Uint32;\r
341 UINT64 Uint64;\r
342 BOOLEAN Boolean;\r
343 VOID *PcdData;\r
344\r
345 RetString = NULL;\r
346\r
347 if (PcdInfo->PcdName != NULL) {\r
348 Print (L"%a\n", PcdInfo->PcdName);\r
349 } else {\r
350 if (TokenSpace == NULL) {\r
351 Print (L"Default Token Space\n");\r
352 } else {\r
353 Print (L"%g\n", TokenSpace);\r
354 }\r
355 }\r
356\r
357 RetString = GetPcdTypeString (TokenSpace, PcdInfo->PcdType);\r
358\r
359 switch (PcdInfo->PcdType) {\r
360 case EFI_PCD_TYPE_8:\r
361 if (TokenSpace == NULL) {\r
362 Uint8 = mPcd->Get8 (TokenNumber);\r
363 } else {\r
364 Uint8 = mPiPcd->Get8 (TokenSpace, TokenNumber);\r
365 }\r
366 Print (L" Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint8);\r
367 break;\r
368 case EFI_PCD_TYPE_16:\r
369 if (TokenSpace == NULL) {\r
370 Uint16 = mPcd->Get16 (TokenNumber);\r
371 } else {\r
372 Uint16 = mPiPcd->Get16 (TokenSpace, TokenNumber);\r
373 }\r
374 Print (L" Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint16);\r
375 break;\r
376 case EFI_PCD_TYPE_32:\r
377 if (TokenSpace == NULL) {\r
378 Uint32 = mPcd->Get32 (TokenNumber);\r
379 } else {\r
380 Uint32 = mPiPcd->Get32 (TokenSpace, TokenNumber);\r
381 }\r
382 Print (L" Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint32);\r
383 break;\r
384 case EFI_PCD_TYPE_64:\r
385 if (TokenSpace == NULL) {\r
386 Uint64 = mPcd->Get64 (TokenNumber);\r
387 } else {\r
388 Uint64 = mPiPcd->Get64 (TokenSpace, TokenNumber);\r
389 }\r
390 Print (L" Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%lx\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint64);\r
391 break;\r
392 case EFI_PCD_TYPE_BOOL:\r
393 if (TokenSpace == NULL) {\r
394 Boolean = mPcd->GetBool (TokenNumber);\r
395 } else {\r
396 Boolean = mPiPcd->GetBool (TokenSpace, TokenNumber);\r
397 }\r
398 Print (L" Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = %a\n", TokenNumber, RetString, PcdInfo->PcdSize, Boolean ? "TRUE" : "FALSE");\r
399 break;\r
400 case EFI_PCD_TYPE_PTR:\r
401 if (TokenSpace == NULL) {\r
402 PcdData = mPcd->GetPtr (TokenNumber);\r
403 } else {\r
404 PcdData = mPiPcd->GetPtr (TokenSpace, TokenNumber);\r
405 }\r
406 Print (L" Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize);\r
407 DumpHex (2, 0, PcdInfo->PcdSize, PcdData);\r
408 break;\r
409 default:\r
410 return;\r
411 }\r
412\r
413 if (RetString != NULL) {\r
414 FreePool (RetString);\r
415 }\r
416 Print (L"\n");\r
417}\r
418\r
419/**\r
420 Show one or all PCDs' info.\r
421\r
422 @param[in] InputPcdName Pointer to PCD name to show. If NULL, show all PCDs' info.\r
423\r
424 @retval EFI_SUCCESS Command completed successfully.\r
425 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to run the command.\r
426 @retval EFI_ABORTED Aborted by user.\r
427 @retval EFI_NOT_FOUND The specified PCD is not found.\r
428**/\r
429static\r
430EFI_STATUS\r
431ProcessPcd (\r
432 IN CHAR16 *InputPcdName\r
433 )\r
434{\r
435 EFI_STATUS Status;\r
436 EFI_GUID *TokenSpace;\r
437 UINTN TokenNumber;\r
438 EFI_PCD_INFO PcdInfo;\r
439 BOOLEAN Found;\r
440 UINTN PcdNameSize;\r
441\r
442 PcdInfo.PcdName = NULL;\r
443 PcdInfo.PcdSize = 0;\r
444 PcdInfo.PcdType = 0xFF;\r
445 Found = FALSE;\r
446\r
447 Print (L"Current system SKU ID: 0x%x\n\n", mPiPcdInfo->GetSku ());\r
448\r
449 TokenSpace = NULL;\r
450 do {\r
451 TokenNumber = 0;\r
452 do {\r
453 Status = mPiPcd->GetNextToken (TokenSpace, &TokenNumber);\r
454 if (!EFI_ERROR (Status) && TokenNumber != 0) {\r
455 if (TokenSpace == NULL) {\r
456 //\r
457 // PCD in default Token Space.\r
458 //\r
459 mPcdInfo->GetInfo (TokenNumber, &PcdInfo);\r
460 } else {\r
461 mPiPcdInfo->GetInfo (TokenSpace, TokenNumber, &PcdInfo);\r
462 }\r
463 if (InputPcdName != NULL) {\r
464 if (PcdInfo.PcdName == NULL) {\r
465 continue;\r
466 }\r
467 PcdNameSize = AsciiStrSize (PcdInfo.PcdName) * sizeof (CHAR16);\r
468 if (mTempPcdNameBuffer == NULL) {\r
469 mTempPcdNameBufferSize = PcdNameSize;\r
470 mTempPcdNameBuffer = AllocatePool (mTempPcdNameBufferSize);\r
471 } else if (mTempPcdNameBufferSize < PcdNameSize) {\r
472 mTempPcdNameBuffer = ReallocatePool (mTempPcdNameBufferSize, PcdNameSize, mTempPcdNameBuffer);\r
473 mTempPcdNameBufferSize = PcdNameSize;\r
474 }\r
475 if (mTempPcdNameBuffer == NULL) {\r
476 return EFI_OUT_OF_RESOURCES;\r
477 }\r
478 AsciiStrToUnicodeStrS (PcdInfo.PcdName, mTempPcdNameBuffer, mTempPcdNameBufferSize / sizeof (CHAR16));\r
479 //\r
480 // Compare the input PCD name with the PCD name in PCD database.\r
481 //\r
482 if ((StrStr (mTempPcdNameBuffer, InputPcdName) != NULL) ||\r
483 (mUnicodeCollation != NULL && mUnicodeCollation->MetaiMatch (mUnicodeCollation, mTempPcdNameBuffer, InputPcdName))) {\r
484 //\r
485 // Found matched PCD.\r
486 //\r
487 DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo);\r
488 Found = TRUE;\r
489 }\r
490 } else {\r
491 DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo);\r
492 }\r
493 }\r
494 } while (!EFI_ERROR (Status) && TokenNumber != 0);\r
495\r
496 Status = mPiPcd->GetNextTokenSpace ((CONST EFI_GUID **) &TokenSpace);\r
497 } while (!EFI_ERROR (Status) && TokenSpace != NULL);\r
498\r
499 if ((InputPcdName != NULL) && !Found) {\r
500 //\r
501 // The specified PCD is not found, print error.\r
502 //\r
503 Print (L"%EError. %NNo matching PCD found: %s.\n", InputPcdName);\r
504 return EFI_NOT_FOUND;\r
505 }\r
506 return EFI_SUCCESS;\r
507}\r
508\r
509/**\r
510 Main entrypoint for DumpDynPcd shell application.\r
511\r
512 @param[in] ImageHandle The image handle.\r
513 @param[in] SystemTable The system table.\r
514\r
515 @retval EFI_SUCCESS Command completed successfully.\r
516 @retval EFI_INVALID_PARAMETER Command usage error.\r
517 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to run the command.\r
518 @retval EFI_ABORTED Aborted by user.\r
519 @retval EFI_NOT_FOUND The specified PCD is not found.\r
520 @retval Others Error status returned from gBS->LocateProtocol.\r
521**/\r
522EFI_STATUS\r
523EFIAPI\r
524DumpDynPcdMain (\r
525 IN EFI_HANDLE ImageHandle,\r
526 IN EFI_SYSTEM_TABLE *SystemTable\r
527 )\r
528{\r
529 EFI_STATUS Status;\r
530 CHAR16 *InputPcdName;\r
531\r
532 InputPcdName = NULL;\r
533\r
534 Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID **) &mUnicodeCollation);\r
535 if (EFI_ERROR (Status)) {\r
536 mUnicodeCollation = NULL;\r
537 }\r
538\r
539 Status = gBS->LocateProtocol (&gEfiPcdProtocolGuid, NULL, (VOID **) &mPiPcd);\r
540 if (EFI_ERROR (Status)) {\r
541 Print (L"DumpDynPcd: %EError. %NPI PCD protocol is not present.\n");\r
542 return Status;\r
543 }\r
544\r
545 Status = gBS->LocateProtocol (&gEfiGetPcdInfoProtocolGuid, NULL, (VOID **) &mPiPcdInfo);\r
546 if (EFI_ERROR (Status)) {\r
547 Print (L"DumpDynPcd: %EError. %NPI PCD info protocol is not present.\n");\r
548 return Status;\r
549 }\r
550\r
551 Status = gBS->LocateProtocol (&gPcdProtocolGuid, NULL, (VOID **) &mPcd);\r
552 if (EFI_ERROR (Status)) {\r
553 Print (L"DumpDynPcd: %EError. %NPCD protocol is not present.\n");\r
554 return Status;\r
555 }\r
556\r
557 Status = gBS->LocateProtocol (&gGetPcdInfoProtocolGuid, NULL, (VOID **) &mPcdInfo);\r
558 if (EFI_ERROR (Status)) {\r
559 Print (L"DumpDynPcd: %EError. %NPCD info protocol is not present.\n");\r
560 return Status;\r
561 }\r
562\r
563 //\r
564 // get the command line arguments\r
565 //\r
566 Status = GetArg();\r
567 if (EFI_ERROR(Status)){\r
568 Print (L"DumpDynPcd: %EError. %NThe input parameters are not recognized.\n");\r
569 Status = EFI_INVALID_PARAMETER;\r
570 return Status;\r
571 }\r
572\r
573 if (Argc > 2){\r
574 Print (L"DumpDynPcd: %EError. %NToo many arguments specified.\n");\r
575 Status = EFI_INVALID_PARAMETER;\r
576 return Status;\r
577 }\r
578\r
579 if (Argc == 1){\r
580 Status = ProcessPcd (InputPcdName);\r
581 goto Done;\r
582 }\r
583\r
584 if ((StrCmp(Argv[1], L"-?") == 0)||(StrCmp(Argv[1], L"-h") == 0)||(StrCmp(Argv[1], L"-H") == 0)){\r
585 ShowHelp ();\r
586 goto Done;\r
587 } else {\r
588 if ((StrCmp(Argv[1], L"-v") == 0)||(StrCmp(Argv[1], L"-V") == 0)){\r
589 ShowVersion ();\r
590 goto Done;\r
591 } else {\r
592 if (StrStr(Argv[1], L"-") != NULL){\r
593 Print (L"DumpDynPcd: %EError. %NThe argument '%B%s%N' is invalid.\n", Argv[1]);\r
594 goto Done;\r
595 }\r
596 }\r
597 }\r
598\r
599 InputPcdName = Argv[1];\r
600 Status = ProcessPcd (InputPcdName);\r
601\r
602 Done:\r
603\r
604 if (mTempPcdNameBuffer != NULL) {\r
605 FreePool (mTempPcdNameBuffer);\r
606 }\r
607\r
608 return Status;\r
609}\r
610\r