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