dsobject.c revision 1.1.1.13
1/******************************************************************************
2 *
3 * Module Name: dsobject - Dispatcher object management routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, 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
72ACPI_STATUS
73AcpiDsBuildInternalObject (
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
126CreateNewObject:
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
188ACPI_STATUS
189AcpiDsBuildInternalBufferObj (
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
302ACPI_STATUS
303AcpiDsCreateNode (
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
375ACPI_STATUS
376AcpiDsInitObjectFromOp (
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