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