1 /******************************************************************************
3 * Module Name: dsobject - Dispatcher object management routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2017, 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 (Op
->Common
.Value
.String
, Status
);
119 return_ACPI_STATUS (Status
);
127 /* Create and init a new internal ACPI object */
129 ObjDesc
= AcpiUtCreateInternalObject (
130 (AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
))->ObjectType
);
133 return_ACPI_STATUS (AE_NO_MEMORY
);
136 Status
= AcpiDsInitObjectFromOp (
137 WalkState
, Op
, Op
->Common
.AmlOpcode
, &ObjDesc
);
138 if (ACPI_FAILURE (Status
))
140 AcpiUtRemoveReference (ObjDesc
);
141 return_ACPI_STATUS (Status
);
145 * Handling for unresolved package reference elements.
146 * These are elements that are namepaths.
148 if ((Op
->Common
.Parent
->Common
.AmlOpcode
== AML_PACKAGE_OP
) ||
149 (Op
->Common
.Parent
->Common
.AmlOpcode
== AML_VARIABLE_PACKAGE_OP
))
151 ObjDesc
->Reference
.Resolved
= TRUE
;
153 if ((Op
->Common
.AmlOpcode
== AML_INT_NAMEPATH_OP
) &&
154 !ObjDesc
->Reference
.Node
)
157 * Name was unresolved above.
158 * Get the prefix node for later lookup
160 ObjDesc
->Reference
.Node
= WalkState
->ScopeInfo
->Scope
.Node
;
161 ObjDesc
->Reference
.Aml
= Op
->Common
.Aml
;
162 ObjDesc
->Reference
.Resolved
= FALSE
;
166 *ObjDescPtr
= ObjDesc
;
167 return_ACPI_STATUS (Status
);
171 /*******************************************************************************
173 * FUNCTION: AcpiDsBuildInternalBufferObj
175 * PARAMETERS: WalkState - Current walk state
176 * Op - Parser object to be translated
177 * BufferLength - Length of the buffer
178 * ObjDescPtr - Where the ACPI internal object is returned
182 * DESCRIPTION: Translate a parser Op package object to the equivalent
185 ******************************************************************************/
188 AcpiDsBuildInternalBufferObj (
189 ACPI_WALK_STATE
*WalkState
,
190 ACPI_PARSE_OBJECT
*Op
,
192 ACPI_OPERAND_OBJECT
**ObjDescPtr
)
194 ACPI_PARSE_OBJECT
*Arg
;
195 ACPI_OPERAND_OBJECT
*ObjDesc
;
196 ACPI_PARSE_OBJECT
*ByteList
;
197 UINT32 ByteListLength
= 0;
200 ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj
);
204 * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
205 * The buffer object already exists (from the NS node), otherwise it must
208 ObjDesc
= *ObjDescPtr
;
211 /* Create a new buffer object */
213 ObjDesc
= AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER
);
214 *ObjDescPtr
= ObjDesc
;
217 return_ACPI_STATUS (AE_NO_MEMORY
);
222 * Second arg is the buffer data (optional) ByteList can be either
223 * individual bytes or a string initializer. In either case, a
224 * ByteList appears in the AML.
226 Arg
= Op
->Common
.Value
.Arg
; /* skip first arg */
228 ByteList
= Arg
->Named
.Next
;
231 if (ByteList
->Common
.AmlOpcode
!= AML_INT_BYTELIST_OP
)
233 ACPI_ERROR ((AE_INFO
,
234 "Expecting bytelist, found AML opcode 0x%X in op %p",
235 ByteList
->Common
.AmlOpcode
, ByteList
));
237 AcpiUtRemoveReference (ObjDesc
);
241 ByteListLength
= (UINT32
) ByteList
->Common
.Value
.Integer
;
245 * The buffer length (number of bytes) will be the larger of:
246 * 1) The specified buffer length and
247 * 2) The length of the initializer byte list
249 ObjDesc
->Buffer
.Length
= BufferLength
;
250 if (ByteListLength
> BufferLength
)
252 ObjDesc
->Buffer
.Length
= ByteListLength
;
255 /* Allocate the buffer */
257 if (ObjDesc
->Buffer
.Length
== 0)
259 ObjDesc
->Buffer
.Pointer
= NULL
;
260 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
,
261 "Buffer defined with zero length in AML, creating\n"));
265 ObjDesc
->Buffer
.Pointer
=
266 ACPI_ALLOCATE_ZEROED (ObjDesc
->Buffer
.Length
);
267 if (!ObjDesc
->Buffer
.Pointer
)
269 AcpiUtDeleteObjectDesc (ObjDesc
);
270 return_ACPI_STATUS (AE_NO_MEMORY
);
273 /* Initialize buffer from the ByteList (if present) */
277 memcpy (ObjDesc
->Buffer
.Pointer
, ByteList
->Named
.Data
,
282 ObjDesc
->Buffer
.Flags
|= AOPOBJ_DATA_VALID
;
283 Op
->Common
.Node
= ACPI_CAST_PTR (ACPI_NAMESPACE_NODE
, ObjDesc
);
284 return_ACPI_STATUS (AE_OK
);
287 /*******************************************************************************
289 * FUNCTION: AcpiDsCreateNode
291 * PARAMETERS: WalkState - Current walk state
292 * Node - NS Node to be initialized
293 * Op - Parser object to be translated
297 * DESCRIPTION: Create the object to be associated with a namespace node
299 ******************************************************************************/
303 ACPI_WALK_STATE
*WalkState
,
304 ACPI_NAMESPACE_NODE
*Node
,
305 ACPI_PARSE_OBJECT
*Op
)
308 ACPI_OPERAND_OBJECT
*ObjDesc
;
311 ACPI_FUNCTION_TRACE_PTR (DsCreateNode
, Op
);
315 * Because of the execution pass through the non-control-method
316 * parts of the table, we can arrive here twice. Only init
317 * the named object node the first time through
319 if (AcpiNsGetAttachedObject (Node
))
321 return_ACPI_STATUS (AE_OK
);
324 if (!Op
->Common
.Value
.Arg
)
326 /* No arguments, there is nothing to do */
328 return_ACPI_STATUS (AE_OK
);
331 /* Build an internal object for the argument(s) */
333 Status
= AcpiDsBuildInternalObject (
334 WalkState
, Op
->Common
.Value
.Arg
, &ObjDesc
);
335 if (ACPI_FAILURE (Status
))
337 return_ACPI_STATUS (Status
);
340 /* Re-type the object according to its argument */
342 Node
->Type
= ObjDesc
->Common
.Type
;
344 /* Attach obj to node */
346 Status
= AcpiNsAttachObject (Node
, ObjDesc
, Node
->Type
);
348 /* Remove local reference to the object */
350 AcpiUtRemoveReference (ObjDesc
);
351 return_ACPI_STATUS (Status
);
354 #endif /* ACPI_NO_METHOD_EXECUTION */
357 /*******************************************************************************
359 * FUNCTION: AcpiDsInitObjectFromOp
361 * PARAMETERS: WalkState - Current walk state
362 * Op - Parser op used to init the internal object
363 * Opcode - AML opcode associated with the object
364 * RetObjDesc - Namespace object to be initialized
368 * DESCRIPTION: Initialize a namespace object from a parser Op and its
369 * associated arguments. The namespace object is a more compact
370 * representation of the Op and its arguments.
372 ******************************************************************************/
375 AcpiDsInitObjectFromOp (
376 ACPI_WALK_STATE
*WalkState
,
377 ACPI_PARSE_OBJECT
*Op
,
379 ACPI_OPERAND_OBJECT
**RetObjDesc
)
381 const ACPI_OPCODE_INFO
*OpInfo
;
382 ACPI_OPERAND_OBJECT
*ObjDesc
;
383 ACPI_STATUS Status
= AE_OK
;
386 ACPI_FUNCTION_TRACE (DsInitObjectFromOp
);
389 ObjDesc
= *RetObjDesc
;
390 OpInfo
= AcpiPsGetOpcodeInfo (Opcode
);
391 if (OpInfo
->Class
== AML_CLASS_UNKNOWN
)
395 return_ACPI_STATUS (AE_TYPE
);
398 /* Perform per-object initialization */
400 switch (ObjDesc
->Common
.Type
)
402 case ACPI_TYPE_BUFFER
:
404 * Defer evaluation of Buffer TermArg operand
406 ObjDesc
->Buffer
.Node
= ACPI_CAST_PTR (
407 ACPI_NAMESPACE_NODE
, WalkState
->Operands
[0]);
408 ObjDesc
->Buffer
.AmlStart
= Op
->Named
.Data
;
409 ObjDesc
->Buffer
.AmlLength
= Op
->Named
.Length
;
412 case ACPI_TYPE_PACKAGE
:
414 * Defer evaluation of Package TermArg operand and all
415 * package elements. (01/2017): We defer the element
416 * resolution to allow forward references from the package
417 * in order to provide compatibility with other ACPI
420 ObjDesc
->Package
.Node
= ACPI_CAST_PTR (
421 ACPI_NAMESPACE_NODE
, WalkState
->Operands
[0]);
425 return_ACPI_STATUS (AE_OK
);
428 ObjDesc
->Package
.AmlStart
= Op
->Named
.Data
;
429 ObjDesc
->Package
.AmlLength
= Op
->Named
.Length
;
432 case ACPI_TYPE_INTEGER
:
434 switch (OpInfo
->Type
)
436 case AML_TYPE_CONSTANT
:
438 * Resolve AML Constants here - AND ONLY HERE!
439 * All constants are integers.
440 * We mark the integer with a flag that indicates that it started
441 * life as a constant -- so that stores to constants will perform
442 * as expected (noop). ZeroOp is used as a placeholder for optional
445 ObjDesc
->Common
.Flags
= AOPOBJ_AML_CONSTANT
;
451 ObjDesc
->Integer
.Value
= 0;
456 ObjDesc
->Integer
.Value
= 1;
461 ObjDesc
->Integer
.Value
= ACPI_UINT64_MAX
;
463 /* Truncate value if we are executing from a 32-bit ACPI table */
465 #ifndef ACPI_NO_METHOD_EXECUTION
466 (void) AcpiExTruncateFor32bitTable (ObjDesc
);
470 case AML_REVISION_OP
:
472 ObjDesc
->Integer
.Value
= ACPI_CA_VERSION
;
477 ACPI_ERROR ((AE_INFO
,
478 "Unknown constant opcode 0x%X", Opcode
));
479 Status
= AE_AML_OPERAND_TYPE
;
484 case AML_TYPE_LITERAL
:
486 ObjDesc
->Integer
.Value
= Op
->Common
.Value
.Integer
;
488 #ifndef ACPI_NO_METHOD_EXECUTION
489 if (AcpiExTruncateFor32bitTable (ObjDesc
))
491 /* Warn if we found a 64-bit constant in a 32-bit table */
493 ACPI_WARNING ((AE_INFO
,
494 "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
495 ACPI_FORMAT_UINT64 (Op
->Common
.Value
.Integer
),
496 (UINT32
) ObjDesc
->Integer
.Value
));
503 ACPI_ERROR ((AE_INFO
, "Unknown Integer type 0x%X",
505 Status
= AE_AML_OPERAND_TYPE
;
510 case ACPI_TYPE_STRING
:
512 ObjDesc
->String
.Pointer
= Op
->Common
.Value
.String
;
513 ObjDesc
->String
.Length
= (UINT32
) strlen (Op
->Common
.Value
.String
);
516 * The string is contained in the ACPI table, don't ever try
519 ObjDesc
->Common
.Flags
|= AOPOBJ_STATIC_POINTER
;
522 case ACPI_TYPE_METHOD
:
525 case ACPI_TYPE_LOCAL_REFERENCE
:
527 switch (OpInfo
->Type
)
529 case AML_TYPE_LOCAL_VARIABLE
:
531 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
533 ObjDesc
->Reference
.Value
= ((UINT32
) Opcode
) - AML_FIRST_LOCAL_OP
;
534 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_LOCAL
;
536 #ifndef ACPI_NO_METHOD_EXECUTION
537 Status
= AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL
,
538 ObjDesc
->Reference
.Value
, WalkState
,
539 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE
,
540 &ObjDesc
->Reference
.Object
));
544 case AML_TYPE_METHOD_ARGUMENT
:
546 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
548 ObjDesc
->Reference
.Value
= ((UINT32
) Opcode
) - AML_FIRST_ARG_OP
;
549 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_ARG
;
551 #ifndef ACPI_NO_METHOD_EXECUTION
552 Status
= AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG
,
553 ObjDesc
->Reference
.Value
, WalkState
,
554 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE
,
555 &ObjDesc
->Reference
.Object
));
559 default: /* Object name or Debug object */
561 switch (Op
->Common
.AmlOpcode
)
563 case AML_INT_NAMEPATH_OP
:
565 /* Node was saved in Op */
567 ObjDesc
->Reference
.Node
= Op
->Common
.Node
;
568 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_NAME
;
571 ObjDesc
->Reference
.Object
= Op
->Common
.Node
->Object
;
577 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_DEBUG
;
582 ACPI_ERROR ((AE_INFO
,
583 "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode
));
584 return_ACPI_STATUS (AE_AML_OPERAND_TYPE
);
592 ACPI_ERROR ((AE_INFO
, "Unimplemented data type: 0x%X",
593 ObjDesc
->Common
.Type
));
595 Status
= AE_AML_OPERAND_TYPE
;
599 return_ACPI_STATUS (Status
);