1 /******************************************************************************
2 *
3 * Module Name: dspkginit - Completion of deferred package initialization
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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
AcpiDsBuildInternalPackageObj(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT * Op,UINT32 ElementCount,ACPI_OPERAND_OBJECT ** ObjDescPtr)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
AcpiDsInitPackageElement(UINT8 ObjectType,ACPI_OPERAND_OBJECT * SourceObject,ACPI_GENERIC_STATE * State,void * Context)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
AcpiDsResolvePackageElement(ACPI_OPERAND_OBJECT ** ElementPtr)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