Path: blob/main/sys/contrib/dev/acpica/components/debugger/dbmethod.c
48406 views
/*******************************************************************************1*2* Module Name: dbmethod - Debug commands for control methods3*4******************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/acdispat.h>154#include <contrib/dev/acpica/include/acnamesp.h>155#include <contrib/dev/acpica/include/acdebug.h>156#include <contrib/dev/acpica/include/acparser.h>157#include <contrib/dev/acpica/include/acpredef.h>158159160#define _COMPONENT ACPI_CA_DEBUGGER161ACPI_MODULE_NAME ("dbmethod")162163/* Local prototypes */164165static ACPI_STATUS166AcpiDbWalkForExecute (167ACPI_HANDLE ObjHandle,168UINT32 NestingLevel,169void *Context,170void **ReturnValue);171172static ACPI_STATUS173AcpiDbEvaluateObject (174ACPI_NAMESPACE_NODE *Node);175176177/*******************************************************************************178*179* FUNCTION: AcpiDbSetMethodBreakpoint180*181* PARAMETERS: Location - AML offset of breakpoint182* WalkState - Current walk info183* Op - Current Op (from parse walk)184*185* RETURN: None186*187* DESCRIPTION: Set a breakpoint in a control method at the specified188* AML offset189*190******************************************************************************/191192void193AcpiDbSetMethodBreakpoint (194char *Location,195ACPI_WALK_STATE *WalkState,196ACPI_PARSE_OBJECT *Op)197{198UINT32 Address;199UINT32 AmlOffset;200201202if (!Op)203{204AcpiOsPrintf ("There is no method currently executing\n");205return;206}207208/* Get and verify the breakpoint address */209210Address = strtoul (Location, NULL, 16);211AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,212WalkState->ParserState.AmlStart);213if (Address <= AmlOffset)214{215AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n",216Address, AmlOffset);217}218219/* Save breakpoint in current walk */220221WalkState->UserBreakpoint = Address;222AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address);223}224225226/*******************************************************************************227*228* FUNCTION: AcpiDbSetMethodCallBreakpoint229*230* PARAMETERS: Op - Current Op (from parse walk)231*232* RETURN: None233*234* DESCRIPTION: Set a breakpoint in a control method at the specified235* AML offset236*237******************************************************************************/238239void240AcpiDbSetMethodCallBreakpoint (241ACPI_PARSE_OBJECT *Op)242{243244245if (!Op)246{247AcpiOsPrintf ("There is no method currently executing\n");248return;249}250251AcpiGbl_StepToNextCall = TRUE;252}253254255/*******************************************************************************256*257* FUNCTION: AcpiDbSetMethodData258*259* PARAMETERS: TypeArg - L for local, A for argument260* IndexArg - which one261* ValueArg - Value to set.262*263* RETURN: None264*265* DESCRIPTION: Set a local or argument for the running control method.266* NOTE: only object supported is Number.267*268******************************************************************************/269270void271AcpiDbSetMethodData (272char *TypeArg,273char *IndexArg,274char *ValueArg)275{276char Type;277UINT32 Index;278UINT32 Value;279ACPI_WALK_STATE *WalkState;280ACPI_OPERAND_OBJECT *ObjDesc;281ACPI_STATUS Status;282ACPI_NAMESPACE_NODE *Node;283284285/* Validate TypeArg */286287AcpiUtStrupr (TypeArg);288Type = TypeArg[0];289if ((Type != 'L') &&290(Type != 'A') &&291(Type != 'N'))292{293AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg);294return;295}296297Value = strtoul (ValueArg, NULL, 16);298299if (Type == 'N')300{301Node = AcpiDbConvertToNode (IndexArg);302if (!Node)303{304return;305}306307if (Node->Type != ACPI_TYPE_INTEGER)308{309AcpiOsPrintf ("Can only set Integer nodes\n");310return;311}312ObjDesc = Node->Object;313ObjDesc->Integer.Value = Value;314return;315}316317/* Get the index and value */318319Index = strtoul (IndexArg, NULL, 16);320321WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);322if (!WalkState)323{324AcpiOsPrintf ("There is no method currently executing\n");325return;326}327328/* Create and initialize the new object */329330ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value);331if (!ObjDesc)332{333AcpiOsPrintf ("Could not create an internal object\n");334return;335}336337/* Store the new object into the target */338339switch (Type)340{341case 'A':342343/* Set a method argument */344345if (Index > ACPI_METHOD_MAX_ARG)346{347AcpiOsPrintf ("Arg%u - Invalid argument name\n",348Index);349goto Cleanup;350}351352Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG,353Index, ObjDesc, WalkState);354if (ACPI_FAILURE (Status))355{356goto Cleanup;357}358359ObjDesc = WalkState->Arguments[Index].Object;360361AcpiOsPrintf ("Arg%u: ", Index);362AcpiDbDisplayInternalObject (ObjDesc, WalkState);363break;364365case 'L':366367/* Set a method local */368369if (Index > ACPI_METHOD_MAX_LOCAL)370{371AcpiOsPrintf ("Local%u - Invalid local variable name\n",372Index);373goto Cleanup;374}375376Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL,377Index, ObjDesc, WalkState);378if (ACPI_FAILURE (Status))379{380goto Cleanup;381}382383ObjDesc = WalkState->LocalVariables[Index].Object;384385AcpiOsPrintf ("Local%u: ", Index);386AcpiDbDisplayInternalObject (ObjDesc, WalkState);387break;388389default:390391break;392}393394Cleanup:395AcpiUtRemoveReference (ObjDesc);396}397398399#ifdef ACPI_DISASSEMBLER400/*******************************************************************************401*402* FUNCTION: AcpiDbDisassembleAml403*404* PARAMETERS: Statements - Number of statements to disassemble405* Op - Current Op (from parse walk)406*407* RETURN: None408*409* DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number410* of statements specified.411*412******************************************************************************/413414void415AcpiDbDisassembleAml (416char *Statements,417ACPI_PARSE_OBJECT *Op)418{419UINT32 NumStatements = 8;420421422if (!Op)423{424AcpiOsPrintf ("There is no method currently executing\n");425return;426}427428if (Statements)429{430NumStatements = strtoul (Statements, NULL, 0);431}432433AcpiDmDisassemble (NULL, Op, NumStatements);434}435436437/*******************************************************************************438*439* FUNCTION: AcpiDbDisassembleMethod440*441* PARAMETERS: Name - Name of control method442*443* RETURN: None444*445* DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number446* of statements specified.447*448******************************************************************************/449450ACPI_STATUS451AcpiDbDisassembleMethod (452char *Name)453{454ACPI_STATUS Status;455ACPI_PARSE_OBJECT *Op;456ACPI_WALK_STATE *WalkState;457ACPI_OPERAND_OBJECT *ObjDesc;458ACPI_NAMESPACE_NODE *Method;459460461Method = AcpiDbConvertToNode (Name);462if (!Method)463{464return (AE_BAD_PARAMETER);465}466467if (Method->Type != ACPI_TYPE_METHOD)468{469ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",470Name, AcpiUtGetTypeName (Method->Type)));471return (AE_BAD_PARAMETER);472}473474ObjDesc = Method->Object;475476Op = AcpiPsCreateScopeOp (ObjDesc->Method.AmlStart);477if (!Op)478{479return (AE_NO_MEMORY);480}481482/* Create and initialize a new walk state */483484WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);485if (!WalkState)486{487return (AE_NO_MEMORY);488}489490Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,491ObjDesc->Method.AmlStart,492ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);493if (ACPI_FAILURE (Status))494{495return (Status);496}497498Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);499if (ACPI_FAILURE(Status))500{501return (Status);502}503504WalkState->OwnerId = ObjDesc->Method.OwnerId;505506/* Push start scope on scope stack and make it current */507508Status = AcpiDsScopeStackPush (Method,509Method->Type, WalkState);510if (ACPI_FAILURE (Status))511{512return (Status);513}514515/* Parse the entire method AML including deferred operators */516517WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;518WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;519520Status = AcpiPsParseAml (WalkState);521if (ACPI_FAILURE(Status))522{523return (Status);524}525526(void) AcpiDmParseDeferredOps (Op);527528/* Now we can disassemble the method */529530AcpiGbl_DmOpt_Verbose = FALSE;531AcpiDmDisassemble (NULL, Op, 0);532AcpiGbl_DmOpt_Verbose = TRUE;533534AcpiPsDeleteParseTree (Op);535536/* Method cleanup */537538AcpiNsDeleteNamespaceSubtree (Method);539AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);540AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);541return (AE_OK);542}543#endif544545546/*******************************************************************************547*548* FUNCTION: AcpiDbEvaluateObject549*550* PARAMETERS: Node - Namespace node for the object551*552* RETURN: Status553*554* DESCRIPTION: Main execution function for the Evaluate/Execute/All debugger555* commands.556*557******************************************************************************/558559static ACPI_STATUS560AcpiDbEvaluateObject (561ACPI_NAMESPACE_NODE *Node)562{563char *Pathname;564UINT32 i;565ACPI_DEVICE_INFO *ObjInfo;566ACPI_OBJECT_LIST ParamObjects;567ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS];568ACPI_BUFFER ReturnObj;569ACPI_STATUS Status;570571572Pathname = AcpiNsGetExternalPathname (Node);573if (!Pathname)574{575return (AE_OK);576}577578/* Get the object info for number of method parameters */579580Status = AcpiGetObjectInfo (Node, &ObjInfo);581if (ACPI_FAILURE (Status))582{583ACPI_FREE (Pathname);584return (Status);585}586587ParamObjects.Pointer = NULL;588ParamObjects.Count = 0;589590if (ObjInfo->Type == ACPI_TYPE_METHOD)591{592/* Setup default parameters */593594for (i = 0; i < ObjInfo->ParamCount; i++)595{596Params[i].Type = ACPI_TYPE_INTEGER;597Params[i].Integer.Value = 1;598}599600ParamObjects.Pointer = Params;601ParamObjects.Count = ObjInfo->ParamCount;602}603604ACPI_FREE (ObjInfo);605ReturnObj.Pointer = NULL;606ReturnObj.Length = ACPI_ALLOCATE_BUFFER;607608/* Do the actual method execution */609610AcpiGbl_MethodExecuting = TRUE;611612Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj);613AcpiGbl_MethodExecuting = FALSE;614615AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status));616if (ReturnObj.Length)617{618AcpiOsPrintf ("Evaluation of %s returned object %p, "619"external buffer length %X\n",620Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length);621622AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);623AcpiOsPrintf ("\n");624}625626ACPI_FREE (Pathname);627628/* Ignore status from method execution */629630return (AE_OK);631632/* Update count, check if we have executed enough methods */633634}635636/*******************************************************************************637*638* FUNCTION: AcpiDbWalkForExecute639*640* PARAMETERS: Callback from WalkNamespace641*642* RETURN: Status643*644* DESCRIPTION: Batch execution function. Evaluates all "predefined" objects --645* the nameseg begins with an underscore.646*647******************************************************************************/648649static ACPI_STATUS650AcpiDbWalkForExecute (651ACPI_HANDLE ObjHandle,652UINT32 NestingLevel,653void *Context,654void **ReturnValue)655{656ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;657ACPI_DB_EXECUTE_WALK *Info = (ACPI_DB_EXECUTE_WALK *) Context;658ACPI_STATUS Status;659const ACPI_PREDEFINED_INFO *Predefined;660661662Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii);663if (!Predefined)664{665return (AE_OK);666}667668if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)669{670return (AE_OK);671}672673AcpiDbEvaluateObject (Node);674675/* Ignore status from object evaluation */676677Status = AE_OK;678679/* Update count, check if we have executed enough methods */680681Info->Count++;682if (Info->Count >= Info->MaxCount)683{684Status = AE_CTRL_TERMINATE;685}686687return (Status);688}689690691/*******************************************************************************692*693* FUNCTION: AcpiDbWalkForExecuteAll694*695* PARAMETERS: Callback from WalkNamespace696*697* RETURN: Status698*699* DESCRIPTION: Batch execution function. Evaluates all objects whose path ends700* with the nameseg "Info->NameSeg". Used for the "ALL" command.701*702******************************************************************************/703704static ACPI_STATUS705AcpiDbWalkForExecuteAll (706ACPI_HANDLE ObjHandle,707UINT32 NestingLevel,708void *Context,709void **ReturnValue)710{711ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;712ACPI_DB_EXECUTE_WALK *Info = (ACPI_DB_EXECUTE_WALK *) Context;713ACPI_STATUS Status;714715716if (!ACPI_COMPARE_NAMESEG (Node->Name.Ascii, Info->NameSeg))717{718return (AE_OK);719}720721if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)722{723return (AE_OK);724}725726/* Now evaluate the input object (node) */727728AcpiDbEvaluateObject (Node);729730/* Ignore status from method execution */731732Status = AE_OK;733734/* Update count of executed methods/objects */735736Info->Count++;737return (Status);738}739740741/*******************************************************************************742*743* FUNCTION: AcpiDbEvaluatePredefinedNames744*745* PARAMETERS: None746*747* RETURN: None748*749* DESCRIPTION: Namespace batch execution. Execute predefined names in the750* namespace, up to the max count, if specified.751*752******************************************************************************/753754void755AcpiDbEvaluatePredefinedNames (756void)757{758ACPI_DB_EXECUTE_WALK Info;759760761Info.Count = 0;762Info.MaxCount = ACPI_UINT32_MAX;763764/* Search all nodes in namespace */765766(void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,767AcpiDbWalkForExecute, NULL, (void *) &Info, NULL);768769AcpiOsPrintf ("Evaluated %u predefined names in the namespace\n", Info.Count);770}771772773/*******************************************************************************774*775* FUNCTION: AcpiDbEvaluateAll776*777* PARAMETERS: NoneAcpiGbl_DbMethodInfo778*779* RETURN: None780*781* DESCRIPTION: Namespace batch execution. Implements the "ALL" command.782* Execute all namepaths whose final nameseg matches the783* input nameseg.784*785******************************************************************************/786787void788AcpiDbEvaluateAll (789char *NameSeg)790{791ACPI_DB_EXECUTE_WALK Info;792793794Info.Count = 0;795Info.MaxCount = ACPI_UINT32_MAX;796ACPI_COPY_NAMESEG (Info.NameSeg, NameSeg);797Info.NameSeg[ACPI_NAMESEG_SIZE] = 0;798799/* Search all nodes in namespace */800801(void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,802AcpiDbWalkForExecuteAll, NULL, (void *) &Info, NULL);803804AcpiOsPrintf ("Evaluated %u names in the namespace\n", Info.Count);805}806807808