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