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