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