Home | History | Annotate | Line # | Download | only in dispatcher
dswload.c revision 1.1.1.2
      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 
     75 ACPI_STATUS
     76 AcpiDsInitCallbacks (
     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 
    127 ACPI_STATUS
    128 AcpiDsLoad1BeginOp (
    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 
    405 ACPI_STATUS
    406 AcpiDsLoad1EndOp (
    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                         REGION_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