1 /******************************************************************************
3 * Module Name: dspkginit - Completion of deferred package initialization
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2018, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
53 #define _COMPONENT ACPI_NAMESPACE
54 ACPI_MODULE_NAME ("dspkginit")
57 /* Local prototypes */
60 AcpiDsResolvePackageElement (
61 ACPI_OPERAND_OBJECT
**Element
);
64 /*******************************************************************************
66 * FUNCTION: AcpiDsBuildInternalPackageObj
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
76 * DESCRIPTION: Translate a parser Op package object to the equivalent
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.)
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.
91 ******************************************************************************/
94 AcpiDsBuildInternalPackageObj (
95 ACPI_WALK_STATE
*WalkState
,
96 ACPI_PARSE_OBJECT
*Op
,
98 ACPI_OPERAND_OBJECT
**ObjDescPtr
)
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
;
110 ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj
);
113 /* Check if we are executing module level code */
115 if (WalkState
->ParseFlags
& ACPI_PARSE_MODULE_LEVEL
)
117 ModuleLevelCode
= TRUE
;
120 /* Find the parent of a possibly nested package */
122 Parent
= Op
->Common
.Parent
;
123 while ((Parent
->Common
.AmlOpcode
== AML_PACKAGE_OP
) ||
124 (Parent
->Common
.AmlOpcode
== AML_VARIABLE_PACKAGE_OP
))
126 Parent
= Parent
->Common
.Parent
;
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.
134 ObjDesc
= *ObjDescPtr
;
137 ObjDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE
);
138 *ObjDescPtr
= ObjDesc
;
141 return_ACPI_STATUS (AE_NO_MEMORY
);
144 ObjDesc
->Package
.Node
= Parent
->Common
.Node
;
147 if (ObjDesc
->Package
.Flags
& AOPOBJ_DATA_VALID
) /* Just in case */
149 return_ACPI_STATUS (AE_OK
);
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
158 if (!ObjDesc
->Package
.Elements
)
160 ObjDesc
->Package
.Elements
= ACPI_ALLOCATE_ZEROED (
161 ((ACPI_SIZE
) ElementCount
+ 1) * sizeof (void *));
163 if (!ObjDesc
->Package
.Elements
)
165 AcpiUtDeleteObjectDesc (ObjDesc
);
166 return_ACPI_STATUS (AE_NO_MEMORY
);
169 ObjDesc
->Package
.Count
= ElementCount
;
172 /* First arg is element count. Second arg begins the initializer list */
174 Arg
= Op
->Common
.Value
.Arg
;
175 Arg
= Arg
->Common
.Next
;
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.
185 ObjDesc
->Package
.AmlStart
= WalkState
->Aml
;
186 ObjDesc
->Package
.AmlLength
= 0;
188 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE
,
189 "%s: Deferring resolution of Package elements\n",
190 ACPI_GET_FUNCTION_NAME
));
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.
199 for (i
= 0; Arg
&& (i
< ElementCount
); i
++)
201 if (Arg
->Common
.AmlOpcode
== AML_INT_RETURN_VALUE_OP
)
203 if (Arg
->Common
.Node
->Type
== ACPI_TYPE_METHOD
)
206 * A method reference "looks" to the parser to be a method
207 * invocation, so we special case it here
209 Arg
->Common
.AmlOpcode
= AML_INT_NAMEPATH_OP
;
210 Status
= AcpiDsBuildInternalObject (
211 WalkState
, Arg
, &ObjDesc
->Package
.Elements
[i
]);
215 /* This package element is already built, just get it */
217 ObjDesc
->Package
.Elements
[i
] =
218 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT
, Arg
->Common
.Node
);
223 Status
= AcpiDsBuildInternalObject (
224 WalkState
, Arg
, &ObjDesc
->Package
.Elements
[i
]);
225 if (Status
== AE_NOT_FOUND
)
227 ACPI_ERROR ((AE_INFO
, "%-48s", "****DS namepath not found"));
230 if (!ModuleLevelCode
)
233 * Initialize this package element. This function handles the
234 * resolution of named references within the package.
235 * Forward references from module-level code are deferred
236 * until all ACPI tables are loaded.
238 AcpiDsInitPackageElement (0, ObjDesc
->Package
.Elements
[i
],
239 NULL
, &ObjDesc
->Package
.Elements
[i
]);
245 /* Existing package, get existing reference count */
247 ReferenceCount
= (*ObjDescPtr
)->Common
.ReferenceCount
;
248 if (ReferenceCount
> 1)
250 /* Make new element ref count match original ref count */
251 /* TBD: Probably need an AcpiUtAddReferences function */
253 for (Index
= 0; Index
< ((UINT32
) ReferenceCount
- 1); Index
++)
255 AcpiUtAddReference ((ObjDesc
->Package
.Elements
[i
]));
260 Arg
= Arg
->Common
.Next
;
263 /* Check for match between NumElements and actual length of PackageList */
268 * NumElements was exhausted, but there are remaining elements in
269 * the PackageList. Truncate the package to NumElements.
271 * Note: technically, this is an error, from ACPI spec: "It is an
272 * error for NumElements to be less than the number of elements in
273 * the PackageList". However, we just print a message and no
274 * exception is returned. This provides compatibility with other
275 * ACPI implementations. Some firmware implementations will alter
276 * the NumElements on the fly, possibly creating this type of
277 * ill-formed package object.
282 * We must delete any package elements that were created earlier
283 * and are not going to be used because of the package truncation.
285 if (Arg
->Common
.Node
)
287 AcpiUtRemoveReference (
288 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT
, Arg
->Common
.Node
));
289 Arg
->Common
.Node
= NULL
;
292 /* Find out how many elements there really are */
295 Arg
= Arg
->Common
.Next
;
299 "Actual Package length (%u) is larger than "
300 "NumElements field (%u), truncated",
303 else if (i
< ElementCount
)
306 * Arg list (elements) was exhausted, but we did not reach
309 * Note: this is not an error, the package is padded out
310 * with NULLs as per the ACPI specification.
312 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO
,
313 "%s: Package List length (%u) smaller than NumElements "
314 "count (%u), padded with null elements\n",
315 ACPI_GET_FUNCTION_NAME
, i
, ElementCount
));
318 /* Module-level packages will be resolved later */
320 if (!ModuleLevelCode
)
322 ObjDesc
->Package
.Flags
|= AOPOBJ_DATA_VALID
;
325 Op
->Common
.Node
= ACPI_CAST_PTR (ACPI_NAMESPACE_NODE
, ObjDesc
);
326 return_ACPI_STATUS (Status
);
330 /*******************************************************************************
332 * FUNCTION: AcpiDsInitPackageElement
334 * PARAMETERS: ACPI_PKG_CALLBACK
338 * DESCRIPTION: Resolve a named reference element within a package object
340 ******************************************************************************/
343 AcpiDsInitPackageElement (
345 ACPI_OPERAND_OBJECT
*SourceObject
,
346 ACPI_GENERIC_STATE
*State
,
349 ACPI_OPERAND_OBJECT
**ElementPtr
;
352 ACPI_FUNCTION_TRACE (DsInitPackageElement
);
357 return_ACPI_STATUS (AE_OK
);
361 * The following code is a bit of a hack to workaround a (current)
362 * limitation of the ACPI_PKG_CALLBACK interface. We need a pointer
363 * to the location within the element array because a new object
364 * may be created and stored there.
368 /* A direct call was made to this function */
370 ElementPtr
= (ACPI_OPERAND_OBJECT
**) Context
;
374 /* Call came from AcpiUtWalkPackageTree */
376 ElementPtr
= State
->Pkg
.ThisTargetObj
;
379 /* We are only interested in reference objects/elements */
381 if (SourceObject
->Common
.Type
== ACPI_TYPE_LOCAL_REFERENCE
)
383 /* Attempt to resolve the (named) reference to a namespace node */
385 AcpiDsResolvePackageElement (ElementPtr
);
387 else if (SourceObject
->Common
.Type
== ACPI_TYPE_PACKAGE
)
389 SourceObject
->Package
.Flags
|= AOPOBJ_DATA_VALID
;
392 return_ACPI_STATUS (AE_OK
);
396 /*******************************************************************************
398 * FUNCTION: AcpiDsResolvePackageElement
400 * PARAMETERS: ElementPtr - Pointer to a reference object
402 * RETURN: Possible new element is stored to the indirect ElementPtr
404 * DESCRIPTION: Resolve a package element that is a reference to a named
407 ******************************************************************************/
410 AcpiDsResolvePackageElement (
411 ACPI_OPERAND_OBJECT
**ElementPtr
)
415 ACPI_GENERIC_STATE ScopeInfo
;
416 ACPI_OPERAND_OBJECT
*Element
= *ElementPtr
;
417 ACPI_NAMESPACE_NODE
*ResolvedNode
;
418 ACPI_NAMESPACE_NODE
*OriginalNode
;
419 char *ExternalPath
= "";
420 ACPI_OBJECT_TYPE Type
;
423 ACPI_FUNCTION_TRACE (DsResolvePackageElement
);
426 /* Check if reference element is already resolved */
428 if (Element
->Reference
.Resolved
)
430 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE
,
431 "%s: Package element is already resolved\n",
432 ACPI_GET_FUNCTION_NAME
));
437 /* Element must be a reference object of correct type */
439 ScopeInfo
.Scope
.Node
= Element
->Reference
.Node
; /* Prefix node */
441 Status
= AcpiNsLookup (&ScopeInfo
, (char *) Element
->Reference
.Aml
,
442 ACPI_TYPE_ANY
, ACPI_IMODE_EXECUTE
,
443 ACPI_NS_SEARCH_PARENT
| ACPI_NS_DONT_OPEN_SCOPE
,
444 NULL
, &ResolvedNode
);
445 if (ACPI_FAILURE (Status
))
447 if ((Status
== AE_NOT_FOUND
) && AcpiGbl_IgnorePackageResolutionErrors
)
450 * Optionally be silent about the NOT_FOUND case for the referenced
451 * name. Although this is potentially a serious problem,
452 * it can generate a lot of noise/errors on platforms whose
453 * firmware carries around a bunch of unused Package objects.
454 * To disable these errors, set this global to TRUE:
455 * AcpiGbl_IgnorePackageResolutionErrors
457 * If the AML actually tries to use such a package, the unresolved
458 * element(s) will be replaced with NULL elements.
461 /* Referenced name not found, set the element to NULL */
463 AcpiUtRemoveReference (*ElementPtr
);
468 Status2
= AcpiNsExternalizeName (ACPI_UINT32_MAX
,
469 (char *) Element
->Reference
.Aml
, NULL
, &ExternalPath
);
471 ACPI_EXCEPTION ((AE_INFO
, Status
,
472 "While resolving a named reference package element - %s",
474 if (ACPI_SUCCESS (Status2
))
476 ACPI_FREE (ExternalPath
);
479 /* Could not resolve name, set the element to NULL */
481 AcpiUtRemoveReference (*ElementPtr
);
485 else if (ResolvedNode
->Type
== ACPI_TYPE_ANY
)
487 /* Named reference not resolved, return a NULL package element */
489 ACPI_ERROR ((AE_INFO
,
490 "Could not resolve named package element [%4.4s] in [%4.4s]",
491 ResolvedNode
->Name
.Ascii
, ScopeInfo
.Scope
.Node
->Name
.Ascii
));
497 * Special handling for Alias objects. We need ResolvedNode to point
498 * to the Alias target. This effectively "resolves" the alias.
500 if (ResolvedNode
->Type
== ACPI_TYPE_LOCAL_ALIAS
)
502 ResolvedNode
= ACPI_CAST_PTR (ACPI_NAMESPACE_NODE
,
503 ResolvedNode
->Object
);
506 /* Update the reference object */
508 Element
->Reference
.Resolved
= TRUE
;
509 Element
->Reference
.Node
= ResolvedNode
;
510 Type
= Element
->Reference
.Node
->Type
;
513 * Attempt to resolve the node to a value before we insert it into
514 * the package. If this is a reference to a common data type,
515 * resolve it immediately. According to the ACPI spec, package
516 * elements can only be "data objects" or method references.
517 * Attempt to resolve to an Integer, Buffer, String or Package.
518 * If cannot, return the named reference (for things like Devices,
519 * Methods, etc.) Buffer Fields and Fields will resolve to simple
520 * objects (int/buf/str/pkg).
522 * NOTE: References to things like Devices, Methods, Mutexes, etc.
523 * will remain as named references. This behavior is not described
524 * in the ACPI spec, but it appears to be an oversight.
526 OriginalNode
= ResolvedNode
;
527 Status
= AcpiExResolveNodeToValue (&ResolvedNode
, NULL
);
528 if (ACPI_FAILURE (Status
))
536 * These object types are a result of named references, so we will
537 * leave them as reference objects. In other words, these types
538 * have no intrinsic "value".
540 case ACPI_TYPE_DEVICE
:
541 case ACPI_TYPE_THERMAL
:
542 case ACPI_TYPE_METHOD
:
545 case ACPI_TYPE_MUTEX
:
546 case ACPI_TYPE_POWER
:
547 case ACPI_TYPE_PROCESSOR
:
548 case ACPI_TYPE_EVENT
:
549 case ACPI_TYPE_REGION
:
551 /* AcpiExResolveNodeToValue gave these an extra reference */
553 AcpiUtRemoveReference (OriginalNode
->Object
);
558 * For all other types - the node was resolved to an actual
559 * operand object with a value, return the object. Remove
560 * a reference on the existing object.
562 AcpiUtRemoveReference (Element
);
563 *ElementPtr
= (ACPI_OPERAND_OBJECT
*) ResolvedNode
;