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