dbutils.c revision 306536
1139749Simp/*******************************************************************************
2196008Smjacob *
3167403Smjacob * Module Name: dbutils - AML debugger utilities
4196008Smjacob *
5167403Smjacob ******************************************************************************/
6167403Smjacob
7167403Smjacob/*
8196008Smjacob * Copyright (C) 2000 - 2016, Intel Corp.
9167403Smjacob * All rights reserved.
10167403Smjacob *
11167403Smjacob * Redistribution and use in source and binary forms, with or without
12167403Smjacob * modification, are permitted provided that the following conditions
13167403Smjacob * are met:
14196008Smjacob * 1. Redistributions of source code must retain the above copyright
15167403Smjacob *    notice, this list of conditions, and the following disclaimer,
16167403Smjacob *    without modification.
17167403Smjacob * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18167403Smjacob *    substantially similar to the "NO WARRANTY" disclaimer below
19167403Smjacob *    ("Disclaimer") and any redistribution must be conditioned upon
20167403Smjacob *    including a substantially similar Disclaimer requirement for further
21167403Smjacob *    binary redistribution.
22167403Smjacob * 3. Neither the names of the above-listed copyright holders nor the names
23167403Smjacob *    of any contributors may be used to endorse or promote products derived
24167403Smjacob *    from this software without specific prior written permission.
25167403Smjacob *
26196008Smjacob * Alternatively, this software may be distributed under the terms of the
27167403Smjacob * GNU General Public License ("GPL") version 2 as published by the Free
28167403Smjacob * Software Foundation.
2955373Smjacob *
3055373Smjacob * NO WARRANTY
3155373Smjacob * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3290224Smjacob * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3390224Smjacob * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3490224Smjacob * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3590224Smjacob * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3655373Smjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3755373Smjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3855373Smjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3955373Smjacob * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4055373Smjacob * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4155373Smjacob * POSSIBILITY OF SUCH DAMAGES.
4255373Smjacob */
43160410Smjacob
44160410Smjacob#include <contrib/dev/acpica/include/acpi.h>
4555373Smjacob#include <contrib/dev/acpica/include/accommon.h>
4655373Smjacob#include <contrib/dev/acpica/include/acnamesp.h>
4755373Smjacob#include <contrib/dev/acpica/include/acdebug.h>
4855373Smjacob
4955373Smjacob
5055373Smjacob#define _COMPONENT          ACPI_CA_DEBUGGER
5155373Smjacob        ACPI_MODULE_NAME    ("dbutils")
5255373Smjacob
5355373Smjacob
5455373Smjacob/* Local prototypes */
55196008Smjacob
56196008Smjacob#ifdef ACPI_OBSOLETE_FUNCTIONS
57196008SmjacobACPI_STATUS
5855373SmjacobAcpiDbSecondPassParse (
59157943Smjacob    ACPI_PARSE_OBJECT       *Root);
60157943Smjacob
61163899Smjacobvoid
62157943SmjacobAcpiDbDumpBuffer (
63157943Smjacob    UINT32                  Address);
64157943Smjacob#endif
65157943Smjacob
66163899Smjacob
67196008Smjacob/*******************************************************************************
6855373Smjacob *
6955373Smjacob * FUNCTION:    AcpiDbMatchArgument
7055373Smjacob *
7155373Smjacob * PARAMETERS:  UserArgument            - User command line
7255373Smjacob *              Arguments               - Array of commands to match against
7355373Smjacob *
7455373Smjacob * RETURN:      Index into command array or ACPI_TYPE_NOT_FOUND if not found
7555373Smjacob *
7655373Smjacob * DESCRIPTION: Search command array for a command match
7755373Smjacob *
7855373Smjacob ******************************************************************************/
7955373Smjacob
8055373SmjacobACPI_OBJECT_TYPE
8155373SmjacobAcpiDbMatchArgument (
8255373Smjacob    char                    *UserArgument,
8355373Smjacob    ACPI_DB_ARGUMENT_INFO   *Arguments)
8455373Smjacob{
8555373Smjacob    UINT32                  i;
8655373Smjacob
8755373Smjacob
8855373Smjacob    if (!UserArgument || UserArgument[0] == 0)
8955373Smjacob    {
9055373Smjacob        return (ACPI_TYPE_NOT_FOUND);
9155373Smjacob    }
9255373Smjacob
9355373Smjacob    for (i = 0; Arguments[i].Name; i++)
9455373Smjacob    {
9555373Smjacob        if (strstr (
9655373Smjacob            ACPI_CAST_PTR (char, Arguments[i].Name),
9772082Sasmodai            ACPI_CAST_PTR (char, UserArgument)) == Arguments[i].Name)
9855373Smjacob        {
9955373Smjacob            return (i);
10055373Smjacob        }
10155373Smjacob    }
10255373Smjacob
10355373Smjacob    /* Argument not recognized */
10455373Smjacob
10555373Smjacob    return (ACPI_TYPE_NOT_FOUND);
10655373Smjacob}
10755373Smjacob
10855373Smjacob
10955373Smjacob/*******************************************************************************
11055373Smjacob *
11155373Smjacob * FUNCTION:    AcpiDbSetOutputDestination
11255373Smjacob *
11355373Smjacob * PARAMETERS:  OutputFlags         - Current flags word
11455373Smjacob *
11555373Smjacob * RETURN:      None
116163899Smjacob *
11755373Smjacob * DESCRIPTION: Set the current destination for debugger output. Also sets
118163899Smjacob *              the debug output level accordingly.
119163899Smjacob *
12055373Smjacob ******************************************************************************/
12155373Smjacob
12255373Smjacobvoid
123154704SmjacobAcpiDbSetOutputDestination (
124163899Smjacob    UINT32                  OutputFlags)
12555373Smjacob{
12655373Smjacob
127154704Smjacob    AcpiGbl_DbOutputFlags = (UINT8) OutputFlags;
128163899Smjacob
12955373Smjacob    if ((OutputFlags & ACPI_DB_REDIRECTABLE_OUTPUT) &&
13055373Smjacob        AcpiGbl_DbOutputToFile)
13155373Smjacob    {
132154704Smjacob        AcpiDbgLevel = AcpiGbl_DbDebugLevel;
133163899Smjacob    }
13455373Smjacob    else
13555373Smjacob    {
136154704Smjacob        AcpiDbgLevel = AcpiGbl_DbConsoleDebugLevel;
137163899Smjacob    }
13855373Smjacob}
139163899Smjacob
140163899Smjacob
141163899Smjacob/*******************************************************************************
14255373Smjacob *
14355373Smjacob * FUNCTION:    AcpiDbDumpExternalObject
14455373Smjacob *
145154704Smjacob * PARAMETERS:  ObjDesc         - External ACPI object to dump
146163899Smjacob *              Level           - Nesting level.
14755373Smjacob *
14855373Smjacob * RETURN:      None
149154704Smjacob *
150163899Smjacob * DESCRIPTION: Dump the contents of an ACPI external object
15155373Smjacob *
15255373Smjacob ******************************************************************************/
15355373Smjacob
154154704Smjacobvoid
155163899SmjacobAcpiDbDumpExternalObject (
15655373Smjacob    ACPI_OBJECT             *ObjDesc,
15755373Smjacob    UINT32                  Level)
158154704Smjacob{
159163899Smjacob    UINT32                  i;
160163899Smjacob
161163899Smjacob
162163899Smjacob    if (!ObjDesc)
16355373Smjacob    {
16455373Smjacob        AcpiOsPrintf ("[Null Object]\n");
165155704Smjacob        return;
166196008Smjacob    }
167163899Smjacob
168196008Smjacob    for (i = 0; i < Level; i++)
16955373Smjacob    {
17087635Smjacob        AcpiOsPrintf ("  ");
17155373Smjacob    }
17255373Smjacob
17355373Smjacob    switch (ObjDesc->Type)
17455373Smjacob    {
175196008Smjacob    case ACPI_TYPE_ANY:
17655373Smjacob
177163899Smjacob        AcpiOsPrintf ("[Null Object] (Type=0)\n");
178163899Smjacob        break;
179163899Smjacob
180163899Smjacob    case ACPI_TYPE_INTEGER:
181163899Smjacob
182163899Smjacob        AcpiOsPrintf ("[Integer] = %8.8X%8.8X\n",
183196008Smjacob            ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
184196008Smjacob        break;
185163899Smjacob
186163899Smjacob    case ACPI_TYPE_STRING:
187163899Smjacob
188163899Smjacob        AcpiOsPrintf ("[String] Length %.2X = ", ObjDesc->String.Length);
189196008Smjacob        AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX);
190163899Smjacob        AcpiOsPrintf ("\n");
191196008Smjacob        break;
192163899Smjacob
193163899Smjacob    case ACPI_TYPE_BUFFER:
194163899Smjacob
195163899Smjacob        AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length);
196163899Smjacob        if (ObjDesc->Buffer.Length)
197163899Smjacob        {
198163899Smjacob            if (ObjDesc->Buffer.Length > 16)
199163899Smjacob            {
200163899Smjacob                AcpiOsPrintf ("\n");
201163899Smjacob            }
202163899Smjacob
203163899Smjacob            AcpiUtDebugDumpBuffer (
204163899Smjacob                ACPI_CAST_PTR (UINT8, ObjDesc->Buffer.Pointer),
205196008Smjacob                ObjDesc->Buffer.Length, DB_BYTE_DISPLAY, _COMPONENT);
206163899Smjacob        }
207163899Smjacob        else
208163899Smjacob        {
209163899Smjacob            AcpiOsPrintf ("\n");
21055373Smjacob        }
211163899Smjacob        break;
21255373Smjacob
21387635Smjacob    case ACPI_TYPE_PACKAGE:
21487635Smjacob
21555373Smjacob        AcpiOsPrintf ("[Package] Contains %u Elements:\n",
216163899Smjacob            ObjDesc->Package.Count);
21755373Smjacob
218196008Smjacob        for (i = 0; i < ObjDesc->Package.Count; i++)
219154704Smjacob        {
220160251Smjacob            AcpiDbDumpExternalObject (
221154704Smjacob                &ObjDesc->Package.Elements[i], Level+1);
222163899Smjacob        }
22387635Smjacob        break;
22455373Smjacob
225163899Smjacob    case ACPI_TYPE_LOCAL_REFERENCE:
226125187Smjacob
22755373Smjacob        AcpiOsPrintf ("[Object Reference] = ");
228196008Smjacob        AcpiDbDisplayInternalObject (ObjDesc->Reference.Handle, NULL);
229154704Smjacob        break;
230160251Smjacob
231154704Smjacob    case ACPI_TYPE_PROCESSOR:
232163899Smjacob
23387635Smjacob        AcpiOsPrintf ("[Processor]\n");
23455373Smjacob        break;
235163899Smjacob
236163899Smjacob    case ACPI_TYPE_POWER:
237163899Smjacob
238163899Smjacob        AcpiOsPrintf ("[Power Resource]\n");
239163899Smjacob        break;
240163899Smjacob
24155373Smjacob    default:
24255373Smjacob
24387635Smjacob        AcpiOsPrintf ("[Unknown Type] %X\n", ObjDesc->Type);
244196008Smjacob        break;
24555373Smjacob    }
24655373Smjacob}
24755373Smjacob
24857216Smjacob
249163899Smjacob/*******************************************************************************
250196008Smjacob *
251163899Smjacob * FUNCTION:    AcpiDbPrepNamestring
252196008Smjacob *
253163899Smjacob * PARAMETERS:  Name            - String to prepare
254196008Smjacob *
255196008Smjacob * RETURN:      None
256196008Smjacob *
257196008Smjacob * DESCRIPTION: Translate all forward slashes and dots to backslashes.
258196008Smjacob *
259196008Smjacob ******************************************************************************/
260196008Smjacob
261196008Smjacobvoid
262160978SmjacobAcpiDbPrepNamestring (
263196008Smjacob    char                    *Name)
264196008Smjacob{
265196008Smjacob
266196008Smjacob    if (!Name)
267196008Smjacob    {
268160978Smjacob        return;
26955373Smjacob    }
270196008Smjacob
271196008Smjacob    AcpiUtStrupr (Name);
272196008Smjacob
273196008Smjacob    /* Convert a leading forward slash to a backslash */
274196008Smjacob
27557216Smjacob    if (*Name == '/')
276196008Smjacob    {
277196008Smjacob        *Name = '\\';
27857216Smjacob    }
27955373Smjacob
280160978Smjacob    /* Ignore a leading backslash, this is the root prefix */
281196008Smjacob
28283027Smjacob    if (ACPI_IS_ROOT_PREFIX (*Name))
28355373Smjacob    {
28455373Smjacob        Name++;
28555373Smjacob    }
28655373Smjacob
287154704Smjacob    /* Convert all slash path separators to dots */
28855373Smjacob
289154704Smjacob    while (*Name)
29055373Smjacob    {
29155373Smjacob        if ((*Name == '/') ||
29255373Smjacob            (*Name == '\\'))
293163899Smjacob        {
294240015Smjacob            *Name = '.';
29555373Smjacob        }
296196008Smjacob
297154704Smjacob        Name++;
298196008Smjacob    }
299163899Smjacob}
300196008Smjacob
301196008Smjacob
302196008Smjacob/*******************************************************************************
303196008Smjacob *
304196008Smjacob * FUNCTION:    AcpiDbLocalNsLookup
305163899Smjacob *
306163899Smjacob * PARAMETERS:  Name            - Name to lookup
307196008Smjacob *
308163899Smjacob * RETURN:      Pointer to a namespace node, null on failure
309163899Smjacob *
310196008Smjacob * DESCRIPTION: Lookup a name in the ACPI namespace
311196008Smjacob *
312154704Smjacob * Note: Currently begins search from the root. Could be enhanced to use
313196008Smjacob * the current prefix (scope) node as the search beginning point.
31498284Smjacob *
315196008Smjacob ******************************************************************************/
316196008Smjacob
317196008SmjacobACPI_NAMESPACE_NODE *
318196008SmjacobAcpiDbLocalNsLookup (
319196008Smjacob    char                    *Name)
320196008Smjacob{
321196008Smjacob    char                    *InternalPath;
322196008Smjacob    ACPI_STATUS             Status;
323196008Smjacob    ACPI_NAMESPACE_NODE     *Node = NULL;
324196008Smjacob
325196008Smjacob
326196008Smjacob    AcpiDbPrepNamestring (Name);
32755373Smjacob
328196008Smjacob    /* Build an internal namestring */
329196008Smjacob
330196008Smjacob    Status = AcpiNsInternalizeName (Name, &InternalPath);
331196008Smjacob    if (ACPI_FAILURE (Status))
332196008Smjacob    {
333196008Smjacob        AcpiOsPrintf ("Invalid namestring: %s\n", Name);
334196008Smjacob        return (NULL);
335196008Smjacob    }
336196008Smjacob
337196008Smjacob    /*
338196008Smjacob     * Lookup the name.
339196008Smjacob     * (Uses root node as the search starting point)
34055373Smjacob     */
341196008Smjacob    Status = AcpiNsLookup (NULL, InternalPath, ACPI_TYPE_ANY,
342196008Smjacob        ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
343196008Smjacob        NULL, &Node);
344196008Smjacob    if (ACPI_FAILURE (Status))
345196008Smjacob    {
346196008Smjacob        AcpiOsPrintf ("Could not locate name: %s, %s\n",
347196008Smjacob            Name, AcpiFormatException (Status));
348196008Smjacob    }
349240015Smjacob
350240015Smjacob    ACPI_FREE (InternalPath);
351196008Smjacob    return (Node);
35255373Smjacob}
353196008Smjacob
354196008Smjacob
355196008Smjacob/*******************************************************************************
356240015Smjacob *
357240015Smjacob * FUNCTION:    AcpiDbUint32ToHexString
358240015Smjacob *
359240015Smjacob * PARAMETERS:  Value           - The value to be converted to string
360240015Smjacob *              Buffer          - Buffer for result (not less than 11 bytes)
361240015Smjacob *
362240015Smjacob * RETURN:      None
363240015Smjacob *
364240015Smjacob * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image
365240015Smjacob *
366196008Smjacob * NOTE: It is the caller's responsibility to ensure that the length of buffer
367196008Smjacob *       is sufficient.
36855373Smjacob *
369196008Smjacob ******************************************************************************/
370196008Smjacob
371240015Smjacobvoid
37255373SmjacobAcpiDbUint32ToHexString (
37355373Smjacob    UINT32                  Value,
37455373Smjacob    char                    *Buffer)
37555373Smjacob{
37655373Smjacob    int                     i;
37755373Smjacob
37855373Smjacob
37955373Smjacob    if (Value == 0)
38055373Smjacob    {
381163899Smjacob        strcpy (Buffer, "0");
382196008Smjacob        return;
383163899Smjacob    }
384163899Smjacob
385163899Smjacob    Buffer[8] = '\0';
386163899Smjacob
387163899Smjacob    for (i = 7; i >= 0; i--)
388163899Smjacob    {
389196008Smjacob        Buffer[i] = AcpiGbl_UpperHexDigits [Value & 0x0F];
390163899Smjacob        Value = Value >> 4;
391196008Smjacob    }
392196008Smjacob}
393160251Smjacob
394196008Smjacob
395163899Smjacob#ifdef ACPI_OBSOLETE_FUNCTIONS
39687635Smjacob/*******************************************************************************
397163899Smjacob *
398163899Smjacob * FUNCTION:    AcpiDbSecondPassParse
399163899Smjacob *
400163899Smjacob * PARAMETERS:  Root            - Root of the parse tree
401163899Smjacob *
402196008Smjacob * RETURN:      Status
40355373Smjacob *
40487635Smjacob * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until
40587635Smjacob *              second pass to parse the control methods
406163899Smjacob *
407163899Smjacob ******************************************************************************/
408163899Smjacob
409163899SmjacobACPI_STATUS
410163899SmjacobAcpiDbSecondPassParse (
411196008Smjacob    ACPI_PARSE_OBJECT       *Root)
41255373Smjacob{
41355373Smjacob    ACPI_PARSE_OBJECT       *Op = Root;
414163899Smjacob    ACPI_PARSE_OBJECT       *Method;
415163899Smjacob    ACPI_PARSE_OBJECT       *SearchOp;
416163899Smjacob    ACPI_PARSE_OBJECT       *StartOp;
417196008Smjacob    ACPI_STATUS             Status = AE_OK;
418163899Smjacob    UINT32                  BaseAmlOffset;
419163899Smjacob    ACPI_WALK_STATE         *WalkState;
420163899Smjacob
421163899Smjacob
422163899Smjacob    ACPI_FUNCTION_ENTRY ();
423163899Smjacob
424163899Smjacob
425163899Smjacob    AcpiOsPrintf ("Pass two parse ....\n");
426163899Smjacob
427196008Smjacob    while (Op)
428196008Smjacob    {
429163899Smjacob        if (Op->Common.AmlOpcode == AML_METHOD_OP)
43055373Smjacob        {
431196008Smjacob            Method = Op;
43298284Smjacob
43355373Smjacob            /* Create a new walk state for the parse */
43455373Smjacob
43555373Smjacob            WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
43655373Smjacob            if (!WalkState)
437154704Smjacob            {
438163899Smjacob                return (AE_NO_MEMORY);
43955373Smjacob            }
44055373Smjacob
441154704Smjacob            /* Init the Walk State */
442163899Smjacob
44355373Smjacob            WalkState->ParserState.Aml          =
44455373Smjacob            WalkState->ParserState.AmlStart     = Method->Named.Data;
44555373Smjacob            WalkState->ParserState.AmlEnd       =
446154704Smjacob            WalkState->ParserState.PkgEnd       = Method->Named.Data +
447163899Smjacob                                                  Method->Named.Length;
44855373Smjacob            WalkState->ParserState.StartScope   = Op;
44955373Smjacob
450154704Smjacob            WalkState->DescendingCallback       = AcpiDsLoad1BeginOp;
451163899Smjacob            WalkState->AscendingCallback        = AcpiDsLoad1EndOp;
452163899Smjacob
453163899Smjacob            /* Perform the AML parse */
454163899Smjacob
45555373Smjacob            Status = AcpiPsParseAml (WalkState);
45655373Smjacob
45755373Smjacob            BaseAmlOffset = (Method->Common.Value.Arg)->Common.AmlOffset + 1;
45855373Smjacob            StartOp = (Method->Common.Value.Arg)->Common.Next;
459196008Smjacob            SearchOp = StartOp;
46055373Smjacob
461196008Smjacob            while (SearchOp)
46255373Smjacob            {
46355373Smjacob                SearchOp->Common.AmlOffset += BaseAmlOffset;
46455373Smjacob                SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
46555373Smjacob            }
46655373Smjacob        }
467196008Smjacob
46855373Smjacob        if (Op->Common.AmlOpcode == AML_REGION_OP)
46955373Smjacob        {
470196008Smjacob            /* TBD: [Investigate] this isn't quite the right thing to do! */
47155373Smjacob            /*
47255373Smjacob             *
47355373Smjacob             * Method = (ACPI_DEFERRED_OP *) Op;
47455373Smjacob             * Status = AcpiPsParseAml (Op, Method->Body, Method->BodyLength);
475196008Smjacob             */
47657216Smjacob        }
47757216Smjacob
47857216Smjacob        if (ACPI_FAILURE (Status))
479240015Smjacob        {
480240015Smjacob            break;
48155373Smjacob        }
48255373Smjacob
48361774Smjacob        Op = AcpiPsGetDepthNext (Root, Op);
48455373Smjacob    }
48555373Smjacob
48655373Smjacob    return (Status);
487240015Smjacob}
488240015Smjacob
489240015Smjacob
490240015Smjacob/*******************************************************************************
491240015Smjacob *
492240015Smjacob * FUNCTION:    AcpiDbDumpBuffer
493240015Smjacob *
494240015Smjacob * PARAMETERS:  Address             - Pointer to the buffer
495240015Smjacob *
496240015Smjacob * RETURN:      None
497240015Smjacob *
498240015Smjacob * DESCRIPTION: Print a portion of a buffer
499240015Smjacob *
50055373Smjacob ******************************************************************************/
501240015Smjacob
502240015Smjacobvoid
50355373SmjacobAcpiDbDumpBuffer (
50455373Smjacob    UINT32                  Address)
50555373Smjacob{
50655373Smjacob
507196008Smjacob    AcpiOsPrintf ("\nLocation %X:\n", Address);
50855373Smjacob
509196008Smjacob    AcpiDbgLevel |= ACPI_LV_TABLES;
51055373Smjacob    AcpiUtDebugDumpBuffer (ACPI_TO_POINTER (Address), 64, DB_BYTE_DISPLAY,
51155373Smjacob        ACPI_UINT32_MAX);
512164908Smjacob}
51355373Smjacob#endif
514196008Smjacob