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