dbutils.c revision 1.16
1/*******************************************************************************
2 *
3 * Module Name: dbutils - AML debugger utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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#include "acpi.h"
45#include "accommon.h"
46#include "acnamesp.h"
47#include "acdebug.h"
48
49
50#define _COMPONENT          ACPI_CA_DEBUGGER
51        ACPI_MODULE_NAME    ("dbutils")
52
53
54/* Local prototypes */
55
56#ifdef ACPI_OBSOLETE_FUNCTIONS
57ACPI_STATUS
58AcpiDbSecondPassParse (
59    ACPI_PARSE_OBJECT       *Root);
60
61void
62AcpiDbDumpBuffer (
63    UINT32                  Address);
64#endif
65
66
67/*******************************************************************************
68 *
69 * FUNCTION:    AcpiDbMatchArgument
70 *
71 * PARAMETERS:  UserArgument            - User command line
72 *              Arguments               - Array of commands to match against
73 *
74 * RETURN:      Index into command array or ACPI_TYPE_NOT_FOUND if not found
75 *
76 * DESCRIPTION: Search command array for a command match
77 *
78 ******************************************************************************/
79
80ACPI_OBJECT_TYPE
81AcpiDbMatchArgument (
82    char                    *UserArgument,
83    ACPI_DB_ARGUMENT_INFO   *Arguments)
84{
85    UINT32                  i;
86
87
88    if (!UserArgument || UserArgument[0] == 0)
89    {
90        return (ACPI_TYPE_NOT_FOUND);
91    }
92
93    for (i = 0; Arguments[i].Name; i++)
94    {
95        if (strstr (
96            ACPI_CAST_PTR (char, Arguments[i].Name),
97            ACPI_CAST_PTR (char, UserArgument)) == Arguments[i].Name)
98        {
99            return (i);
100        }
101    }
102
103    /* Argument not recognized */
104
105    return (ACPI_TYPE_NOT_FOUND);
106}
107
108
109/*******************************************************************************
110 *
111 * FUNCTION:    AcpiDbSetOutputDestination
112 *
113 * PARAMETERS:  OutputFlags         - Current flags word
114 *
115 * RETURN:      None
116 *
117 * DESCRIPTION: Set the current destination for debugger output. Also sets
118 *              the debug output level accordingly.
119 *
120 ******************************************************************************/
121
122void
123AcpiDbSetOutputDestination (
124    UINT32                  OutputFlags)
125{
126
127    AcpiGbl_DbOutputFlags = (UINT8) OutputFlags;
128
129    if ((OutputFlags & ACPI_DB_REDIRECTABLE_OUTPUT) &&
130        AcpiGbl_DbOutputToFile)
131    {
132        AcpiDbgLevel = AcpiGbl_DbDebugLevel;
133    }
134    else
135    {
136        AcpiDbgLevel = AcpiGbl_DbConsoleDebugLevel;
137    }
138}
139
140
141/*******************************************************************************
142 *
143 * FUNCTION:    AcpiDbDumpExternalObject
144 *
145 * PARAMETERS:  ObjDesc         - External ACPI object to dump
146 *              Level           - Nesting level.
147 *
148 * RETURN:      None
149 *
150 * DESCRIPTION: Dump the contents of an ACPI external object
151 *
152 ******************************************************************************/
153
154void
155AcpiDbDumpExternalObject (
156    ACPI_OBJECT             *ObjDesc,
157    UINT32                  Level)
158{
159    UINT32                  i;
160
161
162    if (!ObjDesc)
163    {
164        AcpiOsPrintf ("[Null Object]\n");
165        return;
166    }
167
168    for (i = 0; i < Level; i++)
169    {
170        AcpiOsPrintf ("  ");
171    }
172
173    switch (ObjDesc->Type)
174    {
175    case ACPI_TYPE_ANY:
176
177        AcpiOsPrintf ("[Null Object] (Type=0)\n");
178        break;
179
180    case ACPI_TYPE_INTEGER:
181
182        AcpiOsPrintf ("[Integer] = %8.8X%8.8X\n",
183            ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
184        break;
185
186    case ACPI_TYPE_STRING:
187
188        AcpiOsPrintf ("[String] Length %.2X = ", ObjDesc->String.Length);
189        AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX);
190        AcpiOsPrintf ("\n");
191        break;
192
193    case ACPI_TYPE_BUFFER:
194
195        AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length);
196        if (ObjDesc->Buffer.Length)
197        {
198            if (ObjDesc->Buffer.Length > 16)
199            {
200                AcpiOsPrintf ("\n");
201            }
202
203            AcpiUtDebugDumpBuffer (
204                ACPI_CAST_PTR (UINT8, ObjDesc->Buffer.Pointer),
205                ObjDesc->Buffer.Length, DB_BYTE_DISPLAY, _COMPONENT);
206        }
207        else
208        {
209            AcpiOsPrintf ("\n");
210        }
211        break;
212
213    case ACPI_TYPE_PACKAGE:
214
215        AcpiOsPrintf ("[Package] Contains %u Elements:\n",
216            ObjDesc->Package.Count);
217
218        for (i = 0; i < ObjDesc->Package.Count; i++)
219        {
220            AcpiDbDumpExternalObject (
221                &ObjDesc->Package.Elements[i], Level+1);
222        }
223        break;
224
225    case ACPI_TYPE_LOCAL_REFERENCE:
226
227        AcpiOsPrintf ("[Object Reference] = ");
228        AcpiDbDisplayInternalObject (ObjDesc->Reference.Handle, NULL);
229        break;
230
231    case ACPI_TYPE_PROCESSOR:
232
233        AcpiOsPrintf ("[Processor]\n");
234        break;
235
236    case ACPI_TYPE_POWER:
237
238        AcpiOsPrintf ("[Power Resource]\n");
239        break;
240
241    default:
242
243        AcpiOsPrintf ("[Unknown Type] %X\n", ObjDesc->Type);
244        break;
245    }
246}
247
248
249/*******************************************************************************
250 *
251 * FUNCTION:    AcpiDbPrepNamestring
252 *
253 * PARAMETERS:  Name            - String to prepare
254 *
255 * RETURN:      None
256 *
257 * DESCRIPTION: Translate all forward slashes and dots to backslashes.
258 *
259 ******************************************************************************/
260
261void
262AcpiDbPrepNamestring (
263    char                    *Name)
264{
265
266    if (!Name)
267    {
268        return;
269    }
270
271    AcpiUtStrupr (Name);
272
273    /* Convert a leading forward slash to a backslash */
274
275    if (*Name == '/')
276    {
277        *Name = '\\';
278    }
279
280    /* Ignore a leading backslash, this is the root prefix */
281
282    if (ACPI_IS_ROOT_PREFIX (*Name))
283    {
284        Name++;
285    }
286
287    /* Convert all slash path separators to dots */
288
289    while (*Name)
290    {
291        if ((*Name == '/') ||
292            (*Name == '\\'))
293        {
294            *Name = '.';
295        }
296
297        Name++;
298    }
299}
300
301
302/*******************************************************************************
303 *
304 * FUNCTION:    AcpiDbLocalNsLookup
305 *
306 * PARAMETERS:  Name            - Name to lookup
307 *
308 * RETURN:      Pointer to a namespace node, null on failure
309 *
310 * DESCRIPTION: Lookup a name in the ACPI namespace
311 *
312 * Note: Currently begins search from the root. Could be enhanced to use
313 * the current prefix (scope) node as the search beginning point.
314 *
315 ******************************************************************************/
316
317ACPI_NAMESPACE_NODE *
318AcpiDbLocalNsLookup (
319    char                    *Name)
320{
321    char                    *InternalPath;
322    ACPI_STATUS             Status;
323    ACPI_NAMESPACE_NODE     *Node = NULL;
324
325
326    AcpiDbPrepNamestring (Name);
327
328    /* Build an internal namestring */
329
330    Status = AcpiNsInternalizeName (Name, &InternalPath);
331    if (ACPI_FAILURE (Status))
332    {
333        AcpiOsPrintf ("Invalid namestring: %s\n", Name);
334        return (NULL);
335    }
336
337    /*
338     * Lookup the name.
339     * (Uses root node as the search starting point)
340     */
341    Status = AcpiNsLookup (NULL, InternalPath, ACPI_TYPE_ANY,
342        ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
343        NULL, &Node);
344    if (ACPI_FAILURE (Status))
345    {
346        AcpiOsPrintf ("Could not locate name: %s, %s\n",
347            Name, AcpiFormatException (Status));
348    }
349
350    ACPI_FREE (InternalPath);
351    return (Node);
352}
353
354
355/*******************************************************************************
356 *
357 * FUNCTION:    AcpiDbUint32ToHexString
358 *
359 * PARAMETERS:  Value           - The value to be converted to string
360 *              Buffer          - Buffer for result (not less than 11 bytes)
361 *
362 * RETURN:      None
363 *
364 * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image
365 *
366 * NOTE: It is the caller's responsibility to ensure that the length of buffer
367 *       is sufficient.
368 *
369 ******************************************************************************/
370
371void
372AcpiDbUint32ToHexString (
373    UINT32                  Value,
374    char                    *Buffer)
375{
376    int                     i;
377
378
379    if (Value == 0)
380    {
381        strcpy (Buffer, "0");
382        return;
383    }
384
385    Buffer[8] = '\0';
386
387    for (i = 7; i >= 0; i--)
388    {
389        Buffer[i] = AcpiGbl_UpperHexDigits [Value & 0x0F];
390        Value = Value >> 4;
391    }
392}
393
394
395#ifdef ACPI_OBSOLETE_FUNCTIONS
396/*******************************************************************************
397 *
398 * FUNCTION:    AcpiDbSecondPassParse
399 *
400 * PARAMETERS:  Root            - Root of the parse tree
401 *
402 * RETURN:      Status
403 *
404 * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until
405 *              second pass to parse the control methods
406 *
407 ******************************************************************************/
408
409ACPI_STATUS
410AcpiDbSecondPassParse (
411    ACPI_PARSE_OBJECT       *Root)
412{
413    ACPI_PARSE_OBJECT       *Op = Root;
414    ACPI_PARSE_OBJECT       *Method;
415    ACPI_PARSE_OBJECT       *SearchOp;
416    ACPI_PARSE_OBJECT       *StartOp;
417    ACPI_STATUS             Status = AE_OK;
418    UINT32                  BaseAmlOffset;
419    ACPI_WALK_STATE         *WalkState;
420
421
422    ACPI_FUNCTION_ENTRY ();
423
424
425    AcpiOsPrintf ("Pass two parse ....\n");
426
427    while (Op)
428    {
429        if (Op->Common.AmlOpcode == AML_METHOD_OP)
430        {
431            Method = Op;
432
433            /* Create a new walk state for the parse */
434
435            WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
436            if (!WalkState)
437            {
438                return (AE_NO_MEMORY);
439            }
440
441            /* Init the Walk State */
442
443            WalkState->ParserState.Aml          =
444            WalkState->ParserState.AmlStart     = Method->Named.Data;
445            WalkState->ParserState.AmlEnd       =
446            WalkState->ParserState.PkgEnd       = Method->Named.Data +
447                                                  Method->Named.Length;
448            WalkState->ParserState.StartScope   = Op;
449
450            WalkState->DescendingCallback       = AcpiDsLoad1BeginOp;
451            WalkState->AscendingCallback        = AcpiDsLoad1EndOp;
452
453            /* Perform the AML parse */
454
455            Status = AcpiPsParseAml (WalkState);
456
457            BaseAmlOffset = (Method->Common.Value.Arg)->Common.AmlOffset + 1;
458            StartOp = (Method->Common.Value.Arg)->Common.Next;
459            SearchOp = StartOp;
460
461            while (SearchOp)
462            {
463                SearchOp->Common.AmlOffset += BaseAmlOffset;
464                SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
465            }
466        }
467
468        if (Op->Common.AmlOpcode == AML_REGION_OP)
469        {
470            /* TBD: [Investigate] this isn't quite the right thing to do! */
471            /*
472             *
473             * Method = (ACPI_DEFERRED_OP *) Op;
474             * Status = AcpiPsParseAml (Op, Method->Body, Method->BodyLength);
475             */
476        }
477
478        if (ACPI_FAILURE (Status))
479        {
480            break;
481        }
482
483        Op = AcpiPsGetDepthNext (Root, Op);
484    }
485
486    return (Status);
487}
488
489
490/*******************************************************************************
491 *
492 * FUNCTION:    AcpiDbDumpBuffer
493 *
494 * PARAMETERS:  Address             - Pointer to the buffer
495 *
496 * RETURN:      None
497 *
498 * DESCRIPTION: Print a portion of a buffer
499 *
500 ******************************************************************************/
501
502void
503AcpiDbDumpBuffer (
504    UINT32                  Address)
505{
506
507    AcpiOsPrintf ("\nLocation %X:\n", Address);
508
509    AcpiDbgLevel |= ACPI_LV_TABLES;
510    AcpiUtDebugDumpBuffer (ACPI_TO_POINTER (Address), 64, DB_BYTE_DISPLAY,
511        ACPI_UINT32_MAX);
512}
513#endif
514