Home | History | Annotate | Line # | Download | only in dispatcher
dsobject.c revision 1.1.1.17
      1 /******************************************************************************
      2  *
      3  * Module Name: dsobject - Dispatcher object management routines
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2021, 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 MERCHANTABILITY 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 /*******************************************************************************
     57  *
     58  * FUNCTION:    AcpiDsBuildInternalObject
     59  *
     60  * PARAMETERS:  WalkState       - Current walk state
     61  *              Op              - Parser object to be translated
     62  *              ObjDescPtr      - Where the ACPI internal object is returned
     63  *
     64  * RETURN:      Status
     65  *
     66  * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
     67  *              Simple objects are any objects other than a package object!
     68  *
     69  ******************************************************************************/
     70 
     71 ACPI_STATUS
     72 AcpiDsBuildInternalObject (
     73     ACPI_WALK_STATE         *WalkState,
     74     ACPI_PARSE_OBJECT       *Op,
     75     ACPI_OPERAND_OBJECT     **ObjDescPtr)
     76 {
     77     ACPI_OPERAND_OBJECT     *ObjDesc;
     78     ACPI_STATUS             Status;
     79 
     80 
     81     ACPI_FUNCTION_TRACE (DsBuildInternalObject);
     82 
     83 
     84     *ObjDescPtr = NULL;
     85     if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
     86     {
     87         /*
     88          * This is a named object reference. If this name was
     89          * previously looked up in the namespace, it was stored in
     90          * this op. Otherwise, go ahead and look it up now
     91          */
     92         if (!Op->Common.Node)
     93         {
     94             /* Check if we are resolving a named reference within a package */
     95 
     96             if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
     97                 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
     98             {
     99                 /*
    100                  * We won't resolve package elements here, we will do this
    101                  * after all ACPI tables are loaded into the namespace. This
    102                  * behavior supports both forward references to named objects
    103                  * and external references to objects in other tables.
    104                  */
    105                 goto CreateNewObject;
    106             }
    107             else
    108             {
    109                 Status = AcpiNsLookup (WalkState->ScopeInfo,
    110                     Op->Common.Value.String,
    111                     ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
    112                     ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
    113                     ACPI_CAST_INDIRECT_PTR (
    114                         ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
    115                 if (ACPI_FAILURE (Status))
    116                 {
    117                     ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
    118                         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 
    355 /*******************************************************************************
    356  *
    357  * FUNCTION:    AcpiDsInitObjectFromOp
    358  *
    359  * PARAMETERS:  WalkState       - Current walk state
    360  *              Op              - Parser op used to init the internal object
    361  *              Opcode          - AML opcode associated with the object
    362  *              RetObjDesc      - Namespace object to be initialized
    363  *
    364  * RETURN:      Status
    365  *
    366  * DESCRIPTION: Initialize a namespace object from a parser Op and its
    367  *              associated arguments. The namespace object is a more compact
    368  *              representation of the Op and its arguments.
    369  *
    370  ******************************************************************************/
    371 
    372 ACPI_STATUS
    373 AcpiDsInitObjectFromOp (
    374     ACPI_WALK_STATE         *WalkState,
    375     ACPI_PARSE_OBJECT       *Op,
    376     UINT16                  Opcode,
    377     ACPI_OPERAND_OBJECT     **RetObjDesc)
    378 {
    379     const ACPI_OPCODE_INFO  *OpInfo;
    380     ACPI_OPERAND_OBJECT     *ObjDesc;
    381     ACPI_STATUS             Status = AE_OK;
    382 
    383 
    384     ACPI_FUNCTION_TRACE (DsInitObjectFromOp);
    385 
    386 
    387     ObjDesc = *RetObjDesc;
    388     OpInfo = AcpiPsGetOpcodeInfo (Opcode);
    389     if (OpInfo->Class == AML_CLASS_UNKNOWN)
    390     {
    391         /* Unknown opcode */
    392 
    393         return_ACPI_STATUS (AE_TYPE);
    394     }
    395 
    396     /* Perform per-object initialization */
    397 
    398     switch (ObjDesc->Common.Type)
    399     {
    400     case ACPI_TYPE_BUFFER:
    401         /*
    402          * Defer evaluation of Buffer TermArg operand
    403          */
    404         ObjDesc->Buffer.Node = ACPI_CAST_PTR (
    405             ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
    406         ObjDesc->Buffer.AmlStart = Op->Named.Data;
    407         ObjDesc->Buffer.AmlLength = Op->Named.Length;
    408         break;
    409 
    410     case ACPI_TYPE_PACKAGE:
    411         /*
    412          * Defer evaluation of Package TermArg operand and all
    413          * package elements. (01/2017): We defer the element
    414          * resolution to allow forward references from the package
    415          * in order to provide compatibility with other ACPI
    416          * implementations.
    417          */
    418         ObjDesc->Package.Node = ACPI_CAST_PTR (
    419             ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
    420 
    421         if (!Op->Named.Data)
    422         {
    423             return_ACPI_STATUS (AE_OK);
    424         }
    425 
    426         ObjDesc->Package.AmlStart = Op->Named.Data;
    427         ObjDesc->Package.AmlLength = Op->Named.Length;
    428         break;
    429 
    430     case ACPI_TYPE_INTEGER:
    431 
    432         switch (OpInfo->Type)
    433         {
    434         case AML_TYPE_CONSTANT:
    435             /*
    436              * Resolve AML Constants here - AND ONLY HERE!
    437              * All constants are integers.
    438              * We mark the integer with a flag that indicates that it started
    439              * life as a constant -- so that stores to constants will perform
    440              * as expected (noop). ZeroOp is used as a placeholder for optional
    441              * target operands.
    442              */
    443             ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT;
    444 
    445             switch (Opcode)
    446             {
    447             case AML_ZERO_OP:
    448 
    449                 ObjDesc->Integer.Value = 0;
    450                 break;
    451 
    452             case AML_ONE_OP:
    453 
    454                 ObjDesc->Integer.Value = 1;
    455                 break;
    456 
    457             case AML_ONES_OP:
    458 
    459                 ObjDesc->Integer.Value = ACPI_UINT64_MAX;
    460 
    461                 /* Truncate value if we are executing from a 32-bit ACPI table */
    462 
    463                 (void) AcpiExTruncateFor32bitTable (ObjDesc);
    464                 break;
    465 
    466             case AML_REVISION_OP:
    467 
    468                 ObjDesc->Integer.Value = ACPI_CA_VERSION;
    469                 break;
    470 
    471             default:
    472 
    473                 ACPI_ERROR ((AE_INFO,
    474                     "Unknown constant opcode 0x%X", Opcode));
    475                 Status = AE_AML_OPERAND_TYPE;
    476                 break;
    477             }
    478             break;
    479 
    480         case AML_TYPE_LITERAL:
    481 
    482             ObjDesc->Integer.Value = Op->Common.Value.Integer;
    483 
    484             if (AcpiExTruncateFor32bitTable (ObjDesc))
    485             {
    486                 /* Warn if we found a 64-bit constant in a 32-bit table */
    487 
    488                 ACPI_WARNING ((AE_INFO,
    489                     "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
    490                     ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
    491                     (UINT32) ObjDesc->Integer.Value));
    492             }
    493             break;
    494 
    495         default:
    496 
    497             ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X",
    498                 OpInfo->Type));
    499             Status = AE_AML_OPERAND_TYPE;
    500             break;
    501         }
    502         break;
    503 
    504     case ACPI_TYPE_STRING:
    505 
    506         ObjDesc->String.Pointer = Op->Common.Value.String;
    507         ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String);
    508 
    509         /*
    510          * The string is contained in the ACPI table, don't ever try
    511          * to delete it
    512          */
    513         ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
    514         break;
    515 
    516     case ACPI_TYPE_METHOD:
    517         break;
    518 
    519     case ACPI_TYPE_LOCAL_REFERENCE:
    520 
    521         switch (OpInfo->Type)
    522         {
    523         case AML_TYPE_LOCAL_VARIABLE:
    524 
    525             /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
    526 
    527             ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_LOCAL_OP;
    528             ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL;
    529 
    530             Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL,
    531                 ObjDesc->Reference.Value, WalkState,
    532                 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
    533                     &ObjDesc->Reference.Object));
    534             break;
    535 
    536         case AML_TYPE_METHOD_ARGUMENT:
    537 
    538             /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
    539 
    540             ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_ARG_OP;
    541             ObjDesc->Reference.Class = ACPI_REFCLASS_ARG;
    542 
    543             Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG,
    544                 ObjDesc->Reference.Value, WalkState,
    545                 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
    546                     &ObjDesc->Reference.Object));
    547             break;
    548 
    549         default: /* Object name or Debug object */
    550 
    551             switch (Op->Common.AmlOpcode)
    552             {
    553             case AML_INT_NAMEPATH_OP:
    554 
    555                 /* Node was saved in Op */
    556 
    557                 ObjDesc->Reference.Node = Op->Common.Node;
    558                 ObjDesc->Reference.Class = ACPI_REFCLASS_NAME;
    559                 if (Op->Common.Node)
    560                 {
    561                     ObjDesc->Reference.Object = Op->Common.Node->Object;
    562                 }
    563                 break;
    564 
    565             case AML_DEBUG_OP:
    566 
    567                 ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG;
    568                 break;
    569 
    570             default:
    571 
    572                 ACPI_ERROR ((AE_INFO,
    573                     "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode));
    574                 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    575             }
    576             break;
    577         }
    578         break;
    579 
    580     default:
    581 
    582         ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X",
    583             ObjDesc->Common.Type));
    584 
    585         Status = AE_AML_OPERAND_TYPE;
    586         break;
    587     }
    588 
    589     return_ACPI_STATUS (Status);
    590 }
    591