| /** @file | |
| Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include <Library/PrintLib.h> | |
| #include <Library/UefiLib.h> | |
| #include <Library/ShellLib.h> | |
| #include <Library/UefiBootServicesTableLib.h> | |
| #include <Library/BaseMemoryLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/MemoryAllocationLib.h> | |
| #include "AcpiParser.h" | |
| #include "AcpiTableParser.h" | |
| #include "AcpiView.h" | |
| #include "UefiShellAcpiViewCommandLib.h" | |
| EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL; | |
| // Report variables | |
| STATIC UINT32 mSelectedAcpiTable; | |
| STATIC CONST CHAR16* mSelectedAcpiTableName; | |
| STATIC BOOLEAN mSelectedAcpiTableFound; | |
| STATIC EREPORT_OPTION mReportType; | |
| STATIC UINT32 mTableCount; | |
| STATIC UINT32 mBinTableCount; | |
| STATIC BOOLEAN mVerbose; | |
| STATIC BOOLEAN mConsistencyCheck; | |
| STATIC BOOLEAN mColourHighlighting; | |
| /** | |
| An array of acpiview command line parameters. | |
| **/ | |
| STATIC CONST SHELL_PARAM_ITEM ParamList[] = { | |
| {L"/?", TypeFlag}, | |
| {L"-c", TypeFlag}, | |
| {L"-d", TypeFlag}, | |
| {L"-h", TypeValue}, | |
| {L"-l", TypeFlag}, | |
| {L"-s", TypeValue}, | |
| {L"-v", TypeFlag}, | |
| {NULL, TypeMax} | |
| }; | |
| /** | |
| This function returns the colour highlighting status. | |
| @retval TRUE if colour highlighting is enabled. | |
| **/ | |
| BOOLEAN | |
| GetColourHighlighting ( | |
| VOID | |
| ) | |
| { | |
| return mColourHighlighting; | |
| } | |
| /** | |
| This function sets the colour highlighting status. | |
| @param Highlight The Highlight status. | |
| **/ | |
| VOID | |
| SetColourHighlighting ( | |
| BOOLEAN Highlight | |
| ) | |
| { | |
| mColourHighlighting = Highlight; | |
| } | |
| /** | |
| This function returns the report options. | |
| @retval Returns the report option. | |
| **/ | |
| STATIC | |
| EREPORT_OPTION | |
| GetReportOption ( | |
| VOID | |
| ) | |
| { | |
| return mReportType; | |
| } | |
| /** | |
| This function returns the selected ACPI table. | |
| @retval Returns signature of the selected ACPI table. | |
| **/ | |
| STATIC | |
| UINT32 | |
| GetSelectedAcpiTable ( | |
| VOID | |
| ) | |
| { | |
| return mSelectedAcpiTable; | |
| } | |
| /** | |
| This function dumps the ACPI table to a file. | |
| @param [in] Ptr Pointer to the ACPI table data. | |
| @param [in] Length The length of the ACPI table. | |
| @retval TRUE Success. | |
| @retval FALSE Failure. | |
| **/ | |
| STATIC | |
| BOOLEAN | |
| DumpAcpiTableToFile ( | |
| IN CONST UINT8* Ptr, | |
| IN CONST UINTN Length | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; | |
| SHELL_FILE_HANDLE DumpFileHandle; | |
| UINTN TransferBytes; | |
| DumpFileHandle = NULL; | |
| TransferBytes = Length; | |
| UnicodeSPrint ( | |
| FileNameBuffer, | |
| sizeof (FileNameBuffer), | |
| L".\\%s%04d.bin", | |
| mSelectedAcpiTableName, | |
| mBinTableCount++ | |
| ); | |
| Status = ShellOpenFileByName ( | |
| FileNameBuffer, | |
| &DumpFileHandle, | |
| EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, | |
| 0 | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_READONLY_MEDIA), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview" | |
| ); | |
| return FALSE; | |
| } | |
| Print (L"Dumping ACPI table to : %s ... ", FileNameBuffer); | |
| Status = ShellWriteFile ( | |
| DumpFileHandle, | |
| &TransferBytes, | |
| (VOID*)Ptr | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| Print (L"ERROR: Failed to dump table to binary file.\n"); | |
| TransferBytes = 0; | |
| } else { | |
| Print (L"DONE.\n"); | |
| } | |
| ShellCloseFile (&DumpFileHandle); | |
| return (Length == TransferBytes); | |
| } | |
| /** | |
| This function processes the table reporting options for the ACPI table. | |
| @param [in] Signature The ACPI table Signature. | |
| @param [in] TablePtr Pointer to the ACPI table data. | |
| @param [in] Length The length fo the ACPI table. | |
| @retval Returns TRUE if the ACPI table should be traced. | |
| **/ | |
| BOOLEAN | |
| ProcessTableReportOptions ( | |
| IN CONST UINT32 Signature, | |
| IN CONST UINT8* TablePtr, | |
| IN CONST UINT32 Length | |
| ) | |
| { | |
| UINTN OriginalAttribute; | |
| UINT8* SignaturePtr; | |
| BOOLEAN Log; | |
| BOOLEAN HighLight; | |
| SignaturePtr = (UINT8*)(UINTN)&Signature; | |
| Log = FALSE; | |
| HighLight = GetColourHighlighting (); | |
| switch (GetReportOption ()) { | |
| case ReportAll: | |
| Log = TRUE; | |
| break; | |
| case ReportSelected: | |
| if (Signature == GetSelectedAcpiTable ()) { | |
| Log = TRUE; | |
| mSelectedAcpiTableFound = TRUE; | |
| } | |
| break; | |
| case ReportTableList: | |
| if (mTableCount == 0) { | |
| if (HighLight) { | |
| OriginalAttribute = gST->ConOut->Mode->Attribute; | |
| gST->ConOut->SetAttribute ( | |
| gST->ConOut, | |
| EFI_TEXT_ATTR(EFI_CYAN, | |
| ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) | |
| ); | |
| } | |
| Print (L"\nInstalled Table(s):\n"); | |
| if (HighLight) { | |
| gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); | |
| } | |
| } | |
| Print ( | |
| L"\t%4d. %c%c%c%c\n", | |
| ++mTableCount, | |
| SignaturePtr[0], | |
| SignaturePtr[1], | |
| SignaturePtr[2], | |
| SignaturePtr[3] | |
| ); | |
| break; | |
| case ReportDumpBinFile: | |
| if (Signature == GetSelectedAcpiTable ()) { | |
| mSelectedAcpiTableFound = TRUE; | |
| DumpAcpiTableToFile (TablePtr, Length); | |
| } | |
| break; | |
| case ReportMax: | |
| // We should never be here. | |
| // This case is only present to prevent compiler warning. | |
| break; | |
| } // switch | |
| if (Log) { | |
| if (HighLight) { | |
| OriginalAttribute = gST->ConOut->Mode->Attribute; | |
| gST->ConOut->SetAttribute ( | |
| gST->ConOut, | |
| EFI_TEXT_ATTR(EFI_LIGHTBLUE, | |
| ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) | |
| ); | |
| } | |
| Print ( | |
| L"\n\n --------------- %c%c%c%c Table --------------- \n\n", | |
| SignaturePtr[0], | |
| SignaturePtr[1], | |
| SignaturePtr[2], | |
| SignaturePtr[3] | |
| ); | |
| if (HighLight) { | |
| gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); | |
| } | |
| } | |
| return Log; | |
| } | |
| /** | |
| This function converts a string to ACPI table signature. | |
| @param [in] Str Pointer to the string to be converted to the | |
| ACPI table signature. | |
| @retval The ACPI table signature. | |
| **/ | |
| STATIC | |
| UINT32 | |
| ConvertStrToAcpiSignature ( | |
| IN CONST CHAR16* Str | |
| ) | |
| { | |
| UINT8 Index; | |
| CHAR8 Ptr[4]; | |
| Index = 0; | |
| // Convert to Upper case and convert to ASCII | |
| while ((Index < 4) && (Str[Index] != 0)) { | |
| if (Str[Index] >= L'a' && Str[Index] <= L'z') { | |
| Ptr[Index] = (CHAR8)(Str[Index] - (L'a' - L'A')); | |
| } else { | |
| Ptr[Index] = (CHAR8)Str[Index]; | |
| } | |
| Index++; | |
| } | |
| return *(UINT32*)Ptr; | |
| } | |
| /** | |
| This function iterates the configuration table entries in the | |
| system table, retrieves the RSDP pointer and starts parsing the ACPI tables. | |
| @param [in] SystemTable Pointer to the EFI system table. | |
| @retval Returns EFI_NOT_FOUND if the RSDP pointer is not found. | |
| Returns EFI_UNSUPPORTED if the RSDP version is less than 2. | |
| Returns EFI_SUCCESS if successful. | |
| **/ | |
| STATIC | |
| EFI_STATUS | |
| EFIAPI | |
| AcpiView ( | |
| IN EFI_SYSTEM_TABLE* SystemTable | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINTN Index; | |
| EFI_CONFIGURATION_TABLE* EfiConfigurationTable; | |
| BOOLEAN FoundAcpiTable; | |
| UINTN OriginalAttribute; | |
| UINTN PrintAttribute; | |
| EREPORT_OPTION ReportOption; | |
| UINT8* RsdpPtr; | |
| UINT32 RsdpLength; | |
| UINT8 RsdpRevision; | |
| PARSE_ACPI_TABLE_PROC RsdpParserProc; | |
| BOOLEAN Trace; | |
| // Search the table for an entry that matches the ACPI Table Guid | |
| FoundAcpiTable = FALSE; | |
| for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) { | |
| if (CompareGuid (&gEfiAcpiTableGuid, | |
| &(SystemTable->ConfigurationTable[Index].VendorGuid))) { | |
| EfiConfigurationTable = &SystemTable->ConfigurationTable[Index]; | |
| FoundAcpiTable = TRUE; | |
| break; | |
| } | |
| } | |
| if (FoundAcpiTable) { | |
| RsdpPtr = (UINT8*)EfiConfigurationTable->VendorTable; | |
| // The RSDP revision is 1 byte starting at offset 15 | |
| RsdpRevision = *(RsdpPtr + RSDP_REVISION_OFFSET); | |
| if (RsdpRevision < 2) { | |
| Print ( | |
| L"ERROR: RSDP version less than 2 is not supported.\n" | |
| ); | |
| return EFI_UNSUPPORTED; | |
| } | |
| // The RSDP length is 4 bytes starting at offset 20 | |
| RsdpLength = *(UINT32*)(RsdpPtr + RSDP_LENGTH_OFFSET); | |
| Trace = ProcessTableReportOptions (RSDP_TABLE_INFO, RsdpPtr, RsdpLength); | |
| Status = GetParser (RSDP_TABLE_INFO, &RsdpParserProc); | |
| if (EFI_ERROR (Status)) { | |
| Print ( | |
| L"ERROR: No registered parser found for RSDP.\n" | |
| ); | |
| return Status; | |
| } | |
| RsdpParserProc ( | |
| Trace, | |
| RsdpPtr, | |
| RsdpLength, | |
| RsdpRevision | |
| ); | |
| } else { | |
| IncrementErrorCount (); | |
| Print ( | |
| L"ERROR: Failed to find ACPI Table Guid in System Configuration Table.\n" | |
| ); | |
| return EFI_NOT_FOUND; | |
| } | |
| ReportOption = GetReportOption (); | |
| if (ReportTableList != ReportOption) { | |
| if (((ReportSelected == ReportOption) || | |
| (ReportDumpBinFile == ReportOption)) && | |
| (!mSelectedAcpiTableFound)) { | |
| Print (L"\nRequested ACPI Table not found.\n"); | |
| } else if (ReportDumpBinFile != ReportOption) { | |
| OriginalAttribute = gST->ConOut->Mode->Attribute; | |
| Print (L"\nTable Statistics:\n"); | |
| if (GetColourHighlighting ()) { | |
| PrintAttribute = (GetErrorCount () > 0) ? | |
| EFI_TEXT_ATTR ( | |
| EFI_RED, | |
| ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) | |
| ) : | |
| OriginalAttribute; | |
| gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); | |
| } | |
| Print (L"\t%d Error(s)\n", GetErrorCount ()); | |
| if (GetColourHighlighting ()) { | |
| PrintAttribute = (GetWarningCount () > 0) ? | |
| EFI_TEXT_ATTR ( | |
| EFI_RED, | |
| ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) | |
| ) : | |
| OriginalAttribute; | |
| gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); | |
| } | |
| Print (L"\t%d Warning(s)\n", GetWarningCount ()); | |
| if (GetColourHighlighting ()) { | |
| gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); | |
| } | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Function for 'acpiview' command. | |
| @param[in] ImageHandle Handle to the Image (NULL if Internal). | |
| @param[in] SystemTable Pointer to the System Table (NULL if Internal). | |
| **/ | |
| SHELL_STATUS | |
| EFIAPI | |
| ShellCommandRunAcpiView ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE* SystemTable | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| SHELL_STATUS ShellStatus; | |
| LIST_ENTRY* Package; | |
| CHAR16* ProblemParam; | |
| CONST CHAR16* Temp; | |
| CHAR8 ColourOption[8]; | |
| SHELL_FILE_HANDLE TmpDumpFileHandle; | |
| // Set Defaults | |
| mReportType = ReportAll; | |
| mTableCount = 0; | |
| mBinTableCount = 0; | |
| mSelectedAcpiTable = 0; | |
| mSelectedAcpiTableName = NULL; | |
| mSelectedAcpiTableFound = FALSE; | |
| mVerbose = TRUE; | |
| mConsistencyCheck = TRUE; | |
| ShellStatus = SHELL_SUCCESS; | |
| Package = NULL; | |
| TmpDumpFileHandle = NULL; | |
| // Reset The error/warning counters | |
| ResetErrorCount (); | |
| ResetWarningCount (); | |
| Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); | |
| if (EFI_ERROR (Status)) { | |
| if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_PROBLEM), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview", | |
| ProblemParam | |
| ); | |
| FreePool (ProblemParam); | |
| } else { | |
| Print (L"acpiview: Error processing input parameter(s)\n"); | |
| } | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| } else { | |
| if (ShellCommandLineGetCount (Package) > 1) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_TOO_MANY), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview" | |
| ); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| } else if (ShellCommandLineGetFlag (Package, L"-?")) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GET_HELP_ACPIVIEW), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview" | |
| ); | |
| } else if (ShellCommandLineGetFlag (Package, L"-s") && | |
| ShellCommandLineGetValue (Package, L"-s") == NULL) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_NO_VALUE), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview", | |
| L"-s" | |
| ); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| } else if ((ShellCommandLineGetFlag (Package, L"-s") && | |
| ShellCommandLineGetFlag (Package, L"-l"))) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_TOO_MANY), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview" | |
| ); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| } else if (ShellCommandLineGetFlag (Package, L"-h") && | |
| ShellCommandLineGetValue (Package, L"-h") == NULL) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_NO_VALUE), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview", | |
| L"-h" | |
| ); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| } else if (ShellCommandLineGetFlag (Package, L"-d") && | |
| !ShellCommandLineGetFlag (Package, L"-s")) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_MISSING_OPTION), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview", | |
| L"-s", | |
| L"-d" | |
| ); | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| } else { | |
| // Check if the colour option is set | |
| Temp = ShellCommandLineGetValue (Package, L"-h"); | |
| if (Temp != NULL) { | |
| UnicodeStrToAsciiStrS (Temp, ColourOption, sizeof (ColourOption)); | |
| if ((AsciiStriCmp (ColourOption, "ON") == 0) || | |
| (AsciiStriCmp (ColourOption, "TRUE") == 0)) { | |
| SetColourHighlighting (TRUE); | |
| } else if ((AsciiStriCmp (ColourOption, "OFF") == 0) || | |
| (AsciiStriCmp (ColourOption, "FALSE") == 0)) { | |
| SetColourHighlighting (FALSE); | |
| } | |
| } | |
| if (ShellCommandLineGetFlag (Package, L"-l")) { | |
| mReportType = ReportTableList; | |
| } else { | |
| mSelectedAcpiTableName = ShellCommandLineGetValue (Package, L"-s"); | |
| if (mSelectedAcpiTableName != NULL) { | |
| mSelectedAcpiTable = (UINT32)ConvertStrToAcpiSignature ( | |
| mSelectedAcpiTableName | |
| ); | |
| mReportType = ReportSelected; | |
| if (ShellCommandLineGetFlag (Package, L"-d")) { | |
| // Create a temporary file to check if the media is writable. | |
| CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; | |
| mReportType = ReportDumpBinFile; | |
| UnicodeSPrint ( | |
| FileNameBuffer, | |
| sizeof (FileNameBuffer), | |
| L".\\%s%04d.tmp", | |
| mSelectedAcpiTableName, | |
| mBinTableCount | |
| ); | |
| Status = ShellOpenFileByName ( | |
| FileNameBuffer, | |
| &TmpDumpFileHandle, | |
| EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | | |
| EFI_FILE_MODE_CREATE, | |
| 0 | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| ShellStatus = SHELL_INVALID_PARAMETER; | |
| TmpDumpFileHandle = NULL; | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_GEN_READONLY_MEDIA), | |
| gShellAcpiViewHiiHandle, | |
| L"acpiview" | |
| ); | |
| goto Done; | |
| } | |
| // Delete Temporary file. | |
| ShellDeleteFile (&TmpDumpFileHandle); | |
| } // -d | |
| } // -s | |
| } | |
| // Parse ACPI Table information | |
| Status = AcpiView (SystemTable); | |
| if (EFI_ERROR (Status)) { | |
| ShellStatus = SHELL_NOT_FOUND; | |
| } | |
| } | |
| } | |
| Done: | |
| if (Package != NULL) { | |
| ShellCommandLineFreeVarList (Package); | |
| } | |
| return ShellStatus; | |
| } |