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