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