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