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