dbmethod.c revision 281075
192108Sphk/*******************************************************************************
292108Sphk *
392108Sphk * Module Name: dbmethod - Debug commands for control methods
4248508Skib *
592108Sphk ******************************************************************************/
692108Sphk
792108Sphk/*
892108Sphk * Copyright (C) 2000 - 2015, Intel Corp.
992108Sphk * All rights reserved.
1092108Sphk *
1192108Sphk * Redistribution and use in source and binary forms, with or without
12248508Skib * modification, are permitted provided that the following conditions
13248508Skib * are met:
14248508Skib * 1. Redistributions of source code must retain the above copyright
1592108Sphk *    notice, this list of conditions, and the following disclaimer,
1692108Sphk *    without modification.
1792108Sphk * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1892108Sphk *    substantially similar to the "NO WARRANTY" disclaimer below
1992108Sphk *    ("Disclaimer") and any redistribution must be conditioned upon
2092108Sphk *    including a substantially similar Disclaimer requirement for further
2192108Sphk *    binary redistribution.
2292108Sphk * 3. Neither the names of the above-listed copyright holders nor the names
2392108Sphk *    of any contributors may be used to endorse or promote products derived
2492108Sphk *    from this software without specific prior written permission.
2592108Sphk *
2692108Sphk * Alternatively, this software may be distributed under the terms of the
2792108Sphk * GNU General Public License ("GPL") version 2 as published by the Free
2892108Sphk * Software Foundation.
2992108Sphk *
3092108Sphk * NO WARRANTY
3192108Sphk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3292108Sphk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3392108Sphk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3492108Sphk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3592108Sphk * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3692108Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3792108Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3892108Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3992108Sphk * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40116196Sobrien * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41116196Sobrien * POSSIBILITY OF SUCH DAMAGES.
4292108Sphk */
4392108Sphk
4492108Sphk#include <contrib/dev/acpica/include/acpi.h>
4592108Sphk#include <contrib/dev/acpica/include/accommon.h>
4692108Sphk#include <contrib/dev/acpica/include/acdispat.h>
4792108Sphk#include <contrib/dev/acpica/include/acnamesp.h>
48136755Srwatson#include <contrib/dev/acpica/include/acdebug.h>
49150177Sjhb#include <contrib/dev/acpica/include/acdisasm.h>
50149576Spjd#include <contrib/dev/acpica/include/acparser.h>
51248508Skib#include <contrib/dev/acpica/include/acpredef.h>
52252330Sjeff
5392108Sphk
5492108Sphk#ifdef ACPI_DEBUGGER
5592108Sphk
5693250Sphk#define _COMPONENT          ACPI_CA_DEBUGGER
57112370Sphk        ACPI_MODULE_NAME    ("dbmethod")
5892108Sphk
59114526Sphk
60248508Skib/*******************************************************************************
61248508Skib *
62248508Skib * FUNCTION:    AcpiDbSetMethodBreakpoint
63248508Skib *
64248508Skib * PARAMETERS:  Location            - AML offset of breakpoint
65248508Skib *              WalkState           - Current walk info
66248508Skib *              Op                  - Current Op (from parse walk)
67114526Sphk *
68260385Sscottl * RETURN:      None
69260385Sscottl *
7092108Sphk * DESCRIPTION: Set a breakpoint in a control method at the specified
7192108Sphk *              AML offset
72125137Sphk *
7392108Sphk ******************************************************************************/
74287569Simp
75287569Simpvoid
76287569SimpAcpiDbSetMethodBreakpoint (
77287569Simp    char                    *Location,
78287569Simp    ACPI_WALK_STATE         *WalkState,
79287569Simp    ACPI_PARSE_OBJECT       *Op)
80287569Simp{
81287569Simp    UINT32                  Address;
82287569Simp
83287569Simp
84287569Simp    if (!Op)
85114526Sphk    {
86106338Sphk        AcpiOsPrintf ("There is no method currently executing\n");
87193981Sluigi        return;
88193981Sluigi    }
89193981Sluigi
90193981Sluigi    /* Get and verify the breakpoint address */
91193981Sluigi
92193981Sluigi    Address = ACPI_STRTOUL (Location, NULL, 16);
93193981Sluigi    if (Address <= Op->Common.AmlOffset)
94193981Sluigi    {
95193981Sluigi        AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n",
9692108Sphk            Address, Op->Common.AmlOffset);
9792108Sphk    }
9892108Sphk
9992108Sphk    /* Save breakpoint in current walk */
10092108Sphk
10192108Sphk    WalkState->UserBreakpoint = Address;
10292108Sphk    AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address);
10392108Sphk}
10492108Sphk
10592108Sphk
10692108Sphk/*******************************************************************************
10792108Sphk *
10892108Sphk * FUNCTION:    AcpiDbSetMethodCallBreakpoint
10992108Sphk *
11092108Sphk * PARAMETERS:  Op                  - Current Op (from parse walk)
11192108Sphk *
11292108Sphk * RETURN:      None
11392108Sphk *
11492108Sphk * DESCRIPTION: Set a breakpoint in a control method at the specified
11592108Sphk *              AML offset
11692108Sphk *
11792108Sphk ******************************************************************************/
11892108Sphk
11992108Sphkvoid
12092108SphkAcpiDbSetMethodCallBreakpoint (
12192108Sphk    ACPI_PARSE_OBJECT       *Op)
12292108Sphk{
12392108Sphk
12492108Sphk
12592108Sphk    if (!Op)
12693818Sjhb    {
12792108Sphk        AcpiOsPrintf ("There is no method currently executing\n");
12892108Sphk        return;
12992108Sphk    }
13092108Sphk
13192108Sphk    AcpiGbl_StepToNextCall = TRUE;
13292108Sphk}
13392108Sphk
13492108Sphk
13592108Sphk/*******************************************************************************
136134519Sphk *
137134519Sphk * FUNCTION:    AcpiDbSetMethodData
138134519Sphk *
13992108Sphk * PARAMETERS:  TypeArg         - L for local, A for argument
14092108Sphk *              IndexArg        - which one
14192108Sphk *              ValueArg        - Value to set.
14292108Sphk *
14392108Sphk * RETURN:      None
14492108Sphk *
14592108Sphk * DESCRIPTION: Set a local or argument for the running control method.
14692108Sphk *              NOTE: only object supported is Number.
14792108Sphk *
14892108Sphk ******************************************************************************/
14992108Sphk
150114526Sphkvoid
151149576SpjdAcpiDbSetMethodData (
152173001Spjd    char                    *TypeArg,
153149576Spjd    char                    *IndexArg,
154149576Spjd    char                    *ValueArg)
155149576Spjd{
156149576Spjd    char                    Type;
157149576Spjd    UINT32                  Index;
158149576Spjd    UINT32                  Value;
159149576Spjd    ACPI_WALK_STATE         *WalkState;
16092108Sphk    ACPI_OPERAND_OBJECT     *ObjDesc;
16192108Sphk    ACPI_STATUS             Status;
16292108Sphk    ACPI_NAMESPACE_NODE     *Node;
163134379Sphk
164134379Sphk
165134379Sphk    /* Validate TypeArg */
166134379Sphk
167134379Sphk    AcpiUtStrupr (TypeArg);
168134379Sphk    Type = TypeArg[0];
169149576Spjd    if ((Type != 'L') &&
170173001Spjd        (Type != 'A') &&
171149576Spjd        (Type != 'N'))
172149576Spjd    {
173149576Spjd        AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg);
174149576Spjd        return;
175149576Spjd    }
176149576Spjd
177149576Spjd    Value = ACPI_STRTOUL (ValueArg, NULL, 16);
178134379Sphk
179134379Sphk    if (Type == 'N')
180134379Sphk    {
18192108Sphk        Node = AcpiDbConvertToNode (IndexArg);
18292108Sphk        if (!Node)
18392108Sphk        {
184149576Spjd            return;
185173001Spjd        }
186149576Spjd
18792108Sphk        if (Node->Type != ACPI_TYPE_INTEGER)
188149576Spjd        {
189149576Spjd            AcpiOsPrintf ("Can only set Integer nodes\n");
190149576Spjd            return;
191149576Spjd        }
192149576Spjd        ObjDesc = Node->Object;
193114526Sphk        ObjDesc->Integer.Value = Value;
19492108Sphk        return;
19592108Sphk    }
19692108Sphk
19792108Sphk    /* Get the index and value */
19892108Sphk
19992108Sphk    Index = ACPI_STRTOUL (IndexArg, NULL, 16);
20092108Sphk
201114526Sphk    WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
202104058Sphk    if (!WalkState)
203110517Sphk    {
204104058Sphk        AcpiOsPrintf ("There is no method currently executing\n");
205239132Sjimharris        return;
206239132Sjimharris    }
207239132Sjimharris
208292348Sken    /* Create and initialize the new object */
209292348Sken
210239132Sjimharris    ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value);
211239132Sjimharris    if (!ObjDesc)
212292348Sken    {
213292348Sken        AcpiOsPrintf ("Could not create an internal object\n");
214104058Sphk        return;
215104058Sphk    }
216104058Sphk
217248508Skib    /* Store the new object into the target */
218248508Skib
219248508Skib    switch (Type)
220104058Sphk    {
221193981Sluigi    case 'A':
222193981Sluigi
223193981Sluigi        /* Set a method argument */
224110523Sphk
225104058Sphk        if (Index > ACPI_METHOD_MAX_ARG)
226149576Spjd        {
227173001Spjd            AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index);
228149576Spjd            goto Cleanup;
229149576Spjd        }
230156686Sru
231149576Spjd        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc,
232149576Spjd                    WalkState);
233149576Spjd        if (ACPI_FAILURE (Status))
234149576Spjd        {
23592108Sphk            goto Cleanup;
23692108Sphk        }
23792108Sphk
238159304Spjd        ObjDesc = WalkState->Arguments[Index].Object;
239159304Spjd
240159304Spjd        AcpiOsPrintf ("Arg%u: ", Index);
241159304Spjd        AcpiDmDisplayInternalObject (ObjDesc, WalkState);
242159304Spjd        break;
243159304Spjd
244292348Sken    case 'L':
245159304Spjd
246159304Spjd        /* Set a method local */
247159304Spjd
248159304Spjd        if (Index > ACPI_METHOD_MAX_LOCAL)
249159304Spjd        {
250248508Skib            AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index);
251248508Skib            goto Cleanup;
252248508Skib        }
253159304Spjd
254159304Spjd        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc,
255159304Spjd                    WalkState);
256173001Spjd        if (ACPI_FAILURE (Status))
257159304Spjd        {
258159304Spjd            goto Cleanup;
259159304Spjd        }
260159304Spjd
261159304Spjd        ObjDesc = WalkState->LocalVariables[Index].Object;
262159304Spjd
263159304Spjd        AcpiOsPrintf ("Local%u: ", Index);
264159304Spjd        AcpiDmDisplayInternalObject (ObjDesc, WalkState);
265159304Spjd        break;
266159304Spjd
26792108Sphk    default:
26892108Sphk
26992108Sphk        break;
27092108Sphk    }
27192108Sphk
27292108SphkCleanup:
273125137Sphk    AcpiUtRemoveReference (ObjDesc);
274114526Sphk}
275114526Sphk
276114526Sphk
277114526Sphk/*******************************************************************************
27892108Sphk *
27992108Sphk * FUNCTION:    AcpiDbDisassembleAml
28092108Sphk *
28194283Sphk * PARAMETERS:  Statements          - Number of statements to disassemble
28292108Sphk *              Op                  - Current Op (from parse walk)
28392108Sphk *
28492108Sphk * RETURN:      None
28592108Sphk *
28692108Sphk * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
287134379Sphk *              of statements specified.
288104665Sphk *
289104665Sphk ******************************************************************************/
290104665Sphk
291104665Sphkvoid
292104665SphkAcpiDbDisassembleAml (
293104665Sphk    char                    *Statements,
294104665Sphk    ACPI_PARSE_OBJECT       *Op)
295104665Sphk{
296104665Sphk    UINT32                  NumStatements = 8;
29792108Sphk
29892108Sphk
29992108Sphk    if (!Op)
300163832Spjd    {
301163832Spjd        AcpiOsPrintf ("There is no method currently executing\n");
302163832Spjd        return;
303163832Spjd    }
304163832Spjd
305163832Spjd    if (Statements)
306163832Spjd    {
307163832Spjd        NumStatements = ACPI_STRTOUL (Statements, NULL, 0);
308163832Spjd    }
309212160Sgibbs
310163832Spjd#ifdef ACPI_DISASSEMBLER
311163832Spjd    AcpiDmDisassemble (NULL, Op, NumStatements);
312163832Spjd#endif
313163832Spjd}
314163832Spjd
315163832Spjd
316163832Spjd/*******************************************************************************
317163832Spjd *
318163832Spjd * FUNCTION:    AcpiDbDisassembleMethod
319163832Spjd *
320163832Spjd * PARAMETERS:  Name            - Name of control method
321110471Sphk *
322110471Sphk * RETURN:      None
32392108Sphk *
324110471Sphk * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
325110471Sphk *              of statements specified.
326260385Sscottl *
327260385Sscottl ******************************************************************************/
32892108Sphk
329110471SphkACPI_STATUS
330110471SphkAcpiDbDisassembleMethod (
33192108Sphk    char                    *Name)
332110471Sphk{
33393778Sphk    ACPI_STATUS             Status;
33493778Sphk    ACPI_PARSE_OBJECT       *Op;
33593778Sphk    ACPI_WALK_STATE         *WalkState;
336110471Sphk    ACPI_OPERAND_OBJECT     *ObjDesc;
337110471Sphk    ACPI_NAMESPACE_NODE     *Method;
33893778Sphk
33993778Sphk
34093778Sphk    Method = AcpiDbConvertToNode (Name);
341163832Spjd    if (!Method)
342110471Sphk    {
343110471Sphk        return (AE_BAD_PARAMETER);
34493778Sphk    }
34593778Sphk
346110471Sphk    if (Method->Type != ACPI_TYPE_METHOD)
34793778Sphk    {
34893778Sphk        ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
349110471Sphk            Name, AcpiUtGetTypeName (Method->Type)));
350110471Sphk        return (AE_BAD_PARAMETER);
351238886Smav    }
352238886Smav
353110471Sphk    ObjDesc = Method->Object;
35493778Sphk
35593778Sphk    Op = AcpiPsCreateScopeOp ();
35693778Sphk    if (!Op)
35793778Sphk    {
358206650Savg        return (AE_NO_MEMORY);
359206650Savg    }
360121323Sphk
361108051Sphk    /* Create and initialize a new walk state */
362110471Sphk
363110471Sphk    WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
364108051Sphk    if (!WalkState)
365110471Sphk    {
366110471Sphk        return (AE_NO_MEMORY);
367121253Sphk    }
368121253Sphk
369121253Sphk    Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
370110471Sphk        ObjDesc->Method.AmlStart,
371110471Sphk        ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
372260385Sscottl    if (ACPI_FAILURE (Status))
373260385Sscottl    {
374260385Sscottl        return (Status);
375260385Sscottl    }
376260385Sscottl
377260385Sscottl    Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
378260385Sscottl    WalkState->OwnerId = ObjDesc->Method.OwnerId;
379260385Sscottl
380260385Sscottl    /* Push start scope on scope stack and make it current */
381260385Sscottl
382260385Sscottl    Status = AcpiDsScopeStackPush (Method,
383260385Sscottl        Method->Type, WalkState);
384260385Sscottl    if (ACPI_FAILURE (Status))
385260385Sscottl    {
386260385Sscottl        return (Status);
387260385Sscottl    }
388260385Sscottl
389260385Sscottl    /* Parse the entire method AML including deferred operators */
390260385Sscottl
391260385Sscottl    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
392260385Sscottl    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
393260385Sscottl
394260385Sscottl    Status = AcpiPsParseAml (WalkState);
395260385Sscottl    (void) AcpiDmParseDeferredOps (Op);
396260385Sscottl
397260385Sscottl    /* Now we can disassemble the method */
398260385Sscottl
399260385Sscottl    AcpiGbl_DbOpt_verbose = FALSE;
400260385Sscottl#ifdef ACPI_DISASSEMBLER
401260385Sscottl    AcpiDmDisassemble (NULL, Op, 0);
402260385Sscottl#endif
403260385Sscottl    AcpiGbl_DbOpt_verbose = TRUE;
404260385Sscottl
40593778Sphk    AcpiPsDeleteParseTree (Op);
40693778Sphk
40793778Sphk    /* Method cleanup */
40892108Sphk
409260385Sscottl    AcpiNsDeleteNamespaceSubtree (Method);
410110471Sphk    AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
411110471Sphk    AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
412193981Sluigi    return (AE_OK);
413193981Sluigi}
414193981Sluigi
415193981Sluigi#endif /* ACPI_DEBUGGER */
416193981Sluigi