1 /******************************************************************************
   2  *
   3  * Module Name: excreate - Named object creation
   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 __EXCREATE_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acinterp.h"
  49 #include "amlcode.h"
  50 #include "acnamesp.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_EXECUTER
  54         ACPI_MODULE_NAME    ("excreate")
  55 
  56 
  57 #ifndef ACPI_NO_METHOD_EXECUTION
  58 /*******************************************************************************
  59  *
  60  * FUNCTION:    AcpiExCreateAlias
  61  *
  62  * PARAMETERS:  WalkState            - Current state, contains operands
  63  *
  64  * RETURN:      Status
  65  *
  66  * DESCRIPTION: Create a new named alias
  67  *
  68  ******************************************************************************/
  69 
  70 ACPI_STATUS
  71 AcpiExCreateAlias (
  72     ACPI_WALK_STATE         *WalkState)
  73 {
  74     ACPI_NAMESPACE_NODE     *TargetNode;
  75     ACPI_NAMESPACE_NODE     *AliasNode;
  76     ACPI_STATUS             Status = AE_OK;
  77 
  78 
  79     ACPI_FUNCTION_TRACE (ExCreateAlias);
  80 
  81 
  82     /* Get the source/alias operands (both namespace nodes) */
  83 
  84     AliasNode =  (ACPI_NAMESPACE_NODE *) WalkState->Operands[0];
  85     TargetNode = (ACPI_NAMESPACE_NODE *) WalkState->Operands[1];
  86 
  87     if ((TargetNode->Type == ACPI_TYPE_LOCAL_ALIAS)  ||
  88         (TargetNode->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS))
  89     {
  90         /*
  91          * Dereference an existing alias so that we don't create a chain
  92          * of aliases. With this code, we guarantee that an alias is
  93          * always exactly one level of indirection away from the
  94          * actual aliased name.
  95          */
  96         TargetNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, TargetNode->Object);
  97     }
  98 
  99     /*
 100      * For objects that can never change (i.e., the NS node will
 101      * permanently point to the same object), we can simply attach
 102      * the object to the new NS node. For other objects (such as
 103      * Integers, buffers, etc.), we have to point the Alias node
 104      * to the original Node.
 105      */
 106     switch (TargetNode->Type)
 107     {
 108 
 109     /* For these types, the sub-object can change dynamically via a Store */
 110 
 111     case ACPI_TYPE_INTEGER:
 112     case ACPI_TYPE_STRING:
 113     case ACPI_TYPE_BUFFER:
 114     case ACPI_TYPE_PACKAGE:
 115     case ACPI_TYPE_BUFFER_FIELD:
 116     /*
 117      * These types open a new scope, so we need the NS node in order to access
 118      * any children.
 119      */
 120     case ACPI_TYPE_DEVICE:
 121     case ACPI_TYPE_POWER:
 122     case ACPI_TYPE_PROCESSOR:
 123     case ACPI_TYPE_THERMAL:
 124     case ACPI_TYPE_LOCAL_SCOPE:
 125         /*
 126          * The new alias has the type ALIAS and points to the original
 127          * NS node, not the object itself.
 128          */
 129         AliasNode->Type = ACPI_TYPE_LOCAL_ALIAS;
 130         AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
 131         break;
 132 
 133     case ACPI_TYPE_METHOD:
 134         /*
 135          * Control method aliases need to be differentiated
 136          */
 137         AliasNode->Type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
 138         AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
 139         break;
 140 
 141     default:
 142 
 143         /* Attach the original source object to the new Alias Node */
 144 
 145         /*
 146          * The new alias assumes the type of the target, and it points
 147          * to the same object. The reference count of the object has an
 148          * additional reference to prevent deletion out from under either the
 149          * target node or the alias Node
 150          */
 151         Status = AcpiNsAttachObject (AliasNode,
 152                     AcpiNsGetAttachedObject (TargetNode), TargetNode->Type);
 153         break;
 154     }
 155 
 156     /* Since both operands are Nodes, we don't need to delete them */
 157 
 158     return_ACPI_STATUS (Status);
 159 }
 160 
 161 
 162 /*******************************************************************************
 163  *
 164  * FUNCTION:    AcpiExCreateEvent
 165  *
 166  * PARAMETERS:  WalkState           - Current state
 167  *
 168  * RETURN:      Status
 169  *
 170  * DESCRIPTION: Create a new event object
 171  *
 172  ******************************************************************************/
 173 
 174 ACPI_STATUS
 175 AcpiExCreateEvent (
 176     ACPI_WALK_STATE         *WalkState)
 177 {
 178     ACPI_STATUS             Status;
 179     ACPI_OPERAND_OBJECT     *ObjDesc;
 180 
 181 
 182     ACPI_FUNCTION_TRACE (ExCreateEvent);
 183 
 184 
 185     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_EVENT);
 186     if (!ObjDesc)
 187     {
 188         Status = AE_NO_MEMORY;
 189         goto Cleanup;
 190     }
 191 
 192     /*
 193      * Create the actual OS semaphore, with zero initial units -- meaning
 194      * that the event is created in an unsignalled state
 195      */
 196     Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
 197                 &ObjDesc->Event.OsSemaphore);
 198     if (ACPI_FAILURE (Status))
 199     {
 200         goto Cleanup;
 201     }
 202 
 203     /* Attach object to the Node */
 204 
 205     Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) WalkState->Operands[0],
 206                 ObjDesc, ACPI_TYPE_EVENT);
 207 
 208 Cleanup:
 209     /*
 210      * Remove local reference to the object (on error, will cause deletion
 211      * of both object and semaphore if present.)
 212      */
 213     AcpiUtRemoveReference (ObjDesc);
 214     return_ACPI_STATUS (Status);
 215 }
 216 
 217 
 218 /*******************************************************************************
 219  *
 220  * FUNCTION:    AcpiExCreateMutex
 221  *
 222  * PARAMETERS:  WalkState           - Current state
 223  *
 224  * RETURN:      Status
 225  *
 226  * DESCRIPTION: Create a new mutex object
 227  *
 228  *              Mutex (Name[0], SyncLevel[1])
 229  *
 230  ******************************************************************************/
 231 
 232 ACPI_STATUS
 233 AcpiExCreateMutex (
 234     ACPI_WALK_STATE         *WalkState)
 235 {
 236     ACPI_STATUS             Status = AE_OK;
 237     ACPI_OPERAND_OBJECT     *ObjDesc;
 238 
 239 
 240     ACPI_FUNCTION_TRACE_PTR (ExCreateMutex, ACPI_WALK_OPERANDS);
 241 
 242 
 243     /* Create the new mutex object */
 244 
 245     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
 246     if (!ObjDesc)
 247     {
 248         Status = AE_NO_MEMORY;
 249         goto Cleanup;
 250     }
 251 
 252     /* Create the actual OS Mutex */
 253 
 254     Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex);
 255     if (ACPI_FAILURE (Status))
 256     {
 257         goto Cleanup;
 258     }
 259 
 260     /* Init object and attach to NS node */
 261 
 262     ObjDesc->Mutex.SyncLevel = (UINT8) WalkState->Operands[1]->Integer.Value;
 263     ObjDesc->Mutex.Node = (ACPI_NAMESPACE_NODE *) WalkState->Operands[0];
 264 
 265     Status = AcpiNsAttachObject (ObjDesc->Mutex.Node, ObjDesc, ACPI_TYPE_MUTEX);
 266 
 267 
 268 Cleanup:
 269     /*
 270      * Remove local reference to the object (on error, will cause deletion
 271      * of both object and semaphore if present.)
 272      */
 273     AcpiUtRemoveReference (ObjDesc);
 274     return_ACPI_STATUS (Status);
 275 }
 276 
 277 
 278 /*******************************************************************************
 279  *
 280  * FUNCTION:    AcpiExCreateRegion
 281  *
 282  * PARAMETERS:  AmlStart            - Pointer to the region declaration AML
 283  *              AmlLength           - Max length of the declaration AML
 284  *              SpaceId             - Address space ID for the region
 285  *              WalkState           - Current state
 286  *
 287  * RETURN:      Status
 288  *
 289  * DESCRIPTION: Create a new operation region object
 290  *
 291  ******************************************************************************/
 292 
 293 ACPI_STATUS
 294 AcpiExCreateRegion (
 295     UINT8                   *AmlStart,
 296     UINT32                  AmlLength,
 297     UINT8                   SpaceId,
 298     ACPI_WALK_STATE         *WalkState)
 299 {
 300     ACPI_STATUS             Status;
 301     ACPI_OPERAND_OBJECT     *ObjDesc;
 302     ACPI_NAMESPACE_NODE     *Node;
 303     ACPI_OPERAND_OBJECT     *RegionObj2;
 304 
 305 
 306     ACPI_FUNCTION_TRACE (ExCreateRegion);
 307 
 308 
 309     /* Get the Namespace Node */
 310 
 311     Node = WalkState->Op->Common.Node;
 312 
 313     /*
 314      * If the region object is already attached to this node,
 315      * just return
 316      */
 317     if (AcpiNsGetAttachedObject (Node))
 318     {
 319         return_ACPI_STATUS (AE_OK);
 320     }
 321 
 322     /*
 323      * Space ID must be one of the predefined IDs, or in the user-defined
 324      * range
 325      */
 326     if (!AcpiIsValidSpaceId (SpaceId))
 327     {
 328         /*
 329          * Print an error message, but continue. We don't want to abort
 330          * a table load for this exception. Instead, if the region is
 331          * actually used at runtime, abort the executing method.
 332          */
 333         ACPI_ERROR ((AE_INFO, "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
 334     }
 335 
 336     ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
 337         AcpiUtGetRegionName (SpaceId), SpaceId));
 338 
 339     /* Create the region descriptor */
 340 
 341     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
 342     if (!ObjDesc)
 343     {
 344         Status = AE_NO_MEMORY;
 345         goto Cleanup;
 346     }
 347 
 348     /*
 349      * Remember location in AML stream of address & length
 350      * operands since they need to be evaluated at run time.
 351      */
 352     RegionObj2 = ObjDesc->Common.NextObject;
 353     RegionObj2->Extra.AmlStart = AmlStart;
 354     RegionObj2->Extra.AmlLength = AmlLength;
 355     if (WalkState->ScopeInfo)
 356     {
 357         RegionObj2->Extra.ScopeNode = WalkState->ScopeInfo->Scope.Node;
 358     }
 359     else
 360     {
 361         RegionObj2->Extra.ScopeNode = Node;
 362     }
 363 
 364     /* Init the region from the operands */
 365 
 366     ObjDesc->Region.SpaceId = SpaceId;
 367     ObjDesc->Region.Address = 0;
 368     ObjDesc->Region.Length = 0;
 369     ObjDesc->Region.Node = Node;
 370 
 371     /* Install the new region object in the parent Node */
 372 
 373     Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_REGION);
 374 
 375 
 376 Cleanup:
 377 
 378     /* Remove local reference to the object */
 379 
 380     AcpiUtRemoveReference (ObjDesc);
 381     return_ACPI_STATUS (Status);
 382 }
 383 
 384 
 385 /*******************************************************************************
 386  *
 387  * FUNCTION:    AcpiExCreateProcessor
 388  *
 389  * PARAMETERS:  WalkState           - Current state
 390  *
 391  * RETURN:      Status
 392  *
 393  * DESCRIPTION: Create a new processor object and populate the fields
 394  *
 395  *              Processor (Name[0], CpuID[1], PblockAddr[2], PblockLength[3])
 396  *
 397  ******************************************************************************/
 398 
 399 ACPI_STATUS
 400 AcpiExCreateProcessor (
 401     ACPI_WALK_STATE         *WalkState)
 402 {
 403     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
 404     ACPI_OPERAND_OBJECT     *ObjDesc;
 405     ACPI_STATUS             Status;
 406 
 407 
 408     ACPI_FUNCTION_TRACE_PTR (ExCreateProcessor, WalkState);
 409 
 410 
 411     /* Create the processor object */
 412 
 413     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PROCESSOR);
 414     if (!ObjDesc)
 415     {
 416         return_ACPI_STATUS (AE_NO_MEMORY);
 417     }
 418 
 419     /* Initialize the processor object from the operands */
 420 
 421     ObjDesc->Processor.ProcId = (UINT8) Operand[1]->Integer.Value;
 422     ObjDesc->Processor.Length = (UINT8) Operand[3]->Integer.Value;
 423     ObjDesc->Processor.Address = (ACPI_IO_ADDRESS) Operand[2]->Integer.Value;
 424 
 425     /* Install the processor object in the parent Node */
 426 
 427     Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0],
 428                     ObjDesc, ACPI_TYPE_PROCESSOR);
 429 
 430     /* Remove local reference to the object */
 431 
 432     AcpiUtRemoveReference (ObjDesc);
 433     return_ACPI_STATUS (Status);
 434 }
 435 
 436 
 437 /*******************************************************************************
 438  *
 439  * FUNCTION:    AcpiExCreatePowerResource
 440  *
 441  * PARAMETERS:  WalkState           - Current state
 442  *
 443  * RETURN:      Status
 444  *
 445  * DESCRIPTION: Create a new PowerResource object and populate the fields
 446  *
 447  *              PowerResource (Name[0], SystemLevel[1], ResourceOrder[2])
 448  *
 449  ******************************************************************************/
 450 
 451 ACPI_STATUS
 452 AcpiExCreatePowerResource (
 453     ACPI_WALK_STATE         *WalkState)
 454 {
 455     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
 456     ACPI_STATUS             Status;
 457     ACPI_OPERAND_OBJECT     *ObjDesc;
 458 
 459 
 460     ACPI_FUNCTION_TRACE_PTR (ExCreatePowerResource, WalkState);
 461 
 462 
 463     /* Create the power resource object */
 464 
 465     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_POWER);
 466     if (!ObjDesc)
 467     {
 468         return_ACPI_STATUS (AE_NO_MEMORY);
 469     }
 470 
 471     /* Initialize the power object from the operands */
 472 
 473     ObjDesc->PowerResource.SystemLevel = (UINT8) Operand[1]->Integer.Value;
 474     ObjDesc->PowerResource.ResourceOrder = (UINT16) Operand[2]->Integer.Value;
 475 
 476     /* Install the  power resource object in the parent Node */
 477 
 478     Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0],
 479                     ObjDesc, ACPI_TYPE_POWER);
 480 
 481     /* Remove local reference to the object */
 482 
 483     AcpiUtRemoveReference (ObjDesc);
 484     return_ACPI_STATUS (Status);
 485 }
 486 #endif
 487 
 488 
 489 /*******************************************************************************
 490  *
 491  * FUNCTION:    AcpiExCreateMethod
 492  *
 493  * PARAMETERS:  AmlStart        - First byte of the method's AML
 494  *              AmlLength       - AML byte count for this method
 495  *              WalkState       - Current state
 496  *
 497  * RETURN:      Status
 498  *
 499  * DESCRIPTION: Create a new method object
 500  *
 501  ******************************************************************************/
 502 
 503 ACPI_STATUS
 504 AcpiExCreateMethod (
 505     UINT8                   *AmlStart,
 506     UINT32                  AmlLength,
 507     ACPI_WALK_STATE         *WalkState)
 508 {
 509     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
 510     ACPI_OPERAND_OBJECT     *ObjDesc;
 511     ACPI_STATUS             Status;
 512     UINT8                   MethodFlags;
 513 
 514 
 515     ACPI_FUNCTION_TRACE_PTR (ExCreateMethod, WalkState);
 516 
 517 
 518     /* Create a new method object */
 519 
 520     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
 521     if (!ObjDesc)
 522     {
 523        Status = AE_NO_MEMORY;
 524        goto Exit;
 525     }
 526 
 527     /* Save the method's AML pointer and length  */
 528 
 529     ObjDesc->Method.AmlStart = AmlStart;
 530     ObjDesc->Method.AmlLength = AmlLength;
 531 
 532     /*
 533      * Disassemble the method flags. Split off the ArgCount, Serialized
 534      * flag, and SyncLevel for efficiency.
 535      */
 536     MethodFlags = (UINT8) Operand[1]->Integer.Value;
 537     ObjDesc->Method.ParamCount = (UINT8) (MethodFlags & AML_METHOD_ARG_COUNT);
 538 
 539     /*
 540      * Get the SyncLevel. If method is serialized, a mutex will be
 541      * created for this method when it is parsed.
 542      */
 543     if (MethodFlags & AML_METHOD_SERIALIZED)
 544     {
 545         ObjDesc->Method.InfoFlags = ACPI_METHOD_SERIALIZED;
 546 
 547         /*
 548          * ACPI 1.0: SyncLevel = 0
 549          * ACPI 2.0: SyncLevel = SyncLevel in method declaration
 550          */
 551         ObjDesc->Method.SyncLevel = (UINT8)
 552             ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
 553     }
 554 
 555     /* Attach the new object to the method Node */
 556 
 557     Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0],
 558                     ObjDesc, ACPI_TYPE_METHOD);
 559 
 560     /* Remove local reference to the object */
 561 
 562     AcpiUtRemoveReference (ObjDesc);
 563 
 564 Exit:
 565     /* Remove a reference to the operand */
 566 
 567     AcpiUtRemoveReference (Operand[1]);
 568     return_ACPI_STATUS (Status);
 569 }