]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c
ShellPkg: acpiview: Remove '/?' from valid command line flags
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / AcpiView.c
1 /** @file
2
3 Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5 **/
6
7 #include <Library/PrintLib.h>
8 #include <Library/UefiLib.h>
9 #include <Library/ShellLib.h>
10 #include <Library/UefiBootServicesTableLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include "AcpiParser.h"
15 #include "AcpiTableParser.h"
16 #include "AcpiView.h"
17 #include "UefiShellAcpiViewCommandLib.h"
18
19 EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL;
20
21 // Report variables
22 STATIC UINT32 mSelectedAcpiTable;
23 STATIC CONST CHAR16* mSelectedAcpiTableName;
24 STATIC BOOLEAN mSelectedAcpiTableFound;
25 STATIC EREPORT_OPTION mReportType;
26 STATIC UINT32 mTableCount;
27 STATIC UINT32 mBinTableCount;
28 STATIC BOOLEAN mVerbose;
29 STATIC BOOLEAN mConsistencyCheck;
30 STATIC BOOLEAN mColourHighlighting;
31
32 /**
33 An array of acpiview command line parameters.
34 **/
35 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
36 {L"-c", TypeFlag},
37 {L"-d", TypeFlag},
38 {L"-h", TypeValue},
39 {L"-l", TypeFlag},
40 {L"-s", TypeValue},
41 {L"-v", TypeFlag},
42 {NULL, TypeMax}
43 };
44
45 /**
46 This function returns the colour highlighting status.
47
48 @retval TRUE if colour highlighting is enabled.
49 **/
50 BOOLEAN
51 GetColourHighlighting (
52 VOID
53 )
54 {
55 return mColourHighlighting;
56 }
57
58 /**
59 This function sets the colour highlighting status.
60
61 @param Highlight The Highlight status.
62
63 **/
64 VOID
65 SetColourHighlighting (
66 BOOLEAN Highlight
67 )
68 {
69 mColourHighlighting = Highlight;
70 }
71
72 /**
73 This function returns the report options.
74
75 @retval Returns the report option.
76 **/
77 STATIC
78 EREPORT_OPTION
79 GetReportOption (
80 VOID
81 )
82 {
83 return mReportType;
84 }
85
86 /**
87 This function returns the selected ACPI table.
88
89 @retval Returns signature of the selected ACPI table.
90 **/
91 STATIC
92 UINT32
93 GetSelectedAcpiTable (
94 VOID
95 )
96 {
97 return mSelectedAcpiTable;
98 }
99
100 /**
101 This function dumps the ACPI table to a file.
102
103 @param [in] Ptr Pointer to the ACPI table data.
104 @param [in] Length The length of the ACPI table.
105
106 @retval TRUE Success.
107 @retval FALSE Failure.
108 **/
109 STATIC
110 BOOLEAN
111 DumpAcpiTableToFile (
112 IN CONST UINT8* Ptr,
113 IN CONST UINTN Length
114 )
115 {
116 EFI_STATUS Status;
117 CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];
118 SHELL_FILE_HANDLE DumpFileHandle;
119 UINTN TransferBytes;
120
121 DumpFileHandle = NULL;
122 TransferBytes = Length;
123
124 UnicodeSPrint (
125 FileNameBuffer,
126 sizeof (FileNameBuffer),
127 L".\\%s%04d.bin",
128 mSelectedAcpiTableName,
129 mBinTableCount++
130 );
131
132 Status = ShellOpenFileByName (
133 FileNameBuffer,
134 &DumpFileHandle,
135 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
136 0
137 );
138 if (EFI_ERROR (Status)) {
139 ShellPrintHiiEx (
140 -1,
141 -1,
142 NULL,
143 STRING_TOKEN (STR_GEN_READONLY_MEDIA),
144 gShellAcpiViewHiiHandle,
145 L"acpiview"
146 );
147 return FALSE;
148 }
149
150 Print (L"Dumping ACPI table to : %s ... ", FileNameBuffer);
151
152 Status = ShellWriteFile (
153 DumpFileHandle,
154 &TransferBytes,
155 (VOID*)Ptr
156 );
157 if (EFI_ERROR (Status)) {
158 Print (L"ERROR: Failed to dump table to binary file.\n");
159 TransferBytes = 0;
160 } else {
161 Print (L"DONE.\n");
162 }
163
164 ShellCloseFile (&DumpFileHandle);
165 return (Length == TransferBytes);
166 }
167
168 /**
169 This function processes the table reporting options for the ACPI table.
170
171 @param [in] Signature The ACPI table Signature.
172 @param [in] TablePtr Pointer to the ACPI table data.
173 @param [in] Length The length fo the ACPI table.
174
175 @retval Returns TRUE if the ACPI table should be traced.
176 **/
177 BOOLEAN
178 ProcessTableReportOptions (
179 IN CONST UINT32 Signature,
180 IN CONST UINT8* TablePtr,
181 IN CONST UINT32 Length
182 )
183 {
184 UINTN OriginalAttribute;
185 UINT8* SignaturePtr;
186 BOOLEAN Log;
187 BOOLEAN HighLight;
188
189 SignaturePtr = (UINT8*)(UINTN)&Signature;
190 Log = FALSE;
191 HighLight = GetColourHighlighting ();
192
193 switch (GetReportOption ()) {
194 case ReportAll:
195 Log = TRUE;
196 break;
197 case ReportSelected:
198 if (Signature == GetSelectedAcpiTable ()) {
199 Log = TRUE;
200 mSelectedAcpiTableFound = TRUE;
201 }
202 break;
203 case ReportTableList:
204 if (mTableCount == 0) {
205 if (HighLight) {
206 OriginalAttribute = gST->ConOut->Mode->Attribute;
207 gST->ConOut->SetAttribute (
208 gST->ConOut,
209 EFI_TEXT_ATTR(EFI_CYAN,
210 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))
211 );
212 }
213 Print (L"\nInstalled Table(s):\n");
214 if (HighLight) {
215 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);
216 }
217 }
218 Print (
219 L"\t%4d. %c%c%c%c\n",
220 ++mTableCount,
221 SignaturePtr[0],
222 SignaturePtr[1],
223 SignaturePtr[2],
224 SignaturePtr[3]
225 );
226 break;
227 case ReportDumpBinFile:
228 if (Signature == GetSelectedAcpiTable ()) {
229 mSelectedAcpiTableFound = TRUE;
230 DumpAcpiTableToFile (TablePtr, Length);
231 }
232 break;
233 case ReportMax:
234 // We should never be here.
235 // This case is only present to prevent compiler warning.
236 break;
237 } // switch
238
239 if (Log) {
240 if (HighLight) {
241 OriginalAttribute = gST->ConOut->Mode->Attribute;
242 gST->ConOut->SetAttribute (
243 gST->ConOut,
244 EFI_TEXT_ATTR(EFI_LIGHTBLUE,
245 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))
246 );
247 }
248 Print (
249 L"\n\n --------------- %c%c%c%c Table --------------- \n\n",
250 SignaturePtr[0],
251 SignaturePtr[1],
252 SignaturePtr[2],
253 SignaturePtr[3]
254 );
255 if (HighLight) {
256 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);
257 }
258 }
259
260 return Log;
261 }
262
263 /**
264 This function converts a string to ACPI table signature.
265
266 @param [in] Str Pointer to the string to be converted to the
267 ACPI table signature.
268
269 @retval The ACPI table signature.
270 **/
271 STATIC
272 UINT32
273 ConvertStrToAcpiSignature (
274 IN CONST CHAR16* Str
275 )
276 {
277 UINT8 Index;
278 CHAR8 Ptr[4];
279
280 ZeroMem (Ptr, sizeof (Ptr));
281 Index = 0;
282
283 // Convert to Upper case and convert to ASCII
284 while ((Index < 4) && (Str[Index] != 0)) {
285 if (Str[Index] >= L'a' && Str[Index] <= L'z') {
286 Ptr[Index] = (CHAR8)(Str[Index] - (L'a' - L'A'));
287 } else {
288 Ptr[Index] = (CHAR8)Str[Index];
289 }
290 Index++;
291 }
292 return *(UINT32*)Ptr;
293 }
294
295 /**
296 This function iterates the configuration table entries in the
297 system table, retrieves the RSDP pointer and starts parsing the ACPI tables.
298
299 @param [in] SystemTable Pointer to the EFI system table.
300
301 @retval Returns EFI_NOT_FOUND if the RSDP pointer is not found.
302 Returns EFI_UNSUPPORTED if the RSDP version is less than 2.
303 Returns EFI_SUCCESS if successful.
304 **/
305 STATIC
306 EFI_STATUS
307 EFIAPI
308 AcpiView (
309 IN EFI_SYSTEM_TABLE* SystemTable
310 )
311 {
312 EFI_STATUS Status;
313 UINTN Index;
314 EFI_CONFIGURATION_TABLE* EfiConfigurationTable;
315 BOOLEAN FoundAcpiTable;
316 UINTN OriginalAttribute;
317 UINTN PrintAttribute;
318 EREPORT_OPTION ReportOption;
319 UINT8* RsdpPtr;
320 UINT32 RsdpLength;
321 UINT8 RsdpRevision;
322 PARSE_ACPI_TABLE_PROC RsdpParserProc;
323 BOOLEAN Trace;
324
325 // Search the table for an entry that matches the ACPI Table Guid
326 FoundAcpiTable = FALSE;
327 for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {
328 if (CompareGuid (&gEfiAcpiTableGuid,
329 &(SystemTable->ConfigurationTable[Index].VendorGuid))) {
330 EfiConfigurationTable = &SystemTable->ConfigurationTable[Index];
331 FoundAcpiTable = TRUE;
332 break;
333 }
334 }
335
336 if (FoundAcpiTable) {
337 RsdpPtr = (UINT8*)EfiConfigurationTable->VendorTable;
338
339 // The RSDP revision is 1 byte starting at offset 15
340 RsdpRevision = *(RsdpPtr + RSDP_REVISION_OFFSET);
341
342 if (RsdpRevision < 2) {
343 Print (
344 L"ERROR: RSDP version less than 2 is not supported.\n"
345 );
346 return EFI_UNSUPPORTED;
347 }
348
349 // The RSDP length is 4 bytes starting at offset 20
350 RsdpLength = *(UINT32*)(RsdpPtr + RSDP_LENGTH_OFFSET);
351
352 Trace = ProcessTableReportOptions (RSDP_TABLE_INFO, RsdpPtr, RsdpLength);
353
354 Status = GetParser (RSDP_TABLE_INFO, &RsdpParserProc);
355 if (EFI_ERROR (Status)) {
356 Print (
357 L"ERROR: No registered parser found for RSDP.\n"
358 );
359 return Status;
360 }
361
362 RsdpParserProc (
363 Trace,
364 RsdpPtr,
365 RsdpLength,
366 RsdpRevision
367 );
368
369 } else {
370 IncrementErrorCount ();
371 Print (
372 L"ERROR: Failed to find ACPI Table Guid in System Configuration Table.\n"
373 );
374 return EFI_NOT_FOUND;
375 }
376
377 ReportOption = GetReportOption ();
378 if (ReportTableList != ReportOption) {
379 if (((ReportSelected == ReportOption) ||
380 (ReportDumpBinFile == ReportOption)) &&
381 (!mSelectedAcpiTableFound)) {
382 Print (L"\nRequested ACPI Table not found.\n");
383 } else if (ReportDumpBinFile != ReportOption) {
384 OriginalAttribute = gST->ConOut->Mode->Attribute;
385
386 Print (L"\nTable Statistics:\n");
387
388 if (GetColourHighlighting ()) {
389 PrintAttribute = (GetErrorCount () > 0) ?
390 EFI_TEXT_ATTR (
391 EFI_RED,
392 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)
393 ) :
394 OriginalAttribute;
395 gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute);
396 }
397 Print (L"\t%d Error(s)\n", GetErrorCount ());
398
399 if (GetColourHighlighting ()) {
400 PrintAttribute = (GetWarningCount () > 0) ?
401 EFI_TEXT_ATTR (
402 EFI_RED,
403 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)
404 ) :
405 OriginalAttribute;
406
407 gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute);
408 }
409 Print (L"\t%d Warning(s)\n", GetWarningCount ());
410
411 if (GetColourHighlighting ()) {
412 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);
413 }
414 }
415 }
416 return EFI_SUCCESS;
417 }
418
419 /**
420 Function for 'acpiview' command.
421
422 @param[in] ImageHandle Handle to the Image (NULL if Internal).
423 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
424 **/
425 SHELL_STATUS
426 EFIAPI
427 ShellCommandRunAcpiView (
428 IN EFI_HANDLE ImageHandle,
429 IN EFI_SYSTEM_TABLE* SystemTable
430 )
431 {
432 EFI_STATUS Status;
433 SHELL_STATUS ShellStatus;
434 LIST_ENTRY* Package;
435 CHAR16* ProblemParam;
436 CONST CHAR16* Temp;
437 CHAR8 ColourOption[8];
438 SHELL_FILE_HANDLE TmpDumpFileHandle;
439
440 // Set Defaults
441 mReportType = ReportAll;
442 mTableCount = 0;
443 mBinTableCount = 0;
444 mSelectedAcpiTable = 0;
445 mSelectedAcpiTableName = NULL;
446 mSelectedAcpiTableFound = FALSE;
447 mVerbose = TRUE;
448 mConsistencyCheck = TRUE;
449
450 ShellStatus = SHELL_SUCCESS;
451 Package = NULL;
452 TmpDumpFileHandle = NULL;
453
454 // Reset The error/warning counters
455 ResetErrorCount ();
456 ResetWarningCount ();
457
458 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
459 if (EFI_ERROR (Status)) {
460 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
461 ShellPrintHiiEx (
462 -1,
463 -1,
464 NULL,
465 STRING_TOKEN (STR_GEN_PROBLEM),
466 gShellAcpiViewHiiHandle,
467 L"acpiview",
468 ProblemParam
469 );
470 FreePool (ProblemParam);
471 } else {
472 Print (L"acpiview: Error processing input parameter(s)\n");
473 }
474 ShellStatus = SHELL_INVALID_PARAMETER;
475 } else {
476 if (ShellCommandLineGetCount (Package) > 1) {
477 ShellPrintHiiEx (
478 -1,
479 -1,
480 NULL,
481 STRING_TOKEN (STR_GEN_TOO_MANY),
482 gShellAcpiViewHiiHandle,
483 L"acpiview"
484 );
485 ShellStatus = SHELL_INVALID_PARAMETER;
486 } else if (ShellCommandLineGetFlag (Package, L"-?")) {
487 ShellPrintHiiEx (
488 -1,
489 -1,
490 NULL,
491 STRING_TOKEN (STR_GET_HELP_ACPIVIEW),
492 gShellAcpiViewHiiHandle,
493 L"acpiview"
494 );
495 } else if (ShellCommandLineGetFlag (Package, L"-s") &&
496 ShellCommandLineGetValue (Package, L"-s") == NULL) {
497 ShellPrintHiiEx (
498 -1,
499 -1,
500 NULL,
501 STRING_TOKEN (STR_GEN_NO_VALUE),
502 gShellAcpiViewHiiHandle,
503 L"acpiview",
504 L"-s"
505 );
506 ShellStatus = SHELL_INVALID_PARAMETER;
507 } else if ((ShellCommandLineGetFlag (Package, L"-s") &&
508 ShellCommandLineGetFlag (Package, L"-l"))) {
509 ShellPrintHiiEx (
510 -1,
511 -1,
512 NULL,
513 STRING_TOKEN (STR_GEN_TOO_MANY),
514 gShellAcpiViewHiiHandle,
515 L"acpiview"
516 );
517 ShellStatus = SHELL_INVALID_PARAMETER;
518 } else if (ShellCommandLineGetFlag (Package, L"-h") &&
519 ShellCommandLineGetValue (Package, L"-h") == NULL) {
520 ShellPrintHiiEx (
521 -1,
522 -1,
523 NULL,
524 STRING_TOKEN (STR_GEN_NO_VALUE),
525 gShellAcpiViewHiiHandle,
526 L"acpiview",
527 L"-h"
528 );
529 ShellStatus = SHELL_INVALID_PARAMETER;
530 } else if (ShellCommandLineGetFlag (Package, L"-d") &&
531 !ShellCommandLineGetFlag (Package, L"-s")) {
532 ShellPrintHiiEx (
533 -1,
534 -1,
535 NULL,
536 STRING_TOKEN (STR_GEN_MISSING_OPTION),
537 gShellAcpiViewHiiHandle,
538 L"acpiview",
539 L"-s",
540 L"-d"
541 );
542 ShellStatus = SHELL_INVALID_PARAMETER;
543 } else {
544 // Check if the colour option is set
545 Temp = ShellCommandLineGetValue (Package, L"-h");
546 if (Temp != NULL) {
547 UnicodeStrToAsciiStrS (Temp, ColourOption, sizeof (ColourOption));
548 if ((AsciiStriCmp (ColourOption, "ON") == 0) ||
549 (AsciiStriCmp (ColourOption, "TRUE") == 0)) {
550 SetColourHighlighting (TRUE);
551 } else if ((AsciiStriCmp (ColourOption, "OFF") == 0) ||
552 (AsciiStriCmp (ColourOption, "FALSE") == 0)) {
553 SetColourHighlighting (FALSE);
554 }
555 }
556
557 if (ShellCommandLineGetFlag (Package, L"-l")) {
558 mReportType = ReportTableList;
559 } else {
560 mSelectedAcpiTableName = ShellCommandLineGetValue (Package, L"-s");
561 if (mSelectedAcpiTableName != NULL) {
562 mSelectedAcpiTable = (UINT32)ConvertStrToAcpiSignature (
563 mSelectedAcpiTableName
564 );
565 mReportType = ReportSelected;
566
567 if (ShellCommandLineGetFlag (Package, L"-d")) {
568 // Create a temporary file to check if the media is writable.
569 CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];
570 mReportType = ReportDumpBinFile;
571
572 UnicodeSPrint (
573 FileNameBuffer,
574 sizeof (FileNameBuffer),
575 L".\\%s%04d.tmp",
576 mSelectedAcpiTableName,
577 mBinTableCount
578 );
579
580 Status = ShellOpenFileByName (
581 FileNameBuffer,
582 &TmpDumpFileHandle,
583 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
584 EFI_FILE_MODE_CREATE,
585 0
586 );
587
588 if (EFI_ERROR (Status)) {
589 ShellStatus = SHELL_INVALID_PARAMETER;
590 TmpDumpFileHandle = NULL;
591 ShellPrintHiiEx (
592 -1,
593 -1,
594 NULL,
595 STRING_TOKEN (STR_GEN_READONLY_MEDIA),
596 gShellAcpiViewHiiHandle,
597 L"acpiview"
598 );
599 goto Done;
600 }
601 // Delete Temporary file.
602 ShellDeleteFile (&TmpDumpFileHandle);
603 } // -d
604 } // -s
605 }
606
607 // Parse ACPI Table information
608 Status = AcpiView (SystemTable);
609 if (EFI_ERROR (Status)) {
610 ShellStatus = SHELL_NOT_FOUND;
611 }
612 }
613 }
614
615 Done:
616 if (Package != NULL) {
617 ShellCommandLineFreeVarList (Package);
618 }
619 return ShellStatus;
620 }