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