Home | History | Annotate | Line # | Download | only in disassembler
dmbuffer.c revision 1.1.1.2.2.2
      1 /*******************************************************************************
      2  *
      3  * Module Name: dmbuffer - AML disassembler, buffer and string support
      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 "acdisasm.h"
     48 #include "acparser.h"
     49 #include "amlcode.h"
     50 
     51 
     52 #ifdef ACPI_DISASSEMBLER
     53 
     54 #define _COMPONENT          ACPI_CA_DEBUGGER
     55         ACPI_MODULE_NAME    ("dmbuffer")
     56 
     57 /* Local prototypes */
     58 
     59 static void
     60 AcpiDmUnicode (
     61     ACPI_PARSE_OBJECT       *Op);
     62 
     63 static void
     64 AcpiDmIsEisaIdElement (
     65     ACPI_PARSE_OBJECT       *Op);
     66 
     67 
     68 /*******************************************************************************
     69  *
     70  * FUNCTION:    AcpiDmDisasmByteList
     71  *
     72  * PARAMETERS:  Level               - Current source code indentation level
     73  *              ByteData            - Pointer to the byte list
     74  *              ByteCount           - Length of the byte list
     75  *
     76  * RETURN:      None
     77  *
     78  * DESCRIPTION: Dump an AML "ByteList" in Hex format. 8 bytes per line, prefixed
     79  *              with the hex buffer offset.
     80  *
     81  ******************************************************************************/
     82 
     83 void
     84 AcpiDmDisasmByteList (
     85     UINT32                  Level,
     86     UINT8                   *ByteData,
     87     UINT32                  ByteCount)
     88 {
     89     UINT32                  i;
     90 
     91 
     92     if (!ByteCount)
     93     {
     94         return;
     95     }
     96 
     97     /* Dump the byte list */
     98 
     99     for (i = 0; i < ByteCount; i++)
    100     {
    101         /* New line every 8 bytes */
    102 
    103         if (((i % 8) == 0) && (i < ByteCount))
    104         {
    105             if (i > 0)
    106             {
    107                 AcpiOsPrintf ("\n");
    108             }
    109 
    110             AcpiDmIndent (Level);
    111             if (ByteCount > 7)
    112             {
    113                 AcpiOsPrintf ("/* %04X */    ", i);
    114             }
    115         }
    116 
    117         AcpiOsPrintf ("0x%2.2X", (UINT32) ByteData[i]);
    118 
    119         /* Add comma if there are more bytes to display */
    120 
    121         if (i < (ByteCount -1))
    122         {
    123             AcpiOsPrintf (", ");
    124         }
    125     }
    126 
    127     if (Level)
    128     {
    129         AcpiOsPrintf ("\n");
    130     }
    131 }
    132 
    133 
    134 /*******************************************************************************
    135  *
    136  * FUNCTION:    AcpiDmByteList
    137  *
    138  * PARAMETERS:  Info            - Parse tree walk info
    139  *              Op              - Byte list op
    140  *
    141  * RETURN:      None
    142  *
    143  * DESCRIPTION: Dump a buffer byte list, handling the various types of buffers.
    144  *              Buffer type must be already set in the Op DisasmOpcode.
    145  *
    146  ******************************************************************************/
    147 
    148 void
    149 AcpiDmByteList (
    150     ACPI_OP_WALK_INFO       *Info,
    151     ACPI_PARSE_OBJECT       *Op)
    152 {
    153     UINT8                   *ByteData;
    154     UINT32                  ByteCount;
    155 
    156 
    157     ByteData = Op->Named.Data;
    158     ByteCount = (UINT32) Op->Common.Value.Integer;
    159 
    160     /*
    161      * The byte list belongs to a buffer, and can be produced by either
    162      * a ResourceTemplate, Unicode, quoted string, or a plain byte list.
    163      */
    164     switch (Op->Common.Parent->Common.DisasmOpcode)
    165     {
    166     case ACPI_DASM_RESOURCE:
    167 
    168         AcpiDmResourceTemplate (Info, Op->Common.Parent, ByteData, ByteCount);
    169         break;
    170 
    171     case ACPI_DASM_STRING:
    172 
    173         AcpiDmIndent (Info->Level);
    174         AcpiUtPrintString ((char *) ByteData, ACPI_UINT8_MAX);
    175         AcpiOsPrintf ("\n");
    176         break;
    177 
    178     case ACPI_DASM_UNICODE:
    179 
    180         AcpiDmUnicode (Op);
    181         break;
    182 
    183     case ACPI_DASM_BUFFER:
    184     default:
    185 
    186         /*
    187          * Not a resource, string, or unicode string.
    188          * Just dump the buffer
    189          */
    190         AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount);
    191         break;
    192     }
    193 }
    194 
    195 
    196 /*******************************************************************************
    197  *
    198  * FUNCTION:    AcpiDmIsUnicodeBuffer
    199  *
    200  * PARAMETERS:  Op              - Buffer Object to be examined
    201  *
    202  * RETURN:      TRUE if buffer contains a UNICODE string
    203  *
    204  * DESCRIPTION: Determine if a buffer Op contains a Unicode string
    205  *
    206  ******************************************************************************/
    207 
    208 BOOLEAN
    209 AcpiDmIsUnicodeBuffer (
    210     ACPI_PARSE_OBJECT       *Op)
    211 {
    212     UINT8                   *ByteData;
    213     UINT32                  ByteCount;
    214     UINT32                  WordCount;
    215     ACPI_PARSE_OBJECT       *SizeOp;
    216     ACPI_PARSE_OBJECT       *NextOp;
    217     UINT32                  i;
    218 
    219 
    220     /* Buffer size is the buffer argument */
    221 
    222     SizeOp = Op->Common.Value.Arg;
    223 
    224     /* Next, the initializer byte list to examine */
    225 
    226     NextOp = SizeOp->Common.Next;
    227     if (!NextOp)
    228     {
    229         return (FALSE);
    230     }
    231 
    232     /* Extract the byte list info */
    233 
    234     ByteData = NextOp->Named.Data;
    235     ByteCount = (UINT32) NextOp->Common.Value.Integer;
    236     WordCount = ACPI_DIV_2 (ByteCount);
    237 
    238     /*
    239      * Unicode string must have an even number of bytes and last
    240      * word must be zero
    241      */
    242     if ((!ByteCount)     ||
    243          (ByteCount < 4) ||
    244          (ByteCount & 1) ||
    245         ((UINT16 *) (void *) ByteData)[WordCount - 1] != 0)
    246     {
    247         return (FALSE);
    248     }
    249 
    250     /* For each word, 1st byte must be ascii, 2nd byte must be zero */
    251 
    252     for (i = 0; i < (ByteCount - 2); i += 2)
    253     {
    254         if ((!ACPI_IS_PRINT (ByteData[i])) ||
    255             (ByteData[(ACPI_SIZE) i + 1] != 0))
    256         {
    257             return (FALSE);
    258         }
    259     }
    260 
    261     /* Ignore the Size argument in the disassembly of this buffer op */
    262 
    263     SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    264     return (TRUE);
    265 }
    266 
    267 
    268 /*******************************************************************************
    269  *
    270  * FUNCTION:    AcpiDmIsStringBuffer
    271  *
    272  * PARAMETERS:  Op              - Buffer Object to be examined
    273  *
    274  * RETURN:      TRUE if buffer contains a ASCII string, FALSE otherwise
    275  *
    276  * DESCRIPTION: Determine if a buffer Op contains a ASCII string
    277  *
    278  ******************************************************************************/
    279 
    280 BOOLEAN
    281 AcpiDmIsStringBuffer (
    282     ACPI_PARSE_OBJECT       *Op)
    283 {
    284     UINT8                   *ByteData;
    285     UINT32                  ByteCount;
    286     ACPI_PARSE_OBJECT       *SizeOp;
    287     ACPI_PARSE_OBJECT       *NextOp;
    288     UINT32                  i;
    289 
    290 
    291     /* Buffer size is the buffer argument */
    292 
    293     SizeOp = Op->Common.Value.Arg;
    294 
    295     /* Next, the initializer byte list to examine */
    296 
    297     NextOp = SizeOp->Common.Next;
    298     if (!NextOp)
    299     {
    300         return (FALSE);
    301     }
    302 
    303     /* Extract the byte list info */
    304 
    305     ByteData = NextOp->Named.Data;
    306     ByteCount = (UINT32) NextOp->Common.Value.Integer;
    307 
    308     /* Last byte must be the null terminator */
    309 
    310     if ((!ByteCount)     ||
    311          (ByteCount < 2) ||
    312          (ByteData[ByteCount-1] != 0))
    313     {
    314         return (FALSE);
    315     }
    316 
    317     for (i = 0; i < (ByteCount - 1); i++)
    318     {
    319         /* TBD: allow some escapes (non-ascii chars).
    320          * they will be handled in the string output routine
    321          */
    322 
    323         if (!ACPI_IS_PRINT (ByteData[i]))
    324         {
    325             return (FALSE);
    326         }
    327     }
    328 
    329     return (TRUE);
    330 }
    331 
    332 
    333 /*******************************************************************************
    334  *
    335  * FUNCTION:    AcpiDmUnicode
    336  *
    337  * PARAMETERS:  Op              - Byte List op containing Unicode string
    338  *
    339  * RETURN:      None
    340  *
    341  * DESCRIPTION: Dump Unicode string as a standard ASCII string.  (Remove
    342  *              the extra zero bytes).
    343  *
    344  ******************************************************************************/
    345 
    346 static void
    347 AcpiDmUnicode (
    348     ACPI_PARSE_OBJECT       *Op)
    349 {
    350     UINT16                  *WordData;
    351     UINT32                  WordCount;
    352     UINT32                  i;
    353 
    354 
    355     /* Extract the buffer info as a WORD buffer */
    356 
    357     WordData = ACPI_CAST_PTR (UINT16, Op->Named.Data);
    358     WordCount = ACPI_DIV_2 (((UINT32) Op->Common.Value.Integer));
    359 
    360 
    361     AcpiOsPrintf ("\"");
    362 
    363     /* Write every other byte as an ASCII character */
    364 
    365     for (i = 0; i < (WordCount - 1); i++)
    366     {
    367         AcpiOsPrintf ("%c", (int) WordData[i]);
    368     }
    369 
    370     AcpiOsPrintf ("\")");
    371 }
    372 
    373 
    374 /*******************************************************************************
    375  *
    376  * FUNCTION:    AcpiDmIsEisaIdElement
    377  *
    378  * PARAMETERS:  Op              - Op to be examined
    379  *
    380  * RETURN:      None
    381  *
    382  * DESCRIPTION: Determine if an Op (argument to _HID or _CID) can be converted
    383  *              to an EISA ID.
    384  *
    385  ******************************************************************************/
    386 
    387 static void
    388 AcpiDmIsEisaIdElement (
    389     ACPI_PARSE_OBJECT       *Op)
    390 {
    391     UINT32                  BigEndianId;
    392     UINT32                  Prefix[3];
    393     UINT32                  i;
    394 
    395 
    396     /* The parameter must be either a word or a dword */
    397 
    398     if ((Op->Common.AmlOpcode != AML_DWORD_OP) &&
    399         (Op->Common.AmlOpcode != AML_WORD_OP))
    400     {
    401         return;
    402     }
    403 
    404     /* Swap from little-endian to big-endian to simplify conversion */
    405 
    406     BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer);
    407 
    408     /* Create the 3 leading ASCII letters */
    409 
    410     Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40;
    411     Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40;
    412     Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40;
    413 
    414     /* Verify that all 3 are ascii and alpha */
    415 
    416     for (i = 0; i < 3; i++)
    417     {
    418         if (!ACPI_IS_ASCII (Prefix[i]) ||
    419             !ACPI_IS_ALPHA (Prefix[i]))
    420         {
    421             return;
    422         }
    423     }
    424 
    425     /* OK - mark this node as convertable to an EISA ID */
    426 
    427     Op->Common.DisasmOpcode = ACPI_DASM_EISAID;
    428 }
    429 
    430 
    431 /*******************************************************************************
    432  *
    433  * FUNCTION:    AcpiDmIsEisaId
    434  *
    435  * PARAMETERS:  Op              - Op to be examined
    436  *
    437  * RETURN:      None
    438  *
    439  * DESCRIPTION: Determine if a Name() Op can be converted to an EisaId.
    440  *
    441  ******************************************************************************/
    442 
    443 void
    444 AcpiDmIsEisaId (
    445     ACPI_PARSE_OBJECT       *Op)
    446 {
    447     UINT32                  Name;
    448     ACPI_PARSE_OBJECT       *NextOp;
    449 
    450 
    451     /* Get the NameSegment */
    452 
    453     Name = AcpiPsGetName (Op);
    454     if (!Name)
    455     {
    456         return;
    457     }
    458 
    459     NextOp = AcpiPsGetDepthNext (NULL, Op);
    460     if (!NextOp)
    461     {
    462         return;
    463     }
    464 
    465     /* Check for _HID - has one argument */
    466 
    467     if (ACPI_COMPARE_NAME (&Name, METHOD_NAME__HID))
    468     {
    469         AcpiDmIsEisaIdElement (NextOp);
    470         return;
    471     }
    472 
    473     /* Exit if not _CID */
    474 
    475     if (!ACPI_COMPARE_NAME (&Name, METHOD_NAME__CID))
    476     {
    477         return;
    478     }
    479 
    480     /* _CID can contain a single argument or a package */
    481 
    482     if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP)
    483     {
    484         AcpiDmIsEisaIdElement (NextOp);
    485         return;
    486     }
    487 
    488     /* _CID with Package: get the package length */
    489 
    490     NextOp = AcpiPsGetDepthNext (NULL, NextOp);
    491 
    492     /* Don't need to use the length, just walk the peer list */
    493 
    494     NextOp = NextOp->Common.Next;
    495     while (NextOp)
    496     {
    497         AcpiDmIsEisaIdElement (NextOp);
    498         NextOp = NextOp->Common.Next;
    499     }
    500 }
    501 
    502 
    503 /*******************************************************************************
    504  *
    505  * FUNCTION:    AcpiDmEisaId
    506  *
    507  * PARAMETERS:  EncodedId       - Raw encoded EISA ID.
    508  *
    509  * RETURN:      None
    510  *
    511  * DESCRIPTION: Convert an encoded EISAID back to the original ASCII String.
    512  *
    513  ******************************************************************************/
    514 
    515 void
    516 AcpiDmEisaId (
    517     UINT32                  EncodedId)
    518 {
    519     UINT32                  BigEndianId;
    520 
    521 
    522     /* Swap from little-endian to big-endian to simplify conversion */
    523 
    524     BigEndianId = AcpiUtDwordByteSwap (EncodedId);
    525 
    526 
    527     /* Split to form "AAANNNN" string */
    528 
    529     AcpiOsPrintf ("EisaId (\"%c%c%c%4.4X\")",
    530 
    531         /* Three Alpha characters (AAA), 5 bits each */
    532 
    533         (int) ((BigEndianId >> 26) & 0x1F) + 0x40,
    534         (int) ((BigEndianId >> 21) & 0x1F) + 0x40,
    535         (int) ((BigEndianId >> 16) & 0x1F) + 0x40,
    536 
    537         /* Numeric part (NNNN) is simply the lower 16 bits */
    538 
    539         (UINT32) (BigEndianId & 0xFFFF));
    540 }
    541 
    542 #endif
    543