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