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