dbutils.c revision 222544
1/*******************************************************************************
2 *
3 * Module Name: dbutils - AML debugger utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <contrib/dev/acpica/include/acpi.h>
46#include <contrib/dev/acpica/include/accommon.h>
47#include <contrib/dev/acpica/include/acnamesp.h>
48#include <contrib/dev/acpica/include/acdebug.h>
49#include <contrib/dev/acpica/include/acdisasm.h>
50
51
52#ifdef ACPI_DEBUGGER
53
54#define _COMPONENT          ACPI_CA_DEBUGGER
55        ACPI_MODULE_NAME    ("dbutils")
56
57/* Local prototypes */
58
59#ifdef ACPI_OBSOLETE_FUNCTIONS
60ACPI_STATUS
61AcpiDbSecondPassParse (
62    ACPI_PARSE_OBJECT       *Root);
63
64void
65AcpiDbDumpBuffer (
66    UINT32                  Address);
67#endif
68
69static char                 *Converter = "0123456789ABCDEF";
70
71
72/*******************************************************************************
73 *
74 * FUNCTION:    AcpiDbMatchArgument
75 *
76 * PARAMETERS:  UserArgument            - User command line
77 *              Arguments               - Array of commands to match against
78 *
79 * RETURN:      Index into command array or ACPI_TYPE_NOT_FOUND if not found
80 *
81 * DESCRIPTION: Search command array for a command match
82 *
83 ******************************************************************************/
84
85ACPI_OBJECT_TYPE
86AcpiDbMatchArgument (
87    char                    *UserArgument,
88    ARGUMENT_INFO           *Arguments)
89{
90    UINT32                  i;
91
92
93    if (!UserArgument || UserArgument[0] == 0)
94    {
95        return (ACPI_TYPE_NOT_FOUND);
96    }
97
98    for (i = 0; Arguments[i].Name; i++)
99    {
100        if (ACPI_STRSTR (Arguments[i].Name, UserArgument) == Arguments[i].Name)
101        {
102            return (i);
103        }
104    }
105
106    /* Argument not recognized */
107
108    return (ACPI_TYPE_NOT_FOUND);
109}
110
111
112/*******************************************************************************
113 *
114 * FUNCTION:    AcpiDbSetOutputDestination
115 *
116 * PARAMETERS:  OutputFlags         - Current flags word
117 *
118 * RETURN:      None
119 *
120 * DESCRIPTION: Set the current destination for debugger output.  Also sets
121 *              the debug output level accordingly.
122 *
123 ******************************************************************************/
124
125void
126AcpiDbSetOutputDestination (
127    UINT32                  OutputFlags)
128{
129
130    AcpiGbl_DbOutputFlags = (UINT8) OutputFlags;
131
132    if ((OutputFlags & ACPI_DB_REDIRECTABLE_OUTPUT) && AcpiGbl_DbOutputToFile)
133    {
134        AcpiDbgLevel = AcpiGbl_DbDebugLevel;
135    }
136    else
137    {
138        AcpiDbgLevel = AcpiGbl_DbConsoleDebugLevel;
139    }
140}
141
142
143/*******************************************************************************
144 *
145 * FUNCTION:    AcpiDbDumpExternalObject
146 *
147 * PARAMETERS:  ObjDesc         - External ACPI object to dump
148 *              Level           - Nesting level.
149 *
150 * RETURN:      None
151 *
152 * DESCRIPTION: Dump the contents of an ACPI external object
153 *
154 ******************************************************************************/
155
156void
157AcpiDbDumpExternalObject (
158    ACPI_OBJECT             *ObjDesc,
159    UINT32                  Level)
160{
161    UINT32                  i;
162
163
164    if (!ObjDesc)
165    {
166        AcpiOsPrintf ("[Null Object]\n");
167        return;
168    }
169
170    for (i = 0; i < Level; i++)
171    {
172        AcpiOsPrintf ("  ");
173    }
174
175    switch (ObjDesc->Type)
176    {
177    case ACPI_TYPE_ANY:
178
179        AcpiOsPrintf ("[Null Object] (Type=0)\n");
180        break;
181
182
183    case ACPI_TYPE_INTEGER:
184
185        AcpiOsPrintf ("[Integer] = %8.8X%8.8X\n",
186                    ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
187        break;
188
189
190    case ACPI_TYPE_STRING:
191
192        AcpiOsPrintf ("[String] Length %.2X = ", ObjDesc->String.Length);
193        for (i = 0; i < ObjDesc->String.Length; i++)
194        {
195            AcpiOsPrintf ("%c", ObjDesc->String.Pointer[i]);
196        }
197        AcpiOsPrintf ("\n");
198        break;
199
200
201    case ACPI_TYPE_BUFFER:
202
203        AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length);
204        if (ObjDesc->Buffer.Length)
205        {
206            if (ObjDesc->Buffer.Length > 16)
207            {
208                AcpiOsPrintf ("\n");
209            }
210            AcpiUtDumpBuffer (ACPI_CAST_PTR (UINT8, ObjDesc->Buffer.Pointer),
211                    ObjDesc->Buffer.Length, DB_DWORD_DISPLAY, _COMPONENT);
212        }
213        else
214        {
215            AcpiOsPrintf ("\n");
216        }
217        break;
218
219
220    case ACPI_TYPE_PACKAGE:
221
222        AcpiOsPrintf ("[Package] Contains %u Elements:\n",
223                ObjDesc->Package.Count);
224
225        for (i = 0; i < ObjDesc->Package.Count; i++)
226        {
227            AcpiDbDumpExternalObject (&ObjDesc->Package.Elements[i], Level+1);
228        }
229        break;
230
231
232    case ACPI_TYPE_LOCAL_REFERENCE:
233
234        AcpiOsPrintf ("[Object Reference] = ");
235        AcpiDmDisplayInternalObject (ObjDesc->Reference.Handle, NULL);
236        break;
237
238
239    case ACPI_TYPE_PROCESSOR:
240
241        AcpiOsPrintf ("[Processor]\n");
242        break;
243
244
245    case ACPI_TYPE_POWER:
246
247        AcpiOsPrintf ("[Power Resource]\n");
248        break;
249
250
251    default:
252
253        AcpiOsPrintf ("[Unknown Type] %X\n", ObjDesc->Type);
254        break;
255    }
256}
257
258
259/*******************************************************************************
260 *
261 * FUNCTION:    AcpiDbPrepNamestring
262 *
263 * PARAMETERS:  Name            - String to prepare
264 *
265 * RETURN:      None
266 *
267 * DESCRIPTION: Translate all forward slashes and dots to backslashes.
268 *
269 ******************************************************************************/
270
271void
272AcpiDbPrepNamestring (
273    char                    *Name)
274{
275
276    if (!Name)
277    {
278        return;
279    }
280
281    AcpiUtStrupr (Name);
282
283    /* Convert a leading forward slash to a backslash */
284
285    if (*Name == '/')
286    {
287        *Name = '\\';
288    }
289
290    /* Ignore a leading backslash, this is the root prefix */
291
292    if (*Name == '\\')
293    {
294        Name++;
295    }
296
297    /* Convert all slash path separators to dots */
298
299    while (*Name)
300    {
301        if ((*Name == '/') ||
302            (*Name == '\\'))
303        {
304            *Name = '.';
305        }
306
307        Name++;
308    }
309}
310
311
312/*******************************************************************************
313 *
314 * FUNCTION:    AcpiDbLocalNsLookup
315 *
316 * PARAMETERS:  Name            - Name to lookup
317 *
318 * RETURN:      Pointer to a namespace node, null on failure
319 *
320 * DESCRIPTION: Lookup a name in the ACPI namespace
321 *
322 * Note: Currently begins search from the root.  Could be enhanced to use
323 * the current prefix (scope) node as the search beginning point.
324 *
325 ******************************************************************************/
326
327ACPI_NAMESPACE_NODE *
328AcpiDbLocalNsLookup (
329    char                    *Name)
330{
331    char                    *InternalPath;
332    ACPI_STATUS             Status;
333    ACPI_NAMESPACE_NODE     *Node = NULL;
334
335
336    AcpiDbPrepNamestring (Name);
337
338    /* Build an internal namestring */
339
340    Status = AcpiNsInternalizeName (Name, &InternalPath);
341    if (ACPI_FAILURE (Status))
342    {
343        AcpiOsPrintf ("Invalid namestring: %s\n", Name);
344        return (NULL);
345    }
346
347    /*
348     * Lookup the name.
349     * (Uses root node as the search starting point)
350     */
351    Status = AcpiNsLookup (NULL, InternalPath, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
352                    ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node);
353    if (ACPI_FAILURE (Status))
354    {
355        AcpiOsPrintf ("Could not locate name: %s, %s\n",
356                Name, AcpiFormatException (Status));
357    }
358
359    ACPI_FREE (InternalPath);
360    return (Node);
361}
362
363
364/*******************************************************************************
365 *
366 * FUNCTION:    AcpiDbUInt32ToHexString
367 *
368 * PARAMETERS:  Value           - The value to be converted to string
369 *              Buffer          - Buffer for result (not less than 11 bytes)
370 *
371 * RETURN:      None
372 *
373 * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image
374 *
375 * NOTE: It is the caller's responsibility to ensure that the length of buffer
376 *       is sufficient.
377 *
378 ******************************************************************************/
379
380void
381AcpiDbUInt32ToHexString (
382    UINT32                  Value,
383    char                    *Buffer)
384{
385    int                     i;
386
387
388    if (Value == 0)
389    {
390        ACPI_STRCPY (Buffer, "0");
391        return;
392    }
393
394    Buffer[8] = '\0';
395
396    for (i = 7; i >= 0; i--)
397    {
398        Buffer[i] = Converter [Value & 0x0F];
399        Value = Value >> 4;
400    }
401}
402
403
404#ifdef ACPI_OBSOLETE_FUNCTIONS
405/*******************************************************************************
406 *
407 * FUNCTION:    AcpiDbSecondPassParse
408 *
409 * PARAMETERS:  Root            - Root of the parse tree
410 *
411 * RETURN:      Status
412 *
413 * DESCRIPTION: Second pass parse of the ACPI tables.  We need to wait until
414 *              second pass to parse the control methods
415 *
416 ******************************************************************************/
417
418ACPI_STATUS
419AcpiDbSecondPassParse (
420    ACPI_PARSE_OBJECT       *Root)
421{
422    ACPI_PARSE_OBJECT       *Op = Root;
423    ACPI_PARSE_OBJECT       *Method;
424    ACPI_PARSE_OBJECT       *SearchOp;
425    ACPI_PARSE_OBJECT       *StartOp;
426    ACPI_STATUS             Status = AE_OK;
427    UINT32                  BaseAmlOffset;
428    ACPI_WALK_STATE         *WalkState;
429
430
431    ACPI_FUNCTION_ENTRY ();
432
433
434    AcpiOsPrintf ("Pass two parse ....\n");
435
436    while (Op)
437    {
438        if (Op->Common.AmlOpcode == AML_METHOD_OP)
439        {
440            Method = Op;
441
442            /* Create a new walk state for the parse */
443
444            WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
445            if (!WalkState)
446            {
447                return (AE_NO_MEMORY);
448            }
449
450            /* Init the Walk State */
451
452            WalkState->ParserState.Aml          =
453            WalkState->ParserState.AmlStart     = Method->Named.Data;
454            WalkState->ParserState.AmlEnd       =
455            WalkState->ParserState.PkgEnd       = Method->Named.Data +
456                                                  Method->Named.Length;
457            WalkState->ParserState.StartScope   = Op;
458
459            WalkState->DescendingCallback       = AcpiDsLoad1BeginOp;
460            WalkState->AscendingCallback        = AcpiDsLoad1EndOp;
461
462            /* Perform the AML parse */
463
464            Status = AcpiPsParseAml (WalkState);
465
466            BaseAmlOffset = (Method->Common.Value.Arg)->Common.AmlOffset + 1;
467            StartOp = (Method->Common.Value.Arg)->Common.Next;
468            SearchOp = StartOp;
469
470            while (SearchOp)
471            {
472                SearchOp->Common.AmlOffset += BaseAmlOffset;
473                SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
474            }
475        }
476
477        if (Op->Common.AmlOpcode == AML_REGION_OP)
478        {
479            /* TBD: [Investigate] this isn't quite the right thing to do! */
480            /*
481             *
482             * Method = (ACPI_DEFERRED_OP *) Op;
483             * Status = AcpiPsParseAml (Op, Method->Body, Method->BodyLength);
484             */
485        }
486
487        if (ACPI_FAILURE (Status))
488        {
489            break;
490        }
491
492        Op = AcpiPsGetDepthNext (Root, Op);
493    }
494
495    return (Status);
496}
497
498
499/*******************************************************************************
500 *
501 * FUNCTION:    AcpiDbDumpBuffer
502 *
503 * PARAMETERS:  Address             - Pointer to the buffer
504 *
505 * RETURN:      None
506 *
507 * DESCRIPTION: Print a portion of a buffer
508 *
509 ******************************************************************************/
510
511void
512AcpiDbDumpBuffer (
513    UINT32                  Address)
514{
515
516    AcpiOsPrintf ("\nLocation %X:\n", Address);
517
518    AcpiDbgLevel |= ACPI_LV_TABLES;
519    AcpiUtDumpBuffer (ACPI_TO_POINTER (Address), 64, DB_BYTE_DISPLAY,
520            ACPI_UINT32_MAX);
521}
522#endif
523
524#endif /* ACPI_DEBUGGER */
525
526
527