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