VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c@ 105681

Last change on this file since 105681 was 99404, checked in by vboxsync, 22 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette