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