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