excreate.c revision 217365
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 <contrib/dev/acpica/include/acpi.h> 47#include <contrib/dev/acpica/include/accommon.h> 48#include <contrib/dev/acpica/include/acinterp.h> 49#include <contrib/dev/acpica/include/amlcode.h> 50#include <contrib/dev/acpica/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 70ACPI_STATUS 71AcpiExCreateAlias ( 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 177ACPI_STATUS 178AcpiExCreateEvent ( 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 211Cleanup: 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 235ACPI_STATUS 236AcpiExCreateMutex ( 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 271Cleanup: 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 296ACPI_STATUS 297AcpiExCreateRegion ( 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 { 332 ACPI_ERROR ((AE_INFO, "Invalid AddressSpace type 0x%X", RegionSpace)); 333 return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); 334 } 335 336 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n", 337 AcpiUtGetRegionName (RegionSpace), RegionSpace)); 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 356 /* Init the region from the operands */ 357 358 ObjDesc->Region.SpaceId = RegionSpace; 359 ObjDesc->Region.Address = 0; 360 ObjDesc->Region.Length = 0; 361 ObjDesc->Region.Node = Node; 362 363 /* Install the new region object in the parent Node */ 364 365 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_REGION); 366 367 368Cleanup: 369 370 /* Remove local reference to the object */ 371 372 AcpiUtRemoveReference (ObjDesc); 373 return_ACPI_STATUS (Status); 374} 375 376 377/******************************************************************************* 378 * 379 * FUNCTION: AcpiExCreateProcessor 380 * 381 * PARAMETERS: WalkState - Current state 382 * 383 * RETURN: Status 384 * 385 * DESCRIPTION: Create a new processor object and populate the fields 386 * 387 * Processor (Name[0], CpuID[1], PblockAddr[2], PblockLength[3]) 388 * 389 ******************************************************************************/ 390 391ACPI_STATUS 392AcpiExCreateProcessor ( 393 ACPI_WALK_STATE *WalkState) 394{ 395 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 396 ACPI_OPERAND_OBJECT *ObjDesc; 397 ACPI_STATUS Status; 398 399 400 ACPI_FUNCTION_TRACE_PTR (ExCreateProcessor, WalkState); 401 402 403 /* Create the processor object */ 404 405 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PROCESSOR); 406 if (!ObjDesc) 407 { 408 return_ACPI_STATUS (AE_NO_MEMORY); 409 } 410 411 /* Initialize the processor object from the operands */ 412 413 ObjDesc->Processor.ProcId = (UINT8) Operand[1]->Integer.Value; 414 ObjDesc->Processor.Length = (UINT8) Operand[3]->Integer.Value; 415 ObjDesc->Processor.Address = (ACPI_IO_ADDRESS) Operand[2]->Integer.Value; 416 417 /* Install the processor object in the parent Node */ 418 419 Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], 420 ObjDesc, ACPI_TYPE_PROCESSOR); 421 422 /* Remove local reference to the object */ 423 424 AcpiUtRemoveReference (ObjDesc); 425 return_ACPI_STATUS (Status); 426} 427 428 429/******************************************************************************* 430 * 431 * FUNCTION: AcpiExCreatePowerResource 432 * 433 * PARAMETERS: WalkState - Current state 434 * 435 * RETURN: Status 436 * 437 * DESCRIPTION: Create a new PowerResource object and populate the fields 438 * 439 * PowerResource (Name[0], SystemLevel[1], ResourceOrder[2]) 440 * 441 ******************************************************************************/ 442 443ACPI_STATUS 444AcpiExCreatePowerResource ( 445 ACPI_WALK_STATE *WalkState) 446{ 447 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 448 ACPI_STATUS Status; 449 ACPI_OPERAND_OBJECT *ObjDesc; 450 451 452 ACPI_FUNCTION_TRACE_PTR (ExCreatePowerResource, WalkState); 453 454 455 /* Create the power resource object */ 456 457 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_POWER); 458 if (!ObjDesc) 459 { 460 return_ACPI_STATUS (AE_NO_MEMORY); 461 } 462 463 /* Initialize the power object from the operands */ 464 465 ObjDesc->PowerResource.SystemLevel = (UINT8) Operand[1]->Integer.Value; 466 ObjDesc->PowerResource.ResourceOrder = (UINT16) Operand[2]->Integer.Value; 467 468 /* Install the power resource object in the parent Node */ 469 470 Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], 471 ObjDesc, ACPI_TYPE_POWER); 472 473 /* Remove local reference to the object */ 474 475 AcpiUtRemoveReference (ObjDesc); 476 return_ACPI_STATUS (Status); 477} 478#endif 479 480 481/******************************************************************************* 482 * 483 * FUNCTION: AcpiExCreateMethod 484 * 485 * PARAMETERS: AmlStart - First byte of the method's AML 486 * AmlLength - AML byte count for this method 487 * WalkState - Current state 488 * 489 * RETURN: Status 490 * 491 * DESCRIPTION: Create a new method object 492 * 493 ******************************************************************************/ 494 495ACPI_STATUS 496AcpiExCreateMethod ( 497 UINT8 *AmlStart, 498 UINT32 AmlLength, 499 ACPI_WALK_STATE *WalkState) 500{ 501 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 502 ACPI_OPERAND_OBJECT *ObjDesc; 503 ACPI_STATUS Status; 504 UINT8 MethodFlags; 505 506 507 ACPI_FUNCTION_TRACE_PTR (ExCreateMethod, WalkState); 508 509 510 /* Create a new method object */ 511 512 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 513 if (!ObjDesc) 514 { 515 Status = AE_NO_MEMORY; 516 goto Exit; 517 } 518 519 /* Save the method's AML pointer and length */ 520 521 ObjDesc->Method.AmlStart = AmlStart; 522 ObjDesc->Method.AmlLength = AmlLength; 523 524 /* 525 * Disassemble the method flags. Split off the ArgCount, Serialized 526 * flag, and SyncLevel for efficiency. 527 */ 528 MethodFlags = (UINT8) Operand[1]->Integer.Value; 529 ObjDesc->Method.ParamCount = (UINT8) (MethodFlags & AML_METHOD_ARG_COUNT); 530 531 /* 532 * Get the SyncLevel. If method is serialized, a mutex will be 533 * created for this method when it is parsed. 534 */ 535 if (MethodFlags & AML_METHOD_SERIALIZED) 536 { 537 ObjDesc->Method.InfoFlags = ACPI_METHOD_SERIALIZED; 538 539 /* 540 * ACPI 1.0: SyncLevel = 0 541 * ACPI 2.0: SyncLevel = SyncLevel in method declaration 542 */ 543 ObjDesc->Method.SyncLevel = (UINT8) 544 ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4); 545 } 546 547 /* Attach the new object to the method Node */ 548 549 Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], 550 ObjDesc, ACPI_TYPE_METHOD); 551 552 /* Remove local reference to the object */ 553 554 AcpiUtRemoveReference (ObjDesc); 555 556Exit: 557 /* Remove a reference to the operand */ 558 559 AcpiUtRemoveReference (Operand[1]); 560 return_ACPI_STATUS (Status); 561} 562 563 564