1218585Sjkim/*******************************************************************************
2218585Sjkim *
3218585Sjkim * Module Name: dbmethod - Debug commands for control methods
4218585Sjkim *
5218585Sjkim ******************************************************************************/
6218585Sjkim
7218585Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9218585Sjkim * All rights reserved.
10218585Sjkim *
11218585Sjkim * Redistribution and use in source and binary forms, with or without
12218585Sjkim * modification, are permitted provided that the following conditions
13218585Sjkim * are met:
14218585Sjkim * 1. Redistributions of source code must retain the above copyright
15218585Sjkim *    notice, this list of conditions, and the following disclaimer,
16218585Sjkim *    without modification.
17218585Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18218585Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19218585Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20218585Sjkim *    including a substantially similar Disclaimer requirement for further
21218585Sjkim *    binary redistribution.
22218585Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23218585Sjkim *    of any contributors may be used to endorse or promote products derived
24218585Sjkim *    from this software without specific prior written permission.
25218585Sjkim *
26218585Sjkim * Alternatively, this software may be distributed under the terms of the
27218585Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28218585Sjkim * Software Foundation.
29218585Sjkim *
30218585Sjkim * NO WARRANTY
31218585Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32218585Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33218585Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34218585Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35218585Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36218585Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37218585Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38218585Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39218585Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40218585Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41218585Sjkim * POSSIBILITY OF SUCH DAMAGES.
42218585Sjkim */
43218585Sjkim
44218590Sjkim#include <contrib/dev/acpica/include/acpi.h>
45218590Sjkim#include <contrib/dev/acpica/include/accommon.h>
46218590Sjkim#include <contrib/dev/acpica/include/acdispat.h>
47218590Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48218590Sjkim#include <contrib/dev/acpica/include/acdebug.h>
49218590Sjkim#include <contrib/dev/acpica/include/acparser.h>
50249663Sjkim#include <contrib/dev/acpica/include/acpredef.h>
51218585Sjkim
52218585Sjkim
53218585Sjkim#define _COMPONENT          ACPI_CA_DEBUGGER
54218585Sjkim        ACPI_MODULE_NAME    ("dbmethod")
55218585Sjkim
56218585Sjkim
57218585Sjkim/*******************************************************************************
58218585Sjkim *
59218585Sjkim * FUNCTION:    AcpiDbSetMethodBreakpoint
60218585Sjkim *
61218585Sjkim * PARAMETERS:  Location            - AML offset of breakpoint
62218585Sjkim *              WalkState           - Current walk info
63218585Sjkim *              Op                  - Current Op (from parse walk)
64218585Sjkim *
65218585Sjkim * RETURN:      None
66218585Sjkim *
67218585Sjkim * DESCRIPTION: Set a breakpoint in a control method at the specified
68218585Sjkim *              AML offset
69218585Sjkim *
70218585Sjkim ******************************************************************************/
71218585Sjkim
72218585Sjkimvoid
73218585SjkimAcpiDbSetMethodBreakpoint (
74218585Sjkim    char                    *Location,
75218585Sjkim    ACPI_WALK_STATE         *WalkState,
76218585Sjkim    ACPI_PARSE_OBJECT       *Op)
77218585Sjkim{
78218585Sjkim    UINT32                  Address;
79306536Sjkim    UINT32                  AmlOffset;
80218585Sjkim
81218585Sjkim
82218585Sjkim    if (!Op)
83218585Sjkim    {
84218585Sjkim        AcpiOsPrintf ("There is no method currently executing\n");
85218585Sjkim        return;
86218585Sjkim    }
87218585Sjkim
88218585Sjkim    /* Get and verify the breakpoint address */
89218585Sjkim
90306536Sjkim    Address = strtoul (Location, NULL, 16);
91306536Sjkim    AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
92306536Sjkim        WalkState->ParserState.AmlStart);
93306536Sjkim    if (Address <= AmlOffset)
94218585Sjkim    {
95218585Sjkim        AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n",
96306536Sjkim            Address, AmlOffset);
97218585Sjkim    }
98218585Sjkim
99218585Sjkim    /* Save breakpoint in current walk */
100218585Sjkim
101218585Sjkim    WalkState->UserBreakpoint = Address;
102218585Sjkim    AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address);
103218585Sjkim}
104218585Sjkim
105218585Sjkim
106218585Sjkim/*******************************************************************************
107218585Sjkim *
108218585Sjkim * FUNCTION:    AcpiDbSetMethodCallBreakpoint
109218585Sjkim *
110218585Sjkim * PARAMETERS:  Op                  - Current Op (from parse walk)
111218585Sjkim *
112218585Sjkim * RETURN:      None
113218585Sjkim *
114218585Sjkim * DESCRIPTION: Set a breakpoint in a control method at the specified
115218585Sjkim *              AML offset
116218585Sjkim *
117218585Sjkim ******************************************************************************/
118218585Sjkim
119218585Sjkimvoid
120218585SjkimAcpiDbSetMethodCallBreakpoint (
121218585Sjkim    ACPI_PARSE_OBJECT       *Op)
122218585Sjkim{
123218585Sjkim
124218585Sjkim
125218585Sjkim    if (!Op)
126218585Sjkim    {
127218585Sjkim        AcpiOsPrintf ("There is no method currently executing\n");
128218585Sjkim        return;
129218585Sjkim    }
130218585Sjkim
131218585Sjkim    AcpiGbl_StepToNextCall = TRUE;
132218585Sjkim}
133218585Sjkim
134218585Sjkim
135218585Sjkim/*******************************************************************************
136218585Sjkim *
137218585Sjkim * FUNCTION:    AcpiDbSetMethodData
138218585Sjkim *
139218585Sjkim * PARAMETERS:  TypeArg         - L for local, A for argument
140218585Sjkim *              IndexArg        - which one
141218585Sjkim *              ValueArg        - Value to set.
142218585Sjkim *
143218585Sjkim * RETURN:      None
144218585Sjkim *
145218585Sjkim * DESCRIPTION: Set a local or argument for the running control method.
146218585Sjkim *              NOTE: only object supported is Number.
147218585Sjkim *
148218585Sjkim ******************************************************************************/
149218585Sjkim
150218585Sjkimvoid
151218585SjkimAcpiDbSetMethodData (
152218585Sjkim    char                    *TypeArg,
153218585Sjkim    char                    *IndexArg,
154218585Sjkim    char                    *ValueArg)
155218585Sjkim{
156218585Sjkim    char                    Type;
157218585Sjkim    UINT32                  Index;
158218585Sjkim    UINT32                  Value;
159218585Sjkim    ACPI_WALK_STATE         *WalkState;
160218585Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
161218585Sjkim    ACPI_STATUS             Status;
162218585Sjkim    ACPI_NAMESPACE_NODE     *Node;
163218585Sjkim
164218585Sjkim
165218585Sjkim    /* Validate TypeArg */
166218585Sjkim
167218585Sjkim    AcpiUtStrupr (TypeArg);
168218585Sjkim    Type = TypeArg[0];
169218585Sjkim    if ((Type != 'L') &&
170218585Sjkim        (Type != 'A') &&
171218585Sjkim        (Type != 'N'))
172218585Sjkim    {
173218585Sjkim        AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg);
174218585Sjkim        return;
175218585Sjkim    }
176218585Sjkim
177306536Sjkim    Value = strtoul (ValueArg, NULL, 16);
178218585Sjkim
179218585Sjkim    if (Type == 'N')
180218585Sjkim    {
181218585Sjkim        Node = AcpiDbConvertToNode (IndexArg);
182281075Sdim        if (!Node)
183281075Sdim        {
184281075Sdim            return;
185281075Sdim        }
186281075Sdim
187218585Sjkim        if (Node->Type != ACPI_TYPE_INTEGER)
188218585Sjkim        {
189218585Sjkim            AcpiOsPrintf ("Can only set Integer nodes\n");
190218585Sjkim            return;
191218585Sjkim        }
192218585Sjkim        ObjDesc = Node->Object;
193218585Sjkim        ObjDesc->Integer.Value = Value;
194218585Sjkim        return;
195218585Sjkim    }
196218585Sjkim
197218585Sjkim    /* Get the index and value */
198218585Sjkim
199306536Sjkim    Index = strtoul (IndexArg, NULL, 16);
200218585Sjkim
201218585Sjkim    WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
202218585Sjkim    if (!WalkState)
203218585Sjkim    {
204218585Sjkim        AcpiOsPrintf ("There is no method currently executing\n");
205218585Sjkim        return;
206218585Sjkim    }
207218585Sjkim
208218585Sjkim    /* Create and initialize the new object */
209218585Sjkim
210218585Sjkim    ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value);
211218585Sjkim    if (!ObjDesc)
212218585Sjkim    {
213218585Sjkim        AcpiOsPrintf ("Could not create an internal object\n");
214218585Sjkim        return;
215218585Sjkim    }
216218585Sjkim
217218585Sjkim    /* Store the new object into the target */
218218585Sjkim
219218585Sjkim    switch (Type)
220218585Sjkim    {
221218585Sjkim    case 'A':
222218585Sjkim
223218585Sjkim        /* Set a method argument */
224218585Sjkim
225218585Sjkim        if (Index > ACPI_METHOD_MAX_ARG)
226218585Sjkim        {
227306536Sjkim            AcpiOsPrintf ("Arg%u - Invalid argument name\n",
228306536Sjkim                Index);
229218585Sjkim            goto Cleanup;
230218585Sjkim        }
231218585Sjkim
232306536Sjkim        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG,
233306536Sjkim            Index, ObjDesc, WalkState);
234218585Sjkim        if (ACPI_FAILURE (Status))
235218585Sjkim        {
236218585Sjkim            goto Cleanup;
237218585Sjkim        }
238218585Sjkim
239218585Sjkim        ObjDesc = WalkState->Arguments[Index].Object;
240218585Sjkim
241218585Sjkim        AcpiOsPrintf ("Arg%u: ", Index);
242306536Sjkim        AcpiDbDisplayInternalObject (ObjDesc, WalkState);
243218585Sjkim        break;
244218585Sjkim
245218585Sjkim    case 'L':
246218585Sjkim
247218585Sjkim        /* Set a method local */
248218585Sjkim
249218585Sjkim        if (Index > ACPI_METHOD_MAX_LOCAL)
250218585Sjkim        {
251306536Sjkim            AcpiOsPrintf ("Local%u - Invalid local variable name\n",
252306536Sjkim                Index);
253218585Sjkim            goto Cleanup;
254218585Sjkim        }
255218585Sjkim
256306536Sjkim        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL,
257306536Sjkim            Index, ObjDesc, WalkState);
258218585Sjkim        if (ACPI_FAILURE (Status))
259218585Sjkim        {
260218585Sjkim            goto Cleanup;
261218585Sjkim        }
262218585Sjkim
263218585Sjkim        ObjDesc = WalkState->LocalVariables[Index].Object;
264218585Sjkim
265218585Sjkim        AcpiOsPrintf ("Local%u: ", Index);
266306536Sjkim        AcpiDbDisplayInternalObject (ObjDesc, WalkState);
267218585Sjkim        break;
268218585Sjkim
269218585Sjkim    default:
270250838Sjkim
271218585Sjkim        break;
272218585Sjkim    }
273218585Sjkim
274218585SjkimCleanup:
275218585Sjkim    AcpiUtRemoveReference (ObjDesc);
276218585Sjkim}
277218585Sjkim
278218585Sjkim
279218585Sjkim/*******************************************************************************
280218585Sjkim *
281218585Sjkim * FUNCTION:    AcpiDbDisassembleAml
282218585Sjkim *
283218585Sjkim * PARAMETERS:  Statements          - Number of statements to disassemble
284218585Sjkim *              Op                  - Current Op (from parse walk)
285218585Sjkim *
286218585Sjkim * RETURN:      None
287218585Sjkim *
288218585Sjkim * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
289218585Sjkim *              of statements specified.
290218585Sjkim *
291218585Sjkim ******************************************************************************/
292218585Sjkim
293218585Sjkimvoid
294218585SjkimAcpiDbDisassembleAml (
295218585Sjkim    char                    *Statements,
296218585Sjkim    ACPI_PARSE_OBJECT       *Op)
297218585Sjkim{
298218585Sjkim    UINT32                  NumStatements = 8;
299218585Sjkim
300218585Sjkim
301218585Sjkim    if (!Op)
302218585Sjkim    {
303218585Sjkim        AcpiOsPrintf ("There is no method currently executing\n");
304218585Sjkim        return;
305218585Sjkim    }
306218585Sjkim
307218585Sjkim    if (Statements)
308218585Sjkim    {
309306536Sjkim        NumStatements = strtoul (Statements, NULL, 0);
310218585Sjkim    }
311218585Sjkim
312218590Sjkim#ifdef ACPI_DISASSEMBLER
313218585Sjkim    AcpiDmDisassemble (NULL, Op, NumStatements);
314218590Sjkim#endif
315218585Sjkim}
316218585Sjkim
317218585Sjkim
318218585Sjkim/*******************************************************************************
319218585Sjkim *
320218585Sjkim * FUNCTION:    AcpiDbDisassembleMethod
321218585Sjkim *
322218585Sjkim * PARAMETERS:  Name            - Name of control method
323218585Sjkim *
324218585Sjkim * RETURN:      None
325218585Sjkim *
326218585Sjkim * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
327218585Sjkim *              of statements specified.
328218585Sjkim *
329218585Sjkim ******************************************************************************/
330218585Sjkim
331218585SjkimACPI_STATUS
332218585SjkimAcpiDbDisassembleMethod (
333218585Sjkim    char                    *Name)
334218585Sjkim{
335218585Sjkim    ACPI_STATUS             Status;
336218585Sjkim    ACPI_PARSE_OBJECT       *Op;
337218585Sjkim    ACPI_WALK_STATE         *WalkState;
338218585Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
339218585Sjkim    ACPI_NAMESPACE_NODE     *Method;
340218585Sjkim
341218585Sjkim
342218585Sjkim    Method = AcpiDbConvertToNode (Name);
343218585Sjkim    if (!Method)
344218585Sjkim    {
345218585Sjkim        return (AE_BAD_PARAMETER);
346218585Sjkim    }
347218585Sjkim
348243347Sjkim    if (Method->Type != ACPI_TYPE_METHOD)
349243347Sjkim    {
350243347Sjkim        ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
351243347Sjkim            Name, AcpiUtGetTypeName (Method->Type)));
352243347Sjkim        return (AE_BAD_PARAMETER);
353243347Sjkim    }
354243347Sjkim
355218585Sjkim    ObjDesc = Method->Object;
356218585Sjkim
357306536Sjkim    Op = AcpiPsCreateScopeOp (ObjDesc->Method.AmlStart);
358218585Sjkim    if (!Op)
359218585Sjkim    {
360218585Sjkim        return (AE_NO_MEMORY);
361218585Sjkim    }
362218585Sjkim
363218585Sjkim    /* Create and initialize a new walk state */
364218585Sjkim
365218585Sjkim    WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
366218585Sjkim    if (!WalkState)
367218585Sjkim    {
368218585Sjkim        return (AE_NO_MEMORY);
369218585Sjkim    }
370218585Sjkim
371218585Sjkim    Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
372243347Sjkim        ObjDesc->Method.AmlStart,
373243347Sjkim        ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
374218585Sjkim    if (ACPI_FAILURE (Status))
375218585Sjkim    {
376218585Sjkim        return (Status);
377218585Sjkim    }
378218585Sjkim
379243347Sjkim    Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
380243347Sjkim    WalkState->OwnerId = ObjDesc->Method.OwnerId;
381218585Sjkim
382243347Sjkim    /* Push start scope on scope stack and make it current */
383243347Sjkim
384243347Sjkim    Status = AcpiDsScopeStackPush (Method,
385243347Sjkim        Method->Type, WalkState);
386243347Sjkim    if (ACPI_FAILURE (Status))
387243347Sjkim    {
388243347Sjkim        return (Status);
389243347Sjkim    }
390243347Sjkim
391243347Sjkim    /* Parse the entire method AML including deferred operators */
392243347Sjkim
393218585Sjkim    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
394218585Sjkim    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
395243347Sjkim
396218585Sjkim    Status = AcpiPsParseAml (WalkState);
397306536Sjkim
398306536Sjkim#ifdef ACPI_DISASSEMBLER
399245582Sjkim    (void) AcpiDmParseDeferredOps (Op);
400218585Sjkim
401243347Sjkim    /* Now we can disassemble the method */
402243347Sjkim
403306536Sjkim    AcpiGbl_DmOpt_Verbose = FALSE;
404218585Sjkim    AcpiDmDisassemble (NULL, Op, 0);
405306536Sjkim    AcpiGbl_DmOpt_Verbose = TRUE;
406218590Sjkim#endif
407243347Sjkim
408218585Sjkim    AcpiPsDeleteParseTree (Op);
409243347Sjkim
410243347Sjkim    /* Method cleanup */
411243347Sjkim
412243347Sjkim    AcpiNsDeleteNamespaceSubtree (Method);
413243347Sjkim    AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
414243347Sjkim    AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
415218585Sjkim    return (AE_OK);
416218585Sjkim}
417