/******************************************************************************
*
* Module Name: ahaml - AML opcode decoding for acpihelp utility
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2019, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include "acpihelp.h"
/* Local prototypes */
static void
AhDisplayAmlOpcode (
const AH_AML_OPCODE *Op);
static void
AhDisplayAmlType (
const AH_AML_TYPE *Op);
/*******************************************************************************
*
* FUNCTION: AhFindAmlOpcode (entry point for AML opcode name search)
*
* PARAMETERS: Name - Name or prefix for an AML opcode.
* NULL means "find all"
*
* RETURN: None
*
* DESCRIPTION: Find all AML opcodes that match the input Name or name
* prefix.
*
******************************************************************************/
void
AhFindAmlOpcode (
char *Name)
{
const AH_AML_OPCODE *Op;
BOOLEAN Found = FALSE;
AcpiUtStrupr (Name);
/* Find/display all opcode names that match the input name prefix */
for (Op = Gbl_AmlOpcodeInfo; Op->OpcodeString; Op++)
{
if (!Op->OpcodeName) /* Unused opcodes */
{
continue;
}
if (!Name || (Name[0] == '*'))
{
AhDisplayAmlOpcode (Op);
Found = TRUE;
continue;
}
/* Upper case the opcode name before substring compare */
strcpy (Gbl_Buffer, Op->OpcodeName);
AcpiUtStrupr (Gbl_Buffer);
if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
{
AhDisplayAmlOpcode (Op);
Found = TRUE;
}
}
if (!Found)
{
printf ("%s, no matching AML operators\n", Name);
}
}
/*******************************************************************************
*
* FUNCTION: AhDecodeAmlOpcode (entry point for AML opcode search)
*
* PARAMETERS: OpcodeString - String version of AML opcode
*
* RETURN: None
*
* DESCRIPTION: Display information about the input AML opcode
*
******************************************************************************/
void
AhDecodeAmlOpcode (
char *OpcodeString)
{
const AH_AML_OPCODE *Op;
UINT32 Opcode;
UINT8 Prefix;
if (!OpcodeString)
{
AhFindAmlOpcode (NULL);
return;
}
Opcode = strtoul (OpcodeString, NULL, 16);
if (Opcode > ACPI_UINT16_MAX)
{
printf ("Invalid opcode (more than 16 bits)\n");
return;
}
/* Only valid opcode extension is 0x5B */
Prefix = (Opcode & 0x0000FF00) >> 8;
if (Prefix && (Prefix != 0x5B))
{
printf ("Invalid opcode (invalid extension prefix 0x%X)\n",
Prefix);
return;
}
/* Find/Display the opcode. May fall within an opcode range */
for (Op = Gbl_AmlOpcodeInfo; Op->OpcodeString; Op++)
{
if ((Opcode >= Op->OpcodeRangeStart) &&
(Opcode <= Op->OpcodeRangeEnd))
{
AhDisplayAmlOpcode (Op);
}
}
}
/*******************************************************************************
*
* FUNCTION: AhDisplayAmlOpcode
*
* PARAMETERS: Op - An opcode info struct
*
* RETURN: None
*
* DESCRIPTION: Display the contents of an AML opcode information struct
*
******************************************************************************/
static void
AhDisplayAmlOpcode (
const AH_AML_OPCODE *Op)
{
if (!Op->OpcodeName)
{
printf ("%18s: Opcode=%-9s\n", "Reserved opcode", Op->OpcodeString);
return;
}
/* Opcode name and value(s) */
printf ("%18s: Opcode=%-9s Type (%s)",
Op->OpcodeName, Op->OpcodeString, Op->Type);
/* Optional fixed/static arguments */
if (Op->FixedArguments)
{
printf (" FixedArgs (");
AhPrintOneField (37, 36 + 7 + strlen (Op->Type) + 12,
AH_MAX_AML_LINE_LENGTH, Op->FixedArguments);
printf (")");
}
/* Optional variable-length argument list */
if (Op->VariableArguments)
{
if (Op->FixedArguments)
{
printf ("\n%*s", 36, " ");
}
printf (" VariableArgs (");
AhPrintOneField (37, 15, AH_MAX_AML_LINE_LENGTH, Op->VariableArguments);
printf (")");
}
printf ("\n");
/* Grammar specification */
if (Op->Grammar)
{
AhPrintOneField (37, 0, AH_MAX_AML_LINE_LENGTH, Op->Grammar);
printf ("\n");
}
}
/*******************************************************************************
*
* FUNCTION: AhFindAmlTypes (entry point for AML grammar keyword search)
*
* PARAMETERS: Name - Name or prefix for an AML grammar element.
* NULL means "find all"
*
* RETURN: None
*
* DESCRIPTION: Find all AML grammar keywords that match the input Name or name
* prefix.
*
******************************************************************************/
void
AhFindAmlTypes (
char *Name)
{
const AH_AML_TYPE *Keyword;
BOOLEAN Found = FALSE;
AcpiUtStrupr (Name);
for (Keyword = Gbl_AmlTypesInfo; Keyword->Name; Keyword++)
{
if (!Name)
{
printf (" %s\n", Keyword->Name);
Found = TRUE;
continue;
}
if (*Name == '*')
{
AhDisplayAmlType (Keyword);
Found = TRUE;
continue;
}
/* Upper case the operator name before substring compare */
strcpy (Gbl_Buffer, Keyword->Name);
AcpiUtStrupr (Gbl_Buffer);
if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
{
AhDisplayAmlType (Keyword);
Found = TRUE;
}
}
if (!Found)
{
printf ("%s, no matching AML grammar type\n", Name);
}
}
/*******************************************************************************
*
* FUNCTION: AhDisplayAmlType
*
* PARAMETERS: Op - Pointer to AML grammar info
*
* RETURN: None
*
* DESCRIPTION: Format and display info for an AML grammar element.
*
******************************************************************************/
static void
AhDisplayAmlType (
const AH_AML_TYPE *Op)
{
char *Description;
Description = Op->Description;
printf ("%4s", " "); /* Primary indent */
/* Emit the entire description string */
while (*Description)
{
/* Description can be multiple lines, must indent each */
while (*Description != '\n')
{
printf ("%c", *Description);
Description++;
}
printf ("\n");
Description++;
/* Do indent */
if (*Description)
{
printf ("%8s", " "); /* Secondary indent */
/* Index extra for a comment */
if ((Description[0] == '/') &&
(Description[1] == '/'))
{
printf ("%4s", " ");
}
}
}
printf ("\n");
}