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