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