[ACPICA]
[reactos.git] / reactos / drivers / bus / acpi / acpica / dispatcher / dsobject.c
1 /******************************************************************************
2 *
3 * Module Name: dsobject - Dispatcher object management routines
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2017, 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 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.
42 */
43
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acdispat.h"
49 #include "acnamesp.h"
50 #include "acinterp.h"
51
52 #define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME ("dsobject")
54
55
56 #ifndef ACPI_NO_METHOD_EXECUTION
57 /*******************************************************************************
58 *
59 * FUNCTION: AcpiDsBuildInternalObject
60 *
61 * PARAMETERS: WalkState - Current walk state
62 * Op - Parser object to be translated
63 * ObjDescPtr - Where the ACPI internal object is returned
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
68 * Simple objects are any objects other than a package object!
69 *
70 ******************************************************************************/
71
72 ACPI_STATUS
73 AcpiDsBuildInternalObject (
74 ACPI_WALK_STATE *WalkState,
75 ACPI_PARSE_OBJECT *Op,
76 ACPI_OPERAND_OBJECT **ObjDescPtr)
77 {
78 ACPI_OPERAND_OBJECT *ObjDesc;
79 ACPI_STATUS Status;
80
81
82 ACPI_FUNCTION_TRACE (DsBuildInternalObject);
83
84
85 *ObjDescPtr = NULL;
86 if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
87 {
88 /*
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
92 */
93 if (!Op->Common.Node)
94 {
95 /* Check if we are resolving a named reference within a package */
96
97 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
98 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
99 {
100 /*
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.
105 */
106 goto CreateNewObject;
107 }
108 else
109 {
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))
117 {
118 ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status);
119 return_ACPI_STATUS (Status);
120 }
121 }
122 }
123 }
124
125 CreateNewObject:
126
127 /* Create and init a new internal ACPI object */
128
129 ObjDesc = AcpiUtCreateInternalObject (
130 (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
131 if (!ObjDesc)
132 {
133 return_ACPI_STATUS (AE_NO_MEMORY);
134 }
135
136 Status = AcpiDsInitObjectFromOp (
137 WalkState, Op, Op->Common.AmlOpcode, &ObjDesc);
138 if (ACPI_FAILURE (Status))
139 {
140 AcpiUtRemoveReference (ObjDesc);
141 return_ACPI_STATUS (Status);
142 }
143
144 /*
145 * Handling for unresolved package reference elements.
146 * These are elements that are namepaths.
147 */
148 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
149 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
150 {
151 ObjDesc->Reference.Resolved = TRUE;
152
153 if ((Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
154 !ObjDesc->Reference.Node)
155 {
156 /*
157 * Name was unresolved above.
158 * Get the prefix node for later lookup
159 */
160 ObjDesc->Reference.Node = WalkState->ScopeInfo->Scope.Node;
161 ObjDesc->Reference.Aml = Op->Common.Aml;
162 ObjDesc->Reference.Resolved = FALSE;
163 }
164 }
165
166 *ObjDescPtr = ObjDesc;
167 return_ACPI_STATUS (Status);
168 }
169
170
171 /*******************************************************************************
172 *
173 * FUNCTION: AcpiDsBuildInternalBufferObj
174 *
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
179 *
180 * RETURN: Status
181 *
182 * DESCRIPTION: Translate a parser Op package object to the equivalent
183 * namespace object
184 *
185 ******************************************************************************/
186
187 ACPI_STATUS
188 AcpiDsBuildInternalBufferObj (
189 ACPI_WALK_STATE *WalkState,
190 ACPI_PARSE_OBJECT *Op,
191 UINT32 BufferLength,
192 ACPI_OPERAND_OBJECT **ObjDescPtr)
193 {
194 ACPI_PARSE_OBJECT *Arg;
195 ACPI_OPERAND_OBJECT *ObjDesc;
196 ACPI_PARSE_OBJECT *ByteList;
197 UINT32 ByteListLength = 0;
198
199
200 ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj);
201
202
203 /*
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
206 * be created.
207 */
208 ObjDesc = *ObjDescPtr;
209 if (!ObjDesc)
210 {
211 /* Create a new buffer object */
212
213 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER);
214 *ObjDescPtr = ObjDesc;
215 if (!ObjDesc)
216 {
217 return_ACPI_STATUS (AE_NO_MEMORY);
218 }
219 }
220
221 /*
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.
225 */
226 Arg = Op->Common.Value.Arg; /* skip first arg */
227
228 ByteList = Arg->Named.Next;
229 if (ByteList)
230 {
231 if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP)
232 {
233 ACPI_ERROR ((AE_INFO,
234 "Expecting bytelist, found AML opcode 0x%X in op %p",
235 ByteList->Common.AmlOpcode, ByteList));
236
237 AcpiUtRemoveReference (ObjDesc);
238 return (AE_TYPE);
239 }
240
241 ByteListLength = (UINT32) ByteList->Common.Value.Integer;
242 }
243
244 /*
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
248 */
249 ObjDesc->Buffer.Length = BufferLength;
250 if (ByteListLength > BufferLength)
251 {
252 ObjDesc->Buffer.Length = ByteListLength;
253 }
254
255 /* Allocate the buffer */
256
257 if (ObjDesc->Buffer.Length == 0)
258 {
259 ObjDesc->Buffer.Pointer = NULL;
260 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
261 "Buffer defined with zero length in AML, creating\n"));
262 }
263 else
264 {
265 ObjDesc->Buffer.Pointer =
266 ACPI_ALLOCATE_ZEROED (ObjDesc->Buffer.Length);
267 if (!ObjDesc->Buffer.Pointer)
268 {
269 AcpiUtDeleteObjectDesc (ObjDesc);
270 return_ACPI_STATUS (AE_NO_MEMORY);
271 }
272
273 /* Initialize buffer from the ByteList (if present) */
274
275 if (ByteList)
276 {
277 memcpy (ObjDesc->Buffer.Pointer, ByteList->Named.Data,
278 ByteListLength);
279 }
280 }
281
282 ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID;
283 Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
284 return_ACPI_STATUS (AE_OK);
285 }
286
287 /*******************************************************************************
288 *
289 * FUNCTION: AcpiDsCreateNode
290 *
291 * PARAMETERS: WalkState - Current walk state
292 * Node - NS Node to be initialized
293 * Op - Parser object to be translated
294 *
295 * RETURN: Status
296 *
297 * DESCRIPTION: Create the object to be associated with a namespace node
298 *
299 ******************************************************************************/
300
301 ACPI_STATUS
302 AcpiDsCreateNode (
303 ACPI_WALK_STATE *WalkState,
304 ACPI_NAMESPACE_NODE *Node,
305 ACPI_PARSE_OBJECT *Op)
306 {
307 ACPI_STATUS Status;
308 ACPI_OPERAND_OBJECT *ObjDesc;
309
310
311 ACPI_FUNCTION_TRACE_PTR (DsCreateNode, Op);
312
313
314 /*
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
318 */
319 if (AcpiNsGetAttachedObject (Node))
320 {
321 return_ACPI_STATUS (AE_OK);
322 }
323
324 if (!Op->Common.Value.Arg)
325 {
326 /* No arguments, there is nothing to do */
327
328 return_ACPI_STATUS (AE_OK);
329 }
330
331 /* Build an internal object for the argument(s) */
332
333 Status = AcpiDsBuildInternalObject (
334 WalkState, Op->Common.Value.Arg, &ObjDesc);
335 if (ACPI_FAILURE (Status))
336 {
337 return_ACPI_STATUS (Status);
338 }
339
340 /* Re-type the object according to its argument */
341
342 Node->Type = ObjDesc->Common.Type;
343
344 /* Attach obj to node */
345
346 Status = AcpiNsAttachObject (Node, ObjDesc, Node->Type);
347
348 /* Remove local reference to the object */
349
350 AcpiUtRemoveReference (ObjDesc);
351 return_ACPI_STATUS (Status);
352 }
353
354 #endif /* ACPI_NO_METHOD_EXECUTION */
355
356
357 /*******************************************************************************
358 *
359 * FUNCTION: AcpiDsInitObjectFromOp
360 *
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
365 *
366 * RETURN: Status
367 *
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.
371 *
372 ******************************************************************************/
373
374 ACPI_STATUS
375 AcpiDsInitObjectFromOp (
376 ACPI_WALK_STATE *WalkState,
377 ACPI_PARSE_OBJECT *Op,
378 UINT16 Opcode,
379 ACPI_OPERAND_OBJECT **RetObjDesc)
380 {
381 const ACPI_OPCODE_INFO *OpInfo;
382 ACPI_OPERAND_OBJECT *ObjDesc;
383 ACPI_STATUS Status = AE_OK;
384
385
386 ACPI_FUNCTION_TRACE (DsInitObjectFromOp);
387
388
389 ObjDesc = *RetObjDesc;
390 OpInfo = AcpiPsGetOpcodeInfo (Opcode);
391 if (OpInfo->Class == AML_CLASS_UNKNOWN)
392 {
393 /* Unknown opcode */
394
395 return_ACPI_STATUS (AE_TYPE);
396 }
397
398 /* Perform per-object initialization */
399
400 switch (ObjDesc->Common.Type)
401 {
402 case ACPI_TYPE_BUFFER:
403 /*
404 * Defer evaluation of Buffer TermArg operand
405 */
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;
410 break;
411
412 case ACPI_TYPE_PACKAGE:
413 /*
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
418 * implementations.
419 */
420 ObjDesc->Package.Node = ACPI_CAST_PTR (
421 ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
422
423 if (!Op->Named.Data)
424 {
425 return_ACPI_STATUS (AE_OK);
426 }
427
428 ObjDesc->Package.AmlStart = Op->Named.Data;
429 ObjDesc->Package.AmlLength = Op->Named.Length;
430 break;
431
432 case ACPI_TYPE_INTEGER:
433
434 switch (OpInfo->Type)
435 {
436 case AML_TYPE_CONSTANT:
437 /*
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
443 * target operands.
444 */
445 ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT;
446
447 switch (Opcode)
448 {
449 case AML_ZERO_OP:
450
451 ObjDesc->Integer.Value = 0;
452 break;
453
454 case AML_ONE_OP:
455
456 ObjDesc->Integer.Value = 1;
457 break;
458
459 case AML_ONES_OP:
460
461 ObjDesc->Integer.Value = ACPI_UINT64_MAX;
462
463 /* Truncate value if we are executing from a 32-bit ACPI table */
464
465 #ifndef ACPI_NO_METHOD_EXECUTION
466 (void) AcpiExTruncateFor32bitTable (ObjDesc);
467 #endif
468 break;
469
470 case AML_REVISION_OP:
471
472 ObjDesc->Integer.Value = ACPI_CA_VERSION;
473 break;
474
475 default:
476
477 ACPI_ERROR ((AE_INFO,
478 "Unknown constant opcode 0x%X", Opcode));
479 Status = AE_AML_OPERAND_TYPE;
480 break;
481 }
482 break;
483
484 case AML_TYPE_LITERAL:
485
486 ObjDesc->Integer.Value = Op->Common.Value.Integer;
487
488 #ifndef ACPI_NO_METHOD_EXECUTION
489 if (AcpiExTruncateFor32bitTable (ObjDesc))
490 {
491 /* Warn if we found a 64-bit constant in a 32-bit table */
492
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));
497 }
498 #endif
499 break;
500
501 default:
502
503 ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X",
504 OpInfo->Type));
505 Status = AE_AML_OPERAND_TYPE;
506 break;
507 }
508 break;
509
510 case ACPI_TYPE_STRING:
511
512 ObjDesc->String.Pointer = Op->Common.Value.String;
513 ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String);
514
515 /*
516 * The string is contained in the ACPI table, don't ever try
517 * to delete it
518 */
519 ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
520 break;
521
522 case ACPI_TYPE_METHOD:
523 break;
524
525 case ACPI_TYPE_LOCAL_REFERENCE:
526
527 switch (OpInfo->Type)
528 {
529 case AML_TYPE_LOCAL_VARIABLE:
530
531 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
532
533 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_LOCAL_OP;
534 ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL;
535
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));
541 #endif
542 break;
543
544 case AML_TYPE_METHOD_ARGUMENT:
545
546 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
547
548 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_ARG_OP;
549 ObjDesc->Reference.Class = ACPI_REFCLASS_ARG;
550
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));
556 #endif
557 break;
558
559 default: /* Object name or Debug object */
560
561 switch (Op->Common.AmlOpcode)
562 {
563 case AML_INT_NAMEPATH_OP:
564
565 /* Node was saved in Op */
566
567 ObjDesc->Reference.Node = Op->Common.Node;
568 ObjDesc->Reference.Class = ACPI_REFCLASS_NAME;
569 if (Op->Common.Node)
570 {
571 ObjDesc->Reference.Object = Op->Common.Node->Object;
572 }
573 break;
574
575 case AML_DEBUG_OP:
576
577 ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG;
578 break;
579
580 default:
581
582 ACPI_ERROR ((AE_INFO,
583 "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode));
584 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
585 }
586 break;
587 }
588 break;
589
590 default:
591
592 ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X",
593 ObjDesc->Common.Type));
594
595 Status = AE_AML_OPERAND_TYPE;
596 break;
597 }
598
599 return_ACPI_STATUS (Status);
600 }