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