1 /******************************************************************************
3 * Module Name: dsobject - Dispatcher object management routines
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.
52 #define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME ("dsobject")
56 #ifndef ACPI_NO_METHOD_EXECUTION
57 /*******************************************************************************
59 * FUNCTION: AcpiDsBuildInternalObject
61 * PARAMETERS: WalkState - Current walk state
62 * Op - Parser object to be translated
63 * ObjDescPtr - Where the ACPI internal object is returned
67 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
68 * Simple objects are any objects other than a package object!
70 ******************************************************************************/
73 AcpiDsBuildInternalObject (
74 ACPI_WALK_STATE
*WalkState
,
75 ACPI_PARSE_OBJECT
*Op
,
76 ACPI_OPERAND_OBJECT
**ObjDescPtr
)
78 ACPI_OPERAND_OBJECT
*ObjDesc
;
82 ACPI_FUNCTION_TRACE (DsBuildInternalObject
);
86 if (Op
->Common
.AmlOpcode
== AML_INT_NAMEPATH_OP
)
89 * This is a named object reference. If this name was
90 * previously looked up in the namespace, it was stored in
91 * this op. Otherwise, go ahead and look it up now
95 /* Check if we are resolving a named reference within a package */
97 if ((Op
->Common
.Parent
->Common
.AmlOpcode
== AML_PACKAGE_OP
) ||
98 (Op
->Common
.Parent
->Common
.AmlOpcode
== AML_VARIABLE_PACKAGE_OP
))
101 * We won't resolve package elements here, we will do this
102 * after all ACPI tables are loaded into the namespace. This
103 * behavior supports both forward references to named objects
104 * and external references to objects in other tables.
106 goto CreateNewObject
;
110 Status
= AcpiNsLookup (WalkState
->ScopeInfo
,
111 Op
->Common
.Value
.String
,
112 ACPI_TYPE_ANY
, ACPI_IMODE_EXECUTE
,
113 ACPI_NS_SEARCH_PARENT
| ACPI_NS_DONT_OPEN_SCOPE
, NULL
,
114 ACPI_CAST_INDIRECT_PTR (
115 ACPI_NAMESPACE_NODE
, &(Op
->Common
.Node
)));
116 if (ACPI_FAILURE (Status
))
118 ACPI_ERROR_NAMESPACE (WalkState
->ScopeInfo
,
119 Op
->Common
.Value
.String
, Status
);
120 return_ACPI_STATUS (Status
);
128 /* Create and init a new internal ACPI object */
130 ObjDesc
= AcpiUtCreateInternalObject (
131 (AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
))->ObjectType
);
134 return_ACPI_STATUS (AE_NO_MEMORY
);
137 Status
= AcpiDsInitObjectFromOp (
138 WalkState
, Op
, Op
->Common
.AmlOpcode
, &ObjDesc
);
139 if (ACPI_FAILURE (Status
))
141 AcpiUtRemoveReference (ObjDesc
);
142 return_ACPI_STATUS (Status
);
146 * Handling for unresolved package reference elements.
147 * These are elements that are namepaths.
149 if ((Op
->Common
.Parent
->Common
.AmlOpcode
== AML_PACKAGE_OP
) ||
150 (Op
->Common
.Parent
->Common
.AmlOpcode
== AML_VARIABLE_PACKAGE_OP
))
152 ObjDesc
->Reference
.Resolved
= TRUE
;
154 if ((Op
->Common
.AmlOpcode
== AML_INT_NAMEPATH_OP
) &&
155 !ObjDesc
->Reference
.Node
)
158 * Name was unresolved above.
159 * Get the prefix node for later lookup
161 ObjDesc
->Reference
.Node
= WalkState
->ScopeInfo
->Scope
.Node
;
162 ObjDesc
->Reference
.Aml
= Op
->Common
.Aml
;
163 ObjDesc
->Reference
.Resolved
= FALSE
;
167 *ObjDescPtr
= ObjDesc
;
168 return_ACPI_STATUS (Status
);
172 /*******************************************************************************
174 * FUNCTION: AcpiDsBuildInternalBufferObj
176 * PARAMETERS: WalkState - Current walk state
177 * Op - Parser object to be translated
178 * BufferLength - Length of the buffer
179 * ObjDescPtr - Where the ACPI internal object is returned
183 * DESCRIPTION: Translate a parser Op package object to the equivalent
186 ******************************************************************************/
189 AcpiDsBuildInternalBufferObj (
190 ACPI_WALK_STATE
*WalkState
,
191 ACPI_PARSE_OBJECT
*Op
,
193 ACPI_OPERAND_OBJECT
**ObjDescPtr
)
195 ACPI_PARSE_OBJECT
*Arg
;
196 ACPI_OPERAND_OBJECT
*ObjDesc
;
197 ACPI_PARSE_OBJECT
*ByteList
;
198 UINT32 ByteListLength
= 0;
201 ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj
);
205 * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
206 * The buffer object already exists (from the NS node), otherwise it must
209 ObjDesc
= *ObjDescPtr
;
212 /* Create a new buffer object */
214 ObjDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER
);
215 *ObjDescPtr
= ObjDesc
;
218 return_ACPI_STATUS (AE_NO_MEMORY
);
223 * Second arg is the buffer data (optional) ByteList can be either
224 * individual bytes or a string initializer. In either case, a
225 * ByteList appears in the AML.
227 Arg
= Op
->Common
.Value
.Arg
; /* skip first arg */
229 ByteList
= Arg
->Named
.Next
;
232 if (ByteList
->Common
.AmlOpcode
!= AML_INT_BYTELIST_OP
)
234 ACPI_ERROR ((AE_INFO
,
235 "Expecting bytelist, found AML opcode 0x%X in op %p",
236 ByteList
->Common
.AmlOpcode
, ByteList
));
238 AcpiUtRemoveReference (ObjDesc
);
242 ByteListLength
= (UINT32
) ByteList
->Common
.Value
.Integer
;
246 * The buffer length (number of bytes) will be the larger of:
247 * 1) The specified buffer length and
248 * 2) The length of the initializer byte list
250 ObjDesc
->Buffer
.Length
= BufferLength
;
251 if (ByteListLength
> BufferLength
)
253 ObjDesc
->Buffer
.Length
= ByteListLength
;
256 /* Allocate the buffer */
258 if (ObjDesc
->Buffer
.Length
== 0)
260 ObjDesc
->Buffer
.Pointer
= NULL
;
261 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
,
262 "Buffer defined with zero length in AML, creating\n"));
266 ObjDesc
->Buffer
.Pointer
=
267 ACPI_ALLOCATE_ZEROED (ObjDesc
->Buffer
.Length
);
268 if (!ObjDesc
->Buffer
.Pointer
)
270 AcpiUtDeleteObjectDesc (ObjDesc
);
271 return_ACPI_STATUS (AE_NO_MEMORY
);
274 /* Initialize buffer from the ByteList (if present) */
278 memcpy (ObjDesc
->Buffer
.Pointer
, ByteList
->Named
.Data
,
283 ObjDesc
->Buffer
.Flags
|= AOPOBJ_DATA_VALID
;
284 Op
->Common
.Node
= ACPI_CAST_PTR (ACPI_NAMESPACE_NODE
, ObjDesc
);
285 return_ACPI_STATUS (AE_OK
);
288 /*******************************************************************************
290 * FUNCTION: AcpiDsCreateNode
292 * PARAMETERS: WalkState - Current walk state
293 * Node - NS Node to be initialized
294 * Op - Parser object to be translated
298 * DESCRIPTION: Create the object to be associated with a namespace node
300 ******************************************************************************/
304 ACPI_WALK_STATE
*WalkState
,
305 ACPI_NAMESPACE_NODE
*Node
,
306 ACPI_PARSE_OBJECT
*Op
)
309 ACPI_OPERAND_OBJECT
*ObjDesc
;
312 ACPI_FUNCTION_TRACE_PTR (DsCreateNode
, Op
);
316 * Because of the execution pass through the non-control-method
317 * parts of the table, we can arrive here twice. Only init
318 * the named object node the first time through
320 if (AcpiNsGetAttachedObject (Node
))
322 return_ACPI_STATUS (AE_OK
);
325 if (!Op
->Common
.Value
.Arg
)
327 /* No arguments, there is nothing to do */
329 return_ACPI_STATUS (AE_OK
);
332 /* Build an internal object for the argument(s) */
334 Status
= AcpiDsBuildInternalObject (
335 WalkState
, Op
->Common
.Value
.Arg
, &ObjDesc
);
336 if (ACPI_FAILURE (Status
))
338 return_ACPI_STATUS (Status
);
341 /* Re-type the object according to its argument */
343 Node
->Type
= ObjDesc
->Common
.Type
;
345 /* Attach obj to node */
347 Status
= AcpiNsAttachObject (Node
, ObjDesc
, Node
->Type
);
349 /* Remove local reference to the object */
351 AcpiUtRemoveReference (ObjDesc
);
352 return_ACPI_STATUS (Status
);
355 #endif /* ACPI_NO_METHOD_EXECUTION */
358 /*******************************************************************************
360 * FUNCTION: AcpiDsInitObjectFromOp
362 * PARAMETERS: WalkState - Current walk state
363 * Op - Parser op used to init the internal object
364 * Opcode - AML opcode associated with the object
365 * RetObjDesc - Namespace object to be initialized
369 * DESCRIPTION: Initialize a namespace object from a parser Op and its
370 * associated arguments. The namespace object is a more compact
371 * representation of the Op and its arguments.
373 ******************************************************************************/
376 AcpiDsInitObjectFromOp (
377 ACPI_WALK_STATE
*WalkState
,
378 ACPI_PARSE_OBJECT
*Op
,
380 ACPI_OPERAND_OBJECT
**RetObjDesc
)
382 const ACPI_OPCODE_INFO
*OpInfo
;
383 ACPI_OPERAND_OBJECT
*ObjDesc
;
384 ACPI_STATUS Status
= AE_OK
;
387 ACPI_FUNCTION_TRACE (DsInitObjectFromOp
);
390 ObjDesc
= *RetObjDesc
;
391 OpInfo
= AcpiPsGetOpcodeInfo (Opcode
);
392 if (OpInfo
->Class
== AML_CLASS_UNKNOWN
)
396 return_ACPI_STATUS (AE_TYPE
);
399 /* Perform per-object initialization */
401 switch (ObjDesc
->Common
.Type
)
403 case ACPI_TYPE_BUFFER
:
405 * Defer evaluation of Buffer TermArg operand
407 ObjDesc
->Buffer
.Node
= ACPI_CAST_PTR (
408 ACPI_NAMESPACE_NODE
, WalkState
->Operands
[0]);
409 ObjDesc
->Buffer
.AmlStart
= Op
->Named
.Data
;
410 ObjDesc
->Buffer
.AmlLength
= Op
->Named
.Length
;
413 case ACPI_TYPE_PACKAGE
:
415 * Defer evaluation of Package TermArg operand and all
416 * package elements. (01/2017): We defer the element
417 * resolution to allow forward references from the package
418 * in order to provide compatibility with other ACPI
421 ObjDesc
->Package
.Node
= ACPI_CAST_PTR (
422 ACPI_NAMESPACE_NODE
, WalkState
->Operands
[0]);
426 return_ACPI_STATUS (AE_OK
);
429 ObjDesc
->Package
.AmlStart
= Op
->Named
.Data
;
430 ObjDesc
->Package
.AmlLength
= Op
->Named
.Length
;
433 case ACPI_TYPE_INTEGER
:
435 switch (OpInfo
->Type
)
437 case AML_TYPE_CONSTANT
:
439 * Resolve AML Constants here - AND ONLY HERE!
440 * All constants are integers.
441 * We mark the integer with a flag that indicates that it started
442 * life as a constant -- so that stores to constants will perform
443 * as expected (noop). ZeroOp is used as a placeholder for optional
446 ObjDesc
->Common
.Flags
= AOPOBJ_AML_CONSTANT
;
452 ObjDesc
->Integer
.Value
= 0;
457 ObjDesc
->Integer
.Value
= 1;
462 ObjDesc
->Integer
.Value
= ACPI_UINT64_MAX
;
464 /* Truncate value if we are executing from a 32-bit ACPI table */
466 #ifndef ACPI_NO_METHOD_EXECUTION
467 (void) AcpiExTruncateFor32bitTable (ObjDesc
);
471 case AML_REVISION_OP
:
473 ObjDesc
->Integer
.Value
= ACPI_CA_VERSION
;
478 ACPI_ERROR ((AE_INFO
,
479 "Unknown constant opcode 0x%X", Opcode
));
480 Status
= AE_AML_OPERAND_TYPE
;
485 case AML_TYPE_LITERAL
:
487 ObjDesc
->Integer
.Value
= Op
->Common
.Value
.Integer
;
489 #ifndef ACPI_NO_METHOD_EXECUTION
490 if (AcpiExTruncateFor32bitTable (ObjDesc
))
492 /* Warn if we found a 64-bit constant in a 32-bit table */
494 ACPI_WARNING ((AE_INFO
,
495 "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
496 ACPI_FORMAT_UINT64 (Op
->Common
.Value
.Integer
),
497 (UINT32
) ObjDesc
->Integer
.Value
));
504 ACPI_ERROR ((AE_INFO
, "Unknown Integer type 0x%X",
506 Status
= AE_AML_OPERAND_TYPE
;
511 case ACPI_TYPE_STRING
:
513 ObjDesc
->String
.Pointer
= Op
->Common
.Value
.String
;
514 ObjDesc
->String
.Length
= (UINT32
) strlen (Op
->Common
.Value
.String
);
517 * The string is contained in the ACPI table, don't ever try
520 ObjDesc
->Common
.Flags
|= AOPOBJ_STATIC_POINTER
;
523 case ACPI_TYPE_METHOD
:
526 case ACPI_TYPE_LOCAL_REFERENCE
:
528 switch (OpInfo
->Type
)
530 case AML_TYPE_LOCAL_VARIABLE
:
532 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
534 ObjDesc
->Reference
.Value
= ((UINT32
) Opcode
) - AML_FIRST_LOCAL_OP
;
535 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_LOCAL
;
537 #ifndef ACPI_NO_METHOD_EXECUTION
538 Status
= AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL
,
539 ObjDesc
->Reference
.Value
, WalkState
,
540 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE
,
541 &ObjDesc
->Reference
.Object
));
545 case AML_TYPE_METHOD_ARGUMENT
:
547 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
549 ObjDesc
->Reference
.Value
= ((UINT32
) Opcode
) - AML_FIRST_ARG_OP
;
550 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_ARG
;
552 #ifndef ACPI_NO_METHOD_EXECUTION
553 Status
= AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG
,
554 ObjDesc
->Reference
.Value
, WalkState
,
555 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE
,
556 &ObjDesc
->Reference
.Object
));
560 default: /* Object name or Debug object */
562 switch (Op
->Common
.AmlOpcode
)
564 case AML_INT_NAMEPATH_OP
:
566 /* Node was saved in Op */
568 ObjDesc
->Reference
.Node
= Op
->Common
.Node
;
569 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_NAME
;
572 ObjDesc
->Reference
.Object
= Op
->Common
.Node
->Object
;
578 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_DEBUG
;
583 ACPI_ERROR ((AE_INFO
,
584 "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode
));
585 return_ACPI_STATUS (AE_AML_OPERAND_TYPE
);
593 ACPI_ERROR ((AE_INFO
, "Unimplemented data type: 0x%X",
594 ObjDesc
->Common
.Type
));
596 Status
= AE_AML_OPERAND_TYPE
;
600 return_ACPI_STATUS (Status
);