Home | History | Annotate | Line # | Download | only in compiler
asllength.c revision 1.1.1.2
      1 
      2 /******************************************************************************
      3  *
      4  * Module Name: asllength - Tree walk to determine package and opcode lengths
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2011, Intel Corp.
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions, and the following disclaimer,
     17  *    without modification.
     18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     19  *    substantially similar to the "NO WARRANTY" disclaimer below
     20  *    ("Disclaimer") and any redistribution must be conditioned upon
     21  *    including a substantially similar Disclaimer requirement for further
     22  *    binary redistribution.
     23  * 3. Neither the names of the above-listed copyright holders nor the names
     24  *    of any contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * Alternatively, this software may be distributed under the terms of the
     28  * GNU General Public License ("GPL") version 2 as published by the Free
     29  * Software Foundation.
     30  *
     31  * NO WARRANTY
     32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     42  * POSSIBILITY OF SUCH DAMAGES.
     43  */
     44 
     45 
     46 #include "aslcompiler.h"
     47 #include "aslcompiler.y.h"
     48 #include "amlcode.h"
     49 
     50 
     51 #define _COMPONENT          ACPI_COMPILER
     52         ACPI_MODULE_NAME    ("asllength")
     53 
     54 /* Local prototypes */
     55 
     56 static UINT8
     57 CgGetPackageLenByteCount (
     58     ACPI_PARSE_OBJECT       *Op,
     59     UINT32                  PackageLength);
     60 
     61 static void
     62 CgGenerateAmlOpcodeLength (
     63     ACPI_PARSE_OBJECT       *Op);
     64 
     65 
     66 #ifdef ACPI_OBSOLETE_FUNCTIONS
     67 void
     68 LnAdjustLengthToRoot (
     69     ACPI_PARSE_OBJECT       *Op,
     70     UINT32                  LengthDelta);
     71 #endif
     72 
     73 
     74 /*******************************************************************************
     75  *
     76  * FUNCTION:    LnInitLengthsWalk
     77  *
     78  * PARAMETERS:  ASL_WALK_CALLBACK
     79  *
     80  * RETURN:      Status
     81  *
     82  * DESCRIPTION: Walk callback to initialize (and re-initialize) the node
     83  *              subtree length(s) to zero.  The Subtree lengths are bubbled
     84  *              up to the root node in order to get a total AML length.
     85  *
     86  ******************************************************************************/
     87 
     88 ACPI_STATUS
     89 LnInitLengthsWalk (
     90     ACPI_PARSE_OBJECT       *Op,
     91     UINT32                  Level,
     92     void                    *Context)
     93 {
     94 
     95     Op->Asl.AmlSubtreeLength = 0;
     96     return (AE_OK);
     97 }
     98 
     99 
    100 /*******************************************************************************
    101  *
    102  * FUNCTION:    LnPackageLengthWalk
    103  *
    104  * PARAMETERS:  ASL_WALK_CALLBACK
    105  *
    106  * RETURN:      Status
    107  *
    108  * DESCRIPTION: Walk callback to calculate the total AML length.
    109  *              1) Calculate the AML lengths (opcode, package length, etc.) for
    110  *                 THIS node.
    111  *              2) Bubbble up all of these lengths to the parent node by summing
    112  *                 them all into the parent subtree length.
    113  *
    114  * Note:  The SubtreeLength represents the total AML length of all child nodes
    115  *        in all subtrees under a given node.  Therefore, once this walk is
    116  *        complete, the Root Node subtree length is the AML length of the entire
    117  *        tree (and thus, the entire ACPI table)
    118  *
    119  ******************************************************************************/
    120 
    121 ACPI_STATUS
    122 LnPackageLengthWalk (
    123     ACPI_PARSE_OBJECT       *Op,
    124     UINT32                  Level,
    125     void                    *Context)
    126 {
    127 
    128     /* Generate the AML lengths for this node */
    129 
    130     CgGenerateAmlLengths (Op);
    131 
    132     /* Bubble up all lengths (this node and all below it) to the parent */
    133 
    134     if ((Op->Asl.Parent) &&
    135         (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
    136     {
    137         Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength +
    138                                            Op->Asl.AmlOpcodeLength +
    139                                            Op->Asl.AmlPkgLenBytes +
    140                                            Op->Asl.AmlSubtreeLength);
    141     }
    142     return (AE_OK);
    143 }
    144 
    145 
    146 /*******************************************************************************
    147  *
    148  * FUNCTION:    CgGetPackageLenByteCount
    149  *
    150  * PARAMETERS:  Op              - Parse node
    151  *              PackageLength   - Length to be encoded
    152  *
    153  * RETURN:      Required length of the package length encoding
    154  *
    155  * DESCRIPTION: Calculate the number of bytes required to encode the given
    156  *              package length.
    157  *
    158  ******************************************************************************/
    159 
    160 static UINT8
    161 CgGetPackageLenByteCount (
    162     ACPI_PARSE_OBJECT       *Op,
    163     UINT32                  PackageLength)
    164 {
    165 
    166     /*
    167      * Determine the number of bytes required to encode the package length
    168      * Note: the package length includes the number of bytes used to encode
    169      * the package length, so we must account for this also.
    170      */
    171     if (PackageLength <= (0x0000003F - 1))
    172     {
    173         return (1);
    174     }
    175     else if (PackageLength <= (0x00000FFF - 2))
    176     {
    177         return (2);
    178     }
    179     else if (PackageLength <= (0x000FFFFF - 3))
    180     {
    181         return (3);
    182     }
    183     else if (PackageLength <= (0x0FFFFFFF - 4))
    184     {
    185         return (4);
    186     }
    187     else
    188     {
    189         /* Fatal error - the package length is too large to encode */
    190 
    191         AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL);
    192     }
    193 
    194     return (0);
    195 }
    196 
    197 
    198 /*******************************************************************************
    199  *
    200  * FUNCTION:    CgGenerateAmlOpcodeLength
    201  *
    202  * PARAMETERS:  Op          - Parse node whose AML opcode lengths will be
    203  *                            calculated
    204  *
    205  * RETURN:      None.
    206  *
    207  * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
    208  *              fields for this node.
    209  *
    210  ******************************************************************************/
    211 
    212 static void
    213 CgGenerateAmlOpcodeLength (
    214     ACPI_PARSE_OBJECT       *Op)
    215 {
    216 
    217     /* Check for two-byte opcode */
    218 
    219     if (Op->Asl.AmlOpcode > 0x00FF)
    220     {
    221         Op->Asl.AmlOpcodeLength = 2;
    222     }
    223     else
    224     {
    225         Op->Asl.AmlOpcodeLength = 1;
    226     }
    227 
    228     /* Does this opcode have an associated "PackageLength" field? */
    229 
    230     Op->Asl.AmlPkgLenBytes = 0;
    231     if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
    232     {
    233         Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (
    234                                     Op, Op->Asl.AmlSubtreeLength);
    235     }
    236 
    237     /* Data opcode lengths are easy */
    238 
    239     switch (Op->Asl.AmlOpcode)
    240     {
    241     case AML_BYTE_OP:
    242 
    243         Op->Asl.AmlLength = 1;
    244         break;
    245 
    246     case AML_WORD_OP:
    247 
    248         Op->Asl.AmlLength = 2;
    249         break;
    250 
    251     case AML_DWORD_OP:
    252 
    253         Op->Asl.AmlLength = 4;
    254         break;
    255 
    256     case AML_QWORD_OP:
    257 
    258         Op->Asl.AmlLength = 8;
    259         break;
    260 
    261     default:
    262         /* All data opcodes must be above */
    263         break;
    264     }
    265 }
    266 
    267 
    268 /*******************************************************************************
    269  *
    270  * FUNCTION:    CgGenerateAmlLengths
    271  *
    272  * PARAMETERS:  Op        - Parse node
    273  *
    274  * RETURN:      None.
    275  *
    276  * DESCRIPTION: Generate internal length fields based on the AML opcode or
    277  *              parse opcode.
    278  *
    279  ******************************************************************************/
    280 
    281 void
    282 CgGenerateAmlLengths (
    283     ACPI_PARSE_OBJECT       *Op)
    284 {
    285     char                    *Buffer;
    286     ACPI_STATUS             Status;
    287 
    288 
    289     switch (Op->Asl.AmlOpcode)
    290     {
    291     case AML_RAW_DATA_BYTE:
    292 
    293         Op->Asl.AmlOpcodeLength = 0;
    294         Op->Asl.AmlLength = 1;
    295         return;
    296 
    297     case AML_RAW_DATA_WORD:
    298 
    299         Op->Asl.AmlOpcodeLength = 0;
    300         Op->Asl.AmlLength = 2;
    301         return;
    302 
    303     case AML_RAW_DATA_DWORD:
    304 
    305         Op->Asl.AmlOpcodeLength = 0;
    306         Op->Asl.AmlLength = 4;
    307         return;
    308 
    309     case AML_RAW_DATA_QWORD:
    310 
    311         Op->Asl.AmlOpcodeLength = 0;
    312         Op->Asl.AmlLength = 8;
    313         return;
    314 
    315     case AML_RAW_DATA_BUFFER:
    316 
    317         /* Aml length is/was set by creator */
    318 
    319         Op->Asl.AmlOpcodeLength = 0;
    320         return;
    321 
    322     case AML_RAW_DATA_CHAIN:
    323 
    324         /* Aml length is/was set by creator */
    325 
    326         Op->Asl.AmlOpcodeLength = 0;
    327         return;
    328 
    329     default:
    330         break;
    331     }
    332 
    333     switch (Op->Asl.ParseOpcode)
    334     {
    335     case PARSEOP_DEFINITIONBLOCK:
    336 
    337         Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) +
    338                             Op->Asl.AmlSubtreeLength;
    339         break;
    340 
    341     case PARSEOP_NAMESEG:
    342 
    343         Op->Asl.AmlOpcodeLength = 0;
    344         Op->Asl.AmlLength = 4;
    345         Op->Asl.ExternalName = Op->Asl.Value.String;
    346         break;
    347 
    348     case PARSEOP_NAMESTRING:
    349     case PARSEOP_METHODCALL:
    350 
    351         if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED)
    352         {
    353             break;
    354         }
    355 
    356         Op->Asl.AmlOpcodeLength = 0;
    357         Status = UtInternalizeName (Op->Asl.Value.String, &Buffer);
    358         if (ACPI_FAILURE (Status))
    359         {
    360             DbgPrint (ASL_DEBUG_OUTPUT,
    361                 "Failure from internalize name %X\n", Status);
    362             break;
    363         }
    364 
    365         Op->Asl.ExternalName = Op->Asl.Value.String;
    366         Op->Asl.Value.String = Buffer;
    367         Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED;
    368 
    369         Op->Asl.AmlLength = strlen (Buffer);
    370 
    371         /*
    372          * Check for single backslash reference to root,
    373          * make it a null terminated string in the AML
    374          */
    375         if (Op->Asl.AmlLength == 1)
    376         {
    377             Op->Asl.AmlLength = 2;
    378         }
    379         break;
    380 
    381     case PARSEOP_STRING_LITERAL:
    382 
    383         Op->Asl.AmlOpcodeLength = 1;
    384 
    385         /* Get null terminator */
    386 
    387         Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1;
    388         break;
    389 
    390     case PARSEOP_PACKAGE_LENGTH:
    391 
    392         Op->Asl.AmlOpcodeLength = 0;
    393         Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op,
    394                                     (UINT32) Op->Asl.Value.Integer);
    395         break;
    396 
    397     case PARSEOP_RAW_DATA:
    398 
    399         Op->Asl.AmlOpcodeLength = 0;
    400         break;
    401 
    402     case PARSEOP_DEFAULT_ARG:
    403     case PARSEOP_EXTERNAL:
    404     case PARSEOP_INCLUDE:
    405     case PARSEOP_INCLUDE_END:
    406 
    407         /* Ignore the "default arg" nodes, they are extraneous at this point */
    408 
    409         break;
    410 
    411     default:
    412 
    413         CgGenerateAmlOpcodeLength (Op);
    414         break;
    415     }
    416 }
    417 
    418 
    419 #ifdef ACPI_OBSOLETE_FUNCTIONS
    420 /*******************************************************************************
    421  *
    422  * FUNCTION:    LnAdjustLengthToRoot
    423  *
    424  * PARAMETERS:  Op      - Node whose Length was changed
    425  *
    426  * RETURN:      None.
    427  *
    428  * DESCRIPTION: Change the Subtree length of the given node, and bubble the
    429  *              change all the way up to the root node.  This allows for
    430  *              last second changes to a package length (for example, if the
    431  *              package length encoding gets shorter or longer.)
    432  *
    433  ******************************************************************************/
    434 
    435 void
    436 LnAdjustLengthToRoot (
    437     ACPI_PARSE_OBJECT       *SubtreeOp,
    438     UINT32                  LengthDelta)
    439 {
    440     ACPI_PARSE_OBJECT       *Op;
    441 
    442 
    443     /* Adjust all subtree lengths up to the root */
    444 
    445     Op = SubtreeOp->Asl.Parent;
    446     while (Op)
    447     {
    448         Op->Asl.AmlSubtreeLength -= LengthDelta;
    449         Op = Op->Asl.Parent;
    450     }
    451 
    452     /* Adjust the global table length */
    453 
    454     Gbl_TableLength -= LengthDelta;
    455 }
    456 #endif
    457 
    458 
    459