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