/** @file
Main file for 'acpiview' Shell command function.
Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "AcpiParser.h"
#include "AcpiTableParser.h"
#include "AcpiView.h"
#include "AcpiViewConfig.h"
CONST CHAR16 gShellAcpiViewFileName[] = L"ShellCommand";
EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL;
/**
An array of acpiview command line parameters.
**/
STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
{ L"-q", TypeFlag },
{ L"-d", TypeFlag },
{ L"-h", TypeFlag },
{ L"-l", TypeFlag },
{ L"-s", TypeValue },
{ L"-r", TypeValue },
{ NULL, TypeMax }
};
/**
A list of available table parsers.
*/
STATIC
CONST
ACPI_TABLE_PARSER ParserList[] = {
{ EFI_ACPI_6_3_ARM_ERROR_SOURCE_TABLE_SIGNATURE, ParseAcpiAest },
{ EFI_ACPI_6_4_ARM_PERFORMANCE_MONITORING_UNIT_TABLE_SIGNATURE, ParseAcpiApmt },
{ EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE, ParseAcpiBgrt },
{ EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, ParseAcpiDbg2 },
{ EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
ParseAcpiDsdt },
{ EFI_ACPI_6_4_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE, ParseAcpiErst },
{ EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE, ParseAcpiFacs },
{ EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiFadt },
{ EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiGtdt },
{ EFI_ACPI_6_4_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE, ParseAcpiHmat },
{ EFI_ACPI_6_5_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE, ParseAcpiHpet },
{ EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE, ParseAcpiIort },
{ EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiMadt },
{ EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
ParseAcpiMcfg },
{ EFI_ACPI_6_4_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE,
ParseAcpiPcct },
{ EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE,
ParseAcpiPptt },
{ RSDP_TABLE_INFO, ParseAcpiRsdp },
{ EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE, ParseAcpiSlit },
{ EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, ParseAcpiSpcr },
{ EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE, ParseAcpiSrat },
{ EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiSsdt },
{ EFI_ACPI_6_5_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE, ParseAcpiWsmt },
{ EFI_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiXsdt }
};
/**
This function registers all the available table parsers.
@retval EFI_SUCCESS The parser is registered.
@retval EFI_ALREADY_STARTED The parser for the ACPI Table
was already registered.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_OUT_OF_RESOURCES No space to register the
parser.
**/
EFI_STATUS
RegisterAllParsers (
)
{
EFI_STATUS Status;
UINTN Count;
Status = EFI_SUCCESS;
Count = sizeof (ParserList) / sizeof (ParserList[0]);
while (Count-- != 0) {
Status = RegisterParser (
ParserList[Count].Signature,
ParserList[Count].Parser
);
if (EFI_ERROR (Status)) {
return Status;
}
}
return Status;
}
/**
Dump a buffer to a file. Print error message if a file cannot be created.
@param[in] FileName The filename that shall be created to contain the buffer.
@param[in] Buffer Pointer to buffer that shall be dumped.
@param[in] BufferSize The size of buffer to be dumped in bytes.
@return The number of bytes that were written
**/
UINTN
EFIAPI
ShellDumpBufferToFile (
IN CONST CHAR16 *FileNameBuffer,
IN CONST VOID *Buffer,
IN CONST UINTN BufferSize
)
{
EFI_STATUS Status;
SHELL_FILE_HANDLE DumpFileHandle;
UINTN TransferBytes;
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 0;
}
TransferBytes = BufferSize;
Status = ShellWriteFile (
DumpFileHandle,
&TransferBytes,
(VOID *)Buffer
);
if (EFI_ERROR (Status)) {
Print (L"ERROR: Failed to write binary file.\n");
TransferBytes = 0;
} else {
Print (L"DONE.\n");
}
ShellCloseFile (&DumpFileHandle);
return TransferBytes;
}
/**
Return the file name of the help text file if not using HII.
@return The string pointer to the file name.
**/
CONST CHAR16 *
EFIAPI
ShellCommandGetManFileNameAcpiView (
VOID
)
{
return gShellAcpiViewFileName;
}
/**
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).
@retval SHELL_INVALID_PARAMETER The command line invocation could not be parsed
@retval SHELL_NOT_FOUND The command failed
@retval SHELL_SUCCESS The command was successful
**/
SHELL_STATUS
EFIAPI
ShellCommandRunAcpiView (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
SHELL_STATUS ShellStatus;
LIST_ENTRY *Package;
CHAR16 *ProblemParam;
SHELL_FILE_HANDLE TmpDumpFileHandle;
CONST CHAR16 *MandatoryTableSpecStr;
CONST CHAR16 *SelectedTableName;
// Set configuration defaults
AcpiConfigSetDefaults ();
ShellStatus = SHELL_SUCCESS;
Package = NULL;
TmpDumpFileHandle = NULL;
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"-r") &&
(ShellCommandLineGetValue (Package, L"-r") == NULL))
{
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_GEN_NO_VALUE),
gShellAcpiViewHiiHandle,
L"acpiview",
L"-r"
);
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"-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 {
// Turn on colour highlighting if requested
SetColourHighlighting (ShellCommandLineGetFlag (Package, L"-h"));
// Surpress consistency checking if requested
SetConsistencyChecking (!ShellCommandLineGetFlag (Package, L"-q"));
// Evaluate the parameters for mandatory ACPI table presence checks
SetMandatoryTableValidate (ShellCommandLineGetFlag (Package, L"-r"));
MandatoryTableSpecStr = ShellCommandLineGetValue (Package, L"-r");
if (MandatoryTableSpecStr != NULL) {
SetMandatoryTableSpec (ShellHexStrToUintn (MandatoryTableSpecStr));
}
if (ShellCommandLineGetFlag (Package, L"-l")) {
SetReportOption (ReportTableList);
} else {
SelectedTableName = ShellCommandLineGetValue (Package, L"-s");
if (SelectedTableName != NULL) {
SelectAcpiTable (SelectedTableName);
SetReportOption (ReportSelected);
if (ShellCommandLineGetFlag (Package, L"-d")) {
// Create a temporary file to check if the media is writable.
CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];
SetReportOption (ReportDumpBinFile);
UnicodeSPrint (
FileNameBuffer,
sizeof (FileNameBuffer),
L".\\%s0000.tmp",
SelectedTableName
);
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;
}
/**
Constructor for the Shell AcpiView Command library.
Install the handlers for acpiview UEFI Shell command.
@param ImageHandle The image handle of the process.
@param SystemTable The EFI System Table pointer.
@retval EFI_SUCCESS The Shell command handlers were installed
successfully.
@retval EFI_DEVICE_ERROR Hii package failed to install.
**/
EFI_STATUS
EFIAPI
UefiShellAcpiViewCommandLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
gShellAcpiViewHiiHandle = NULL;
// Check Shell Profile Debug1 bit of the profiles mask
if ((PcdGet8 (PcdShellProfileMask) & BIT1) == 0) {
return EFI_SUCCESS;
}
Status = RegisterAllParsers ();
if (EFI_ERROR (Status)) {
Print (L"acpiview: Error failed to register parser.\n");
return Status;
}
gShellAcpiViewHiiHandle = HiiAddPackages (
&gShellAcpiViewHiiGuid,
gImageHandle,
UefiShellAcpiViewCommandLibStrings,
NULL
);
if (gShellAcpiViewHiiHandle == NULL) {
return EFI_DEVICE_ERROR;
}
// Install our Shell command handler
ShellCommandRegisterCommandName (
L"acpiview",
ShellCommandRunAcpiView,
ShellCommandGetManFileNameAcpiView,
0,
L"acpiview",
TRUE,
gShellAcpiViewHiiHandle,
STRING_TOKEN (STR_GET_HELP_ACPIVIEW)
);
return EFI_SUCCESS;
}
/**
Destructor for the library. free any resources.
@param ImageHandle The image handle of the process.
@param SystemTable The EFI System Table pointer.
**/
EFI_STATUS
EFIAPI
UefiShellAcpiViewCommandLibDestructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
if (gShellAcpiViewHiiHandle != NULL) {
HiiRemovePackages (gShellAcpiViewHiiHandle);
}
return EFI_SUCCESS;
}