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