1/******************************************************************************
2 *
3 * Module Name: dswload - Dispatcher first pass namespace load callbacks
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, 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#define __DSWLOAD_C__
45
46#include "acpi.h"
47#include "accommon.h"
48#include "acparser.h"
49#include "amlcode.h"
50#include "acdispat.h"
51#include "acinterp.h"
52#include "acnamesp.h"
53
54#ifdef ACPI_ASL_COMPILER
55#include "acdisasm.h"
56#endif
57
58#define _COMPONENT          ACPI_DISPATCHER
59        ACPI_MODULE_NAME    ("dswload")
60
61
62/*******************************************************************************
63 *
64 * FUNCTION:    AcpiDsInitCallbacks
65 *
66 * PARAMETERS:  WalkState       - Current state of the parse tree walk
67 *              PassNumber      - 1, 2, or 3
68 *
69 * RETURN:      Status
70 *
71 * DESCRIPTION: Init walk state callbacks
72 *
73 ******************************************************************************/
74
75ACPI_STATUS
76AcpiDsInitCallbacks (
77    ACPI_WALK_STATE         *WalkState,
78    UINT32                  PassNumber)
79{
80
81    switch (PassNumber)
82    {
83    case 1:
84        WalkState->ParseFlags         = ACPI_PARSE_LOAD_PASS1 |
85                                        ACPI_PARSE_DELETE_TREE;
86        WalkState->DescendingCallback = AcpiDsLoad1BeginOp;
87        WalkState->AscendingCallback  = AcpiDsLoad1EndOp;
88        break;
89
90    case 2:
91        WalkState->ParseFlags         = ACPI_PARSE_LOAD_PASS1 |
92                                        ACPI_PARSE_DELETE_TREE;
93        WalkState->DescendingCallback = AcpiDsLoad2BeginOp;
94        WalkState->AscendingCallback  = AcpiDsLoad2EndOp;
95        break;
96
97    case 3:
98#ifndef ACPI_NO_METHOD_EXECUTION
99        WalkState->ParseFlags        |= ACPI_PARSE_EXECUTE  |
100                                        ACPI_PARSE_DELETE_TREE;
101        WalkState->DescendingCallback = AcpiDsExecBeginOp;
102        WalkState->AscendingCallback  = AcpiDsExecEndOp;
103#endif
104        break;
105
106    default:
107        return (AE_BAD_PARAMETER);
108    }
109
110    return (AE_OK);
111}
112
113
114/*******************************************************************************
115 *
116 * FUNCTION:    AcpiDsLoad1BeginOp
117 *
118 * PARAMETERS:  WalkState       - Current state of the parse tree walk
119 *              OutOp           - Where to return op if a new one is created
120 *
121 * RETURN:      Status
122 *
123 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
124 *
125 ******************************************************************************/
126
127ACPI_STATUS
128AcpiDsLoad1BeginOp (
129    ACPI_WALK_STATE         *WalkState,
130    ACPI_PARSE_OBJECT       **OutOp)
131{
132    ACPI_PARSE_OBJECT       *Op;
133    ACPI_NAMESPACE_NODE     *Node;
134    ACPI_STATUS             Status;
135    ACPI_OBJECT_TYPE        ObjectType;
136    char                    *Path;
137    UINT32                  Flags;
138
139
140    ACPI_FUNCTION_TRACE (DsLoad1BeginOp);
141
142
143    Op = WalkState->Op;
144    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState));
145
146    /* We are only interested in opcodes that have an associated name */
147
148    if (Op)
149    {
150        if (!(WalkState->OpInfo->Flags & AML_NAMED))
151        {
152            *OutOp = Op;
153            return_ACPI_STATUS (AE_OK);
154        }
155
156        /* Check if this object has already been installed in the namespace */
157
158        if (Op->Common.Node)
159        {
160            *OutOp = Op;
161            return_ACPI_STATUS (AE_OK);
162        }
163    }
164
165    Path = AcpiPsGetNextNamestring (&WalkState->ParserState);
166
167    /* Map the raw opcode into an internal object type */
168
169    ObjectType = WalkState->OpInfo->ObjectType;
170
171    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
172        "State=%p Op=%p [%s]\n", WalkState, Op, AcpiUtGetTypeName (ObjectType)));
173
174    switch (WalkState->Opcode)
175    {
176    case AML_SCOPE_OP:
177
178        /*
179         * The target name of the Scope() operator must exist at this point so
180         * that we can actually open the scope to enter new names underneath it.
181         * Allow search-to-root for single namesegs.
182         */
183        Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
184                        ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node));
185#ifdef ACPI_ASL_COMPILER
186        if (Status == AE_NOT_FOUND)
187        {
188            /*
189             * Table disassembly:
190             * Target of Scope() not found. Generate an External for it, and
191             * insert the name into the namespace.
192             */
193            AcpiDmAddToExternalList (Op, Path, ACPI_TYPE_DEVICE, 0);
194            Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
195                       ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
196                       WalkState, &Node);
197        }
198#endif
199        if (ACPI_FAILURE (Status))
200        {
201            ACPI_ERROR_NAMESPACE (Path, Status);
202            return_ACPI_STATUS (Status);
203        }
204
205        /*
206         * Check to make sure that the target is
207         * one of the opcodes that actually opens a scope
208         */
209        switch (Node->Type)
210        {
211        case ACPI_TYPE_ANY:
212        case ACPI_TYPE_LOCAL_SCOPE:         /* Scope  */
213        case ACPI_TYPE_DEVICE:
214        case ACPI_TYPE_POWER:
215        case ACPI_TYPE_PROCESSOR:
216        case ACPI_TYPE_THERMAL:
217
218            /* These are acceptable types */
219            break;
220
221        case ACPI_TYPE_INTEGER:
222        case ACPI_TYPE_STRING:
223        case ACPI_TYPE_BUFFER:
224
225            /*
226             * These types we will allow, but we will change the type.
227             * This enables some existing code of the form:
228             *
229             *  Name (DEB, 0)
230             *  Scope (DEB) { ... }
231             *
232             * Note: silently change the type here. On the second pass,
233             * we will report a warning
234             */
235            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
236                "Type override - [%4.4s] had invalid type (%s) "
237                "for Scope operator, changed to type ANY\n",
238                AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type)));
239
240            Node->Type = ACPI_TYPE_ANY;
241            WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY;
242            break;
243
244        default:
245
246            /* All other types are an error */
247
248            ACPI_ERROR ((AE_INFO,
249                "Invalid type (%s) for target of "
250                "Scope operator [%4.4s] (Cannot override)",
251                AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node)));
252
253            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
254        }
255        break;
256
257
258    default:
259        /*
260         * For all other named opcodes, we will enter the name into
261         * the namespace.
262         *
263         * Setup the search flags.
264         * Since we are entering a name into the namespace, we do not want to
265         * enable the search-to-root upsearch.
266         *
267         * There are only two conditions where it is acceptable that the name
268         * already exists:
269         *    1) the Scope() operator can reopen a scoping object that was
270         *       previously defined (Scope, Method, Device, etc.)
271         *    2) Whenever we are parsing a deferred opcode (OpRegion, Buffer,
272         *       BufferField, or Package), the name of the object is already
273         *       in the namespace.
274         */
275        if (WalkState->DeferredNode)
276        {
277            /* This name is already in the namespace, get the node */
278
279            Node = WalkState->DeferredNode;
280            Status = AE_OK;
281            break;
282        }
283
284        /*
285         * If we are executing a method, do not create any namespace objects
286         * during the load phase, only during execution.
287         */
288        if (WalkState->MethodNode)
289        {
290            Node = NULL;
291            Status = AE_OK;
292            break;
293        }
294
295        Flags = ACPI_NS_NO_UPSEARCH;
296        if ((WalkState->Opcode != AML_SCOPE_OP) &&
297            (!(WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP)))
298        {
299            Flags |= ACPI_NS_ERROR_IF_FOUND;
300            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n",
301                    AcpiUtGetTypeName (ObjectType)));
302        }
303        else
304        {
305            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
306                "[%s] Both Find or Create allowed\n",
307                    AcpiUtGetTypeName (ObjectType)));
308        }
309
310        /*
311         * Enter the named type into the internal namespace. We enter the name
312         * as we go downward in the parse tree. Any necessary subobjects that
313         * involve arguments to the opcode must be created as we go back up the
314         * parse tree later.
315         */
316        Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
317                        ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node);
318        if (ACPI_FAILURE (Status))
319        {
320            if (Status == AE_ALREADY_EXISTS)
321            {
322                /* The name already exists in this scope */
323
324                if (Node->Flags & ANOBJ_IS_EXTERNAL)
325                {
326                    /*
327                     * Allow one create on an object or segment that was
328                     * previously declared External
329                     */
330                    Node->Flags &= ~ANOBJ_IS_EXTERNAL;
331                    Node->Type = (UINT8) ObjectType;
332
333                    /* Just retyped a node, probably will need to open a scope */
334
335                    if (AcpiNsOpensScope (ObjectType))
336                    {
337                        Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
338                        if (ACPI_FAILURE (Status))
339                        {
340                            return_ACPI_STATUS (Status);
341                        }
342                    }
343
344                    Status = AE_OK;
345                }
346            }
347
348            if (ACPI_FAILURE (Status))
349            {
350                ACPI_ERROR_NAMESPACE (Path, Status);
351                return_ACPI_STATUS (Status);
352            }
353        }
354        break;
355    }
356
357    /* Common exit */
358
359    if (!Op)
360    {
361        /* Create a new op */
362
363        Op = AcpiPsAllocOp (WalkState->Opcode);
364        if (!Op)
365        {
366            return_ACPI_STATUS (AE_NO_MEMORY);
367        }
368    }
369
370    /* Initialize the op */
371
372#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
373    Op->Named.Path = ACPI_CAST_PTR (UINT8, Path);
374#endif
375
376    if (Node)
377    {
378        /*
379         * Put the Node in the "op" object that the parser uses, so we
380         * can get it again quickly when this scope is closed
381         */
382        Op->Common.Node = Node;
383        Op->Named.Name = Node->Name.Integer;
384    }
385
386    AcpiPsAppendArg (AcpiPsGetParentScope (&WalkState->ParserState), Op);
387    *OutOp = Op;
388    return_ACPI_STATUS (Status);
389}
390
391
392/*******************************************************************************
393 *
394 * FUNCTION:    AcpiDsLoad1EndOp
395 *
396 * PARAMETERS:  WalkState       - Current state of the parse tree walk
397 *
398 * RETURN:      Status
399 *
400 * DESCRIPTION: Ascending callback used during the loading of the namespace,
401 *              both control methods and everything else.
402 *
403 ******************************************************************************/
404
405ACPI_STATUS
406AcpiDsLoad1EndOp (
407    ACPI_WALK_STATE         *WalkState)
408{
409    ACPI_PARSE_OBJECT       *Op;
410    ACPI_OBJECT_TYPE        ObjectType;
411    ACPI_STATUS             Status = AE_OK;
412
413
414    ACPI_FUNCTION_TRACE (DsLoad1EndOp);
415
416
417    Op = WalkState->Op;
418    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState));
419
420    /* We are only interested in opcodes that have an associated name */
421
422    if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_FIELD)))
423    {
424        return_ACPI_STATUS (AE_OK);
425    }
426
427    /* Get the object type to determine if we should pop the scope */
428
429    ObjectType = WalkState->OpInfo->ObjectType;
430
431#ifndef ACPI_NO_METHOD_EXECUTION
432    if (WalkState->OpInfo->Flags & AML_FIELD)
433    {
434        /*
435         * If we are executing a method, do not create any namespace objects
436         * during the load phase, only during execution.
437         */
438        if (!WalkState->MethodNode)
439        {
440            if (WalkState->Opcode == AML_FIELD_OP          ||
441                WalkState->Opcode == AML_BANK_FIELD_OP     ||
442                WalkState->Opcode == AML_INDEX_FIELD_OP)
443            {
444                Status = AcpiDsInitFieldObjects (Op, WalkState);
445            }
446        }
447        return_ACPI_STATUS (Status);
448    }
449
450    /*
451     * If we are executing a method, do not create any namespace objects
452     * during the load phase, only during execution.
453     */
454    if (!WalkState->MethodNode)
455    {
456        if (Op->Common.AmlOpcode == AML_REGION_OP)
457        {
458            Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length,
459                        (ACPI_ADR_SPACE_TYPE) ((Op->Common.Value.Arg)->Common.Value.Integer),
460                        WalkState);
461            if (ACPI_FAILURE (Status))
462            {
463                return_ACPI_STATUS (Status);
464            }
465        }
466        else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP)
467        {
468            Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length,
469                        ACPI_ADR_SPACE_DATA_TABLE, WalkState);
470            if (ACPI_FAILURE (Status))
471            {
472                return_ACPI_STATUS (Status);
473            }
474        }
475    }
476#endif
477
478    if (Op->Common.AmlOpcode == AML_NAME_OP)
479    {
480        /* For Name opcode, get the object type from the argument */
481
482        if (Op->Common.Value.Arg)
483        {
484            ObjectType = (AcpiPsGetOpcodeInfo (
485                (Op->Common.Value.Arg)->Common.AmlOpcode))->ObjectType;
486
487            /* Set node type if we have a namespace node */
488
489            if (Op->Common.Node)
490            {
491                Op->Common.Node->Type = (UINT8) ObjectType;
492            }
493        }
494    }
495
496    /*
497     * If we are executing a method, do not create any namespace objects
498     * during the load phase, only during execution.
499     */
500    if (!WalkState->MethodNode)
501    {
502        if (Op->Common.AmlOpcode == AML_METHOD_OP)
503        {
504            /*
505             * MethodOp PkgLength NameString MethodFlags TermList
506             *
507             * Note: We must create the method node/object pair as soon as we
508             * see the method declaration. This allows later pass1 parsing
509             * of invocations of the method (need to know the number of
510             * arguments.)
511             */
512            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
513                "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
514                WalkState, Op, Op->Named.Node));
515
516            if (!AcpiNsGetAttachedObject (Op->Named.Node))
517            {
518                WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node);
519                WalkState->NumOperands = 1;
520
521                Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
522                if (ACPI_SUCCESS (Status))
523                {
524                    Status = AcpiExCreateMethod (Op->Named.Data,
525                                        Op->Named.Length, WalkState);
526                }
527
528                WalkState->Operands[0] = NULL;
529                WalkState->NumOperands = 0;
530
531                if (ACPI_FAILURE (Status))
532                {
533                    return_ACPI_STATUS (Status);
534                }
535            }
536        }
537    }
538
539    /* Pop the scope stack (only if loading a table) */
540
541    if (!WalkState->MethodNode &&
542        AcpiNsOpensScope (ObjectType))
543    {
544        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n",
545            AcpiUtGetTypeName (ObjectType), Op));
546
547        Status = AcpiDsScopeStackPop (WalkState);
548    }
549
550    return_ACPI_STATUS (Status);
551}
552