at v2.6.12 18 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: excreate - Named object creation 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2005, R. Byron Moore 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 45#include <acpi/acpi.h> 46#include <acpi/acinterp.h> 47#include <acpi/amlcode.h> 48#include <acpi/acnamesp.h> 49#include <acpi/acevents.h> 50#include <acpi/actables.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: acpi_ex_create_alias 61 * 62 * PARAMETERS: walk_state - Current state, contains operands 63 * 64 * RETURN: Status 65 * 66 * DESCRIPTION: Create a new named alias 67 * 68 ****************************************************************************/ 69 70acpi_status 71acpi_ex_create_alias ( 72 struct acpi_walk_state *walk_state) 73{ 74 struct acpi_namespace_node *target_node; 75 struct acpi_namespace_node *alias_node; 76 acpi_status status = AE_OK; 77 78 79 ACPI_FUNCTION_TRACE ("ex_create_alias"); 80 81 82 /* Get the source/alias operands (both namespace nodes) */ 83 84 alias_node = (struct acpi_namespace_node *) walk_state->operands[0]; 85 target_node = (struct acpi_namespace_node *) walk_state->operands[1]; 86 87 if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) || 88 (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { 89 /* 90 * Dereference an existing alias so that we don't create a chain 91 * of aliases. With this code, we guarantee that an alias is 92 * always exactly one level of indirection away from the 93 * actual aliased name. 94 */ 95 target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object); 96 } 97 98 /* 99 * For objects that can never change (i.e., the NS node will 100 * permanently point to the same object), we can simply attach 101 * the object to the new NS node. For other objects (such as 102 * Integers, buffers, etc.), we have to point the Alias node 103 * to the original Node. 104 */ 105 switch (target_node->type) { 106 case ACPI_TYPE_INTEGER: 107 case ACPI_TYPE_STRING: 108 case ACPI_TYPE_BUFFER: 109 case ACPI_TYPE_PACKAGE: 110 case ACPI_TYPE_BUFFER_FIELD: 111 112 /* 113 * The new alias has the type ALIAS and points to the original 114 * NS node, not the object itself. This is because for these 115 * types, the object can change dynamically via a Store. 116 */ 117 alias_node->type = ACPI_TYPE_LOCAL_ALIAS; 118 alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node); 119 break; 120 121 case ACPI_TYPE_METHOD: 122 123 /* 124 * The new alias has the type ALIAS and points to the original 125 * NS node, not the object itself. This is because for these 126 * types, the object can change dynamically via a Store. 127 */ 128 alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; 129 alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node); 130 break; 131 132 default: 133 134 /* Attach the original source object to the new Alias Node */ 135 136 /* 137 * The new alias assumes the type of the target, and it points 138 * to the same object. The reference count of the object has an 139 * additional reference to prevent deletion out from under either the 140 * target node or the alias Node 141 */ 142 status = acpi_ns_attach_object (alias_node, 143 acpi_ns_get_attached_object (target_node), 144 target_node->type); 145 break; 146 } 147 148 /* Since both operands are Nodes, we don't need to delete them */ 149 150 return_ACPI_STATUS (status); 151} 152 153 154/***************************************************************************** 155 * 156 * FUNCTION: acpi_ex_create_event 157 * 158 * PARAMETERS: walk_state - Current state 159 * 160 * RETURN: Status 161 * 162 * DESCRIPTION: Create a new event object 163 * 164 ****************************************************************************/ 165 166acpi_status 167acpi_ex_create_event ( 168 struct acpi_walk_state *walk_state) 169{ 170 acpi_status status; 171 union acpi_operand_object *obj_desc; 172 173 174 ACPI_FUNCTION_TRACE ("ex_create_event"); 175 176 177 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT); 178 if (!obj_desc) { 179 status = AE_NO_MEMORY; 180 goto cleanup; 181 } 182 183 /* 184 * Create the actual OS semaphore, with zero initial units -- meaning 185 * that the event is created in an unsignalled state 186 */ 187 status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, 188 &obj_desc->event.semaphore); 189 if (ACPI_FAILURE (status)) { 190 goto cleanup; 191 } 192 193 /* Attach object to the Node */ 194 195 status = acpi_ns_attach_object ((struct acpi_namespace_node *) walk_state->operands[0], 196 obj_desc, ACPI_TYPE_EVENT); 197 198cleanup: 199 /* 200 * Remove local reference to the object (on error, will cause deletion 201 * of both object and semaphore if present.) 202 */ 203 acpi_ut_remove_reference (obj_desc); 204 return_ACPI_STATUS (status); 205} 206 207 208/***************************************************************************** 209 * 210 * FUNCTION: acpi_ex_create_mutex 211 * 212 * PARAMETERS: walk_state - Current state 213 * 214 * RETURN: Status 215 * 216 * DESCRIPTION: Create a new mutex object 217 * 218 * Mutex (Name[0], sync_level[1]) 219 * 220 ****************************************************************************/ 221 222acpi_status 223acpi_ex_create_mutex ( 224 struct acpi_walk_state *walk_state) 225{ 226 acpi_status status = AE_OK; 227 union acpi_operand_object *obj_desc; 228 229 230 ACPI_FUNCTION_TRACE_PTR ("ex_create_mutex", ACPI_WALK_OPERANDS); 231 232 233 /* Create the new mutex object */ 234 235 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX); 236 if (!obj_desc) { 237 status = AE_NO_MEMORY; 238 goto cleanup; 239 } 240 241 /* 242 * Create the actual OS semaphore. 243 * One unit max to make it a mutex, with one initial unit to allow 244 * the mutex to be acquired. 245 */ 246 status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); 247 if (ACPI_FAILURE (status)) { 248 goto cleanup; 249 } 250 251 /* Init object and attach to NS node */ 252 253 obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value; 254 obj_desc->mutex.node = (struct acpi_namespace_node *) walk_state->operands[0]; 255 256 status = acpi_ns_attach_object (obj_desc->mutex.node, 257 obj_desc, ACPI_TYPE_MUTEX); 258 259 260cleanup: 261 /* 262 * Remove local reference to the object (on error, will cause deletion 263 * of both object and semaphore if present.) 264 */ 265 acpi_ut_remove_reference (obj_desc); 266 return_ACPI_STATUS (status); 267} 268 269 270/***************************************************************************** 271 * 272 * FUNCTION: acpi_ex_create_region 273 * 274 * PARAMETERS: aml_start - Pointer to the region declaration AML 275 * aml_length - Max length of the declaration AML 276 * Operands - List of operands for the opcode 277 * walk_state - Current state 278 * 279 * RETURN: Status 280 * 281 * DESCRIPTION: Create a new operation region object 282 * 283 ****************************************************************************/ 284 285acpi_status 286acpi_ex_create_region ( 287 u8 *aml_start, 288 u32 aml_length, 289 u8 region_space, 290 struct acpi_walk_state *walk_state) 291{ 292 acpi_status status; 293 union acpi_operand_object *obj_desc; 294 struct acpi_namespace_node *node; 295 union acpi_operand_object *region_obj2; 296 297 298 ACPI_FUNCTION_TRACE ("ex_create_region"); 299 300 301 /* Get the Namespace Node */ 302 303 node = walk_state->op->common.node; 304 305 /* 306 * If the region object is already attached to this node, 307 * just return 308 */ 309 if (acpi_ns_get_attached_object (node)) { 310 return_ACPI_STATUS (AE_OK); 311 } 312 313 /* 314 * Space ID must be one of the predefined IDs, or in the user-defined 315 * range 316 */ 317 if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && 318 (region_space < ACPI_USER_REGION_BEGIN)) { 319 ACPI_REPORT_ERROR (("Invalid address_space type %X\n", region_space)); 320 return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); 321 } 322 323 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n", 324 acpi_ut_get_region_name (region_space), region_space)); 325 326 /* Create the region descriptor */ 327 328 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION); 329 if (!obj_desc) { 330 status = AE_NO_MEMORY; 331 goto cleanup; 332 } 333 334 /* 335 * Remember location in AML stream of address & length 336 * operands since they need to be evaluated at run time. 337 */ 338 region_obj2 = obj_desc->common.next_object; 339 region_obj2->extra.aml_start = aml_start; 340 region_obj2->extra.aml_length = aml_length; 341 342 /* Init the region from the operands */ 343 344 obj_desc->region.space_id = region_space; 345 obj_desc->region.address = 0; 346 obj_desc->region.length = 0; 347 obj_desc->region.node = node; 348 349 /* Install the new region object in the parent Node */ 350 351 status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION); 352 353 354cleanup: 355 356 /* Remove local reference to the object */ 357 358 acpi_ut_remove_reference (obj_desc); 359 return_ACPI_STATUS (status); 360} 361 362 363/***************************************************************************** 364 * 365 * FUNCTION: acpi_ex_create_table_region 366 * 367 * PARAMETERS: walk_state - Current state 368 * 369 * RETURN: Status 370 * 371 * DESCRIPTION: Create a new data_table_region object 372 * 373 ****************************************************************************/ 374 375acpi_status 376acpi_ex_create_table_region ( 377 struct acpi_walk_state *walk_state) 378{ 379 acpi_status status; 380 union acpi_operand_object **operand = &walk_state->operands[0]; 381 union acpi_operand_object *obj_desc; 382 struct acpi_namespace_node *node; 383 struct acpi_table_header *table; 384 union acpi_operand_object *region_obj2; 385 386 387 ACPI_FUNCTION_TRACE ("ex_create_table_region"); 388 389 390 /* Get the Node from the object stack */ 391 392 node = walk_state->op->common.node; 393 394 /* 395 * If the region object is already attached to this node, 396 * just return 397 */ 398 if (acpi_ns_get_attached_object (node)) { 399 return_ACPI_STATUS (AE_OK); 400 } 401 402 /* Find the ACPI table */ 403 404 status = acpi_tb_find_table (operand[1]->string.pointer, 405 operand[2]->string.pointer, 406 operand[3]->string.pointer, &table); 407 if (ACPI_FAILURE (status)) { 408 return_ACPI_STATUS (status); 409 } 410 411 /* Create the region descriptor */ 412 413 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION); 414 if (!obj_desc) { 415 return_ACPI_STATUS (AE_NO_MEMORY); 416 } 417 418 region_obj2 = obj_desc->common.next_object; 419 region_obj2->extra.region_context = NULL; 420 421 /* Init the region from the operands */ 422 423 obj_desc->region.space_id = REGION_DATA_TABLE; 424 obj_desc->region.address = (acpi_physical_address) ACPI_TO_INTEGER (table); 425 obj_desc->region.length = table->length; 426 obj_desc->region.node = node; 427 obj_desc->region.flags = AOPOBJ_DATA_VALID; 428 429 /* Install the new region object in the parent Node */ 430 431 status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION); 432 if (ACPI_FAILURE (status)) { 433 goto cleanup; 434 } 435 436 status = acpi_ev_initialize_region (obj_desc, FALSE); 437 if (ACPI_FAILURE (status)) { 438 if (status == AE_NOT_EXIST) { 439 status = AE_OK; 440 } 441 else { 442 goto cleanup; 443 } 444 } 445 446 obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE; 447 448 449cleanup: 450 451 /* Remove local reference to the object */ 452 453 acpi_ut_remove_reference (obj_desc); 454 return_ACPI_STATUS (status); 455} 456 457 458/***************************************************************************** 459 * 460 * FUNCTION: acpi_ex_create_processor 461 * 462 * PARAMETERS: walk_state - Current state 463 * 464 * RETURN: Status 465 * 466 * DESCRIPTION: Create a new processor object and populate the fields 467 * 468 * Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3]) 469 * 470 ****************************************************************************/ 471 472acpi_status 473acpi_ex_create_processor ( 474 struct acpi_walk_state *walk_state) 475{ 476 union acpi_operand_object **operand = &walk_state->operands[0]; 477 union acpi_operand_object *obj_desc; 478 acpi_status status; 479 480 481 ACPI_FUNCTION_TRACE_PTR ("ex_create_processor", walk_state); 482 483 484 /* Create the processor object */ 485 486 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR); 487 if (!obj_desc) { 488 return_ACPI_STATUS (AE_NO_MEMORY); 489 } 490 491 /* 492 * Initialize the processor object from the operands 493 */ 494 obj_desc->processor.proc_id = (u8) operand[1]->integer.value; 495 obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value; 496 obj_desc->processor.length = (u8) operand[3]->integer.value; 497 498 /* Install the processor object in the parent Node */ 499 500 status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0], 501 obj_desc, ACPI_TYPE_PROCESSOR); 502 503 /* Remove local reference to the object */ 504 505 acpi_ut_remove_reference (obj_desc); 506 return_ACPI_STATUS (status); 507} 508 509 510/***************************************************************************** 511 * 512 * FUNCTION: acpi_ex_create_power_resource 513 * 514 * PARAMETERS: walk_state - Current state 515 * 516 * RETURN: Status 517 * 518 * DESCRIPTION: Create a new power_resource object and populate the fields 519 * 520 * power_resource (Name[0], system_level[1], resource_order[2]) 521 * 522 ****************************************************************************/ 523 524acpi_status 525acpi_ex_create_power_resource ( 526 struct acpi_walk_state *walk_state) 527{ 528 union acpi_operand_object **operand = &walk_state->operands[0]; 529 acpi_status status; 530 union acpi_operand_object *obj_desc; 531 532 533 ACPI_FUNCTION_TRACE_PTR ("ex_create_power_resource", walk_state); 534 535 536 /* Create the power resource object */ 537 538 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER); 539 if (!obj_desc) { 540 return_ACPI_STATUS (AE_NO_MEMORY); 541 } 542 543 /* Initialize the power object from the operands */ 544 545 obj_desc->power_resource.system_level = (u8) operand[1]->integer.value; 546 obj_desc->power_resource.resource_order = (u16) operand[2]->integer.value; 547 548 /* Install the power resource object in the parent Node */ 549 550 status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0], 551 obj_desc, ACPI_TYPE_POWER); 552 553 /* Remove local reference to the object */ 554 555 acpi_ut_remove_reference (obj_desc); 556 return_ACPI_STATUS (status); 557} 558 559#endif 560 561/***************************************************************************** 562 * 563 * FUNCTION: acpi_ex_create_method 564 * 565 * PARAMETERS: aml_start - First byte of the method's AML 566 * aml_length - AML byte count for this method 567 * walk_state - Current state 568 * 569 * RETURN: Status 570 * 571 * DESCRIPTION: Create a new method object 572 * 573 ****************************************************************************/ 574 575acpi_status 576acpi_ex_create_method ( 577 u8 *aml_start, 578 u32 aml_length, 579 struct acpi_walk_state *walk_state) 580{ 581 union acpi_operand_object **operand = &walk_state->operands[0]; 582 union acpi_operand_object *obj_desc; 583 acpi_status status; 584 u8 method_flags; 585 586 587 ACPI_FUNCTION_TRACE_PTR ("ex_create_method", walk_state); 588 589 590 /* Create a new method object */ 591 592 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD); 593 if (!obj_desc) { 594 return_ACPI_STATUS (AE_NO_MEMORY); 595 } 596 597 /* Save the method's AML pointer and length */ 598 599 obj_desc->method.aml_start = aml_start; 600 obj_desc->method.aml_length = aml_length; 601 602 /* 603 * Disassemble the method flags. Split off the Arg Count 604 * for efficiency 605 */ 606 method_flags = (u8) operand[1]->integer.value; 607 608 obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT); 609 obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT); 610 611 /* 612 * Get the concurrency count. If required, a semaphore will be 613 * created for this method when it is parsed. 614 */ 615 if (acpi_gbl_all_methods_serialized) { 616 obj_desc->method.concurrency = 1; 617 obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; 618 } 619 else if (method_flags & AML_METHOD_SERIALIZED) { 620 /* 621 * ACPI 1.0: Concurrency = 1 622 * ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1) 623 */ 624 obj_desc->method.concurrency = (u8) 625 (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1); 626 } 627 else { 628 obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY; 629 } 630 631 /* Attach the new object to the method Node */ 632 633 status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0], 634 obj_desc, ACPI_TYPE_METHOD); 635 636 /* Remove local reference to the object */ 637 638 acpi_ut_remove_reference (obj_desc); 639 640 /* Remove a reference to the operand */ 641 642 acpi_ut_remove_reference (operand[1]); 643 return_ACPI_STATUS (status); 644} 645 646