Home | History | Annotate | Line # | Download | only in dispatcher
dsobject.c revision 1.1.1.2.20.2
      1 /******************************************************************************
      2  *
      3  * Module Name: dsobject - Dispatcher object management routines
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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 #include "acpi.h"
     45 #include "accommon.h"
     46 #include "acparser.h"
     47 #include "amlcode.h"
     48 #include "acdispat.h"
     49 #include "acnamesp.h"
     50 #include "acinterp.h"
     51 
     52 #define _COMPONENT          ACPI_DISPATCHER
     53         ACPI_MODULE_NAME    ("dsobject")
     54 
     55 
     56 #ifndef ACPI_NO_METHOD_EXECUTION
     57 /*******************************************************************************
     58  *
     59  * FUNCTION:    AcpiDsBuildInternalObject
     60  *
     61  * PARAMETERS:  WalkState       - Current walk state
     62  *              Op              - Parser object to be translated
     63  *              ObjDescPtr      - Where the ACPI internal object is returned
     64  *
     65  * RETURN:      Status
     66  *
     67  * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
     68  *              Simple objects are any objects other than a package object!
     69  *
     70  ******************************************************************************/
     71 
     72 ACPI_STATUS
     73 AcpiDsBuildInternalObject (
     74     ACPI_WALK_STATE         *WalkState,
     75     ACPI_PARSE_OBJECT       *Op,
     76     ACPI_OPERAND_OBJECT     **ObjDescPtr)
     77 {
     78     ACPI_OPERAND_OBJECT     *ObjDesc;
     79     ACPI_STATUS             Status;
     80 
     81 
     82     ACPI_FUNCTION_TRACE (DsBuildInternalObject);
     83 
     84 
     85     *ObjDescPtr = NULL;
     86     if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
     87     {
     88         /*
     89          * This is a named object reference. If this name was
     90          * previously looked up in the namespace, it was stored in
     91          * this op. Otherwise, go ahead and look it up now
     92          */
     93         if (!Op->Common.Node)
     94         {
     95             /* Check if we are resolving a named reference within a package */
     96 
     97             if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
     98                 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
     99             {
    100                 /*
    101                  * We won't resolve package elements here, we will do this
    102                  * after all ACPI tables are loaded into the namespace. This
    103                  * behavior supports both forward references to named objects
    104                  * and external references to objects in other tables.
    105                  */
    106                 goto CreateNewObject;
    107             }
    108             else
    109             {
    110                 Status = AcpiNsLookup (WalkState->ScopeInfo,
    111                     Op->Common.Value.String,
    112                     ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
    113                     ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
    114                     ACPI_CAST_INDIRECT_PTR (
    115                         ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
    116                 if (ACPI_FAILURE (Status))
    117                 {
    118                     ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
    119                         Op->Common.Value.String, Status);
    120                     return_ACPI_STATUS (Status);
    121                 }
    122             }
    123         }
    124     }
    125 
    126 CreateNewObject:
    127 
    128     /* Create and init a new internal ACPI object */
    129 
    130     ObjDesc = AcpiUtCreateInternalObject (
    131         (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
    132     if (!ObjDesc)
    133     {
    134         return_ACPI_STATUS (AE_NO_MEMORY);
    135     }
    136 
    137     Status = AcpiDsInitObjectFromOp (
    138         WalkState, Op, Op->Common.AmlOpcode, &ObjDesc);
    139     if (ACPI_FAILURE (Status))
    140     {
    141         AcpiUtRemoveReference (ObjDesc);
    142         return_ACPI_STATUS (Status);
    143     }
    144 
    145     /*
    146      * Handling for unresolved package reference elements.
    147      * These are elements that are namepaths.
    148      */
    149     if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
    150         (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
    151     {
    152         ObjDesc->Reference.Resolved = TRUE;
    153 
    154         if ((Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    155             !ObjDesc->Reference.Node)
    156         {
    157             /*
    158              * Name was unresolved above.
    159              * Get the prefix node for later lookup
    160              */
    161             ObjDesc->Reference.Node = WalkState->ScopeInfo->Scope.Node;
    162             ObjDesc->Reference.Aml = Op->Common.Aml;
    163             ObjDesc->Reference.Resolved = FALSE;
    164         }
    165     }
    166 
    167     *ObjDescPtr = ObjDesc;
    168     return_ACPI_STATUS (Status);
    169 }
    170 
    171 
    172 /*******************************************************************************
    173  *
    174  * FUNCTION:    AcpiDsBuildInternalBufferObj
    175  *
    176  * PARAMETERS:  WalkState       - Current walk state
    177  *              Op              - Parser object to be translated
    178  *              BufferLength    - Length of the buffer
    179  *              ObjDescPtr      - Where the ACPI internal object is returned
    180  *
    181  * RETURN:      Status
    182  *
    183  * DESCRIPTION: Translate a parser Op package object to the equivalent
    184  *              namespace object
    185  *
    186  ******************************************************************************/
    187 
    188 ACPI_STATUS
    189 AcpiDsBuildInternalBufferObj (
    190     ACPI_WALK_STATE         *WalkState,
    191     ACPI_PARSE_OBJECT       *Op,
    192     UINT32                  BufferLength,
    193     ACPI_OPERAND_OBJECT     **ObjDescPtr)
    194 {
    195     ACPI_PARSE_OBJECT       *Arg;
    196     ACPI_OPERAND_OBJECT     *ObjDesc;
    197     ACPI_PARSE_OBJECT       *ByteList;
    198     UINT32                  ByteListLength = 0;
    199 
    200 
    201     ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj);
    202 
    203 
    204     /*
    205      * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
    206      * The buffer object already exists (from the NS node), otherwise it must
    207      * be created.
    208      */
    209     ObjDesc = *ObjDescPtr;
    210     if (!ObjDesc)
    211     {
    212         /* Create a new buffer object */
    213 
    214         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER);
    215         *ObjDescPtr = ObjDesc;
    216         if (!ObjDesc)
    217         {
    218             return_ACPI_STATUS (AE_NO_MEMORY);
    219         }
    220     }
    221 
    222     /*
    223      * Second arg is the buffer data (optional) ByteList can be either
    224      * individual bytes or a string initializer. In either case, a
    225      * ByteList appears in the AML.
    226      */
    227     Arg = Op->Common.Value.Arg;         /* skip first arg */
    228 
    229     ByteList = Arg->Named.Next;
    230     if (ByteList)
    231     {
    232         if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP)
    233         {
    234             ACPI_ERROR ((AE_INFO,
    235                 "Expecting bytelist, found AML opcode 0x%X in op %p",
    236                 ByteList->Common.AmlOpcode, ByteList));
    237 
    238             AcpiUtRemoveReference (ObjDesc);
    239             return (AE_TYPE);
    240         }
    241 
    242         ByteListLength = (UINT32) ByteList->Common.Value.Integer;
    243     }
    244 
    245     /*
    246      * The buffer length (number of bytes) will be the larger of:
    247      * 1) The specified buffer length and
    248      * 2) The length of the initializer byte list
    249      */
    250     ObjDesc->Buffer.Length = BufferLength;
    251     if (ByteListLength > BufferLength)
    252     {
    253         ObjDesc->Buffer.Length = ByteListLength;
    254     }
    255 
    256     /* Allocate the buffer */
    257 
    258     if (ObjDesc->Buffer.Length == 0)
    259     {
    260         ObjDesc->Buffer.Pointer = NULL;
    261         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    262             "Buffer defined with zero length in AML, creating\n"));
    263     }
    264     else
    265     {
    266         ObjDesc->Buffer.Pointer =
    267             ACPI_ALLOCATE_ZEROED (ObjDesc->Buffer.Length);
    268         if (!ObjDesc->Buffer.Pointer)
    269         {
    270             AcpiUtDeleteObjectDesc (ObjDesc);
    271             return_ACPI_STATUS (AE_NO_MEMORY);
    272         }
    273 
    274         /* Initialize buffer from the ByteList (if present) */
    275 
    276         if (ByteList)
    277         {
    278             memcpy (ObjDesc->Buffer.Pointer, ByteList->Named.Data,
    279                 ByteListLength);
    280         }
    281     }
    282 
    283     ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID;
    284     Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
    285     return_ACPI_STATUS (AE_OK);
    286 }
    287 
    288 /*******************************************************************************
    289  *
    290  * FUNCTION:    AcpiDsCreateNode
    291  *
    292  * PARAMETERS:  WalkState       - Current walk state
    293  *              Node            - NS Node to be initialized
    294  *              Op              - Parser object to be translated
    295  *
    296  * RETURN:      Status
    297  *
    298  * DESCRIPTION: Create the object to be associated with a namespace node
    299  *
    300  ******************************************************************************/
    301 
    302 ACPI_STATUS
    303 AcpiDsCreateNode (
    304     ACPI_WALK_STATE         *WalkState,
    305     ACPI_NAMESPACE_NODE     *Node,
    306     ACPI_PARSE_OBJECT       *Op)
    307 {
    308     ACPI_STATUS             Status;
    309     ACPI_OPERAND_OBJECT     *ObjDesc;
    310 
    311 
    312     ACPI_FUNCTION_TRACE_PTR (DsCreateNode, Op);
    313 
    314 
    315     /*
    316      * Because of the execution pass through the non-control-method
    317      * parts of the table, we can arrive here twice. Only init
    318      * the named object node the first time through
    319      */
    320     if (AcpiNsGetAttachedObject (Node))
    321     {
    322         return_ACPI_STATUS (AE_OK);
    323     }
    324 
    325     if (!Op->Common.Value.Arg)
    326     {
    327         /* No arguments, there is nothing to do */
    328 
    329         return_ACPI_STATUS (AE_OK);
    330     }
    331 
    332     /* Build an internal object for the argument(s) */
    333 
    334     Status = AcpiDsBuildInternalObject (
    335         WalkState, Op->Common.Value.Arg, &ObjDesc);
    336     if (ACPI_FAILURE (Status))
    337     {
    338         return_ACPI_STATUS (Status);
    339     }
    340 
    341     /* Re-type the object according to its argument */
    342 
    343     Node->Type = ObjDesc->Common.Type;
    344 
    345     /* Attach obj to node */
    346 
    347     Status = AcpiNsAttachObject (Node, ObjDesc, Node->Type);
    348 
    349     /* Remove local reference to the object */
    350 
    351     AcpiUtRemoveReference (ObjDesc);
    352     return_ACPI_STATUS (Status);
    353 }
    354 
    355 #endif /* ACPI_NO_METHOD_EXECUTION */
    356 
    357 
    358 /*******************************************************************************
    359  *
    360  * FUNCTION:    AcpiDsInitObjectFromOp
    361  *
    362  * PARAMETERS:  WalkState       - Current walk state
    363  *              Op              - Parser op used to init the internal object
    364  *              Opcode          - AML opcode associated with the object
    365  *              RetObjDesc      - Namespace object to be initialized
    366  *
    367  * RETURN:      Status
    368  *
    369  * DESCRIPTION: Initialize a namespace object from a parser Op and its
    370  *              associated arguments. The namespace object is a more compact
    371  *              representation of the Op and its arguments.
    372  *
    373  ******************************************************************************/
    374 
    375 ACPI_STATUS
    376 AcpiDsInitObjectFromOp (
    377     ACPI_WALK_STATE         *WalkState,
    378     ACPI_PARSE_OBJECT       *Op,
    379     UINT16                  Opcode,
    380     ACPI_OPERAND_OBJECT     **RetObjDesc)
    381 {
    382     const ACPI_OPCODE_INFO  *OpInfo;
    383     ACPI_OPERAND_OBJECT     *ObjDesc;
    384     ACPI_STATUS             Status = AE_OK;
    385 
    386 
    387     ACPI_FUNCTION_TRACE (DsInitObjectFromOp);
    388 
    389 
    390     ObjDesc = *RetObjDesc;
    391     OpInfo = AcpiPsGetOpcodeInfo (Opcode);
    392     if (OpInfo->Class == AML_CLASS_UNKNOWN)
    393     {
    394         /* Unknown opcode */
    395 
    396         return_ACPI_STATUS (AE_TYPE);
    397     }
    398 
    399     /* Perform per-object initialization */
    400 
    401     switch (ObjDesc->Common.Type)
    402     {
    403     case ACPI_TYPE_BUFFER:
    404         /*
    405          * Defer evaluation of Buffer TermArg operand
    406          */
    407         ObjDesc->Buffer.Node = ACPI_CAST_PTR (
    408             ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
    409         ObjDesc->Buffer.AmlStart = Op->Named.Data;
    410         ObjDesc->Buffer.AmlLength = Op->Named.Length;
    411         break;
    412 
    413     case ACPI_TYPE_PACKAGE:
    414         /*
    415          * Defer evaluation of Package TermArg operand and all
    416          * package elements. (01/2017): We defer the element
    417          * resolution to allow forward references from the package
    418          * in order to provide compatibility with other ACPI
    419          * implementations.
    420          */
    421         ObjDesc->Package.Node = ACPI_CAST_PTR (
    422             ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
    423 
    424         if (!Op->Named.Data)
    425         {
    426             return_ACPI_STATUS (AE_OK);
    427         }
    428 
    429         ObjDesc->Package.AmlStart = Op->Named.Data;
    430         ObjDesc->Package.AmlLength = Op->Named.Length;
    431         break;
    432 
    433     case ACPI_TYPE_INTEGER:
    434 
    435         switch (OpInfo->Type)
    436         {
    437         case AML_TYPE_CONSTANT:
    438             /*
    439              * Resolve AML Constants here - AND ONLY HERE!
    440              * All constants are integers.
    441              * We mark the integer with a flag that indicates that it started
    442              * life as a constant -- so that stores to constants will perform
    443              * as expected (noop). ZeroOp is used as a placeholder for optional
    444              * target operands.
    445              */
    446             ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT;
    447 
    448             switch (Opcode)
    449             {
    450             case AML_ZERO_OP:
    451 
    452                 ObjDesc->Integer.Value = 0;
    453                 break;
    454 
    455             case AML_ONE_OP:
    456 
    457                 ObjDesc->Integer.Value = 1;
    458                 break;
    459 
    460             case AML_ONES_OP:
    461 
    462                 ObjDesc->Integer.Value = ACPI_UINT64_MAX;
    463 
    464                 /* Truncate value if we are executing from a 32-bit ACPI table */
    465 
    466 #ifndef ACPI_NO_METHOD_EXECUTION
    467                 (void) AcpiExTruncateFor32bitTable (ObjDesc);
    468 #endif
    469                 break;
    470 
    471             case AML_REVISION_OP:
    472 
    473                 ObjDesc->Integer.Value = ACPI_CA_VERSION;
    474                 break;
    475 
    476             default:
    477 
    478                 ACPI_ERROR ((AE_INFO,
    479                     "Unknown constant opcode 0x%X", Opcode));
    480                 Status = AE_AML_OPERAND_TYPE;
    481                 break;
    482             }
    483             break;
    484 
    485         case AML_TYPE_LITERAL:
    486 
    487             ObjDesc->Integer.Value = Op->Common.Value.Integer;
    488 
    489 #ifndef ACPI_NO_METHOD_EXECUTION
    490             if (AcpiExTruncateFor32bitTable (ObjDesc))
    491             {
    492                 /* Warn if we found a 64-bit constant in a 32-bit table */
    493 
    494                 ACPI_WARNING ((AE_INFO,
    495                     "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
    496                     ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
    497                     (UINT32) ObjDesc->Integer.Value));
    498             }
    499 #endif
    500             break;
    501 
    502         default:
    503 
    504             ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X",
    505                 OpInfo->Type));
    506             Status = AE_AML_OPERAND_TYPE;
    507             break;
    508         }
    509         break;
    510 
    511     case ACPI_TYPE_STRING:
    512 
    513         ObjDesc->String.Pointer = Op->Common.Value.String;
    514         ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String);
    515 
    516         /*
    517          * The string is contained in the ACPI table, don't ever try
    518          * to delete it
    519          */
    520         ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
    521         break;
    522 
    523     case ACPI_TYPE_METHOD:
    524         break;
    525 
    526     case ACPI_TYPE_LOCAL_REFERENCE:
    527 
    528         switch (OpInfo->Type)
    529         {
    530         case AML_TYPE_LOCAL_VARIABLE:
    531 
    532             /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
    533 
    534             ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_LOCAL_OP;
    535             ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL;
    536 
    537 #ifndef ACPI_NO_METHOD_EXECUTION
    538             Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL,
    539                 ObjDesc->Reference.Value, WalkState,
    540                 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
    541                     &ObjDesc->Reference.Object));
    542 #endif
    543             break;
    544 
    545         case AML_TYPE_METHOD_ARGUMENT:
    546 
    547             /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
    548 
    549             ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_ARG_OP;
    550             ObjDesc->Reference.Class = ACPI_REFCLASS_ARG;
    551 
    552 #ifndef ACPI_NO_METHOD_EXECUTION
    553             Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG,
    554                 ObjDesc->Reference.Value, WalkState,
    555                 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
    556                     &ObjDesc->Reference.Object));
    557 #endif
    558             break;
    559 
    560         default: /* Object name or Debug object */
    561 
    562             switch (Op->Common.AmlOpcode)
    563             {
    564             case AML_INT_NAMEPATH_OP:
    565 
    566                 /* Node was saved in Op */
    567 
    568                 ObjDesc->Reference.Node = Op->Common.Node;
    569                 ObjDesc->Reference.Class = ACPI_REFCLASS_NAME;
    570                 if (Op->Common.Node)
    571                 {
    572                     ObjDesc->Reference.Object = Op->Common.Node->Object;
    573                 }
    574                 break;
    575 
    576             case AML_DEBUG_OP:
    577 
    578                 ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG;
    579                 break;
    580 
    581             default:
    582 
    583                 ACPI_ERROR ((AE_INFO,
    584                     "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode));
    585                 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    586             }
    587             break;
    588         }
    589         break;
    590 
    591     default:
    592 
    593         ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X",
    594             ObjDesc->Common.Type));
    595 
    596         Status = AE_AML_OPERAND_TYPE;
    597         break;
    598     }
    599 
    600     return_ACPI_STATUS (Status);
    601 }
    602