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