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