dsobject.c revision 1.1.1.14 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 /*******************************************************************************
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 *
358 * FUNCTION: AcpiDsInitObjectFromOp
359 *
360 * PARAMETERS: WalkState - Current walk state
361 * Op - Parser op used to init the internal object
362 * Opcode - AML opcode associated with the object
363 * RetObjDesc - Namespace object to be initialized
364 *
365 * RETURN: Status
366 *
367 * DESCRIPTION: Initialize a namespace object from a parser Op and its
368 * associated arguments. The namespace object is a more compact
369 * representation of the Op and its arguments.
370 *
371 ******************************************************************************/
372
373 ACPI_STATUS
374 AcpiDsInitObjectFromOp (
375 ACPI_WALK_STATE *WalkState,
376 ACPI_PARSE_OBJECT *Op,
377 UINT16 Opcode,
378 ACPI_OPERAND_OBJECT **RetObjDesc)
379 {
380 const ACPI_OPCODE_INFO *OpInfo;
381 ACPI_OPERAND_OBJECT *ObjDesc;
382 ACPI_STATUS Status = AE_OK;
383
384
385 ACPI_FUNCTION_TRACE (DsInitObjectFromOp);
386
387
388 ObjDesc = *RetObjDesc;
389 OpInfo = AcpiPsGetOpcodeInfo (Opcode);
390 if (OpInfo->Class == AML_CLASS_UNKNOWN)
391 {
392 /* Unknown opcode */
393
394 return_ACPI_STATUS (AE_TYPE);
395 }
396
397 /* Perform per-object initialization */
398
399 switch (ObjDesc->Common.Type)
400 {
401 case ACPI_TYPE_BUFFER:
402 /*
403 * Defer evaluation of Buffer TermArg operand
404 */
405 ObjDesc->Buffer.Node = ACPI_CAST_PTR (
406 ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
407 ObjDesc->Buffer.AmlStart = Op->Named.Data;
408 ObjDesc->Buffer.AmlLength = Op->Named.Length;
409 break;
410
411 case ACPI_TYPE_PACKAGE:
412 /*
413 * Defer evaluation of Package TermArg operand and all
414 * package elements. (01/2017): We defer the element
415 * resolution to allow forward references from the package
416 * in order to provide compatibility with other ACPI
417 * implementations.
418 */
419 ObjDesc->Package.Node = ACPI_CAST_PTR (
420 ACPI_NAMESPACE_NODE, WalkState->Operands[0]);
421
422 if (!Op->Named.Data)
423 {
424 return_ACPI_STATUS (AE_OK);
425 }
426
427 ObjDesc->Package.AmlStart = Op->Named.Data;
428 ObjDesc->Package.AmlLength = Op->Named.Length;
429 break;
430
431 case ACPI_TYPE_INTEGER:
432
433 switch (OpInfo->Type)
434 {
435 case AML_TYPE_CONSTANT:
436 /*
437 * Resolve AML Constants here - AND ONLY HERE!
438 * All constants are integers.
439 * We mark the integer with a flag that indicates that it started
440 * life as a constant -- so that stores to constants will perform
441 * as expected (noop). ZeroOp is used as a placeholder for optional
442 * target operands.
443 */
444 ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT;
445
446 switch (Opcode)
447 {
448 case AML_ZERO_OP:
449
450 ObjDesc->Integer.Value = 0;
451 break;
452
453 case AML_ONE_OP:
454
455 ObjDesc->Integer.Value = 1;
456 break;
457
458 case AML_ONES_OP:
459
460 ObjDesc->Integer.Value = ACPI_UINT64_MAX;
461
462 /* Truncate value if we are executing from a 32-bit ACPI table */
463
464 (void) AcpiExTruncateFor32bitTable (ObjDesc);
465 break;
466
467 case AML_REVISION_OP:
468
469 ObjDesc->Integer.Value = ACPI_CA_VERSION;
470 break;
471
472 default:
473
474 ACPI_ERROR ((AE_INFO,
475 "Unknown constant opcode 0x%X", Opcode));
476 Status = AE_AML_OPERAND_TYPE;
477 break;
478 }
479 break;
480
481 case AML_TYPE_LITERAL:
482
483 ObjDesc->Integer.Value = Op->Common.Value.Integer;
484
485 if (AcpiExTruncateFor32bitTable (ObjDesc))
486 {
487 /* Warn if we found a 64-bit constant in a 32-bit table */
488
489 ACPI_WARNING ((AE_INFO,
490 "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
491 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
492 (UINT32) ObjDesc->Integer.Value));
493 }
494 break;
495
496 default:
497
498 ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X",
499 OpInfo->Type));
500 Status = AE_AML_OPERAND_TYPE;
501 break;
502 }
503 break;
504
505 case ACPI_TYPE_STRING:
506
507 ObjDesc->String.Pointer = Op->Common.Value.String;
508 ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String);
509
510 /*
511 * The string is contained in the ACPI table, don't ever try
512 * to delete it
513 */
514 ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
515 break;
516
517 case ACPI_TYPE_METHOD:
518 break;
519
520 case ACPI_TYPE_LOCAL_REFERENCE:
521
522 switch (OpInfo->Type)
523 {
524 case AML_TYPE_LOCAL_VARIABLE:
525
526 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
527
528 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_LOCAL_OP;
529 ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL;
530
531 Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL,
532 ObjDesc->Reference.Value, WalkState,
533 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
534 &ObjDesc->Reference.Object));
535 break;
536
537 case AML_TYPE_METHOD_ARGUMENT:
538
539 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
540
541 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_ARG_OP;
542 ObjDesc->Reference.Class = ACPI_REFCLASS_ARG;
543
544 Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG,
545 ObjDesc->Reference.Value, WalkState,
546 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
547 &ObjDesc->Reference.Object));
548 break;
549
550 default: /* Object name or Debug object */
551
552 switch (Op->Common.AmlOpcode)
553 {
554 case AML_INT_NAMEPATH_OP:
555
556 /* Node was saved in Op */
557
558 ObjDesc->Reference.Node = Op->Common.Node;
559 ObjDesc->Reference.Class = ACPI_REFCLASS_NAME;
560 if (Op->Common.Node)
561 {
562 ObjDesc->Reference.Object = Op->Common.Node->Object;
563 }
564 break;
565
566 case AML_DEBUG_OP:
567
568 ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG;
569 break;
570
571 default:
572
573 ACPI_ERROR ((AE_INFO,
574 "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode));
575 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
576 }
577 break;
578 }
579 break;
580
581 default:
582
583 ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X",
584 ObjDesc->Common.Type));
585
586 Status = AE_AML_OPERAND_TYPE;
587 break;
588 }
589
590 return_ACPI_STATUS (Status);
591 }
592