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 "acpi.h"
  46 #include "accommon.h"
  47 #include "acnamesp.h"
  48 #include "acdebug.h"
  49 #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
  60 ACPI_STATUS
  61 AcpiDbSecondPassParse (
  62     ACPI_PARSE_OBJECT       *Root);
  63 
  64 void
  65 AcpiDbDumpBuffer (
  66     UINT32                  Address);
  67 #endif
  68 
  69 static 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 
  85 ACPI_OBJECT_TYPE
  86 AcpiDbMatchArgument (
  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 
 125 void
 126 AcpiDbSetOutputDestination (
 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 
 156 void
 157 AcpiDbDumpExternalObject (
 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 
 271 void
 272 AcpiDbPrepNamestring (
 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 
 327 ACPI_NAMESPACE_NODE *
 328 AcpiDbLocalNsLookup (
 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 
 380 void
 381 AcpiDbUInt32ToHexString (
 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 
 418 ACPI_STATUS
 419 AcpiDbSecondPassParse (
 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 
 511 void
 512 AcpiDbDumpBuffer (
 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