1 | /****************************************************************************** |
2 | * |
3 | * Module Name: dsobject - Dispatcher object management routines |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, 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 | /* Local prototypes */ |
56 | |
57 | static ACPI_STATUS |
58 | AcpiDsBuildInternalObject ( |
59 | ACPI_WALK_STATE *WalkState, |
60 | ACPI_PARSE_OBJECT *Op, |
61 | ACPI_OPERAND_OBJECT **ObjDescPtr); |
62 | |
63 | |
64 | #ifndef ACPI_NO_METHOD_EXECUTION |
65 | /******************************************************************************* |
66 | * |
67 | * FUNCTION: AcpiDsBuildInternalObject |
68 | * |
69 | * PARAMETERS: WalkState - Current walk state |
70 | * Op - Parser object to be translated |
71 | * ObjDescPtr - Where the ACPI internal object is returned |
72 | * |
73 | * RETURN: Status |
74 | * |
75 | * DESCRIPTION: Translate a parser Op object to the equivalent namespace object |
76 | * Simple objects are any objects other than a package object! |
77 | * |
78 | ******************************************************************************/ |
79 | |
80 | static ACPI_STATUS |
81 | AcpiDsBuildInternalObject ( |
82 | ACPI_WALK_STATE *WalkState, |
83 | ACPI_PARSE_OBJECT *Op, |
84 | ACPI_OPERAND_OBJECT **ObjDescPtr) |
85 | { |
86 | ACPI_OPERAND_OBJECT *ObjDesc; |
87 | ACPI_STATUS Status; |
88 | ACPI_OBJECT_TYPE Type; |
89 | |
90 | |
91 | ACPI_FUNCTION_TRACE (DsBuildInternalObject); |
92 | |
93 | |
94 | *ObjDescPtr = NULL; |
95 | if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) |
96 | { |
97 | /* |
98 | * This is a named object reference. If this name was |
99 | * previously looked up in the namespace, it was stored in this op. |
100 | * Otherwise, go ahead and look it up now |
101 | */ |
102 | if (!Op->Common.Node) |
103 | { |
104 | Status = AcpiNsLookup (WalkState->ScopeInfo, |
105 | Op->Common.Value.String, |
106 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, |
107 | ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, |
108 | ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node))); |
109 | if (ACPI_FAILURE (Status)) |
110 | { |
111 | /* Check if we are resolving a named reference within a package */ |
112 | |
113 | if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) && |
114 | |
115 | ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || |
116 | (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) |
117 | { |
118 | /* |
119 | * We didn't find the target and we are populating elements |
120 | * of a package - ignore if slack enabled. Some ASL code |
121 | * contains dangling invalid references in packages and |
122 | * expects that no exception will be issued. Leave the |
123 | * element as a null element. It cannot be used, but it |
124 | * can be overwritten by subsequent ASL code - this is |
125 | * typically the case. |
126 | */ |
127 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
128 | "Ignoring unresolved reference in package [%4.4s]\n" , |
129 | WalkState->ScopeInfo->Scope.Node->Name.Ascii)); |
130 | |
131 | return_ACPI_STATUS (AE_OK); |
132 | } |
133 | else |
134 | { |
135 | ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status); |
136 | } |
137 | |
138 | return_ACPI_STATUS (Status); |
139 | } |
140 | } |
141 | |
142 | /* Special object resolution for elements of a package */ |
143 | |
144 | if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || |
145 | (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) |
146 | { |
147 | /* |
148 | * Attempt to resolve the node to a value before we insert it into |
149 | * the package. If this is a reference to a common data type, |
150 | * resolve it immediately. According to the ACPI spec, package |
151 | * elements can only be "data objects" or method references. |
152 | * Attempt to resolve to an Integer, Buffer, String or Package. |
153 | * If cannot, return the named reference (for things like Devices, |
154 | * Methods, etc.) Buffer Fields and Fields will resolve to simple |
155 | * objects (int/buf/str/pkg). |
156 | * |
157 | * NOTE: References to things like Devices, Methods, Mutexes, etc. |
158 | * will remain as named references. This behavior is not described |
159 | * in the ACPI spec, but it appears to be an oversight. |
160 | */ |
161 | ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Op->Common.Node); |
162 | |
163 | Status = AcpiExResolveNodeToValue ( |
164 | ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc), |
165 | WalkState); |
166 | if (ACPI_FAILURE (Status)) |
167 | { |
168 | return_ACPI_STATUS (Status); |
169 | } |
170 | |
171 | /* |
172 | * Special handling for Alias objects. We need to setup the type |
173 | * and the Op->Common.Node to point to the Alias target. Note, |
174 | * Alias has at most one level of indirection internally. |
175 | */ |
176 | Type = Op->Common.Node->Type; |
177 | if (Type == ACPI_TYPE_LOCAL_ALIAS) |
178 | { |
179 | Type = ObjDesc->Common.Type; |
180 | Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, |
181 | Op->Common.Node->Object); |
182 | } |
183 | |
184 | switch (Type) |
185 | { |
186 | /* |
187 | * For these types, we need the actual node, not the subobject. |
188 | * However, the subobject did not get an extra reference count above. |
189 | * |
190 | * TBD: should ExResolveNodeToValue be changed to fix this? |
191 | */ |
192 | case ACPI_TYPE_DEVICE: |
193 | case ACPI_TYPE_THERMAL: |
194 | |
195 | AcpiUtAddReference (Op->Common.Node->Object); |
196 | |
197 | /*lint -fallthrough */ |
198 | /* |
199 | * For these types, we need the actual node, not the subobject. |
200 | * The subobject got an extra reference count in ExResolveNodeToValue. |
201 | */ |
202 | case ACPI_TYPE_MUTEX: |
203 | case ACPI_TYPE_METHOD: |
204 | case ACPI_TYPE_POWER: |
205 | case ACPI_TYPE_PROCESSOR: |
206 | case ACPI_TYPE_EVENT: |
207 | case ACPI_TYPE_REGION: |
208 | |
209 | /* We will create a reference object for these types below */ |
210 | break; |
211 | |
212 | default: |
213 | /* |
214 | * All other types - the node was resolved to an actual |
215 | * object, we are done. |
216 | */ |
217 | goto Exit; |
218 | } |
219 | } |
220 | } |
221 | |
222 | /* Create and init a new internal ACPI object */ |
223 | |
224 | ObjDesc = AcpiUtCreateInternalObject ( |
225 | (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); |
226 | if (!ObjDesc) |
227 | { |
228 | return_ACPI_STATUS (AE_NO_MEMORY); |
229 | } |
230 | |
231 | Status = AcpiDsInitObjectFromOp ( |
232 | WalkState, Op, Op->Common.AmlOpcode, &ObjDesc); |
233 | if (ACPI_FAILURE (Status)) |
234 | { |
235 | AcpiUtRemoveReference (ObjDesc); |
236 | return_ACPI_STATUS (Status); |
237 | } |
238 | |
239 | Exit: |
240 | *ObjDescPtr = ObjDesc; |
241 | return_ACPI_STATUS (Status); |
242 | } |
243 | |
244 | |
245 | /******************************************************************************* |
246 | * |
247 | * FUNCTION: AcpiDsBuildInternalBufferObj |
248 | * |
249 | * PARAMETERS: WalkState - Current walk state |
250 | * Op - Parser object to be translated |
251 | * BufferLength - Length of the buffer |
252 | * ObjDescPtr - Where the ACPI internal object is returned |
253 | * |
254 | * RETURN: Status |
255 | * |
256 | * DESCRIPTION: Translate a parser Op package object to the equivalent |
257 | * namespace object |
258 | * |
259 | ******************************************************************************/ |
260 | |
261 | ACPI_STATUS |
262 | AcpiDsBuildInternalBufferObj ( |
263 | ACPI_WALK_STATE *WalkState, |
264 | ACPI_PARSE_OBJECT *Op, |
265 | UINT32 BufferLength, |
266 | ACPI_OPERAND_OBJECT **ObjDescPtr) |
267 | { |
268 | ACPI_PARSE_OBJECT *Arg; |
269 | ACPI_OPERAND_OBJECT *ObjDesc; |
270 | ACPI_PARSE_OBJECT *ByteList; |
271 | UINT32 ByteListLength = 0; |
272 | |
273 | |
274 | ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj); |
275 | |
276 | |
277 | /* |
278 | * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". |
279 | * The buffer object already exists (from the NS node), otherwise it must |
280 | * be created. |
281 | */ |
282 | ObjDesc = *ObjDescPtr; |
283 | if (!ObjDesc) |
284 | { |
285 | /* Create a new buffer object */ |
286 | |
287 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); |
288 | *ObjDescPtr = ObjDesc; |
289 | if (!ObjDesc) |
290 | { |
291 | return_ACPI_STATUS (AE_NO_MEMORY); |
292 | } |
293 | } |
294 | |
295 | /* |
296 | * Second arg is the buffer data (optional) ByteList can be either |
297 | * individual bytes or a string initializer. In either case, a |
298 | * ByteList appears in the AML. |
299 | */ |
300 | Arg = Op->Common.Value.Arg; /* skip first arg */ |
301 | |
302 | ByteList = Arg->Named.Next; |
303 | if (ByteList) |
304 | { |
305 | if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP) |
306 | { |
307 | ACPI_ERROR ((AE_INFO, |
308 | "Expecting bytelist, found AML opcode 0x%X in op %p" , |
309 | ByteList->Common.AmlOpcode, ByteList)); |
310 | |
311 | AcpiUtRemoveReference (ObjDesc); |
312 | return (AE_TYPE); |
313 | } |
314 | |
315 | ByteListLength = (UINT32) ByteList->Common.Value.Integer; |
316 | } |
317 | |
318 | /* |
319 | * The buffer length (number of bytes) will be the larger of: |
320 | * 1) The specified buffer length and |
321 | * 2) The length of the initializer byte list |
322 | */ |
323 | ObjDesc->Buffer.Length = BufferLength; |
324 | if (ByteListLength > BufferLength) |
325 | { |
326 | ObjDesc->Buffer.Length = ByteListLength; |
327 | } |
328 | |
329 | /* Allocate the buffer */ |
330 | |
331 | if (ObjDesc->Buffer.Length == 0) |
332 | { |
333 | ObjDesc->Buffer.Pointer = NULL; |
334 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
335 | "Buffer defined with zero length in AML, creating\n" )); |
336 | } |
337 | else |
338 | { |
339 | ObjDesc->Buffer.Pointer = |
340 | ACPI_ALLOCATE_ZEROED (ObjDesc->Buffer.Length); |
341 | if (!ObjDesc->Buffer.Pointer) |
342 | { |
343 | AcpiUtDeleteObjectDesc (ObjDesc); |
344 | return_ACPI_STATUS (AE_NO_MEMORY); |
345 | } |
346 | |
347 | /* Initialize buffer from the ByteList (if present) */ |
348 | |
349 | if (ByteList) |
350 | { |
351 | memcpy (ObjDesc->Buffer.Pointer, ByteList->Named.Data, |
352 | ByteListLength); |
353 | } |
354 | } |
355 | |
356 | ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; |
357 | Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); |
358 | return_ACPI_STATUS (AE_OK); |
359 | } |
360 | |
361 | |
362 | /******************************************************************************* |
363 | * |
364 | * FUNCTION: AcpiDsBuildInternalPackageObj |
365 | * |
366 | * PARAMETERS: WalkState - Current walk state |
367 | * Op - Parser object to be translated |
368 | * ElementCount - Number of elements in the package - this is |
369 | * the NumElements argument to Package() |
370 | * ObjDescPtr - Where the ACPI internal object is returned |
371 | * |
372 | * RETURN: Status |
373 | * |
374 | * DESCRIPTION: Translate a parser Op package object to the equivalent |
375 | * namespace object |
376 | * |
377 | * NOTE: The number of elements in the package will be always be the NumElements |
378 | * count, regardless of the number of elements in the package list. If |
379 | * NumElements is smaller, only that many package list elements are used. |
380 | * if NumElements is larger, the Package object is padded out with |
381 | * objects of type Uninitialized (as per ACPI spec.) |
382 | * |
383 | * Even though the ASL compilers do not allow NumElements to be smaller |
384 | * than the Package list length (for the fixed length package opcode), some |
385 | * BIOS code modifies the AML on the fly to adjust the NumElements, and |
386 | * this code compensates for that. This also provides compatibility with |
387 | * other AML interpreters. |
388 | * |
389 | ******************************************************************************/ |
390 | |
391 | ACPI_STATUS |
392 | AcpiDsBuildInternalPackageObj ( |
393 | ACPI_WALK_STATE *WalkState, |
394 | ACPI_PARSE_OBJECT *Op, |
395 | UINT32 ElementCount, |
396 | ACPI_OPERAND_OBJECT **ObjDescPtr) |
397 | { |
398 | ACPI_PARSE_OBJECT *Arg; |
399 | ACPI_PARSE_OBJECT *Parent; |
400 | ACPI_OPERAND_OBJECT *ObjDesc = NULL; |
401 | ACPI_STATUS Status = AE_OK; |
402 | UINT32 i; |
403 | UINT16 Index; |
404 | UINT16 ReferenceCount; |
405 | |
406 | |
407 | ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); |
408 | |
409 | |
410 | /* Find the parent of a possibly nested package */ |
411 | |
412 | Parent = Op->Common.Parent; |
413 | while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || |
414 | (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) |
415 | { |
416 | Parent = Parent->Common.Parent; |
417 | } |
418 | |
419 | /* |
420 | * If we are evaluating a Named package object "Name (xxxx, Package)", |
421 | * the package object already exists, otherwise it must be created. |
422 | */ |
423 | ObjDesc = *ObjDescPtr; |
424 | if (!ObjDesc) |
425 | { |
426 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); |
427 | *ObjDescPtr = ObjDesc; |
428 | if (!ObjDesc) |
429 | { |
430 | return_ACPI_STATUS (AE_NO_MEMORY); |
431 | } |
432 | |
433 | ObjDesc->Package.Node = Parent->Common.Node; |
434 | } |
435 | |
436 | /* |
437 | * Allocate the element array (array of pointers to the individual |
438 | * objects) based on the NumElements parameter. Add an extra pointer slot |
439 | * so that the list is always null terminated. |
440 | */ |
441 | ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED ( |
442 | ((ACPI_SIZE) ElementCount + 1) * sizeof (void *)); |
443 | |
444 | if (!ObjDesc->Package.Elements) |
445 | { |
446 | AcpiUtDeleteObjectDesc (ObjDesc); |
447 | return_ACPI_STATUS (AE_NO_MEMORY); |
448 | } |
449 | |
450 | ObjDesc->Package.Count = ElementCount; |
451 | |
452 | /* |
453 | * Initialize the elements of the package, up to the NumElements count. |
454 | * Package is automatically padded with uninitialized (NULL) elements |
455 | * if NumElements is greater than the package list length. Likewise, |
456 | * Package is truncated if NumElements is less than the list length. |
457 | */ |
458 | Arg = Op->Common.Value.Arg; |
459 | Arg = Arg->Common.Next; |
460 | for (i = 0; Arg && (i < ElementCount); i++) |
461 | { |
462 | if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) |
463 | { |
464 | if (Arg->Common.Node->Type == ACPI_TYPE_METHOD) |
465 | { |
466 | /* |
467 | * A method reference "looks" to the parser to be a method |
468 | * invocation, so we special case it here |
469 | */ |
470 | Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP; |
471 | Status = AcpiDsBuildInternalObject ( |
472 | WalkState, Arg, &ObjDesc->Package.Elements[i]); |
473 | } |
474 | else |
475 | { |
476 | /* This package element is already built, just get it */ |
477 | |
478 | ObjDesc->Package.Elements[i] = |
479 | ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node); |
480 | } |
481 | } |
482 | else |
483 | { |
484 | Status = AcpiDsBuildInternalObject ( |
485 | WalkState, Arg, &ObjDesc->Package.Elements[i]); |
486 | } |
487 | |
488 | if (*ObjDescPtr) |
489 | { |
490 | /* Existing package, get existing reference count */ |
491 | |
492 | ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount; |
493 | if (ReferenceCount > 1) |
494 | { |
495 | /* Make new element ref count match original ref count */ |
496 | |
497 | for (Index = 0; Index < (ReferenceCount - 1); Index++) |
498 | { |
499 | AcpiUtAddReference ((ObjDesc->Package.Elements[i])); |
500 | } |
501 | } |
502 | } |
503 | |
504 | Arg = Arg->Common.Next; |
505 | } |
506 | |
507 | /* Check for match between NumElements and actual length of PackageList */ |
508 | |
509 | if (Arg) |
510 | { |
511 | /* |
512 | * NumElements was exhausted, but there are remaining elements in the |
513 | * PackageList. Truncate the package to NumElements. |
514 | * |
515 | * Note: technically, this is an error, from ACPI spec: "It is an error |
516 | * for NumElements to be less than the number of elements in the |
517 | * PackageList". However, we just print a message and |
518 | * no exception is returned. This provides Windows compatibility. Some |
519 | * BIOSs will alter the NumElements on the fly, creating this type |
520 | * of ill-formed package object. |
521 | */ |
522 | while (Arg) |
523 | { |
524 | /* |
525 | * We must delete any package elements that were created earlier |
526 | * and are not going to be used because of the package truncation. |
527 | */ |
528 | if (Arg->Common.Node) |
529 | { |
530 | AcpiUtRemoveReference ( |
531 | ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node)); |
532 | Arg->Common.Node = NULL; |
533 | } |
534 | |
535 | /* Find out how many elements there really are */ |
536 | |
537 | i++; |
538 | Arg = Arg->Common.Next; |
539 | } |
540 | |
541 | ACPI_INFO (( |
542 | "Actual Package length (%u) is larger than " |
543 | "NumElements field (%u), truncated" , |
544 | i, ElementCount)); |
545 | } |
546 | else if (i < ElementCount) |
547 | { |
548 | /* |
549 | * Arg list (elements) was exhausted, but we did not reach NumElements count. |
550 | * Note: this is not an error, the package is padded out with NULLs. |
551 | */ |
552 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
553 | "Package List length (%u) smaller than NumElements " |
554 | "count (%u), padded with null elements\n" , |
555 | i, ElementCount)); |
556 | } |
557 | |
558 | ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; |
559 | Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); |
560 | return_ACPI_STATUS (Status); |
561 | } |
562 | |
563 | |
564 | /******************************************************************************* |
565 | * |
566 | * FUNCTION: AcpiDsCreateNode |
567 | * |
568 | * PARAMETERS: WalkState - Current walk state |
569 | * Node - NS Node to be initialized |
570 | * Op - Parser object to be translated |
571 | * |
572 | * RETURN: Status |
573 | * |
574 | * DESCRIPTION: Create the object to be associated with a namespace node |
575 | * |
576 | ******************************************************************************/ |
577 | |
578 | ACPI_STATUS |
579 | AcpiDsCreateNode ( |
580 | ACPI_WALK_STATE *WalkState, |
581 | ACPI_NAMESPACE_NODE *Node, |
582 | ACPI_PARSE_OBJECT *Op) |
583 | { |
584 | ACPI_STATUS Status; |
585 | ACPI_OPERAND_OBJECT *ObjDesc; |
586 | |
587 | |
588 | ACPI_FUNCTION_TRACE_PTR (DsCreateNode, Op); |
589 | |
590 | |
591 | /* |
592 | * Because of the execution pass through the non-control-method |
593 | * parts of the table, we can arrive here twice. Only init |
594 | * the named object node the first time through |
595 | */ |
596 | if (AcpiNsGetAttachedObject (Node)) |
597 | { |
598 | return_ACPI_STATUS (AE_OK); |
599 | } |
600 | |
601 | if (!Op->Common.Value.Arg) |
602 | { |
603 | /* No arguments, there is nothing to do */ |
604 | |
605 | return_ACPI_STATUS (AE_OK); |
606 | } |
607 | |
608 | /* Build an internal object for the argument(s) */ |
609 | |
610 | Status = AcpiDsBuildInternalObject ( |
611 | WalkState, Op->Common.Value.Arg, &ObjDesc); |
612 | if (ACPI_FAILURE (Status)) |
613 | { |
614 | return_ACPI_STATUS (Status); |
615 | } |
616 | |
617 | /* Re-type the object according to its argument */ |
618 | |
619 | Node->Type = ObjDesc->Common.Type; |
620 | |
621 | /* Attach obj to node */ |
622 | |
623 | Status = AcpiNsAttachObject (Node, ObjDesc, Node->Type); |
624 | |
625 | /* Remove local reference to the object */ |
626 | |
627 | AcpiUtRemoveReference (ObjDesc); |
628 | return_ACPI_STATUS (Status); |
629 | } |
630 | |
631 | #endif /* ACPI_NO_METHOD_EXECUTION */ |
632 | |
633 | |
634 | /******************************************************************************* |
635 | * |
636 | * FUNCTION: AcpiDsInitObjectFromOp |
637 | * |
638 | * PARAMETERS: WalkState - Current walk state |
639 | * Op - Parser op used to init the internal object |
640 | * Opcode - AML opcode associated with the object |
641 | * RetObjDesc - Namespace object to be initialized |
642 | * |
643 | * RETURN: Status |
644 | * |
645 | * DESCRIPTION: Initialize a namespace object from a parser Op and its |
646 | * associated arguments. The namespace object is a more compact |
647 | * representation of the Op and its arguments. |
648 | * |
649 | ******************************************************************************/ |
650 | |
651 | ACPI_STATUS |
652 | AcpiDsInitObjectFromOp ( |
653 | ACPI_WALK_STATE *WalkState, |
654 | ACPI_PARSE_OBJECT *Op, |
655 | UINT16 Opcode, |
656 | ACPI_OPERAND_OBJECT **RetObjDesc) |
657 | { |
658 | const ACPI_OPCODE_INFO *OpInfo; |
659 | ACPI_OPERAND_OBJECT *ObjDesc; |
660 | ACPI_STATUS Status = AE_OK; |
661 | |
662 | |
663 | ACPI_FUNCTION_TRACE (DsInitObjectFromOp); |
664 | |
665 | |
666 | ObjDesc = *RetObjDesc; |
667 | OpInfo = AcpiPsGetOpcodeInfo (Opcode); |
668 | if (OpInfo->Class == AML_CLASS_UNKNOWN) |
669 | { |
670 | /* Unknown opcode */ |
671 | |
672 | return_ACPI_STATUS (AE_TYPE); |
673 | } |
674 | |
675 | /* Perform per-object initialization */ |
676 | |
677 | switch (ObjDesc->Common.Type) |
678 | { |
679 | case ACPI_TYPE_BUFFER: |
680 | /* |
681 | * Defer evaluation of Buffer TermArg operand |
682 | */ |
683 | ObjDesc->Buffer.Node = ACPI_CAST_PTR ( |
684 | ACPI_NAMESPACE_NODE, WalkState->Operands[0]); |
685 | ObjDesc->Buffer.AmlStart = Op->Named.Data; |
686 | ObjDesc->Buffer.AmlLength = Op->Named.Length; |
687 | break; |
688 | |
689 | case ACPI_TYPE_PACKAGE: |
690 | /* |
691 | * Defer evaluation of Package TermArg operand |
692 | */ |
693 | ObjDesc->Package.Node = ACPI_CAST_PTR ( |
694 | ACPI_NAMESPACE_NODE, WalkState->Operands[0]); |
695 | ObjDesc->Package.AmlStart = Op->Named.Data; |
696 | ObjDesc->Package.AmlLength = Op->Named.Length; |
697 | break; |
698 | |
699 | case ACPI_TYPE_INTEGER: |
700 | |
701 | switch (OpInfo->Type) |
702 | { |
703 | case AML_TYPE_CONSTANT: |
704 | /* |
705 | * Resolve AML Constants here - AND ONLY HERE! |
706 | * All constants are integers. |
707 | * We mark the integer with a flag that indicates that it started |
708 | * life as a constant -- so that stores to constants will perform |
709 | * as expected (noop). ZeroOp is used as a placeholder for optional |
710 | * target operands. |
711 | */ |
712 | ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT; |
713 | |
714 | switch (Opcode) |
715 | { |
716 | case AML_ZERO_OP: |
717 | |
718 | ObjDesc->Integer.Value = 0; |
719 | break; |
720 | |
721 | case AML_ONE_OP: |
722 | |
723 | ObjDesc->Integer.Value = 1; |
724 | break; |
725 | |
726 | case AML_ONES_OP: |
727 | |
728 | ObjDesc->Integer.Value = ACPI_UINT64_MAX; |
729 | |
730 | /* Truncate value if we are executing from a 32-bit ACPI table */ |
731 | |
732 | #ifndef ACPI_NO_METHOD_EXECUTION |
733 | (void) AcpiExTruncateFor32bitTable (ObjDesc); |
734 | #endif |
735 | break; |
736 | |
737 | case AML_REVISION_OP: |
738 | |
739 | ObjDesc->Integer.Value = ACPI_CA_VERSION; |
740 | break; |
741 | |
742 | default: |
743 | |
744 | ACPI_ERROR ((AE_INFO, |
745 | "Unknown constant opcode 0x%X" , Opcode)); |
746 | Status = AE_AML_OPERAND_TYPE; |
747 | break; |
748 | } |
749 | break; |
750 | |
751 | case AML_TYPE_LITERAL: |
752 | |
753 | ObjDesc->Integer.Value = Op->Common.Value.Integer; |
754 | |
755 | #ifndef ACPI_NO_METHOD_EXECUTION |
756 | if (AcpiExTruncateFor32bitTable (ObjDesc)) |
757 | { |
758 | /* Warn if we found a 64-bit constant in a 32-bit table */ |
759 | |
760 | ACPI_WARNING ((AE_INFO, |
761 | "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X" , |
762 | ACPI_FORMAT_UINT64 (Op->Common.Value.Integer), |
763 | (UINT32) ObjDesc->Integer.Value)); |
764 | } |
765 | #endif |
766 | break; |
767 | |
768 | default: |
769 | |
770 | ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X" , |
771 | OpInfo->Type)); |
772 | Status = AE_AML_OPERAND_TYPE; |
773 | break; |
774 | } |
775 | break; |
776 | |
777 | case ACPI_TYPE_STRING: |
778 | |
779 | ObjDesc->String.Pointer = Op->Common.Value.String; |
780 | ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String); |
781 | |
782 | /* |
783 | * The string is contained in the ACPI table, don't ever try |
784 | * to delete it |
785 | */ |
786 | ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; |
787 | break; |
788 | |
789 | case ACPI_TYPE_METHOD: |
790 | break; |
791 | |
792 | case ACPI_TYPE_LOCAL_REFERENCE: |
793 | |
794 | switch (OpInfo->Type) |
795 | { |
796 | case AML_TYPE_LOCAL_VARIABLE: |
797 | |
798 | /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ |
799 | |
800 | ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_LOCAL_OP; |
801 | ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL; |
802 | |
803 | #ifndef ACPI_NO_METHOD_EXECUTION |
804 | Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL, |
805 | ObjDesc->Reference.Value, WalkState, |
806 | ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, |
807 | &ObjDesc->Reference.Object)); |
808 | #endif |
809 | break; |
810 | |
811 | case AML_TYPE_METHOD_ARGUMENT: |
812 | |
813 | /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ |
814 | |
815 | ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_ARG_OP; |
816 | ObjDesc->Reference.Class = ACPI_REFCLASS_ARG; |
817 | |
818 | #ifndef ACPI_NO_METHOD_EXECUTION |
819 | Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG, |
820 | ObjDesc->Reference.Value, WalkState, |
821 | ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, |
822 | &ObjDesc->Reference.Object)); |
823 | #endif |
824 | break; |
825 | |
826 | default: /* Object name or Debug object */ |
827 | |
828 | switch (Op->Common.AmlOpcode) |
829 | { |
830 | case AML_INT_NAMEPATH_OP: |
831 | |
832 | /* Node was saved in Op */ |
833 | |
834 | ObjDesc->Reference.Node = Op->Common.Node; |
835 | ObjDesc->Reference.Object = Op->Common.Node->Object; |
836 | ObjDesc->Reference.Class = ACPI_REFCLASS_NAME; |
837 | break; |
838 | |
839 | case AML_DEBUG_OP: |
840 | |
841 | ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG; |
842 | break; |
843 | |
844 | default: |
845 | |
846 | ACPI_ERROR ((AE_INFO, |
847 | "Unimplemented reference type for AML opcode: 0x%4.4X" , Opcode)); |
848 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); |
849 | } |
850 | break; |
851 | } |
852 | break; |
853 | |
854 | default: |
855 | |
856 | ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X" , |
857 | ObjDesc->Common.Type)); |
858 | |
859 | Status = AE_AML_OPERAND_TYPE; |
860 | break; |
861 | } |
862 | |
863 | return_ACPI_STATUS (Status); |
864 | } |
865 | |