1 /******************************************************************************
3 * Module Name: dsobject - Dispatcher object management routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2019, 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 /*******************************************************************************
58 * FUNCTION: AcpiDsBuildInternalObject
60 * PARAMETERS: WalkState - Current walk state
61 * Op - Parser object to be translated
62 * ObjDescPtr - Where the ACPI internal object is returned
66 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
67 * Simple objects are any objects other than a package object!
69 ******************************************************************************/
72 AcpiDsBuildInternalObject (
73 ACPI_WALK_STATE
*WalkState
,
74 ACPI_PARSE_OBJECT
*Op
,
75 ACPI_OPERAND_OBJECT
**ObjDescPtr
)
77 ACPI_OPERAND_OBJECT
*ObjDesc
;
81 ACPI_FUNCTION_TRACE (DsBuildInternalObject
);
85 if (Op
->Common
.AmlOpcode
== AML_INT_NAMEPATH_OP
)
88 * This is a named object reference. If this name was
89 * previously looked up in the namespace, it was stored in
90 * this op. Otherwise, go ahead and look it up now
94 /* Check if we are resolving a named reference within a package */
96 if ((Op
->Common
.Parent
->Common
.AmlOpcode
== AML_PACKAGE_OP
) ||
97 (Op
->Common
.Parent
->Common
.AmlOpcode
== AML_VARIABLE_PACKAGE_OP
))
100 * We won't resolve package elements here, we will do this
101 * after all ACPI tables are loaded into the namespace. This
102 * behavior supports both forward references to named objects
103 * and external references to objects in other tables.
105 goto CreateNewObject
;
109 Status
= AcpiNsLookup (WalkState
->ScopeInfo
,
110 Op
->Common
.Value
.String
,
111 ACPI_TYPE_ANY
, ACPI_IMODE_EXECUTE
,
112 ACPI_NS_SEARCH_PARENT
| ACPI_NS_DONT_OPEN_SCOPE
, NULL
,
113 ACPI_CAST_INDIRECT_PTR (
114 ACPI_NAMESPACE_NODE
, &(Op
->Common
.Node
)));
115 if (ACPI_FAILURE (Status
))
117 ACPI_ERROR_NAMESPACE (WalkState
->ScopeInfo
,
118 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
);
355 /*******************************************************************************
357 * FUNCTION: AcpiDsInitObjectFromOp
359 * PARAMETERS: WalkState - Current walk state
360 * Op - Parser op used to init the internal object
361 * Opcode - AML opcode associated with the object
362 * RetObjDesc - Namespace object to be initialized
366 * DESCRIPTION: Initialize a namespace object from a parser Op and its
367 * associated arguments. The namespace object is a more compact
368 * representation of the Op and its arguments.
370 ******************************************************************************/
373 AcpiDsInitObjectFromOp (
374 ACPI_WALK_STATE
*WalkState
,
375 ACPI_PARSE_OBJECT
*Op
,
377 ACPI_OPERAND_OBJECT
**RetObjDesc
)
379 const ACPI_OPCODE_INFO
*OpInfo
;
380 ACPI_OPERAND_OBJECT
*ObjDesc
;
381 ACPI_STATUS Status
= AE_OK
;
384 ACPI_FUNCTION_TRACE (DsInitObjectFromOp
);
387 ObjDesc
= *RetObjDesc
;
388 OpInfo
= AcpiPsGetOpcodeInfo (Opcode
);
389 if (OpInfo
->Class
== AML_CLASS_UNKNOWN
)
393 return_ACPI_STATUS (AE_TYPE
);
396 /* Perform per-object initialization */
398 switch (ObjDesc
->Common
.Type
)
400 case ACPI_TYPE_BUFFER
:
402 * Defer evaluation of Buffer TermArg operand
404 ObjDesc
->Buffer
.Node
= ACPI_CAST_PTR (
405 ACPI_NAMESPACE_NODE
, WalkState
->Operands
[0]);
406 ObjDesc
->Buffer
.AmlStart
= Op
->Named
.Data
;
407 ObjDesc
->Buffer
.AmlLength
= Op
->Named
.Length
;
410 case ACPI_TYPE_PACKAGE
:
412 * Defer evaluation of Package TermArg operand and all
413 * package elements. (01/2017): We defer the element
414 * resolution to allow forward references from the package
415 * in order to provide compatibility with other ACPI
418 ObjDesc
->Package
.Node
= ACPI_CAST_PTR (
419 ACPI_NAMESPACE_NODE
, WalkState
->Operands
[0]);
423 return_ACPI_STATUS (AE_OK
);
426 ObjDesc
->Package
.AmlStart
= Op
->Named
.Data
;
427 ObjDesc
->Package
.AmlLength
= Op
->Named
.Length
;
430 case ACPI_TYPE_INTEGER
:
432 switch (OpInfo
->Type
)
434 case AML_TYPE_CONSTANT
:
436 * Resolve AML Constants here - AND ONLY HERE!
437 * All constants are integers.
438 * We mark the integer with a flag that indicates that it started
439 * life as a constant -- so that stores to constants will perform
440 * as expected (noop). ZeroOp is used as a placeholder for optional
443 ObjDesc
->Common
.Flags
= AOPOBJ_AML_CONSTANT
;
449 ObjDesc
->Integer
.Value
= 0;
454 ObjDesc
->Integer
.Value
= 1;
459 ObjDesc
->Integer
.Value
= ACPI_UINT64_MAX
;
461 /* Truncate value if we are executing from a 32-bit ACPI table */
463 (void) AcpiExTruncateFor32bitTable (ObjDesc
);
466 case AML_REVISION_OP
:
468 ObjDesc
->Integer
.Value
= ACPI_CA_VERSION
;
473 ACPI_ERROR ((AE_INFO
,
474 "Unknown constant opcode 0x%X", Opcode
));
475 Status
= AE_AML_OPERAND_TYPE
;
480 case AML_TYPE_LITERAL
:
482 ObjDesc
->Integer
.Value
= Op
->Common
.Value
.Integer
;
484 if (AcpiExTruncateFor32bitTable (ObjDesc
))
486 /* Warn if we found a 64-bit constant in a 32-bit table */
488 ACPI_WARNING ((AE_INFO
,
489 "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
490 ACPI_FORMAT_UINT64 (Op
->Common
.Value
.Integer
),
491 (UINT32
) ObjDesc
->Integer
.Value
));
497 ACPI_ERROR ((AE_INFO
, "Unknown Integer type 0x%X",
499 Status
= AE_AML_OPERAND_TYPE
;
504 case ACPI_TYPE_STRING
:
506 ObjDesc
->String
.Pointer
= Op
->Common
.Value
.String
;
507 ObjDesc
->String
.Length
= (UINT32
) strlen (Op
->Common
.Value
.String
);
510 * The string is contained in the ACPI table, don't ever try
513 ObjDesc
->Common
.Flags
|= AOPOBJ_STATIC_POINTER
;
516 case ACPI_TYPE_METHOD
:
519 case ACPI_TYPE_LOCAL_REFERENCE
:
521 switch (OpInfo
->Type
)
523 case AML_TYPE_LOCAL_VARIABLE
:
525 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
527 ObjDesc
->Reference
.Value
= ((UINT32
) Opcode
) - AML_FIRST_LOCAL_OP
;
528 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_LOCAL
;
530 Status
= AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL
,
531 ObjDesc
->Reference
.Value
, WalkState
,
532 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE
,
533 &ObjDesc
->Reference
.Object
));
536 case AML_TYPE_METHOD_ARGUMENT
:
538 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
540 ObjDesc
->Reference
.Value
= ((UINT32
) Opcode
) - AML_FIRST_ARG_OP
;
541 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_ARG
;
543 Status
= AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG
,
544 ObjDesc
->Reference
.Value
, WalkState
,
545 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE
,
546 &ObjDesc
->Reference
.Object
));
549 default: /* Object name or Debug object */
551 switch (Op
->Common
.AmlOpcode
)
553 case AML_INT_NAMEPATH_OP
:
555 /* Node was saved in Op */
557 ObjDesc
->Reference
.Node
= Op
->Common
.Node
;
558 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_NAME
;
561 ObjDesc
->Reference
.Object
= Op
->Common
.Node
->Object
;
567 ObjDesc
->Reference
.Class
= ACPI_REFCLASS_DEBUG
;
572 ACPI_ERROR ((AE_INFO
,
573 "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode
));
574 return_ACPI_STATUS (AE_AML_OPERAND_TYPE
);
582 ACPI_ERROR ((AE_INFO
, "Unimplemented data type: 0x%X",
583 ObjDesc
->Common
.Type
));
585 Status
= AE_AML_OPERAND_TYPE
;
589 return_ACPI_STATUS (Status
);