1 /*******************************************************************************
   2  *
   3  * Module Name: dmresrc.c - Resource Descriptor disassembly
   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 "amlcode.h"
  48 #include "acdisasm.h"
  49 
  50 #ifdef ACPI_DISASSEMBLER
  51 
  52 #define _COMPONENT          ACPI_CA_DEBUGGER
  53         ACPI_MODULE_NAME    ("dbresrc")
  54 
  55 
  56 /* Dispatch tables for Resource disassembly functions */
  57 
  58 typedef
  59 void (*ACPI_RESOURCE_HANDLER) (
  60     AML_RESOURCE            *Resource,
  61     UINT32                  Length,
  62     UINT32                  Level);
  63 
  64 static ACPI_RESOURCE_HANDLER    AcpiGbl_DmResourceDispatch [] =
  65 {
  66     /* Small descriptors */
  67 
  68     NULL,                           /* 0x00, Reserved */
  69     NULL,                           /* 0x01, Reserved */
  70     NULL,                           /* 0x02, Reserved */
  71     NULL,                           /* 0x03, Reserved */
  72     AcpiDmIrqDescriptor,            /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */
  73     AcpiDmDmaDescriptor,            /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */
  74     AcpiDmStartDependentDescriptor, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */
  75     AcpiDmEndDependentDescriptor,   /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
  76     AcpiDmIoDescriptor,             /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */
  77     AcpiDmFixedIoDescriptor,        /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */
  78     NULL,                           /* 0x0A, Reserved */
  79     NULL,                           /* 0x0B, Reserved */
  80     NULL,                           /* 0x0C, Reserved */
  81     NULL,                           /* 0x0D, Reserved */
  82     AcpiDmVendorSmallDescriptor,    /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */
  83     NULL,                           /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */
  84 
  85     /* Large descriptors */
  86 
  87     NULL,                           /* 0x00, Reserved */
  88     AcpiDmMemory24Descriptor,       /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */
  89     AcpiDmGenericRegisterDescriptor,/* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */
  90     NULL,                           /* 0x03, Reserved */
  91     AcpiDmVendorLargeDescriptor,    /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */
  92     AcpiDmMemory32Descriptor,       /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */
  93     AcpiDmFixedMemory32Descriptor,  /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */
  94     AcpiDmDwordDescriptor,          /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */
  95     AcpiDmWordDescriptor,           /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */
  96     AcpiDmInterruptDescriptor,      /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */
  97     AcpiDmQwordDescriptor,          /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */
  98     AcpiDmExtendedDescriptor        /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */
  99 };
 100 
 101 
 102 /* Only used for single-threaded applications */
 103 /* TBD: remove when name is passed as parameter to the dump functions */
 104 
 105 static UINT32               ResourceName;
 106 
 107 
 108 /*******************************************************************************
 109  *
 110  * FUNCTION:    AcpiDmDescriptorName
 111  *
 112  * PARAMETERS:  None
 113  *
 114  * RETURN:      None
 115  *
 116  * DESCRIPTION: Emit a name for the descriptor if one is present (indicated
 117  *              by the name being changed from the default name.) A name is only
 118  *              emitted if a reference to the descriptor has been made somewhere
 119  *              in the original ASL code.
 120  *
 121  ******************************************************************************/
 122 
 123 void
 124 AcpiDmDescriptorName (
 125     void)
 126 {
 127 
 128     if (ResourceName == ACPI_DEFAULT_RESNAME)
 129     {
 130         return;
 131     }
 132 
 133     AcpiOsPrintf ("%4.4s", (char *) &ResourceName);
 134 }
 135 
 136 
 137 /*******************************************************************************
 138  *
 139  * FUNCTION:    AcpiDmDumpInteger*
 140  *
 141  * PARAMETERS:  Value               - Value to emit
 142  *              Name                - Associated name (emitted as a comment)
 143  *
 144  * RETURN:      None
 145  *
 146  * DESCRIPTION: Integer output helper functions
 147  *
 148  ******************************************************************************/
 149 
 150 void
 151 AcpiDmDumpInteger8 (
 152     UINT8                   Value,
 153     char                    *Name)
 154 {
 155     AcpiOsPrintf ("0x%2.2X,               // %s\n", Value, Name);
 156 }
 157 
 158 void
 159 AcpiDmDumpInteger16 (
 160     UINT16                  Value,
 161     char                    *Name)
 162 {
 163     AcpiOsPrintf ("0x%4.4X,             // %s\n", Value, Name);
 164 }
 165 
 166 void
 167 AcpiDmDumpInteger32 (
 168     UINT32                  Value,
 169     char                    *Name)
 170 {
 171     AcpiOsPrintf ("0x%8.8X,         // %s\n", Value, Name);
 172 }
 173 
 174 void
 175 AcpiDmDumpInteger64 (
 176     UINT64                  Value,
 177     char                    *Name)
 178 {
 179     AcpiOsPrintf ("0x%8.8X%8.8X, // %s\n", ACPI_FORMAT_UINT64 (Value), Name);
 180 }
 181 
 182 
 183 /*******************************************************************************
 184  *
 185  * FUNCTION:    AcpiDmBitList
 186  *
 187  * PARAMETERS:  Mask            - 16-bit value corresponding to 16 interrupt
 188  *                                or DMA values
 189  *
 190  * RETURN:      None
 191  *
 192  * DESCRIPTION: Dump a bit mask as a list of individual interrupt/DMA levels.
 193  *
 194  ******************************************************************************/
 195 
 196 void
 197 AcpiDmBitList (
 198     UINT16                  Mask)
 199 {
 200     UINT32                  i;
 201     BOOLEAN                 Previous = FALSE;
 202 
 203 
 204     /* Open the initializer list */
 205 
 206     AcpiOsPrintf ("{");
 207 
 208     /* Examine each bit */
 209 
 210     for (i = 0; i < 16; i++)
 211     {
 212         /* Only interested in bits that are set to 1 */
 213 
 214         if (Mask & 1)
 215         {
 216             if (Previous)
 217             {
 218                 AcpiOsPrintf (",");
 219             }
 220             Previous = TRUE;
 221             AcpiOsPrintf ("%u", i);
 222         }
 223 
 224         Mask >>= 1;
 225     }
 226 
 227     /* Close list */
 228 
 229     AcpiOsPrintf ("}\n");
 230 }
 231 
 232 
 233 /*******************************************************************************
 234  *
 235  * FUNCTION:    AcpiDmResourceTemplate
 236  *
 237  * PARAMETERS:  Info            - Curent parse tree walk info
 238  *              ByteData        - Pointer to the byte list data
 239  *              ByteCount       - Length of the byte list
 240  *
 241  * RETURN:      None
 242  *
 243  * DESCRIPTION: Dump the contents of a Resource Template containing a set of
 244  *              Resource Descriptors.
 245  *
 246  ******************************************************************************/
 247 
 248 void
 249 AcpiDmResourceTemplate (
 250     ACPI_OP_WALK_INFO       *Info,
 251     ACPI_PARSE_OBJECT       *Op,
 252     UINT8                   *ByteData,
 253     UINT32                  ByteCount)
 254 {
 255     ACPI_STATUS             Status;
 256     UINT32                  CurrentByteOffset;
 257     UINT8                   ResourceType;
 258     UINT32                  ResourceLength;
 259     void                    *Aml;
 260     UINT32                  Level;
 261     BOOLEAN                 DependentFns = FALSE;
 262     UINT8                   ResourceIndex;
 263     ACPI_NAMESPACE_NODE     *Node;
 264 
 265 
 266     Level = Info->Level;
 267     ResourceName = ACPI_DEFAULT_RESNAME;
 268     Node = Op->Common.Node;
 269     if (Node)
 270     {
 271         Node = Node->Child;
 272     }
 273 
 274     for (CurrentByteOffset = 0; CurrentByteOffset < ByteCount;)
 275     {
 276         Aml = &ByteData[CurrentByteOffset];
 277 
 278         /* Get the descriptor type and length */
 279 
 280         ResourceType = AcpiUtGetResourceType (Aml);
 281         ResourceLength = AcpiUtGetResourceLength (Aml);
 282 
 283         /* Validate the Resource Type and Resource Length */
 284 
 285         Status = AcpiUtValidateResource (Aml, &ResourceIndex);
 286         if (ACPI_FAILURE (Status))
 287         {
 288             AcpiOsPrintf ("/*** Could not validate Resource, type (%X) %s***/\n",
 289                 ResourceType, AcpiFormatException (Status));
 290             return;
 291         }
 292 
 293         /* Point to next descriptor */
 294 
 295         CurrentByteOffset += AcpiUtGetDescriptorLength (Aml);
 296 
 297         /* Descriptor pre-processing */
 298 
 299         switch (ResourceType)
 300         {
 301         case ACPI_RESOURCE_NAME_START_DEPENDENT:
 302 
 303             /* Finish a previous StartDependentFns */
 304 
 305             if (DependentFns)
 306             {
 307                 Level--;
 308                 AcpiDmIndent (Level);
 309                 AcpiOsPrintf ("}\n");
 310             }
 311             break;
 312 
 313         case ACPI_RESOURCE_NAME_END_DEPENDENT:
 314 
 315             Level--;
 316             DependentFns = FALSE;
 317             break;
 318 
 319         case ACPI_RESOURCE_NAME_END_TAG:
 320 
 321             /* Normal exit, the resource list is finished */
 322 
 323             if (DependentFns)
 324             {
 325                 /*
 326                  * Close an open StartDependentDescriptor. This indicates a
 327                  * missing EndDependentDescriptor.
 328                  */
 329                 Level--;
 330                 DependentFns = FALSE;
 331 
 332                 /* Go ahead and insert EndDependentFn() */
 333 
 334                 AcpiDmEndDependentDescriptor (Aml, ResourceLength, Level);
 335 
 336                 AcpiDmIndent (Level);
 337                 AcpiOsPrintf (
 338                     "/*** Disassembler: inserted missing EndDependentFn () ***/\n");
 339             }
 340             return;
 341 
 342         default:
 343             break;
 344         }
 345 
 346         /* Disassemble the resource structure */
 347 
 348         if (Node)
 349         {
 350             ResourceName = Node->Name.Integer;
 351             Node = Node->Peer;
 352         }
 353 
 354         AcpiGbl_DmResourceDispatch [ResourceIndex] (
 355             Aml, ResourceLength, Level);
 356 
 357         /* Descriptor post-processing */
 358 
 359         if (ResourceType == ACPI_RESOURCE_NAME_START_DEPENDENT)
 360         {
 361             DependentFns = TRUE;
 362             Level++;
 363         }
 364     }
 365 }
 366 
 367 
 368 /*******************************************************************************
 369  *
 370  * FUNCTION:    AcpiDmIsResourceTemplate
 371  *
 372  * PARAMETERS:  Op          - Buffer Op to be examined
 373  *
 374  * RETURN:      Status. AE_OK if valid template
 375  *
 376  * DESCRIPTION: Walk a byte list to determine if it consists of a valid set
 377  *              of resource descriptors.  Nothing is output.
 378  *
 379  ******************************************************************************/
 380 
 381 ACPI_STATUS
 382 AcpiDmIsResourceTemplate (
 383     ACPI_PARSE_OBJECT       *Op)
 384 {
 385     ACPI_STATUS             Status;
 386     ACPI_PARSE_OBJECT       *NextOp;
 387     UINT8                   *Aml;
 388     UINT8                   *EndAml;
 389     ACPI_SIZE               Length;
 390 
 391 
 392     /* This op must be a buffer */
 393 
 394     if (Op->Common.AmlOpcode != AML_BUFFER_OP)
 395     {
 396         return (AE_TYPE);
 397     }
 398 
 399     /* Get the ByteData list and length */
 400 
 401     NextOp = Op->Common.Value.Arg;
 402     NextOp = NextOp->Common.Next;
 403     if (!NextOp)
 404     {
 405         return (AE_TYPE);
 406     }
 407 
 408     Aml = NextOp->Named.Data;
 409     Length = (ACPI_SIZE) NextOp->Common.Value.Integer;
 410 
 411     /* Walk the byte list, abort on any invalid descriptor type or length */
 412 
 413     Status = AcpiUtWalkAmlResources (Aml, Length, NULL, &EndAml);
 414     if (ACPI_FAILURE (Status))
 415     {
 416         return (AE_TYPE);
 417     }
 418 
 419     /*
 420      * For the resource template to be valid, one EndTag must appear
 421      * at the very end of the ByteList, not before. (For proper disassembly
 422      * of a ResourceTemplate, the buffer must not have any extra data after
 423      * the EndTag.)
 424      */
 425     if ((Aml + Length - sizeof (AML_RESOURCE_END_TAG)) != EndAml)
 426     {
 427         return (AE_AML_NO_RESOURCE_END_TAG);
 428     }
 429 
 430     /*
 431      * All resource descriptors are valid, therefore this list appears
 432      * to be a valid resource template
 433      */
 434     return (AE_OK);
 435 }
 436 
 437 #endif