1/****************************************************************************** 2 * 3 * Module Name: dswload - Dispatcher namespace load callbacks 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#include "acevents.h" 34 35 36#define _COMPONENT ACPI_DISPATCHER 37 MODULE_NAME ("dswload") 38 39 40/******************************************************************************* 41 * 42 * FUNCTION: Acpi_ds_init_callbacks 43 * 44 * PARAMETERS: Walk_state - Current state of the parse tree walk 45 * Pass_number - 1, 2, or 3 46 * 47 * RETURN: Status 48 * 49 * DESCRIPTION: Init walk state callbacks 50 * 51 ******************************************************************************/ 52 53acpi_status 54acpi_ds_init_callbacks ( 55 acpi_walk_state *walk_state, 56 u32 pass_number) 57{ 58 59 switch (pass_number) { 60 case 1: 61 walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; 62 walk_state->descending_callback = acpi_ds_load1_begin_op; 63 walk_state->ascending_callback = acpi_ds_load1_end_op; 64 break; 65 66 case 2: 67 walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; 68 walk_state->descending_callback = acpi_ds_load2_begin_op; 69 walk_state->ascending_callback = acpi_ds_load2_end_op; 70 break; 71 72 case 3: 73 walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE; 74 walk_state->descending_callback = acpi_ds_exec_begin_op; 75 walk_state->ascending_callback = acpi_ds_exec_end_op; 76 break; 77 78 default: 79 return (AE_BAD_PARAMETER); 80 break; 81 } 82 83 return (AE_OK); 84} 85 86 87/******************************************************************************* 88 * 89 * FUNCTION: Acpi_ds_load1_begin_op 90 * 91 * PARAMETERS: Walk_state - Current state of the parse tree walk 92 * Op - Op that has been just been reached in the 93 * walk; Arguments have not been evaluated yet. 94 * 95 * RETURN: Status 96 * 97 * DESCRIPTION: Descending callback used during the loading of ACPI tables. 98 * 99 ******************************************************************************/ 100 101acpi_status 102acpi_ds_load1_begin_op ( 103 acpi_walk_state *walk_state, 104 acpi_parse_object **out_op) 105{ 106 acpi_parse_object *op; 107 acpi_namespace_node *node; 108 acpi_status status; 109 acpi_object_type8 data_type; 110 NATIVE_CHAR *path; 111 112 113 PROC_NAME ("Ds_load1_begin_op"); 114 115 op = walk_state->op; 116 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); 117 118 119 /* We are only interested in opcodes that have an associated name */ 120 121 if (walk_state->op) { 122 if (!(walk_state->op_info->flags & AML_NAMED)) { 123 *out_op = op; 124 return (AE_OK); 125 } 126 127 /* Check if this object has already been installed in the namespace */ 128 129 if (op->node) { 130 *out_op = op; 131 return (AE_OK); 132 } 133 } 134 135 path = acpi_ps_get_next_namestring (&walk_state->parser_state); 136 137 /* Map the raw opcode into an internal object type */ 138 139 data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode); 140 141 142 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 143 "State=%p Op=%p Type=%x\n", walk_state, op, data_type)); 144 145 146 if (walk_state->opcode == AML_SCOPE_OP) { 147 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 148 "State=%p Op=%p Type=%x\n", walk_state, op, data_type)); 149 } 150 151 /* 152 * Enter the named type into the internal namespace. We enter the name 153 * as we go downward in the parse tree. Any necessary subobjects that involve 154 * arguments to the opcode must be created as we go back up the parse tree later. 155 */ 156 status = acpi_ns_lookup (walk_state->scope_info, path, data_type, 157 IMODE_LOAD_PASS1, NS_NO_UPSEARCH, walk_state, &(node)); 158 159 if (ACPI_FAILURE (status)) { 160 return (status); 161 } 162 163 if (!op) { 164 /* Create a new op */ 165 166 op = acpi_ps_alloc_op (walk_state->opcode); 167 if (!op) { 168 return (AE_NO_MEMORY); 169 } 170 } 171 172 /* Initialize */ 173 174 ((acpi_parse2_object *)op)->name = node->name; 175 176 /* 177 * Put the Node in the "op" object that the parser uses, so we 178 * can get it again quickly when this scope is closed 179 */ 180 op->node = node; 181 acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op); 182 183 *out_op = op; 184 return (status); 185} 186 187 188/******************************************************************************* 189 * 190 * FUNCTION: Acpi_ds_load1_end_op 191 * 192 * PARAMETERS: Walk_state - Current state of the parse tree walk 193 * Op - Op that has been just been completed in the 194 * walk; Arguments have now been evaluated. 195 * 196 * RETURN: Status 197 * 198 * DESCRIPTION: Ascending callback used during the loading of the namespace, 199 * both control methods and everything else. 200 * 201 ******************************************************************************/ 202 203acpi_status 204acpi_ds_load1_end_op ( 205 acpi_walk_state *walk_state) 206{ 207 acpi_parse_object *op; 208 acpi_object_type8 data_type; 209 210 211 PROC_NAME ("Ds_load1_end_op"); 212 213 op = walk_state->op; 214 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); 215 216 217 /* We are only interested in opcodes that have an associated name */ 218 219 if (!(walk_state->op_info->flags & AML_NAMED)) { 220 return (AE_OK); 221 } 222 223 /* Get the type to determine if we should pop the scope */ 224 225 data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); 226 227 if (op->opcode == AML_NAME_OP) { 228 /* For Name opcode, check the argument */ 229 230 if (op->value.arg) { 231 data_type = acpi_ds_map_opcode_to_data_type ( 232 (op->value.arg)->opcode, NULL); 233 ((acpi_namespace_node *)op->node)->type = 234 (u8) data_type; 235 } 236 } 237 238 /* Pop the scope stack */ 239 240 if (acpi_ns_opens_scope (data_type)) { 241 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", 242 acpi_ut_get_type_name (data_type), op)); 243 244 acpi_ds_scope_stack_pop (walk_state); 245 } 246 247 return (AE_OK); 248} 249 250 251/******************************************************************************* 252 * 253 * FUNCTION: Acpi_ds_load2_begin_op 254 * 255 * PARAMETERS: Walk_state - Current state of the parse tree walk 256 * Op - Op that has been just been reached in the 257 * walk; Arguments have not been evaluated yet. 258 * 259 * RETURN: Status 260 * 261 * DESCRIPTION: Descending callback used during the loading of ACPI tables. 262 * 263 ******************************************************************************/ 264 265acpi_status 266acpi_ds_load2_begin_op ( 267 acpi_walk_state *walk_state, 268 acpi_parse_object **out_op) 269{ 270 acpi_parse_object *op; 271 acpi_namespace_node *node; 272 acpi_status status; 273 acpi_object_type8 data_type; 274 NATIVE_CHAR *buffer_ptr; 275 void *original = NULL; 276 277 278 PROC_NAME ("Ds_load2_begin_op"); 279 280 op = walk_state->op; 281 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); 282 283 284 if (op) { 285 /* We only care about Namespace opcodes here */ 286 287 if (!(walk_state->op_info->flags & AML_NSOPCODE) && 288 walk_state->opcode != AML_INT_NAMEPATH_OP) { 289 return (AE_OK); 290 } 291 292 /* TBD: [Restructure] Temp! same code as in psparse */ 293 294 if (!(walk_state->op_info->flags & AML_NAMED)) { 295 return (AE_OK); 296 } 297 298 /* 299 * Get the name we are going to enter or lookup in the namespace 300 */ 301 if (walk_state->opcode == AML_INT_NAMEPATH_OP) { 302 /* For Namepath op, get the path string */ 303 304 buffer_ptr = op->value.string; 305 if (!buffer_ptr) { 306 /* No name, just exit */ 307 308 return (AE_OK); 309 } 310 } 311 else { 312 /* Get name from the op */ 313 314 buffer_ptr = (NATIVE_CHAR *) &((acpi_parse2_object *)op)->name; 315 } 316 } 317 else { 318 buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state); 319 } 320 321 322 /* Map the raw opcode into an internal object type */ 323 324 data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode); 325 326 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 327 "State=%p Op=%p Type=%x\n", walk_state, op, data_type)); 328 329 330 if (walk_state->opcode == AML_FIELD_OP || 331 walk_state->opcode == AML_BANK_FIELD_OP || 332 walk_state->opcode == AML_INDEX_FIELD_OP) { 333 node = NULL; 334 status = AE_OK; 335 } 336 337 else if (walk_state->opcode == AML_INT_NAMEPATH_OP) { 338 /* 339 * The Name_path is an object reference to an existing object. Don't enter the 340 * name into the namespace, but look it up for use later 341 */ 342 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type, 343 IMODE_EXECUTE, NS_SEARCH_PARENT, walk_state, &(node)); 344 } 345 346 else { 347 if (op && op->node) { 348 original = op->node; 349 node = op->node; 350 351 if (acpi_ns_opens_scope (data_type)) { 352 status = acpi_ds_scope_stack_push (node, data_type, walk_state); 353 if (ACPI_FAILURE (status)) { 354 return (status); 355 } 356 357 } 358 return (AE_OK); 359 } 360 361 /* 362 * Enter the named type into the internal namespace. We enter the name 363 * as we go downward in the parse tree. Any necessary subobjects that involve 364 * arguments to the opcode must be created as we go back up the parse tree later. 365 */ 366 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type, 367 IMODE_EXECUTE, NS_NO_UPSEARCH, walk_state, &(node)); 368 } 369 370 if (ACPI_SUCCESS (status)) { 371 if (!op) { 372 /* Create a new op */ 373 374 op = acpi_ps_alloc_op (walk_state->opcode); 375 if (!op) { 376 return (AE_NO_MEMORY); 377 } 378 379 /* Initialize */ 380 381 ((acpi_parse2_object *)op)->name = node->name; 382 *out_op = op; 383 } 384 385 /* 386 * Put the Node in the "op" object that the parser uses, so we 387 * can get it again quickly when this scope is closed 388 */ 389 op->node = node; 390 391 if (original) { 392 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "old %p new %p\n", original, node)); 393 394 if (original != node) { 395 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 396 "Lookup match error: old %p new %p\n", original, node)); 397 } 398 } 399 } 400 401 return (status); 402} 403 404 405/******************************************************************************* 406 * 407 * FUNCTION: Acpi_ds_load2_end_op 408 * 409 * PARAMETERS: Walk_state - Current state of the parse tree walk 410 * Op - Op that has been just been completed in the 411 * walk; Arguments have now been evaluated. 412 * 413 * RETURN: Status 414 * 415 * DESCRIPTION: Ascending callback used during the loading of the namespace, 416 * both control methods and everything else. 417 * 418 ******************************************************************************/ 419 420acpi_status 421acpi_ds_load2_end_op ( 422 acpi_walk_state *walk_state) 423{ 424 acpi_parse_object *op; 425 acpi_status status = AE_OK; 426 acpi_object_type8 data_type; 427 acpi_namespace_node *node; 428 acpi_parse_object *arg; 429 acpi_namespace_node *new_node; 430 u32 i; 431 432 433 PROC_NAME ("Ds_load2_end_op"); 434 435 op = walk_state->op; 436 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); 437 438 439 /* Only interested in opcodes that have namespace objects */ 440 441 if (!(walk_state->op_info->flags & AML_NSOBJECT)) { 442 return (AE_OK); 443 } 444 445 if (op->opcode == AML_SCOPE_OP) { 446 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 447 "Ending scope Op=%p State=%p\n", op, walk_state)); 448 449 if (((acpi_parse2_object *)op)->name == -1) { 450 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unnamed scope! Op=%p State=%p\n", 451 op, walk_state)); 452 return (AE_OK); 453 } 454 } 455 456 457 data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); 458 459 /* 460 * Get the Node/name from the earlier lookup 461 * (It was saved in the *op structure) 462 */ 463 node = op->node; 464 465 /* 466 * Put the Node on the object stack (Contains the ACPI Name of 467 * this object) 468 */ 469 walk_state->operands[0] = (void *) node; 470 walk_state->num_operands = 1; 471 472 /* Pop the scope stack */ 473 474 if (acpi_ns_opens_scope (data_type)) { 475 476 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", 477 acpi_ut_get_type_name (data_type), op)); 478 acpi_ds_scope_stack_pop (walk_state); 479 } 480 481 /* 482 * Named operations are as follows: 483 * 484 * AML_ALIAS 485 * AML_BANKFIELD 486 * AML_CREATEBITFIELD 487 * AML_CREATEBYTEFIELD 488 * AML_CREATEDWORDFIELD 489 * AML_CREATEFIELD 490 * AML_CREATEQWORDFIELD 491 * AML_CREATEWORDFIELD 492 * AML_DATA_REGION 493 * AML_DEVICE 494 * AML_EVENT 495 * AML_FIELD 496 * AML_INDEXFIELD 497 * AML_METHOD 498 * AML_METHODCALL 499 * AML_MUTEX 500 * AML_NAME 501 * AML_NAMEDFIELD 502 * AML_OPREGION 503 * AML_POWERRES 504 * AML_PROCESSOR 505 * AML_SCOPE 506 * AML_THERMALZONE 507 */ 508 509 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 510 "Create-Load [%s] State=%p Op=%p Named_obj=%p\n", 511 acpi_ps_get_opcode_name (op->opcode), walk_state, op, node)); 512 513 /* Decode the opcode */ 514 515 arg = op->value.arg; 516 517 switch (walk_state->op_info->type) { 518 case AML_TYPE_CREATE_FIELD: 519 520 /* 521 * Create the field object, but the field buffer and index must 522 * be evaluated later during the execution phase 523 */ 524 status = acpi_ds_create_buffer_field (op, walk_state); 525 break; 526 527 528 case AML_TYPE_NAMED_FIELD: 529 530 arg = op->value.arg; 531 switch (op->opcode) { 532 case AML_INDEX_FIELD_OP: 533 534 status = acpi_ds_create_index_field (op, (acpi_handle) arg->node, 535 walk_state); 536 break; 537 538 539 case AML_BANK_FIELD_OP: 540 541 status = acpi_ds_create_bank_field (op, arg->node, walk_state); 542 break; 543 544 545 case AML_FIELD_OP: 546 547 status = acpi_ds_create_field (op, arg->node, walk_state); 548 break; 549 } 550 break; 551 552 553 case AML_TYPE_NAMED_SIMPLE: 554 555 status = acpi_ds_create_operands (walk_state, arg); 556 if (ACPI_FAILURE (status)) { 557 goto cleanup; 558 } 559 560 switch (op->opcode) { 561 case AML_PROCESSOR_OP: 562 563 status = acpi_ex_create_processor (walk_state); 564 break; 565 566 567 case AML_POWER_RES_OP: 568 569 status = acpi_ex_create_power_resource (walk_state); 570 break; 571 572 573 case AML_MUTEX_OP: 574 575 status = acpi_ex_create_mutex (walk_state); 576 break; 577 578 579 case AML_EVENT_OP: 580 581 status = acpi_ex_create_event (walk_state); 582 break; 583 584 585 case AML_DATA_REGION_OP: 586 587 status = acpi_ex_create_table_region (walk_state); 588 break; 589 590 case AML_ALIAS_OP: 591 592 status = acpi_ex_create_alias (walk_state); 593 break; 594 595 default: 596 /* Unknown opcode */ 597 598 status = AE_OK; 599 goto cleanup; 600 break; 601 } 602 603 /* Delete operands */ 604 605 for (i = 1; i < walk_state->num_operands; i++) { 606 acpi_ut_remove_reference (walk_state->operands[i]); 607 walk_state->operands[i] = NULL; 608 } 609 610 break; 611 612 613 case AML_TYPE_NAMED_COMPLEX: 614 615 switch (op->opcode) { 616 case AML_METHOD_OP: 617 /* 618 * Method_op Pkg_length Names_string Method_flags Term_list 619 */ 620 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 621 "LOADING-Method: State=%p Op=%p Named_obj=%p\n", 622 walk_state, op, node)); 623 624 if (!node->object) { 625 status = acpi_ds_create_operands (walk_state, arg); 626 if (ACPI_FAILURE (status)) { 627 goto cleanup; 628 } 629 630 status = acpi_ex_create_method (((acpi_parse2_object *) op)->data, 631 ((acpi_parse2_object *) op)->length, 632 walk_state); 633 } 634 break; 635 636 637 case AML_REGION_OP: 638 /* 639 * The Op_region is not fully parsed at this time. Only valid argument is the Space_id. 640 * (We must save the address of the AML of the address and length operands) 641 */ 642 status = acpi_ex_create_region (((acpi_parse2_object *) op)->data, 643 ((acpi_parse2_object *) op)->length, 644 (ACPI_ADR_SPACE_TYPE) arg->value.integer, walk_state); 645 break; 646 647 648 case AML_NAME_OP: 649 650 status = acpi_ds_create_node (walk_state, node, op); 651 break; 652 } 653 break; 654 655 656 case AML_CLASS_INTERNAL: 657 658 /* case AML_INT_NAMEPATH_OP: */ 659 break; 660 661 662 case AML_CLASS_METHOD_CALL: 663 664 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 665 "RESOLVING-Method_call: State=%p Op=%p Named_obj=%p\n", 666 walk_state, op, node)); 667 668 /* 669 * Lookup the method name and save the Node 670 */ 671 status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, 672 ACPI_TYPE_ANY, IMODE_LOAD_PASS2, 673 NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, 674 walk_state, &(new_node)); 675 if (ACPI_SUCCESS (status)) { 676 /* TBD: has name already been resolved by here ??*/ 677 678 /* TBD: [Restructure] Make sure that what we found is indeed a method! */ 679 /* We didn't search for a method on purpose, to see if the name would resolve! */ 680 681 /* We could put the returned object (Node) on the object stack for later, but 682 * for now, we will put it in the "op" object that the parser uses, so we 683 * can get it again at the end of this scope 684 */ 685 op->node = new_node; 686 } 687 688 break; 689 690 691 default: 692 break; 693 } 694 695 696cleanup: 697 698 /* Remove the Node pushed at the very beginning */ 699 700 walk_state->operands[0] = NULL; 701 walk_state->num_operands = 0; 702 return (status); 703} 704 705 706