1 /****************************************************************************** 2 * 3 * Module Name: dspkginit - Completion of deferred package initialization 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2020, 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.h" 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "amlcode.h" 48 #include "acdispat.h" 49 #include "acinterp.h" 50 #include "acparser.h" 51 52 53 #define _COMPONENT ACPI_NAMESPACE 54 ACPI_MODULE_NAME ("dspkginit") 55 56 57 /* Local prototypes */ 58 59 static void 60 AcpiDsResolvePackageElement ( 61 ACPI_OPERAND_OBJECT **Element); 62 63 64 /******************************************************************************* 65 * 66 * FUNCTION: AcpiDsBuildInternalPackageObj 67 * 68 * PARAMETERS: WalkState - Current walk state 69 * Op - Parser object to be translated 70 * ElementCount - Number of elements in the package - this is 71 * the NumElements argument to Package() 72 * ObjDescPtr - Where the ACPI internal object is returned 73 * 74 * RETURN: Status 75 * 76 * DESCRIPTION: Translate a parser Op package object to the equivalent 77 * namespace object 78 * 79 * NOTE: The number of elements in the package will be always be the NumElements 80 * count, regardless of the number of elements in the package list. If 81 * NumElements is smaller, only that many package list elements are used. 82 * if NumElements is larger, the Package object is padded out with 83 * objects of type Uninitialized (as per ACPI spec.) 84 * 85 * Even though the ASL compilers do not allow NumElements to be smaller 86 * than the Package list length (for the fixed length package opcode), some 87 * BIOS code modifies the AML on the fly to adjust the NumElements, and 88 * this code compensates for that. This also provides compatibility with 89 * other AML interpreters. 90 * 91 ******************************************************************************/ 92 93 ACPI_STATUS 94 AcpiDsBuildInternalPackageObj ( 95 ACPI_WALK_STATE *WalkState, 96 ACPI_PARSE_OBJECT *Op, 97 UINT32 ElementCount, 98 ACPI_OPERAND_OBJECT **ObjDescPtr) 99 { 100 ACPI_PARSE_OBJECT *Arg; 101 ACPI_PARSE_OBJECT *Parent; 102 ACPI_OPERAND_OBJECT *ObjDesc = NULL; 103 ACPI_STATUS Status = AE_OK; 104 BOOLEAN ModuleLevelCode = FALSE; 105 UINT16 ReferenceCount; 106 UINT32 Index; 107 UINT32 i; 108 109 110 ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); 111 112 113 /* Check if we are executing module level code */ 114 115 if (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) 116 { 117 ModuleLevelCode = TRUE; 118 } 119 120 /* Find the parent of a possibly nested package */ 121 122 Parent = Op->Common.Parent; 123 while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 124 (Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) 125 { 126 Parent = Parent->Common.Parent; 127 } 128 129 /* 130 * If we are evaluating a Named package object of the form: 131 * Name (xxxx, Package) 132 * the package object already exists, otherwise it must be created. 133 */ 134 ObjDesc = *ObjDescPtr; 135 if (!ObjDesc) 136 { 137 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); 138 *ObjDescPtr = ObjDesc; 139 if (!ObjDesc) 140 { 141 return_ACPI_STATUS (AE_NO_MEMORY); 142 } 143 144 ObjDesc->Package.Node = Parent->Common.Node; 145 } 146 147 if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID) /* Just in case */ 148 { 149 return_ACPI_STATUS (AE_OK); 150 } 151 152 /* 153 * Allocate the element array (array of pointers to the individual 154 * objects) if necessary. the count is based on the NumElements 155 * parameter. Add an extra pointer slot so that the list is always 156 * null terminated. 157 */ 158 if (!ObjDesc->Package.Elements) 159 { 160 ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED ( 161 ((ACPI_SIZE) ElementCount + 1) * sizeof (void *)); 162 163 if (!ObjDesc->Package.Elements) 164 { 165 AcpiUtDeleteObjectDesc (ObjDesc); 166 return_ACPI_STATUS (AE_NO_MEMORY); 167 } 168 169 ObjDesc->Package.Count = ElementCount; 170 } 171 172 /* First arg is element count. Second arg begins the initializer list */ 173 174 Arg = Op->Common.Value.Arg; 175 Arg = Arg->Common.Next; 176 177 /* 178 * If we are executing module-level code, we will defer the 179 * full resolution of the package elements in order to support 180 * forward references from the elements. This provides 181 * compatibility with other ACPI implementations. 182 */ 183 if (ModuleLevelCode) 184 { 185 ObjDesc->Package.AmlStart = WalkState->Aml; 186 ObjDesc->Package.AmlLength = 0; 187 188 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE, 189 "%s: Deferring resolution of Package elements\n", 190 ACPI_GET_FUNCTION_NAME)); 191 } 192 193 /* 194 * Initialize the elements of the package, up to the NumElements count. 195 * Package is automatically padded with uninitialized (NULL) elements 196 * if NumElements is greater than the package list length. Likewise, 197 * Package is truncated if NumElements is less than the list length. 198 */ 199 for (i = 0; Arg && (i < ElementCount); i++) 200 { 201 if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) 202 { 203 if (!Arg->Common.Node) 204 { 205 /* 206 * This is the case where an expression has returned a value. 207 * The use of expressions (TermArgs) within individual 208 * package elements is not supported by the AML interpreter, 209 * even though the ASL grammar supports it. Example: 210 * 211 * Name (INT1, 0x1234) 212 * 213 * Name (PKG3, Package () { 214 * Add (INT1, 0xAAAA0000) 215 * }) 216 * 217 * 1) No known AML interpreter supports this type of construct 218 * 2) This fixes a fault if the construct is encountered 219 */ 220 ACPI_EXCEPTION ((AE_INFO, AE_SUPPORT, 221 "Expressions within package elements are not supported")); 222 223 /* Cleanup the return object, it is not needed */ 224 225 AcpiUtRemoveReference (WalkState->Results->Results.ObjDesc[0]); 226 return_ACPI_STATUS (AE_SUPPORT); 227 } 228 229 if (Arg->Common.Node->Type == ACPI_TYPE_METHOD) 230 { 231 /* 232 * A method reference "looks" to the parser to be a method 233 * invocation, so we special case it here 234 */ 235 Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP; 236 Status = AcpiDsBuildInternalObject ( 237 WalkState, Arg, &ObjDesc->Package.Elements[i]); 238 } 239 else 240 { 241 /* This package element is already built, just get it */ 242 243 ObjDesc->Package.Elements[i] = 244 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node); 245 } 246 } 247 else 248 { 249 Status = AcpiDsBuildInternalObject ( 250 WalkState, Arg, &ObjDesc->Package.Elements[i]); 251 if (Status == AE_NOT_FOUND) 252 { 253 ACPI_ERROR ((AE_INFO, "%-48s", "****DS namepath not found")); 254 } 255 256 if (!ModuleLevelCode) 257 { 258 /* 259 * Initialize this package element. This function handles the 260 * resolution of named references within the package. 261 * Forward references from module-level code are deferred 262 * until all ACPI tables are loaded. 263 */ 264 AcpiDsInitPackageElement (0, ObjDesc->Package.Elements[i], 265 NULL, &ObjDesc->Package.Elements[i]); 266 } 267 } 268 269 if (*ObjDescPtr) 270 { 271 /* Existing package, get existing reference count */ 272 273 ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount; 274 if (ReferenceCount > 1) 275 { 276 /* Make new element ref count match original ref count */ 277 /* TBD: Probably need an AcpiUtAddReferences function */ 278 279 for (Index = 0; Index < ((UINT32) ReferenceCount - 1); Index++) 280 { 281 AcpiUtAddReference ((ObjDesc->Package.Elements[i])); 282 } 283 } 284 } 285 286 Arg = Arg->Common.Next; 287 } 288 289 /* Check for match between NumElements and actual length of PackageList */ 290 291 if (Arg) 292 { 293 /* 294 * NumElements was exhausted, but there are remaining elements in 295 * the PackageList. Truncate the package to NumElements. 296 * 297 * Note: technically, this is an error, from ACPI spec: "It is an 298 * error for NumElements to be less than the number of elements in 299 * the PackageList". However, we just print a message and no 300 * exception is returned. This provides compatibility with other 301 * ACPI implementations. Some firmware implementations will alter 302 * the NumElements on the fly, possibly creating this type of 303 * ill-formed package object. 304 */ 305 while (Arg) 306 { 307 /* 308 * We must delete any package elements that were created earlier 309 * and are not going to be used because of the package truncation. 310 */ 311 if (Arg->Common.Node) 312 { 313 AcpiUtRemoveReference ( 314 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node)); 315 Arg->Common.Node = NULL; 316 } 317 318 /* Find out how many elements there really are */ 319 320 i++; 321 Arg = Arg->Common.Next; 322 } 323 324 ACPI_INFO (( 325 "Actual Package length (%u) is larger than " 326 "NumElements field (%u), truncated", 327 i, ElementCount)); 328 } 329 else if (i < ElementCount) 330 { 331 /* 332 * Arg list (elements) was exhausted, but we did not reach 333 * NumElements count. 334 * 335 * Note: this is not an error, the package is padded out 336 * with NULLs as per the ACPI specification. 337 */ 338 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, 339 "%s: Package List length (%u) smaller than NumElements " 340 "count (%u), padded with null elements\n", 341 ACPI_GET_FUNCTION_NAME, i, ElementCount)); 342 } 343 344 /* Module-level packages will be resolved later */ 345 346 if (!ModuleLevelCode) 347 { 348 ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; 349 } 350 351 Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); 352 return_ACPI_STATUS (Status); 353 } 354 355 356 /******************************************************************************* 357 * 358 * FUNCTION: AcpiDsInitPackageElement 359 * 360 * PARAMETERS: ACPI_PKG_CALLBACK 361 * 362 * RETURN: Status 363 * 364 * DESCRIPTION: Resolve a named reference element within a package object 365 * 366 ******************************************************************************/ 367 368 ACPI_STATUS 369 AcpiDsInitPackageElement ( 370 UINT8 ObjectType, 371 ACPI_OPERAND_OBJECT *SourceObject, 372 ACPI_GENERIC_STATE *State, 373 void *Context) 374 { 375 ACPI_OPERAND_OBJECT **ElementPtr; 376 377 378 ACPI_FUNCTION_TRACE (DsInitPackageElement); 379 380 381 if (!SourceObject) 382 { 383 return_ACPI_STATUS (AE_OK); 384 } 385 386 /* 387 * The following code is a bit of a hack to workaround a (current) 388 * limitation of the ACPI_PKG_CALLBACK interface. We need a pointer 389 * to the location within the element array because a new object 390 * may be created and stored there. 391 */ 392 if (Context) 393 { 394 /* A direct call was made to this function */ 395 396 ElementPtr = (ACPI_OPERAND_OBJECT **) Context; 397 } 398 else 399 { 400 /* Call came from AcpiUtWalkPackageTree */ 401 402 ElementPtr = State->Pkg.ThisTargetObj; 403 } 404 405 /* We are only interested in reference objects/elements */ 406 407 if (SourceObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) 408 { 409 /* Attempt to resolve the (named) reference to a namespace node */ 410 411 AcpiDsResolvePackageElement (ElementPtr); 412 } 413 else if (SourceObject->Common.Type == ACPI_TYPE_PACKAGE) 414 { 415 SourceObject->Package.Flags |= AOPOBJ_DATA_VALID; 416 } 417 418 return_ACPI_STATUS (AE_OK); 419 } 420 421 422 /******************************************************************************* 423 * 424 * FUNCTION: AcpiDsResolvePackageElement 425 * 426 * PARAMETERS: ElementPtr - Pointer to a reference object 427 * 428 * RETURN: Possible new element is stored to the indirect ElementPtr 429 * 430 * DESCRIPTION: Resolve a package element that is a reference to a named 431 * object. 432 * 433 ******************************************************************************/ 434 435 static void 436 AcpiDsResolvePackageElement ( 437 ACPI_OPERAND_OBJECT **ElementPtr) 438 { 439 ACPI_STATUS Status; 440 ACPI_STATUS Status2; 441 ACPI_GENERIC_STATE ScopeInfo; 442 ACPI_OPERAND_OBJECT *Element = *ElementPtr; 443 ACPI_NAMESPACE_NODE *ResolvedNode; 444 ACPI_NAMESPACE_NODE *OriginalNode; 445 char *ExternalPath = ""; 446 ACPI_OBJECT_TYPE Type; 447 448 449 ACPI_FUNCTION_TRACE (DsResolvePackageElement); 450 451 452 /* Check if reference element is already resolved */ 453 454 if (Element->Reference.Resolved) 455 { 456 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE, 457 "%s: Package element is already resolved\n", 458 ACPI_GET_FUNCTION_NAME)); 459 460 return_VOID; 461 } 462 463 /* Element must be a reference object of correct type */ 464 465 ScopeInfo.Scope.Node = Element->Reference.Node; /* Prefix node */ 466 467 Status = AcpiNsLookup (&ScopeInfo, (char *) Element->Reference.Aml, 468 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 469 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 470 NULL, &ResolvedNode); 471 if (ACPI_FAILURE (Status)) 472 { 473 if ((Status == AE_NOT_FOUND) && AcpiGbl_IgnorePackageResolutionErrors) 474 { 475 /* 476 * Optionally be silent about the NOT_FOUND case for the referenced 477 * name. Although this is potentially a serious problem, 478 * it can generate a lot of noise/errors on platforms whose 479 * firmware carries around a bunch of unused Package objects. 480 * To disable these errors, set this global to TRUE: 481 * AcpiGbl_IgnorePackageResolutionErrors 482 * 483 * If the AML actually tries to use such a package, the unresolved 484 * element(s) will be replaced with NULL elements. 485 */ 486 487 /* Referenced name not found, set the element to NULL */ 488 489 AcpiUtRemoveReference (*ElementPtr); 490 *ElementPtr = NULL; 491 return_VOID; 492 } 493 494 Status2 = AcpiNsExternalizeName (ACPI_UINT32_MAX, 495 (char *) Element->Reference.Aml, NULL, &ExternalPath); 496 497 ACPI_EXCEPTION ((AE_INFO, Status, 498 "While resolving a named reference package element - %s", 499 ExternalPath)); 500 if (ACPI_SUCCESS (Status2)) 501 { 502 ACPI_FREE (ExternalPath); 503 } 504 505 /* Could not resolve name, set the element to NULL */ 506 507 AcpiUtRemoveReference (*ElementPtr); 508 *ElementPtr = NULL; 509 return_VOID; 510 } 511 else if (ResolvedNode->Type == ACPI_TYPE_ANY) 512 { 513 /* Named reference not resolved, return a NULL package element */ 514 515 ACPI_ERROR ((AE_INFO, 516 "Could not resolve named package element [%4.4s] in [%4.4s]", 517 ResolvedNode->Name.Ascii, ScopeInfo.Scope.Node->Name.Ascii)); 518 *ElementPtr = NULL; 519 return_VOID; 520 } 521 522 /* 523 * Special handling for Alias objects. We need ResolvedNode to point 524 * to the Alias target. This effectively "resolves" the alias. 525 */ 526 if (ResolvedNode->Type == ACPI_TYPE_LOCAL_ALIAS) 527 { 528 ResolvedNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 529 ResolvedNode->Object); 530 } 531 532 /* Update the reference object */ 533 534 Element->Reference.Resolved = TRUE; 535 Element->Reference.Node = ResolvedNode; 536 Type = Element->Reference.Node->Type; 537 538 /* 539 * Attempt to resolve the node to a value before we insert it into 540 * the package. If this is a reference to a common data type, 541 * resolve it immediately. According to the ACPI spec, package 542 * elements can only be "data objects" or method references. 543 * Attempt to resolve to an Integer, Buffer, String or Package. 544 * If cannot, return the named reference (for things like Devices, 545 * Methods, etc.) Buffer Fields and Fields will resolve to simple 546 * objects (int/buf/str/pkg). 547 * 548 * NOTE: References to things like Devices, Methods, Mutexes, etc. 549 * will remain as named references. This behavior is not described 550 * in the ACPI spec, but it appears to be an oversight. 551 */ 552 OriginalNode = ResolvedNode; 553 Status = AcpiExResolveNodeToValue (&ResolvedNode, NULL); 554 if (ACPI_FAILURE (Status)) 555 { 556 return_VOID; 557 } 558 559 switch (Type) 560 { 561 /* 562 * These object types are a result of named references, so we will 563 * leave them as reference objects. In other words, these types 564 * have no intrinsic "value". 565 */ 566 case ACPI_TYPE_DEVICE: 567 case ACPI_TYPE_THERMAL: 568 case ACPI_TYPE_METHOD: 569 break; 570 571 case ACPI_TYPE_MUTEX: 572 case ACPI_TYPE_POWER: 573 case ACPI_TYPE_PROCESSOR: 574 case ACPI_TYPE_EVENT: 575 case ACPI_TYPE_REGION: 576 577 /* AcpiExResolveNodeToValue gave these an extra reference */ 578 579 AcpiUtRemoveReference (OriginalNode->Object); 580 break; 581 582 default: 583 /* 584 * For all other types - the node was resolved to an actual 585 * operand object with a value, return the object. Remove 586 * a reference on the existing object. 587 */ 588 AcpiUtRemoveReference (Element); 589 *ElementPtr = (ACPI_OPERAND_OBJECT *) ResolvedNode; 590 break; 591 } 592 593 return_VOID; 594 } 595