[ACPICA] Update to version 20190108. CORE-15593
[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 - 2019, 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 /*******************************************************************************
57 *
58 * FUNCTION: AcpiDsBuildInternalObject
59 *
60 * PARAMETERS: WalkState - Current walk state
61 * Op - Parser object to be translated
62 * ObjDescPtr - Where the ACPI internal object is returned
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
67 * Simple objects are any objects other than a package object!
68 *
69 ******************************************************************************/
70
71 ACPI_STATUS
72 AcpiDsBuildInternalObject (
73 ACPI_WALK_STATE *WalkState,
74 ACPI_PARSE_OBJECT *Op,
75 ACPI_OPERAND_OBJECT **ObjDescPtr)
76 {
77 ACPI_OPERAND_OBJECT *ObjDesc;
78 ACPI_STATUS Status;
79
80
81 ACPI_FUNCTION_TRACE (DsBuildInternalObject);
82
83
84 *ObjDescPtr = NULL;
85 if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
86 {
87 /*
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
91 */
92 if (!Op->Common.Node)
93 {
94 /* Check if we are resolving a named reference within a package */
95
96 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
97 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
98 {
99 /*
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.
104 */
105 goto CreateNewObject;
106 }
107 else
108 {
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))
116 {
117 ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
118 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
355 /*******************************************************************************
356 *
357 * FUNCTION: AcpiDsInitObjectFromOp
358 *
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
363 *
364 * RETURN: Status
365 *
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.
369 *
370 ******************************************************************************/
371
372 ACPI_STATUS
373 AcpiDsInitObjectFromOp (
374 ACPI_WALK_STATE *WalkState,
375 ACPI_PARSE_OBJECT *Op,
376 UINT16 Opcode,
377 ACPI_OPERAND_OBJECT **RetObjDesc)
378 {
379 const ACPI_OPCODE_INFO *OpInfo;
380 ACPI_OPERAND_OBJECT *ObjDesc;
381 ACPI_STATUS Status = AE_OK;
382
383
384 ACPI_FUNCTION_TRACE (DsInitObjectFromOp);
385
386
387 ObjDesc = *RetObjDesc;
388 OpInfo = AcpiPsGetOpcodeInfo (Opcode);
389 if (OpInfo->Class == AML_CLASS_UNKNOWN)
390 {
391 /* Unknown opcode */
392
393 return_ACPI_STATUS (AE_TYPE);
394 }
395
396 /* Perform per-object initialization */
397
398 switch (ObjDesc->Common.Type)
399 {
400 case ACPI_TYPE_BUFFER:
401 /*
402 * Defer evaluation of Buffer TermArg operand
403 */
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;
408 break;
409
410 case ACPI_TYPE_PACKAGE:
411 /*
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
416 * implementations.
417 */
418 ObjDesc->Package.Node = ACPI_CAST_PTR (
419 ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
420
421 if (!Op->Named.Data)
422 {
423 return_ACPI_STATUS (AE_OK);
424 }
425
426 ObjDesc->Package.AmlStart = Op->Named.Data;
427 ObjDesc->Package.AmlLength = Op->Named.Length;
428 break;
429
430 case ACPI_TYPE_INTEGER:
431
432 switch (OpInfo->Type)
433 {
434 case AML_TYPE_CONSTANT:
435 /*
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
441 * target operands.
442 */
443 ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT;
444
445 switch (Opcode)
446 {
447 case AML_ZERO_OP:
448
449 ObjDesc->Integer.Value = 0;
450 break;
451
452 case AML_ONE_OP:
453
454 ObjDesc->Integer.Value = 1;
455 break;
456
457 case AML_ONES_OP:
458
459 ObjDesc->Integer.Value = ACPI_UINT64_MAX;
460
461 /* Truncate value if we are executing from a 32-bit ACPI table */
462
463 (void) AcpiExTruncateFor32bitTable (ObjDesc);
464 break;
465
466 case AML_REVISION_OP:
467
468 ObjDesc->Integer.Value = ACPI_CA_VERSION;
469 break;
470
471 default:
472
473 ACPI_ERROR ((AE_INFO,
474 "Unknown constant opcode 0x%X", Opcode));
475 Status = AE_AML_OPERAND_TYPE;
476 break;
477 }
478 break;
479
480 case AML_TYPE_LITERAL:
481
482 ObjDesc->Integer.Value = Op->Common.Value.Integer;
483
484 if (AcpiExTruncateFor32bitTable (ObjDesc))
485 {
486 /* Warn if we found a 64-bit constant in a 32-bit table */
487
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));
492 }
493 break;
494
495 default:
496
497 ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X",
498 OpInfo->Type));
499 Status = AE_AML_OPERAND_TYPE;
500 break;
501 }
502 break;
503
504 case ACPI_TYPE_STRING:
505
506 ObjDesc->String.Pointer = Op->Common.Value.String;
507 ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String);
508
509 /*
510 * The string is contained in the ACPI table, don't ever try
511 * to delete it
512 */
513 ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
514 break;
515
516 case ACPI_TYPE_METHOD:
517 break;
518
519 case ACPI_TYPE_LOCAL_REFERENCE:
520
521 switch (OpInfo->Type)
522 {
523 case AML_TYPE_LOCAL_VARIABLE:
524
525 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
526
527 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_LOCAL_OP;
528 ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL;
529
530 Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL,
531 ObjDesc->Reference.Value, WalkState,
532 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
533 &ObjDesc->Reference.Object));
534 break;
535
536 case AML_TYPE_METHOD_ARGUMENT:
537
538 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
539
540 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_ARG_OP;
541 ObjDesc->Reference.Class = ACPI_REFCLASS_ARG;
542
543 Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG,
544 ObjDesc->Reference.Value, WalkState,
545 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
546 &ObjDesc->Reference.Object));
547 break;
548
549 default: /* Object name or Debug object */
550
551 switch (Op->Common.AmlOpcode)
552 {
553 case AML_INT_NAMEPATH_OP:
554
555 /* Node was saved in Op */
556
557 ObjDesc->Reference.Node = Op->Common.Node;
558 ObjDesc->Reference.Class = ACPI_REFCLASS_NAME;
559 if (Op->Common.Node)
560 {
561 ObjDesc->Reference.Object = Op->Common.Node->Object;
562 }
563 break;
564
565 case AML_DEBUG_OP:
566
567 ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG;
568 break;
569
570 default:
571
572 ACPI_ERROR ((AE_INFO,
573 "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode));
574 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
575 }
576 break;
577 }
578 break;
579
580 default:
581
582 ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X",
583 ObjDesc->Common.Type));
584
585 Status = AE_AML_OPERAND_TYPE;
586 break;
587 }
588
589 return_ACPI_STATUS (Status);
590 }