1/****************************************************************************** 2 * 3 * Module Name: dsobject - Dispatcher object management routines 4 * $Revision: 1.1.1.1 $ 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000, 2001 R. Byron Moore 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 27#include "acpi.h" 28#include "acparser.h" 29#include "amlcode.h" 30#include "acdispat.h" 31#include "acinterp.h" 32#include "acnamesp.h" 33 34#define _COMPONENT ACPI_DISPATCHER 35 MODULE_NAME ("dsobject") 36 37 38/******************************************************************************* 39 * 40 * FUNCTION: Acpi_ds_init_one_object 41 * 42 * PARAMETERS: Obj_handle - Node 43 * Level - Current nesting level 44 * Context - Points to a init info struct 45 * Return_value - Not used 46 * 47 * RETURN: Status 48 * 49 * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object 50 * within the namespace. 51 * 52 * Currently, the only objects that require initialization are: 53 * 1) Methods 54 * 2) Op Regions 55 * 56 ******************************************************************************/ 57 58acpi_status 59acpi_ds_init_one_object ( 60 acpi_handle obj_handle, 61 u32 level, 62 void *context, 63 void **return_value) 64{ 65 acpi_object_type8 type; 66 acpi_status status; 67 acpi_init_walk_info *info = (acpi_init_walk_info *) context; 68 u8 table_revision; 69 70 71 PROC_NAME ("Ds_init_one_object"); 72 73 74 info->object_count++; 75 table_revision = info->table_desc->pointer->revision; 76 77 /* 78 * We are only interested in objects owned by the table that 79 * was just loaded 80 */ 81 if (((acpi_namespace_node *) obj_handle)->owner_id != 82 info->table_desc->table_id) { 83 return (AE_OK); 84 } 85 86 87 /* And even then, we are only interested in a few object types */ 88 89 type = acpi_ns_get_type (obj_handle); 90 91 switch (type) { 92 93 case ACPI_TYPE_REGION: 94 95 acpi_ds_initialize_region (obj_handle); 96 97 info->op_region_count++; 98 break; 99 100 101 case ACPI_TYPE_METHOD: 102 103 info->method_count++; 104 105 if (!(acpi_dbg_level & ACPI_LV_INIT)) { 106 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, ".")); 107 } 108 109 /* 110 * Set the execution data width (32 or 64) based upon the 111 * revision number of the parent ACPI table. 112 */ 113 if (table_revision == 1) { 114 ((acpi_namespace_node *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; 115 } 116 117 /* 118 * Always parse methods to detect errors, we may delete 119 * the parse tree below 120 */ 121 status = acpi_ds_parse_method (obj_handle); 122 if (ACPI_FAILURE (status)) { 123 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n", 124 obj_handle, (char*)&((acpi_namespace_node *)obj_handle)->name, 125 acpi_format_exception (status))); 126 127 /* This parse failed, but we will continue parsing more methods */ 128 129 break; 130 } 131 132 /* 133 * Delete the parse tree. We simple re-parse the method 134 * for every execution since there isn't much overhead 135 */ 136 acpi_ns_delete_namespace_subtree (obj_handle); 137 break; 138 139 default: 140 break; 141 } 142 143 /* 144 * We ignore errors from above, and always return OK, since 145 * we don't want to abort the walk on a single error. 146 */ 147 return (AE_OK); 148} 149 150 151/******************************************************************************* 152 * 153 * FUNCTION: Acpi_ds_initialize_objects 154 * 155 * PARAMETERS: None 156 * 157 * RETURN: Status 158 * 159 * DESCRIPTION: Walk the entire namespace and perform any necessary 160 * initialization on the objects found therein 161 * 162 ******************************************************************************/ 163 164acpi_status 165acpi_ds_initialize_objects ( 166 acpi_table_desc *table_desc, 167 acpi_namespace_node *start_node) 168{ 169 acpi_status status; 170 acpi_init_walk_info info; 171 172 173 FUNCTION_TRACE ("Ds_initialize_objects"); 174 175 176 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 177 "**** Starting initialization of namespace objects ****\n")); 178 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Parsing Methods:")); 179 180 181 info.method_count = 0; 182 info.op_region_count = 0; 183 info.object_count = 0; 184 info.table_desc = table_desc; 185 186 187 /* Walk entire namespace from the supplied root */ 188 189 status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, 190 acpi_ds_init_one_object, &info, NULL); 191 if (ACPI_FAILURE (status)) { 192 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status)); 193 } 194 195 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, 196 "\n%d Control Methods found and parsed (%d nodes total)\n", 197 info.method_count, info.object_count)); 198 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 199 "%d Control Methods found\n", info.method_count)); 200 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 201 "%d Op Regions found\n", info.op_region_count)); 202 203 return_ACPI_STATUS (AE_OK); 204} 205 206 207/***************************************************************************** 208 * 209 * FUNCTION: Acpi_ds_init_object_from_op 210 * 211 * PARAMETERS: Op - Parser op used to init the internal object 212 * Opcode - AML opcode associated with the object 213 * Obj_desc - Namespace object to be initialized 214 * 215 * RETURN: Status 216 * 217 * DESCRIPTION: Initialize a namespace object from a parser Op and its 218 * associated arguments. The namespace object is a more compact 219 * representation of the Op and its arguments. 220 * 221 ****************************************************************************/ 222 223acpi_status 224acpi_ds_init_object_from_op ( 225 acpi_walk_state *walk_state, 226 acpi_parse_object *op, 227 u16 opcode, 228 acpi_operand_object **ret_obj_desc) 229{ 230 acpi_status status; 231 acpi_parse_object *arg; 232 acpi_parse2_object *byte_list; 233 acpi_operand_object *arg_desc; 234 const acpi_opcode_info *op_info; 235 acpi_operand_object *obj_desc; 236 237 238 PROC_NAME ("Ds_init_object_from_op"); 239 240 241 obj_desc = *ret_obj_desc; 242 op_info = acpi_ps_get_opcode_info (opcode); 243 if (op_info->class == AML_CLASS_UNKNOWN) { 244 /* Unknown opcode */ 245 246 return (AE_TYPE); 247 } 248 249 250 /* Get and prepare the first argument */ 251 252 switch (obj_desc->common.type) { 253 case ACPI_TYPE_BUFFER: 254 255 /* First arg is a number */ 256 257 acpi_ds_create_operand (walk_state, op->value.arg, 0); 258 arg_desc = walk_state->operands [walk_state->num_operands - 1]; 259 acpi_ds_obj_stack_pop (1, walk_state); 260 261 /* Resolve the object (could be an arg or local) */ 262 263 status = acpi_ex_resolve_to_value (&arg_desc, walk_state); 264 if (ACPI_FAILURE (status)) { 265 acpi_ut_remove_reference (arg_desc); 266 return (status); 267 } 268 269 /* We are expecting a number */ 270 271 if (arg_desc->common.type != ACPI_TYPE_INTEGER) { 272 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 273 "Expecting number, got obj: %p type %X\n", 274 arg_desc, arg_desc->common.type)); 275 acpi_ut_remove_reference (arg_desc); 276 return (AE_TYPE); 277 } 278 279 /* Get the value, delete the internal object */ 280 281 obj_desc->buffer.length = (u32) arg_desc->integer.value; 282 acpi_ut_remove_reference (arg_desc); 283 284 /* Allocate the buffer */ 285 286 if (obj_desc->buffer.length == 0) { 287 obj_desc->buffer.pointer = NULL; 288 REPORT_WARNING (("Buffer created with zero length in AML\n")); 289 break; 290 } 291 292 else { 293 obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE ( 294 obj_desc->buffer.length); 295 296 if (!obj_desc->buffer.pointer) { 297 return (AE_NO_MEMORY); 298 } 299 } 300 301 /* 302 * Second arg is the buffer data (optional) Byte_list can be either 303 * individual bytes or a string initializer. 304 */ 305 arg = op->value.arg; /* skip first arg */ 306 307 byte_list = (acpi_parse2_object *) arg->next; 308 if (byte_list) { 309 if (byte_list->opcode != AML_INT_BYTELIST_OP) { 310 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Expecting bytelist, got: %p\n", 311 byte_list)); 312 return (AE_TYPE); 313 } 314 315 MEMCPY (obj_desc->buffer.pointer, byte_list->data, 316 obj_desc->buffer.length); 317 } 318 319 break; 320 321 322 case ACPI_TYPE_PACKAGE: 323 324 /* 325 * When called, an internal package object has already been built and 326 * is pointed to by Obj_desc. Acpi_ds_build_internal_object builds another 327 * internal package object, so remove reference to the original so 328 * that it is deleted. Error checking is done within the remove 329 * reference function. 330 */ 331 acpi_ut_remove_reference (obj_desc); 332 status = acpi_ds_build_internal_object (walk_state, op, ret_obj_desc); 333 break; 334 335 case ACPI_TYPE_INTEGER: 336 obj_desc->integer.value = op->value.integer; 337 break; 338 339 340 case ACPI_TYPE_STRING: 341 obj_desc->string.pointer = op->value.string; 342 obj_desc->string.length = STRLEN (op->value.string); 343 344 /* 345 * The string is contained in the ACPI table, don't ever try 346 * to delete it 347 */ 348 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; 349 break; 350 351 352 case ACPI_TYPE_METHOD: 353 break; 354 355 356 case INTERNAL_TYPE_REFERENCE: 357 358 switch (op_info->type) { 359 case AML_TYPE_LOCAL_VARIABLE: 360 361 /* Split the opcode into a base opcode + offset */ 362 363 obj_desc->reference.opcode = AML_LOCAL_OP; 364 obj_desc->reference.offset = opcode - AML_LOCAL_OP; 365 break; 366 367 368 case AML_TYPE_METHOD_ARGUMENT: 369 370 /* Split the opcode into a base opcode + offset */ 371 372 obj_desc->reference.opcode = AML_ARG_OP; 373 obj_desc->reference.offset = opcode - AML_ARG_OP; 374 break; 375 376 377 default: /* Constants, Literals, etc.. */ 378 379 if (op->opcode == AML_INT_NAMEPATH_OP) { 380 /* Node was saved in Op */ 381 382 obj_desc->reference.node = op->node; 383 } 384 385 obj_desc->reference.opcode = opcode; 386 break; 387 } 388 389 break; 390 391 392 default: 393 394 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %x\n", 395 obj_desc->common.type)); 396 397 break; 398 } 399 400 return (AE_OK); 401} 402 403 404/***************************************************************************** 405 * 406 * FUNCTION: Acpi_ds_build_internal_simple_obj 407 * 408 * PARAMETERS: Op - Parser object to be translated 409 * Obj_desc_ptr - Where the ACPI internal object is returned 410 * 411 * RETURN: Status 412 * 413 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object 414 * Simple objects are any objects other than a package object! 415 * 416 ****************************************************************************/ 417 418static acpi_status 419acpi_ds_build_internal_simple_obj ( 420 acpi_walk_state *walk_state, 421 acpi_parse_object *op, 422 acpi_operand_object **obj_desc_ptr) 423{ 424 acpi_operand_object *obj_desc; 425 acpi_object_type8 type; 426 acpi_status status; 427 u32 length; 428 char *name; 429 430 431 FUNCTION_TRACE ("Ds_build_internal_simple_obj"); 432 433 434 if (op->opcode == AML_INT_NAMEPATH_OP) { 435 /* 436 * This is an object reference. If The name was 437 * previously looked up in the NS, it is stored in this op. 438 * Otherwise, go ahead and look it up now 439 */ 440 if (!op->node) { 441 status = acpi_ns_lookup (walk_state->scope_info, 442 op->value.string, ACPI_TYPE_ANY, 443 IMODE_EXECUTE, 444 NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, 445 NULL, 446 (acpi_namespace_node **)&(op->node)); 447 448 if (ACPI_FAILURE (status)) { 449 if (status == AE_NOT_FOUND) { 450 name = NULL; 451 acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name); 452 453 if (name) { 454 REPORT_WARNING (("Reference %s at AML %X not found\n", 455 name, op->aml_offset)); 456 ACPI_MEM_FREE (name); 457 } 458 459 else { 460 REPORT_WARNING (("Reference %s at AML %X not found\n", 461 op->value.string, op->aml_offset)); 462 } 463 464 *obj_desc_ptr = NULL; 465 } 466 467 else { 468 return_ACPI_STATUS (status); 469 } 470 } 471 } 472 473 /* 474 * The reference will be a Reference 475 * TBD: [Restructure] unless we really need a separate 476 * type of INTERNAL_TYPE_REFERENCE change 477 * Acpi_ds_map_opcode_to_data_type to handle this case 478 */ 479 type = INTERNAL_TYPE_REFERENCE; 480 } 481 else { 482 type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL); 483 } 484 485 486 /* Create and init the internal ACPI object */ 487 488 obj_desc = acpi_ut_create_internal_object (type); 489 if (!obj_desc) { 490 return_ACPI_STATUS (AE_NO_MEMORY); 491 } 492 493 status = acpi_ds_init_object_from_op (walk_state, op, op->opcode, &obj_desc); 494 if (ACPI_FAILURE (status)) { 495 acpi_ut_remove_reference (obj_desc); 496 return_ACPI_STATUS (status); 497 } 498 499 *obj_desc_ptr = obj_desc; 500 501 return_ACPI_STATUS (AE_OK); 502} 503 504 505/***************************************************************************** 506 * 507 * FUNCTION: Acpi_ds_build_internal_package_obj 508 * 509 * PARAMETERS: Op - Parser object to be translated 510 * Obj_desc_ptr - Where the ACPI internal object is returned 511 * 512 * RETURN: Status 513 * 514 * DESCRIPTION: Translate a parser Op package object to the equivalent 515 * namespace object 516 * 517 ****************************************************************************/ 518 519acpi_status 520acpi_ds_build_internal_package_obj ( 521 acpi_walk_state *walk_state, 522 acpi_parse_object *op, 523 acpi_operand_object **obj_desc_ptr) 524{ 525 acpi_parse_object *arg; 526 acpi_operand_object *obj_desc; 527 acpi_status status = AE_OK; 528 529 530 FUNCTION_TRACE ("Ds_build_internal_package_obj"); 531 532 533 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE); 534 *obj_desc_ptr = obj_desc; 535 if (!obj_desc) { 536 return_ACPI_STATUS (AE_NO_MEMORY); 537 } 538 539 if (op->opcode == AML_VAR_PACKAGE_OP) { 540 /* 541 * Variable length package parameters are evaluated JIT 542 */ 543 return_ACPI_STATUS (AE_OK); 544 } 545 546 /* The first argument must be the package length */ 547 548 arg = op->value.arg; 549 obj_desc->package.count = arg->value.integer32; 550 551 /* 552 * Allocate the array of pointers (ptrs to the 553 * individual objects) Add an extra pointer slot so 554 * that the list is always null terminated. 555 */ 556 obj_desc->package.elements = ACPI_MEM_CALLOCATE ( 557 (obj_desc->package.count + 1) * sizeof (void *)); 558 559 if (!obj_desc->package.elements) { 560 acpi_ut_delete_object_desc (obj_desc); 561 return_ACPI_STATUS (AE_NO_MEMORY); 562 } 563 564 obj_desc->package.next_element = obj_desc->package.elements; 565 566 /* 567 * Now init the elements of the package 568 */ 569 arg = arg->next; 570 while (arg) { 571 if (arg->opcode == AML_PACKAGE_OP) { 572 status = acpi_ds_build_internal_package_obj (walk_state, arg, 573 obj_desc->package.next_element); 574 } 575 576 else { 577 status = acpi_ds_build_internal_simple_obj (walk_state, arg, 578 obj_desc->package.next_element); 579 } 580 581 obj_desc->package.next_element++; 582 arg = arg->next; 583 } 584 585 obj_desc->package.flags |= AOPOBJ_DATA_VALID; 586 return_ACPI_STATUS (status); 587} 588 589 590/***************************************************************************** 591 * 592 * FUNCTION: Acpi_ds_build_internal_object 593 * 594 * PARAMETERS: Op - Parser object to be translated 595 * Obj_desc_ptr - Where the ACPI internal object is returned 596 * 597 * RETURN: Status 598 * 599 * DESCRIPTION: Translate a parser Op object to the equivalent namespace 600 * object 601 * 602 ****************************************************************************/ 603 604acpi_status 605acpi_ds_build_internal_object ( 606 acpi_walk_state *walk_state, 607 acpi_parse_object *op, 608 acpi_operand_object **obj_desc_ptr) 609{ 610 acpi_status status; 611 612 613 switch (op->opcode) { 614 case AML_PACKAGE_OP: 615 case AML_VAR_PACKAGE_OP: 616 617 status = acpi_ds_build_internal_package_obj (walk_state, op, obj_desc_ptr); 618 break; 619 620 621 default: 622 623 status = acpi_ds_build_internal_simple_obj (walk_state, op, obj_desc_ptr); 624 break; 625 } 626 627 return (status); 628} 629 630 631/***************************************************************************** 632 * 633 * FUNCTION: Acpi_ds_create_node 634 * 635 * PARAMETERS: Op - Parser object to be translated 636 * Obj_desc_ptr - Where the ACPI internal object is returned 637 * 638 * RETURN: Status 639 * 640 * DESCRIPTION: 641 * 642 ****************************************************************************/ 643 644acpi_status 645acpi_ds_create_node ( 646 acpi_walk_state *walk_state, 647 acpi_namespace_node *node, 648 acpi_parse_object *op) 649{ 650 acpi_status status; 651 acpi_operand_object *obj_desc; 652 653 654 FUNCTION_TRACE_PTR ("Ds_create_node", op); 655 656 657 /* 658 * Because of the execution pass through the non-control-method 659 * parts of the table, we can arrive here twice. Only init 660 * the named object node the first time through 661 */ 662 if (node->object) { 663 return_ACPI_STATUS (AE_OK); 664 } 665 666 if (!op->value.arg) { 667 /* No arguments, there is nothing to do */ 668 669 return_ACPI_STATUS (AE_OK); 670 } 671 672 /* Build an internal object for the argument(s) */ 673 674 status = acpi_ds_build_internal_object (walk_state, op->value.arg, &obj_desc); 675 if (ACPI_FAILURE (status)) { 676 return_ACPI_STATUS (status); 677 } 678 679 /* Re-type the object according to it's argument */ 680 681 node->type = obj_desc->common.type; 682 683 /* Init obj */ 684 685 status = acpi_ns_attach_object (node, obj_desc, (u8) node->type); 686 687 /* Remove local reference to the object */ 688 689 acpi_ut_remove_reference (obj_desc); 690 return_ACPI_STATUS (status); 691} 692 693 694