1 /****************************************************************************** 2 * 3 * Module Name: dsobject - Dispatcher object management routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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 <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 #include "acdispat.h" 49 #include "acnamesp.h" 50 #include "acinterp.h" 51 52 #define _COMPONENT ACPI_DISPATCHER 53 ACPI_MODULE_NAME("dsobject") 54 55 #ifndef ACPI_NO_METHOD_EXECUTION 56 /******************************************************************************* 57 * 58 * FUNCTION: acpi_ds_build_internal_object 59 * 60 * PARAMETERS: walk_state - Current walk state 61 * op - Parser object to be translated 62 * obj_desc_ptr - Where the ACPI internal object is returned 63 * 64 * RETURN: Status 65 * 66 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object 67 * Simple objects are any objects other than a package object! 68 * 69 ******************************************************************************/ 70 acpi_status 71 acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, 72 union acpi_parse_object *op, 73 union acpi_operand_object **obj_desc_ptr) 74 { 75 union acpi_operand_object *obj_desc; 76 acpi_status status; 77 78 ACPI_FUNCTION_TRACE(ds_build_internal_object); 79 80 *obj_desc_ptr = NULL; 81 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { 82 /* 83 * This is a named object reference. If this name was 84 * previously looked up in the namespace, it was stored in 85 * this op. Otherwise, go ahead and look it up now 86 */ 87 if (!op->common.node) { 88 89 /* Check if we are resolving a named reference within a package */ 90 91 if ((op->common.parent->common.aml_opcode == 92 AML_PACKAGE_OP) 93 || (op->common.parent->common.aml_opcode == 94 AML_VARIABLE_PACKAGE_OP)) { 95 /* 96 * We won't resolve package elements here, we will do this 97 * after all ACPI tables are loaded into the namespace. This 98 * behavior supports both forward references to named objects 99 * and external references to objects in other tables. 100 */ 101 goto create_new_object; 102 } else { 103 status = acpi_ns_lookup(walk_state->scope_info, 104 op->common.value.string, 105 ACPI_TYPE_ANY, 106 ACPI_IMODE_EXECUTE, 107 ACPI_NS_SEARCH_PARENT | 108 ACPI_NS_DONT_OPEN_SCOPE, 109 NULL, 110 ACPI_CAST_INDIRECT_PTR 111 (struct 112 acpi_namespace_node, 113 &(op->common.node))); 114 if (ACPI_FAILURE(status)) { 115 ACPI_ERROR_NAMESPACE(op->common.value. 116 string, status); 117 return_ACPI_STATUS(status); 118 } 119 } 120 } 121 } 122 123 create_new_object: 124 125 /* Create and init a new internal ACPI object */ 126 127 obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info 128 (op->common.aml_opcode))-> 129 object_type); 130 if (!obj_desc) { 131 return_ACPI_STATUS(AE_NO_MEMORY); 132 } 133 134 status = 135 acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode, 136 &obj_desc); 137 if (ACPI_FAILURE(status)) { 138 acpi_ut_remove_reference(obj_desc); 139 return_ACPI_STATUS(status); 140 } 141 142 /* 143 * Handling for unresolved package reference elements. 144 * These are elements that are namepaths. 145 */ 146 if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || 147 (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) { 148 obj_desc->reference.resolved = TRUE; 149 150 if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP) && 151 !obj_desc->reference.node) { 152 /* 153 * Name was unresolved above. 154 * Get the prefix node for later lookup 155 */ 156 obj_desc->reference.node = 157 walk_state->scope_info->scope.node; 158 obj_desc->reference.aml = op->common.aml; 159 obj_desc->reference.resolved = FALSE; 160 } 161 } 162 163 *obj_desc_ptr = obj_desc; 164 return_ACPI_STATUS(status); 165 } 166 167 /******************************************************************************* 168 * 169 * FUNCTION: acpi_ds_build_internal_buffer_obj 170 * 171 * PARAMETERS: walk_state - Current walk state 172 * op - Parser object to be translated 173 * buffer_length - Length of the buffer 174 * obj_desc_ptr - Where the ACPI internal object is returned 175 * 176 * RETURN: Status 177 * 178 * DESCRIPTION: Translate a parser Op package object to the equivalent 179 * namespace object 180 * 181 ******************************************************************************/ 182 183 acpi_status 184 acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, 185 union acpi_parse_object *op, 186 u32 buffer_length, 187 union acpi_operand_object **obj_desc_ptr) 188 { 189 union acpi_parse_object *arg; 190 union acpi_operand_object *obj_desc; 191 union acpi_parse_object *byte_list; 192 u32 byte_list_length = 0; 193 194 ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj); 195 196 /* 197 * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". 198 * The buffer object already exists (from the NS node), otherwise it must 199 * be created. 200 */ 201 obj_desc = *obj_desc_ptr; 202 if (!obj_desc) { 203 204 /* Create a new buffer object */ 205 206 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); 207 *obj_desc_ptr = obj_desc; 208 if (!obj_desc) { 209 return_ACPI_STATUS(AE_NO_MEMORY); 210 } 211 } 212 213 /* 214 * Second arg is the buffer data (optional) byte_list can be either 215 * individual bytes or a string initializer. In either case, a 216 * byte_list appears in the AML. 217 */ 218 arg = op->common.value.arg; /* skip first arg */ 219 220 byte_list = arg->named.next; 221 if (byte_list) { 222 if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { 223 ACPI_ERROR((AE_INFO, 224 "Expecting bytelist, found AML opcode 0x%X in op %p", 225 byte_list->common.aml_opcode, byte_list)); 226 227 acpi_ut_remove_reference(obj_desc); 228 return (AE_TYPE); 229 } 230 231 byte_list_length = (u32) byte_list->common.value.integer; 232 } 233 234 /* 235 * The buffer length (number of bytes) will be the larger of: 236 * 1) The specified buffer length and 237 * 2) The length of the initializer byte list 238 */ 239 obj_desc->buffer.length = buffer_length; 240 if (byte_list_length > buffer_length) { 241 obj_desc->buffer.length = byte_list_length; 242 } 243 244 /* Allocate the buffer */ 245 246 if (obj_desc->buffer.length == 0) { 247 obj_desc->buffer.pointer = NULL; 248 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 249 "Buffer defined with zero length in AML, creating\n")); 250 } else { 251 obj_desc->buffer.pointer = 252 ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length); 253 if (!obj_desc->buffer.pointer) { 254 acpi_ut_delete_object_desc(obj_desc); 255 return_ACPI_STATUS(AE_NO_MEMORY); 256 } 257 258 /* Initialize buffer from the byte_list (if present) */ 259 260 if (byte_list) { 261 memcpy(obj_desc->buffer.pointer, byte_list->named.data, 262 byte_list_length); 263 } 264 } 265 266 obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; 267 op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); 268 return_ACPI_STATUS(AE_OK); 269 } 270 271 /******************************************************************************* 272 * 273 * FUNCTION: acpi_ds_create_node 274 * 275 * PARAMETERS: walk_state - Current walk state 276 * node - NS Node to be initialized 277 * op - Parser object to be translated 278 * 279 * RETURN: Status 280 * 281 * DESCRIPTION: Create the object to be associated with a namespace node 282 * 283 ******************************************************************************/ 284 285 acpi_status 286 acpi_ds_create_node(struct acpi_walk_state *walk_state, 287 struct acpi_namespace_node *node, 288 union acpi_parse_object *op) 289 { 290 acpi_status status; 291 union acpi_operand_object *obj_desc; 292 293 ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); 294 295 /* 296 * Because of the execution pass through the non-control-method 297 * parts of the table, we can arrive here twice. Only init 298 * the named object node the first time through 299 */ 300 if (acpi_ns_get_attached_object(node)) { 301 return_ACPI_STATUS(AE_OK); 302 } 303 304 if (!op->common.value.arg) { 305 306 /* No arguments, there is nothing to do */ 307 308 return_ACPI_STATUS(AE_OK); 309 } 310 311 /* Build an internal object for the argument(s) */ 312 313 status = 314 acpi_ds_build_internal_object(walk_state, op->common.value.arg, 315 &obj_desc); 316 if (ACPI_FAILURE(status)) { 317 return_ACPI_STATUS(status); 318 } 319 320 /* Re-type the object according to its argument */ 321 322 node->type = obj_desc->common.type; 323 324 /* Attach obj to node */ 325 326 status = acpi_ns_attach_object(node, obj_desc, node->type); 327 328 /* Remove local reference to the object */ 329 330 acpi_ut_remove_reference(obj_desc); 331 return_ACPI_STATUS(status); 332 } 333 334 #endif /* ACPI_NO_METHOD_EXECUTION */ 335 336 /******************************************************************************* 337 * 338 * FUNCTION: acpi_ds_init_object_from_op 339 * 340 * PARAMETERS: walk_state - Current walk state 341 * op - Parser op used to init the internal object 342 * opcode - AML opcode associated with the object 343 * ret_obj_desc - Namespace object to be initialized 344 * 345 * RETURN: Status 346 * 347 * DESCRIPTION: Initialize a namespace object from a parser Op and its 348 * associated arguments. The namespace object is a more compact 349 * representation of the Op and its arguments. 350 * 351 ******************************************************************************/ 352 353 acpi_status 354 acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, 355 union acpi_parse_object *op, 356 u16 opcode, 357 union acpi_operand_object **ret_obj_desc) 358 { 359 const struct acpi_opcode_info *op_info; 360 union acpi_operand_object *obj_desc; 361 acpi_status status = AE_OK; 362 363 ACPI_FUNCTION_TRACE(ds_init_object_from_op); 364 365 obj_desc = *ret_obj_desc; 366 op_info = acpi_ps_get_opcode_info(opcode); 367 if (op_info->class == AML_CLASS_UNKNOWN) { 368 369 /* Unknown opcode */ 370 371 return_ACPI_STATUS(AE_TYPE); 372 } 373 374 /* Perform per-object initialization */ 375 376 switch (obj_desc->common.type) { 377 case ACPI_TYPE_BUFFER: 378 /* 379 * Defer evaluation of Buffer term_arg operand 380 */ 381 obj_desc->buffer.node = 382 ACPI_CAST_PTR(struct acpi_namespace_node, 383 walk_state->operands[0]); 384 obj_desc->buffer.aml_start = op->named.data; 385 obj_desc->buffer.aml_length = op->named.length; 386 break; 387 388 case ACPI_TYPE_PACKAGE: 389 /* 390 * Defer evaluation of Package term_arg operand and all 391 * package elements. (01/2017): We defer the element 392 * resolution to allow forward references from the package 393 * in order to provide compatibility with other ACPI 394 * implementations. 395 */ 396 obj_desc->package.node = 397 ACPI_CAST_PTR(struct acpi_namespace_node, 398 walk_state->operands[0]); 399 400 if (!op->named.data) { 401 return_ACPI_STATUS(AE_OK); 402 } 403 404 obj_desc->package.aml_start = op->named.data; 405 obj_desc->package.aml_length = op->named.length; 406 break; 407 408 case ACPI_TYPE_INTEGER: 409 410 switch (op_info->type) { 411 case AML_TYPE_CONSTANT: 412 /* 413 * Resolve AML Constants here - AND ONLY HERE! 414 * All constants are integers. 415 * We mark the integer with a flag that indicates that it started 416 * life as a constant -- so that stores to constants will perform 417 * as expected (noop). zero_op is used as a placeholder for optional 418 * target operands. 419 */ 420 obj_desc->common.flags = AOPOBJ_AML_CONSTANT; 421 422 switch (opcode) { 423 case AML_ZERO_OP: 424 425 obj_desc->integer.value = 0; 426 break; 427 428 case AML_ONE_OP: 429 430 obj_desc->integer.value = 1; 431 break; 432 433 case AML_ONES_OP: 434 435 obj_desc->integer.value = ACPI_UINT64_MAX; 436 437 /* Truncate value if we are executing from a 32-bit ACPI table */ 438 439 #ifndef ACPI_NO_METHOD_EXECUTION 440 (void)acpi_ex_truncate_for32bit_table(obj_desc); 441 #endif 442 break; 443 444 case AML_REVISION_OP: 445 446 obj_desc->integer.value = ACPI_CA_VERSION; 447 break; 448 449 default: 450 451 ACPI_ERROR((AE_INFO, 452 "Unknown constant opcode 0x%X", 453 opcode)); 454 status = AE_AML_OPERAND_TYPE; 455 break; 456 } 457 break; 458 459 case AML_TYPE_LITERAL: 460 461 obj_desc->integer.value = op->common.value.integer; 462 463 #ifndef ACPI_NO_METHOD_EXECUTION 464 if (acpi_ex_truncate_for32bit_table(obj_desc)) { 465 466 /* Warn if we found a 64-bit constant in a 32-bit table */ 467 468 ACPI_WARNING((AE_INFO, 469 "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X", 470 ACPI_FORMAT_UINT64(op->common. 471 value.integer), 472 (u32)obj_desc->integer.value)); 473 } 474 #endif 475 break; 476 477 default: 478 479 ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X", 480 op_info->type)); 481 status = AE_AML_OPERAND_TYPE; 482 break; 483 } 484 break; 485 486 case ACPI_TYPE_STRING: 487 488 obj_desc->string.pointer = op->common.value.string; 489 obj_desc->string.length = (u32)strlen(op->common.value.string); 490 491 /* 492 * The string is contained in the ACPI table, don't ever try 493 * to delete it 494 */ 495 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; 496 break; 497 498 case ACPI_TYPE_METHOD: 499 break; 500 501 case ACPI_TYPE_LOCAL_REFERENCE: 502 503 switch (op_info->type) { 504 case AML_TYPE_LOCAL_VARIABLE: 505 506 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */ 507 508 obj_desc->reference.value = 509 ((u32)opcode) - AML_FIRST_LOCAL_OP; 510 obj_desc->reference.class = ACPI_REFCLASS_LOCAL; 511 512 #ifndef ACPI_NO_METHOD_EXECUTION 513 status = 514 acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, 515 obj_desc->reference. 516 value, walk_state, 517 ACPI_CAST_INDIRECT_PTR 518 (struct 519 acpi_namespace_node, 520 &obj_desc->reference. 521 object)); 522 #endif 523 break; 524 525 case AML_TYPE_METHOD_ARGUMENT: 526 527 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */ 528 529 obj_desc->reference.value = 530 ((u32)opcode) - AML_FIRST_ARG_OP; 531 obj_desc->reference.class = ACPI_REFCLASS_ARG; 532 533 #ifndef ACPI_NO_METHOD_EXECUTION 534 status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, 535 obj_desc-> 536 reference.value, 537 walk_state, 538 ACPI_CAST_INDIRECT_PTR 539 (struct 540 acpi_namespace_node, 541 &obj_desc-> 542 reference. 543 object)); 544 #endif 545 break; 546 547 default: /* Object name or Debug object */ 548 549 switch (op->common.aml_opcode) { 550 case AML_INT_NAMEPATH_OP: 551 552 /* Node was saved in Op */ 553 554 obj_desc->reference.node = op->common.node; 555 obj_desc->reference.class = ACPI_REFCLASS_NAME; 556 if (op->common.node) { 557 obj_desc->reference.object = 558 op->common.node->object; 559 } 560 break; 561 562 case AML_DEBUG_OP: 563 564 obj_desc->reference.class = ACPI_REFCLASS_DEBUG; 565 break; 566 567 default: 568 569 ACPI_ERROR((AE_INFO, 570 "Unimplemented reference type for AML opcode: 0x%4.4X", 571 opcode)); 572 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 573 } 574 break; 575 } 576 break; 577 578 default: 579 580 ACPI_ERROR((AE_INFO, "Unimplemented data type: 0x%X", 581 obj_desc->common.type)); 582 583 status = AE_AML_OPERAND_TYPE; 584 break; 585 } 586 587 return_ACPI_STATUS(status); 588 } 589