1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: dspkginit - Completion of deferred package initialization 5 * 6 * Copyright (C) 2000 - 2023, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "acnamesp.h" 13 #include "amlcode.h" 14 #include "acdispat.h" 15 #include "acinterp.h" 16 #include "acparser.h" 17 18 #define _COMPONENT ACPI_NAMESPACE 19 ACPI_MODULE_NAME("dspkginit") 20 21 /* Local prototypes */ 22 static void 23 acpi_ds_resolve_package_element(union acpi_operand_object **element); 24 25 /******************************************************************************* 26 * 27 * FUNCTION: acpi_ds_build_internal_package_obj 28 * 29 * PARAMETERS: walk_state - Current walk state 30 * op - Parser object to be translated 31 * element_count - Number of elements in the package - this is 32 * the num_elements argument to Package() 33 * obj_desc_ptr - Where the ACPI internal object is returned 34 * 35 * RETURN: Status 36 * 37 * DESCRIPTION: Translate a parser Op package object to the equivalent 38 * namespace object 39 * 40 * NOTE: The number of elements in the package will be always be the num_elements 41 * count, regardless of the number of elements in the package list. If 42 * num_elements is smaller, only that many package list elements are used. 43 * if num_elements is larger, the Package object is padded out with 44 * objects of type Uninitialized (as per ACPI spec.) 45 * 46 * Even though the ASL compilers do not allow num_elements to be smaller 47 * than the Package list length (for the fixed length package opcode), some 48 * BIOS code modifies the AML on the fly to adjust the num_elements, and 49 * this code compensates for that. This also provides compatibility with 50 * other AML interpreters. 51 * 52 ******************************************************************************/ 53 54 acpi_status 55 acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, 56 union acpi_parse_object *op, 57 u32 element_count, 58 union acpi_operand_object **obj_desc_ptr) 59 { 60 union acpi_parse_object *arg; 61 union acpi_parse_object *parent; 62 union acpi_operand_object *obj_desc = NULL; 63 acpi_status status = AE_OK; 64 u8 module_level_code = FALSE; 65 u16 reference_count; 66 u32 index; 67 u32 i; 68 69 ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); 70 71 /* Check if we are executing module level code */ 72 73 if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) { 74 module_level_code = TRUE; 75 } 76 77 /* Find the parent of a possibly nested package */ 78 79 parent = op->common.parent; 80 while ((parent->common.aml_opcode == AML_PACKAGE_OP) || 81 (parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) { 82 parent = parent->common.parent; 83 } 84 85 /* 86 * If we are evaluating a Named package object of the form: 87 * Name (xxxx, Package) 88 * the package object already exists, otherwise it must be created. 89 */ 90 obj_desc = *obj_desc_ptr; 91 if (!obj_desc) { 92 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); 93 *obj_desc_ptr = obj_desc; 94 if (!obj_desc) { 95 return_ACPI_STATUS(AE_NO_MEMORY); 96 } 97 98 obj_desc->package.node = parent->common.node; 99 } 100 101 if (obj_desc->package.flags & AOPOBJ_DATA_VALID) { /* Just in case */ 102 return_ACPI_STATUS(AE_OK); 103 } 104 105 /* 106 * Allocate the element array (array of pointers to the individual 107 * objects) if necessary. the count is based on the num_elements 108 * parameter. Add an extra pointer slot so that the list is always 109 * null terminated. 110 */ 111 if (!obj_desc->package.elements) { 112 obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) 113 element_count 114 + 115 1) * 116 sizeof(void 117 *)); 118 119 if (!obj_desc->package.elements) { 120 acpi_ut_delete_object_desc(obj_desc); 121 return_ACPI_STATUS(AE_NO_MEMORY); 122 } 123 124 obj_desc->package.count = element_count; 125 } 126 127 /* First arg is element count. Second arg begins the initializer list */ 128 129 arg = op->common.value.arg; 130 arg = arg->common.next; 131 132 /* 133 * If we are executing module-level code, we will defer the 134 * full resolution of the package elements in order to support 135 * forward references from the elements. This provides 136 * compatibility with other ACPI implementations. 137 */ 138 if (module_level_code) { 139 obj_desc->package.aml_start = walk_state->aml; 140 obj_desc->package.aml_length = 0; 141 142 ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE, 143 "%s: Deferring resolution of Package elements\n", 144 ACPI_GET_FUNCTION_NAME)); 145 } 146 147 /* 148 * Initialize the elements of the package, up to the num_elements count. 149 * Package is automatically padded with uninitialized (NULL) elements 150 * if num_elements is greater than the package list length. Likewise, 151 * Package is truncated if num_elements is less than the list length. 152 */ 153 for (i = 0; arg && (i < element_count); i++) { 154 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { 155 if (!arg->common.node) { 156 /* 157 * This is the case where an expression has returned a value. 158 * The use of expressions (term_args) within individual 159 * package elements is not supported by the AML interpreter, 160 * even though the ASL grammar supports it. Example: 161 * 162 * Name (INT1, 0x1234) 163 * 164 * Name (PKG3, Package () { 165 * Add (INT1, 0xAAAA0000) 166 * }) 167 * 168 * 1) No known AML interpreter supports this type of construct 169 * 2) This fixes a fault if the construct is encountered 170 */ 171 ACPI_EXCEPTION((AE_INFO, AE_SUPPORT, 172 "Expressions within package elements are not supported")); 173 174 /* Cleanup the return object, it is not needed */ 175 176 acpi_ut_remove_reference(walk_state->results-> 177 results.obj_desc[0]); 178 return_ACPI_STATUS(AE_SUPPORT); 179 } 180 181 if (arg->common.node->type == ACPI_TYPE_METHOD) { 182 /* 183 * A method reference "looks" to the parser to be a method 184 * invocation, so we special case it here 185 */ 186 arg->common.aml_opcode = AML_INT_NAMEPATH_OP; 187 status = 188 acpi_ds_build_internal_object(walk_state, 189 arg, 190 &obj_desc-> 191 package. 192 elements[i]); 193 } else { 194 /* This package element is already built, just get it */ 195 196 obj_desc->package.elements[i] = 197 ACPI_CAST_PTR(union acpi_operand_object, 198 arg->common.node); 199 } 200 } else { 201 status = 202 acpi_ds_build_internal_object(walk_state, arg, 203 &obj_desc->package. 204 elements[i]); 205 if (status == AE_NOT_FOUND) { 206 ACPI_ERROR((AE_INFO, "%-48s", 207 "****DS namepath not found")); 208 } 209 210 if (!module_level_code) { 211 /* 212 * Initialize this package element. This function handles the 213 * resolution of named references within the package. 214 * Forward references from module-level code are deferred 215 * until all ACPI tables are loaded. 216 */ 217 acpi_ds_init_package_element(0, 218 obj_desc->package. 219 elements[i], NULL, 220 &obj_desc->package. 221 elements[i]); 222 } 223 } 224 225 if (*obj_desc_ptr) { 226 227 /* Existing package, get existing reference count */ 228 229 reference_count = 230 (*obj_desc_ptr)->common.reference_count; 231 if (reference_count > 1) { 232 233 /* Make new element ref count match original ref count */ 234 /* TBD: Probably need an acpi_ut_add_references function */ 235 236 for (index = 0; 237 index < ((u32)reference_count - 1); 238 index++) { 239 acpi_ut_add_reference((obj_desc-> 240 package. 241 elements[i])); 242 } 243 } 244 } 245 246 arg = arg->common.next; 247 } 248 249 /* Check for match between num_elements and actual length of package_list */ 250 251 if (arg) { 252 /* 253 * num_elements was exhausted, but there are remaining elements in 254 * the package_list. Truncate the package to num_elements. 255 * 256 * Note: technically, this is an error, from ACPI spec: "It is an 257 * error for NumElements to be less than the number of elements in 258 * the PackageList". However, we just print a message and no 259 * exception is returned. This provides compatibility with other 260 * ACPI implementations. Some firmware implementations will alter 261 * the num_elements on the fly, possibly creating this type of 262 * ill-formed package object. 263 */ 264 while (arg) { 265 /* 266 * We must delete any package elements that were created earlier 267 * and are not going to be used because of the package truncation. 268 */ 269 if (arg->common.node) { 270 acpi_ut_remove_reference(ACPI_CAST_PTR 271 (union 272 acpi_operand_object, 273 arg->common.node)); 274 arg->common.node = NULL; 275 } 276 277 /* Find out how many elements there really are */ 278 279 i++; 280 arg = arg->common.next; 281 } 282 283 ACPI_INFO(("Actual Package length (%u) is larger than " 284 "NumElements field (%u), truncated", 285 i, element_count)); 286 } else if (i < element_count) { 287 /* 288 * Arg list (elements) was exhausted, but we did not reach 289 * num_elements count. 290 * 291 * Note: this is not an error, the package is padded out 292 * with NULLs as per the ACPI specification. 293 */ 294 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, 295 "%s: Package List length (%u) smaller than NumElements " 296 "count (%u), padded with null elements\n", 297 ACPI_GET_FUNCTION_NAME, i, 298 element_count)); 299 } 300 301 /* Module-level packages will be resolved later */ 302 303 if (!module_level_code) { 304 obj_desc->package.flags |= AOPOBJ_DATA_VALID; 305 } 306 307 op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); 308 return_ACPI_STATUS(status); 309 } 310 311 /******************************************************************************* 312 * 313 * FUNCTION: acpi_ds_init_package_element 314 * 315 * PARAMETERS: acpi_pkg_callback 316 * 317 * RETURN: Status 318 * 319 * DESCRIPTION: Resolve a named reference element within a package object 320 * 321 ******************************************************************************/ 322 323 acpi_status 324 acpi_ds_init_package_element(u8 object_type, 325 union acpi_operand_object *source_object, 326 union acpi_generic_state *state, void *context) 327 { 328 union acpi_operand_object **element_ptr; 329 330 ACPI_FUNCTION_TRACE(ds_init_package_element); 331 332 if (!source_object) { 333 return_ACPI_STATUS(AE_OK); 334 } 335 336 /* 337 * The following code is a bit of a hack to workaround a (current) 338 * limitation of the acpi_pkg_callback interface. We need a pointer 339 * to the location within the element array because a new object 340 * may be created and stored there. 341 */ 342 if (context) { 343 344 /* A direct call was made to this function */ 345 346 element_ptr = (union acpi_operand_object **)context; 347 } else { 348 /* Call came from acpi_ut_walk_package_tree */ 349 350 element_ptr = state->pkg.this_target_obj; 351 } 352 353 /* We are only interested in reference objects/elements */ 354 355 if (source_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) { 356 357 /* Attempt to resolve the (named) reference to a namespace node */ 358 359 acpi_ds_resolve_package_element(element_ptr); 360 } else if (source_object->common.type == ACPI_TYPE_PACKAGE) { 361 source_object->package.flags |= AOPOBJ_DATA_VALID; 362 } 363 364 return_ACPI_STATUS(AE_OK); 365 } 366 367 /******************************************************************************* 368 * 369 * FUNCTION: acpi_ds_resolve_package_element 370 * 371 * PARAMETERS: element_ptr - Pointer to a reference object 372 * 373 * RETURN: Possible new element is stored to the indirect element_ptr 374 * 375 * DESCRIPTION: Resolve a package element that is a reference to a named 376 * object. 377 * 378 ******************************************************************************/ 379 380 static void 381 acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr) 382 { 383 acpi_status status; 384 acpi_status status2; 385 union acpi_generic_state scope_info; 386 union acpi_operand_object *element = *element_ptr; 387 struct acpi_namespace_node *resolved_node; 388 struct acpi_namespace_node *original_node; 389 char *external_path = ""; 390 acpi_object_type type; 391 392 ACPI_FUNCTION_TRACE(ds_resolve_package_element); 393 394 /* Check if reference element is already resolved */ 395 396 if (element->reference.resolved) { 397 ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE, 398 "%s: Package element is already resolved\n", 399 ACPI_GET_FUNCTION_NAME)); 400 401 return_VOID; 402 } 403 404 /* Element must be a reference object of correct type */ 405 406 scope_info.scope.node = element->reference.node; /* Prefix node */ 407 408 status = acpi_ns_lookup(&scope_info, (char *)element->reference.aml, 409 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 410 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 411 NULL, &resolved_node); 412 if (ACPI_FAILURE(status)) { 413 if ((status == AE_NOT_FOUND) 414 && acpi_gbl_ignore_package_resolution_errors) { 415 /* 416 * Optionally be silent about the NOT_FOUND case for the referenced 417 * name. Although this is potentially a serious problem, 418 * it can generate a lot of noise/errors on platforms whose 419 * firmware carries around a bunch of unused Package objects. 420 * To disable these errors, set this global to TRUE: 421 * acpi_gbl_ignore_package_resolution_errors 422 * 423 * If the AML actually tries to use such a package, the unresolved 424 * element(s) will be replaced with NULL elements. 425 */ 426 427 /* Referenced name not found, set the element to NULL */ 428 429 acpi_ut_remove_reference(*element_ptr); 430 *element_ptr = NULL; 431 return_VOID; 432 } 433 434 status2 = acpi_ns_externalize_name(ACPI_UINT32_MAX, 435 (char *)element->reference. 436 aml, NULL, &external_path); 437 438 ACPI_EXCEPTION((AE_INFO, status, 439 "While resolving a named reference package element - %s", 440 external_path)); 441 if (ACPI_SUCCESS(status2)) { 442 ACPI_FREE(external_path); 443 } 444 445 /* Could not resolve name, set the element to NULL */ 446 447 acpi_ut_remove_reference(*element_ptr); 448 *element_ptr = NULL; 449 return_VOID; 450 } else if (resolved_node->type == ACPI_TYPE_ANY) { 451 452 /* Named reference not resolved, return a NULL package element */ 453 454 ACPI_ERROR((AE_INFO, 455 "Could not resolve named package element [%4.4s] in [%4.4s]", 456 resolved_node->name.ascii, 457 scope_info.scope.node->name.ascii)); 458 *element_ptr = NULL; 459 return_VOID; 460 } 461 462 /* 463 * Special handling for Alias objects. We need resolved_node to point 464 * to the Alias target. This effectively "resolves" the alias. 465 */ 466 if (resolved_node->type == ACPI_TYPE_LOCAL_ALIAS) { 467 resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node, 468 resolved_node->object); 469 } 470 471 /* Update the reference object */ 472 473 element->reference.resolved = TRUE; 474 element->reference.node = resolved_node; 475 type = element->reference.node->type; 476 477 /* 478 * Attempt to resolve the node to a value before we insert it into 479 * the package. If this is a reference to a common data type, 480 * resolve it immediately. According to the ACPI spec, package 481 * elements can only be "data objects" or method references. 482 * Attempt to resolve to an Integer, Buffer, String or Package. 483 * If cannot, return the named reference (for things like Devices, 484 * Methods, etc.) Buffer Fields and Fields will resolve to simple 485 * objects (int/buf/str/pkg). 486 * 487 * NOTE: References to things like Devices, Methods, Mutexes, etc. 488 * will remain as named references. This behavior is not described 489 * in the ACPI spec, but it appears to be an oversight. 490 */ 491 original_node = resolved_node; 492 status = acpi_ex_resolve_node_to_value(&resolved_node, NULL); 493 if (ACPI_FAILURE(status)) { 494 return_VOID; 495 } 496 497 switch (type) { 498 /* 499 * These object types are a result of named references, so we will 500 * leave them as reference objects. In other words, these types 501 * have no intrinsic "value". 502 */ 503 case ACPI_TYPE_DEVICE: 504 case ACPI_TYPE_THERMAL: 505 case ACPI_TYPE_METHOD: 506 break; 507 508 case ACPI_TYPE_MUTEX: 509 case ACPI_TYPE_POWER: 510 case ACPI_TYPE_PROCESSOR: 511 case ACPI_TYPE_EVENT: 512 case ACPI_TYPE_REGION: 513 514 /* acpi_ex_resolve_node_to_value gave these an extra reference */ 515 516 acpi_ut_remove_reference(original_node->object); 517 break; 518 519 default: 520 /* 521 * For all other types - the node was resolved to an actual 522 * operand object with a value, return the object. Remove 523 * a reference on the existing object. 524 */ 525 acpi_ut_remove_reference(element); 526 *element_ptr = (union acpi_operand_object *)resolved_node; 527 break; 528 } 529 530 return_VOID; 531 } 532