]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/contrib/dev/acpica/dsopcode.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / contrib / dev / acpica / dsopcode.c
1 /******************************************************************************
2  *
3  * Module Name: dsopcode - Dispatcher Op Region support and handling of
4  *                         "control" opcodes
5  *              $Revision: 1.111 $
6  *
7  *****************************************************************************/
8
9 /******************************************************************************
10  *
11  * 1. Copyright Notice
12  *
13  * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
14  * All rights reserved.
15  *
16  * 2. License
17  *
18  * 2.1. This is your license from Intel Corp. under its intellectual property
19  * rights.  You may have additional license terms from the party that provided
20  * you this software, covering your right to use that party's intellectual
21  * property rights.
22  *
23  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24  * copy of the source code appearing in this file ("Covered Code") an
25  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26  * base code distributed originally by Intel ("Original Intel Code") to copy,
27  * make derivatives, distribute, use and display any portion of the Covered
28  * Code in any form, with the right to sublicense such rights; and
29  *
30  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31  * license (with the right to sublicense), under only those claims of Intel
32  * patents that are infringed by the Original Intel Code, to make, use, sell,
33  * offer to sell, and import the Covered Code and derivative works thereof
34  * solely to the minimum extent necessary to exercise the above copyright
35  * license, and in no event shall the patent license extend to any additions
36  * to or modifications of the Original Intel Code.  No other license or right
37  * is granted directly or by implication, estoppel or otherwise;
38  *
39  * The above copyright and patent license is granted only if the following
40  * conditions are met:
41  *
42  * 3. Conditions
43  *
44  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45  * Redistribution of source code of any substantial portion of the Covered
46  * Code or modification with rights to further distribute source must include
47  * the above Copyright Notice, the above License, this list of Conditions,
48  * and the following Disclaimer and Export Compliance provision.  In addition,
49  * Licensee must cause all Covered Code to which Licensee contributes to
50  * contain a file documenting the changes Licensee made to create that Covered
51  * Code and the date of any change.  Licensee must include in that file the
52  * documentation of any changes made by any predecessor Licensee.  Licensee
53  * must include a prominent statement that the modification is derived,
54  * directly or indirectly, from Original Intel Code.
55  *
56  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57  * Redistribution of source code of any substantial portion of the Covered
58  * Code or modification without rights to further distribute source must
59  * include the following Disclaimer and Export Compliance provision in the
60  * documentation and/or other materials provided with distribution.  In
61  * addition, Licensee may not authorize further sublicense of source of any
62  * portion of the Covered Code, and must include terms to the effect that the
63  * license from Licensee to its licensee is limited to the intellectual
64  * property embodied in the software Licensee provides to its licensee, and
65  * not to intellectual property embodied in modifications its licensee may
66  * make.
67  *
68  * 3.3. Redistribution of Executable. Redistribution in executable form of any
69  * substantial portion of the Covered Code or modification must reproduce the
70  * above Copyright Notice, and the following Disclaimer and Export Compliance
71  * provision in the documentation and/or other materials provided with the
72  * distribution.
73  *
74  * 3.4. Intel retains all right, title, and interest in and to the Original
75  * Intel Code.
76  *
77  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78  * Intel shall be used in advertising or otherwise to promote the sale, use or
79  * other dealings in products derived from or relating to the Covered Code
80  * without prior written authorization from Intel.
81  *
82  * 4. Disclaimer and Export Compliance
83  *
84  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
87  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
89  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90  * PARTICULAR PURPOSE.
91  *
92  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
98  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99  * LIMITED REMEDY.
100  *
101  * 4.3. Licensee shall not export, either directly or indirectly, any of this
102  * software or system incorporating such software without first obtaining any
103  * required license or other approval from the U. S. Department of Commerce or
104  * any other agency or department of the United States Government.  In the
105  * event Licensee exports any such software from the United States or
106  * re-exports any such software from a foreign destination, Licensee shall
107  * ensure that the distribution and export/re-export of the software is in
108  * compliance with all laws, regulations, orders, or other restrictions of the
109  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110  * any of its subsidiaries will export/re-export any technical data, process,
111  * software, or service, directly or indirectly, to any country for which the
112  * United States government or any agency thereof requires an export license,
113  * other governmental approval, or letter of assurance, without first obtaining
114  * such license, approval or letter.
115  *
116  *****************************************************************************/
117
118 #define __DSOPCODE_C__
119
120 #include <contrib/dev/acpica/acpi.h>
121 #include <contrib/dev/acpica/acparser.h>
122 #include <contrib/dev/acpica/amlcode.h>
123 #include <contrib/dev/acpica/acdispat.h>
124 #include <contrib/dev/acpica/acinterp.h>
125 #include <contrib/dev/acpica/acnamesp.h>
126 #include <contrib/dev/acpica/acevents.h>
127
128 #define _COMPONENT          ACPI_DISPATCHER
129         ACPI_MODULE_NAME    ("dsopcode")
130
131 /* Local prototypes */
132
133 static ACPI_STATUS
134 AcpiDsExecuteArguments (
135     ACPI_NAMESPACE_NODE     *Node,
136     ACPI_NAMESPACE_NODE     *ScopeNode,
137     UINT32                  AmlLength,
138     UINT8                   *AmlStart);
139
140 static ACPI_STATUS
141 AcpiDsInitBufferField (
142     UINT16                  AmlOpcode,
143     ACPI_OPERAND_OBJECT     *ObjDesc,
144     ACPI_OPERAND_OBJECT     *BufferDesc,
145     ACPI_OPERAND_OBJECT     *OffsetDesc,
146     ACPI_OPERAND_OBJECT     *LengthDesc,
147     ACPI_OPERAND_OBJECT     *ResultDesc);
148
149
150 /*******************************************************************************
151  *
152  * FUNCTION:    AcpiDsExecuteArguments
153  *
154  * PARAMETERS:  Node                - Object NS node
155  *              ScopeNode           - Parent NS node
156  *              AmlLength           - Length of executable AML
157  *              AmlStart            - Pointer to the AML
158  *
159  * RETURN:      Status.
160  *
161  * DESCRIPTION: Late (deferred) execution of region or field arguments
162  *
163  ******************************************************************************/
164
165 static ACPI_STATUS
166 AcpiDsExecuteArguments (
167     ACPI_NAMESPACE_NODE     *Node,
168     ACPI_NAMESPACE_NODE     *ScopeNode,
169     UINT32                  AmlLength,
170     UINT8                   *AmlStart)
171 {
172     ACPI_STATUS             Status;
173     ACPI_PARSE_OBJECT       *Op;
174     ACPI_WALK_STATE         *WalkState;
175
176
177     ACPI_FUNCTION_TRACE (DsExecuteArguments);
178
179
180     /*
181      * Allocate a new parser op to be the root of the parsed tree
182      */
183     Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP);
184     if (!Op)
185     {
186         return_ACPI_STATUS (AE_NO_MEMORY);
187     }
188
189     /* Save the Node for use in AcpiPsParseAml */
190
191     Op->Common.Node = ScopeNode;
192
193     /* Create and initialize a new parser state */
194
195     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
196     if (!WalkState)
197     {
198         Status = AE_NO_MEMORY;
199         goto Cleanup;
200     }
201
202     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart,
203                     AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
204     if (ACPI_FAILURE (Status))
205     {
206         AcpiDsDeleteWalkState (WalkState);
207         goto Cleanup;
208     }
209
210     /* Mark this parse as a deferred opcode */
211
212     WalkState->ParseFlags = ACPI_PARSE_DEFERRED_OP;
213     WalkState->DeferredNode = Node;
214
215     /* Pass1: Parse the entire declaration */
216
217     Status = AcpiPsParseAml (WalkState);
218     if (ACPI_FAILURE (Status))
219     {
220         goto Cleanup;
221     }
222
223     /* Get and init the Op created above */
224
225     Op->Common.Node = Node;
226     AcpiPsDeleteParseTree (Op);
227
228     /* Evaluate the deferred arguments */
229
230     Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP);
231     if (!Op)
232     {
233         return_ACPI_STATUS (AE_NO_MEMORY);
234     }
235
236     Op->Common.Node = ScopeNode;
237
238     /* Create and initialize a new parser state */
239
240     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
241     if (!WalkState)
242     {
243         Status = AE_NO_MEMORY;
244         goto Cleanup;
245     }
246
247     /* Execute the opcode and arguments */
248
249     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart,
250                     AmlLength, NULL, ACPI_IMODE_EXECUTE);
251     if (ACPI_FAILURE (Status))
252     {
253         AcpiDsDeleteWalkState (WalkState);
254         goto Cleanup;
255     }
256
257     /* Mark this execution as a deferred opcode */
258
259     WalkState->DeferredNode = Node;
260     Status = AcpiPsParseAml (WalkState);
261
262 Cleanup:
263     AcpiPsDeleteParseTree (Op);
264     return_ACPI_STATUS (Status);
265 }
266
267
268 /*******************************************************************************
269  *
270  * FUNCTION:    AcpiDsGetBufferFieldArguments
271  *
272  * PARAMETERS:  ObjDesc         - A valid BufferField object
273  *
274  * RETURN:      Status.
275  *
276  * DESCRIPTION: Get BufferField Buffer and Index.  This implements the late
277  *              evaluation of these field attributes.
278  *
279  ******************************************************************************/
280
281 ACPI_STATUS
282 AcpiDsGetBufferFieldArguments (
283     ACPI_OPERAND_OBJECT     *ObjDesc)
284 {
285     ACPI_OPERAND_OBJECT     *ExtraDesc;
286     ACPI_NAMESPACE_NODE     *Node;
287     ACPI_STATUS             Status;
288
289
290     ACPI_FUNCTION_TRACE_PTR (DsGetBufferFieldArguments, ObjDesc);
291
292
293     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
294     {
295         return_ACPI_STATUS (AE_OK);
296     }
297
298     /* Get the AML pointer (method object) and BufferField node */
299
300     ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc);
301     Node = ObjDesc->BufferField.Node;
302
303     ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_BUFFER_FIELD, Node, NULL));
304     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
305         AcpiUtGetNodeName (Node)));
306
307     /* Execute the AML code for the TermArg arguments */
308
309     Status = AcpiDsExecuteArguments (Node, AcpiNsGetParentNode (Node),
310                 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart);
311     return_ACPI_STATUS (Status);
312 }
313
314
315 /*******************************************************************************
316  *
317  * FUNCTION:    AcpiDsGetBufferArguments
318  *
319  * PARAMETERS:  ObjDesc         - A valid Buffer object
320  *
321  * RETURN:      Status.
322  *
323  * DESCRIPTION: Get Buffer length and initializer byte list.  This implements
324  *              the late evaluation of these attributes.
325  *
326  ******************************************************************************/
327
328 ACPI_STATUS
329 AcpiDsGetBufferArguments (
330     ACPI_OPERAND_OBJECT     *ObjDesc)
331 {
332     ACPI_NAMESPACE_NODE     *Node;
333     ACPI_STATUS             Status;
334
335
336     ACPI_FUNCTION_TRACE_PTR (DsGetBufferArguments, ObjDesc);
337
338
339     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
340     {
341         return_ACPI_STATUS (AE_OK);
342     }
343
344     /* Get the Buffer node */
345
346     Node = ObjDesc->Buffer.Node;
347     if (!Node)
348     {
349         ACPI_ERROR ((AE_INFO,
350             "No pointer back to NS node in buffer obj %p", ObjDesc));
351         return_ACPI_STATUS (AE_AML_INTERNAL);
352     }
353
354     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n"));
355
356     /* Execute the AML code for the TermArg arguments */
357
358     Status = AcpiDsExecuteArguments (Node, Node,
359                 ObjDesc->Buffer.AmlLength, ObjDesc->Buffer.AmlStart);
360     return_ACPI_STATUS (Status);
361 }
362
363
364 /*******************************************************************************
365  *
366  * FUNCTION:    AcpiDsGetPackageArguments
367  *
368  * PARAMETERS:  ObjDesc         - A valid Package object
369  *
370  * RETURN:      Status.
371  *
372  * DESCRIPTION: Get Package length and initializer byte list.  This implements
373  *              the late evaluation of these attributes.
374  *
375  ******************************************************************************/
376
377 ACPI_STATUS
378 AcpiDsGetPackageArguments (
379     ACPI_OPERAND_OBJECT     *ObjDesc)
380 {
381     ACPI_NAMESPACE_NODE     *Node;
382     ACPI_STATUS             Status;
383
384
385     ACPI_FUNCTION_TRACE_PTR (DsGetPackageArguments, ObjDesc);
386
387
388     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
389     {
390         return_ACPI_STATUS (AE_OK);
391     }
392
393     /* Get the Package node */
394
395     Node = ObjDesc->Package.Node;
396     if (!Node)
397     {
398         ACPI_ERROR ((AE_INFO,
399             "No pointer back to NS node in package %p", ObjDesc));
400         return_ACPI_STATUS (AE_AML_INTERNAL);
401     }
402
403     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n"));
404
405     /* Execute the AML code for the TermArg arguments */
406
407     Status = AcpiDsExecuteArguments (Node, Node,
408                 ObjDesc->Package.AmlLength, ObjDesc->Package.AmlStart);
409     return_ACPI_STATUS (Status);
410 }
411
412
413 /*****************************************************************************
414  *
415  * FUNCTION:    AcpiDsGetRegionArguments
416  *
417  * PARAMETERS:  ObjDesc         - A valid region object
418  *
419  * RETURN:      Status.
420  *
421  * DESCRIPTION: Get region address and length.  This implements the late
422  *              evaluation of these region attributes.
423  *
424  ****************************************************************************/
425
426 ACPI_STATUS
427 AcpiDsGetRegionArguments (
428     ACPI_OPERAND_OBJECT     *ObjDesc)
429 {
430     ACPI_NAMESPACE_NODE     *Node;
431     ACPI_STATUS             Status;
432     ACPI_OPERAND_OBJECT     *ExtraDesc;
433
434
435     ACPI_FUNCTION_TRACE_PTR (DsGetRegionArguments, ObjDesc);
436
437
438     if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID)
439     {
440         return_ACPI_STATUS (AE_OK);
441     }
442
443     ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc);
444     if (!ExtraDesc)
445     {
446         return_ACPI_STATUS (AE_NOT_EXIST);
447     }
448
449     /* Get the Region node */
450
451     Node = ObjDesc->Region.Node;
452
453     ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_REGION, Node, NULL));
454
455     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
456         AcpiUtGetNodeName (Node), ExtraDesc->Extra.AmlStart));
457
458     /* Execute the argument AML */
459
460     Status = AcpiDsExecuteArguments (Node, AcpiNsGetParentNode (Node),
461                 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart);
462     if (ACPI_FAILURE (Status))
463     {
464         return_ACPI_STATUS (Status);
465     }
466
467     /* Validate the region address/length via the host OS */
468
469     Status = AcpiOsValidateAddress (ObjDesc->Region.SpaceId,
470                 ObjDesc->Region.Address, (ACPI_SIZE) ObjDesc->Region.Length);
471     if (ACPI_FAILURE (Status))
472     {
473         /*
474          * Invalid address/length. We will emit an error message and mark
475          * the region as invalid, so that it will cause an additional error if
476          * it is ever used. Then return AE_OK.
477          */
478         ACPI_EXCEPTION ((AE_INFO, Status,
479             "During address validation of OpRegion [%4.4s]", Node->Name.Ascii));
480         ObjDesc->Common.Flags |= AOPOBJ_INVALID;
481         Status = AE_OK;
482     }
483
484     return_ACPI_STATUS (Status);
485 }
486
487
488 /*******************************************************************************
489  *
490  * FUNCTION:    AcpiDsInitializeRegion
491  *
492  * PARAMETERS:  ObjHandle       - Region namespace node
493  *
494  * RETURN:      Status
495  *
496  * DESCRIPTION: Front end to EvInitializeRegion
497  *
498  ******************************************************************************/
499
500 ACPI_STATUS
501 AcpiDsInitializeRegion (
502     ACPI_HANDLE             ObjHandle)
503 {
504     ACPI_OPERAND_OBJECT     *ObjDesc;
505     ACPI_STATUS             Status;
506
507
508     ObjDesc = AcpiNsGetAttachedObject (ObjHandle);
509
510     /* Namespace is NOT locked */
511
512     Status = AcpiEvInitializeRegion (ObjDesc, FALSE);
513     return (Status);
514 }
515
516
517 /*******************************************************************************
518  *
519  * FUNCTION:    AcpiDsInitBufferField
520  *
521  * PARAMETERS:  AmlOpcode       - CreateXxxField
522  *              ObjDesc         - BufferField object
523  *              BufferDesc      - Host Buffer
524  *              OffsetDesc      - Offset into buffer
525  *              LengthDesc      - Length of field (CREATE_FIELD_OP only)
526  *              ResultDesc      - Where to store the result
527  *
528  * RETURN:      Status
529  *
530  * DESCRIPTION: Perform actual initialization of a buffer field
531  *
532  ******************************************************************************/
533
534 static ACPI_STATUS
535 AcpiDsInitBufferField (
536     UINT16                  AmlOpcode,
537     ACPI_OPERAND_OBJECT     *ObjDesc,
538     ACPI_OPERAND_OBJECT     *BufferDesc,
539     ACPI_OPERAND_OBJECT     *OffsetDesc,
540     ACPI_OPERAND_OBJECT     *LengthDesc,
541     ACPI_OPERAND_OBJECT     *ResultDesc)
542 {
543     UINT32                  Offset;
544     UINT32                  BitOffset;
545     UINT32                  BitCount;
546     UINT8                   FieldFlags;
547     ACPI_STATUS             Status;
548
549
550     ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc);
551
552
553     /* Host object must be a Buffer */
554
555     if (ACPI_GET_OBJECT_TYPE (BufferDesc) != ACPI_TYPE_BUFFER)
556     {
557         ACPI_ERROR ((AE_INFO,
558             "Target of Create Field is not a Buffer object - %s",
559             AcpiUtGetObjectTypeName (BufferDesc)));
560
561         Status = AE_AML_OPERAND_TYPE;
562         goto Cleanup;
563     }
564
565     /*
566      * The last parameter to all of these opcodes (ResultDesc) started
567      * out as a NameString, and should therefore now be a NS node
568      * after resolution in AcpiExResolveOperands().
569      */
570     if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED)
571     {
572         ACPI_ERROR ((AE_INFO,
573             "(%s) destination not a NS Node [%s]",
574             AcpiPsGetOpcodeName (AmlOpcode),
575             AcpiUtGetDescriptorName (ResultDesc)));
576
577         Status = AE_AML_OPERAND_TYPE;
578         goto Cleanup;
579     }
580
581     Offset = (UINT32) OffsetDesc->Integer.Value;
582
583     /*
584      * Setup the Bit offsets and counts, according to the opcode
585      */
586     switch (AmlOpcode)
587     {
588     case AML_CREATE_FIELD_OP:
589
590         /* Offset is in bits, count is in bits */
591
592         FieldFlags = AML_FIELD_ACCESS_BYTE;
593         BitOffset  = Offset;
594         BitCount   = (UINT32) LengthDesc->Integer.Value;
595
596         /* Must have a valid (>0) bit count */
597
598         if (BitCount == 0)
599         {
600             ACPI_ERROR ((AE_INFO,
601                 "Attempt to CreateField of length zero"));
602             Status = AE_AML_OPERAND_VALUE;
603             goto Cleanup;
604         }
605         break;
606
607     case AML_CREATE_BIT_FIELD_OP:
608
609         /* Offset is in bits, Field is one bit */
610
611         BitOffset  = Offset;
612         BitCount   = 1;
613         FieldFlags = AML_FIELD_ACCESS_BYTE;
614         break;
615
616     case AML_CREATE_BYTE_FIELD_OP:
617
618         /* Offset is in bytes, field is one byte */
619
620         BitOffset  = 8 * Offset;
621         BitCount   = 8;
622         FieldFlags = AML_FIELD_ACCESS_BYTE;
623         break;
624
625     case AML_CREATE_WORD_FIELD_OP:
626
627         /* Offset is in bytes, field is one word */
628
629         BitOffset  = 8 * Offset;
630         BitCount   = 16;
631         FieldFlags = AML_FIELD_ACCESS_WORD;
632         break;
633
634     case AML_CREATE_DWORD_FIELD_OP:
635
636         /* Offset is in bytes, field is one dword */
637
638         BitOffset  = 8 * Offset;
639         BitCount   = 32;
640         FieldFlags = AML_FIELD_ACCESS_DWORD;
641         break;
642
643     case AML_CREATE_QWORD_FIELD_OP:
644
645         /* Offset is in bytes, field is one qword */
646
647         BitOffset  = 8 * Offset;
648         BitCount   = 64;
649         FieldFlags = AML_FIELD_ACCESS_QWORD;
650         break;
651
652     default:
653
654         ACPI_ERROR ((AE_INFO,
655             "Unknown field creation opcode %02x",
656             AmlOpcode));
657         Status = AE_AML_BAD_OPCODE;
658         goto Cleanup;
659     }
660
661     /* Entire field must fit within the current length of the buffer */
662
663     if ((BitOffset + BitCount) >
664         (8 * (UINT32) BufferDesc->Buffer.Length))
665     {
666         ACPI_ERROR ((AE_INFO,
667             "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)",
668             AcpiUtGetNodeName (ResultDesc),
669             BitOffset + BitCount,
670             AcpiUtGetNodeName (BufferDesc->Buffer.Node),
671             8 * (UINT32) BufferDesc->Buffer.Length));
672         Status = AE_AML_BUFFER_LIMIT;
673         goto Cleanup;
674     }
675
676     /*
677      * Initialize areas of the field object that are common to all fields
678      * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK),
679      * UPDATE_RULE = 0 (UPDATE_PRESERVE)
680      */
681     Status = AcpiExPrepCommonFieldObject (ObjDesc, FieldFlags, 0,
682                                             BitOffset, BitCount);
683     if (ACPI_FAILURE (Status))
684     {
685         goto Cleanup;
686     }
687
688     ObjDesc->BufferField.BufferObj = BufferDesc;
689
690     /* Reference count for BufferDesc inherits ObjDesc count */
691
692     BufferDesc->Common.ReferenceCount = (UINT16)
693         (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount);
694
695
696 Cleanup:
697
698     /* Always delete the operands */
699
700     AcpiUtRemoveReference (OffsetDesc);
701     AcpiUtRemoveReference (BufferDesc);
702
703     if (AmlOpcode == AML_CREATE_FIELD_OP)
704     {
705         AcpiUtRemoveReference (LengthDesc);
706     }
707
708     /* On failure, delete the result descriptor */
709
710     if (ACPI_FAILURE (Status))
711     {
712         AcpiUtRemoveReference (ResultDesc);     /* Result descriptor */
713     }
714     else
715     {
716         /* Now the address and length are valid for this BufferField */
717
718         ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID;
719     }
720
721     return_ACPI_STATUS (Status);
722 }
723
724
725 /*******************************************************************************
726  *
727  * FUNCTION:    AcpiDsEvalBufferFieldOperands
728  *
729  * PARAMETERS:  WalkState       - Current walk
730  *              Op              - A valid BufferField Op object
731  *
732  * RETURN:      Status
733  *
734  * DESCRIPTION: Get BufferField Buffer and Index
735  *              Called from AcpiDsExecEndOp during BufferField parse tree walk
736  *
737  ******************************************************************************/
738
739 ACPI_STATUS
740 AcpiDsEvalBufferFieldOperands (
741     ACPI_WALK_STATE         *WalkState,
742     ACPI_PARSE_OBJECT       *Op)
743 {
744     ACPI_STATUS             Status;
745     ACPI_OPERAND_OBJECT     *ObjDesc;
746     ACPI_NAMESPACE_NODE     *Node;
747     ACPI_PARSE_OBJECT       *NextOp;
748
749
750     ACPI_FUNCTION_TRACE_PTR (DsEvalBufferFieldOperands, Op);
751
752
753     /*
754      * This is where we evaluate the address and length fields of the
755      * CreateXxxField declaration
756      */
757     Node =  Op->Common.Node;
758
759     /* NextOp points to the op that holds the Buffer */
760
761     NextOp = Op->Common.Value.Arg;
762
763     /* Evaluate/create the address and length operands */
764
765     Status = AcpiDsCreateOperands (WalkState, NextOp);
766     if (ACPI_FAILURE (Status))
767     {
768         return_ACPI_STATUS (Status);
769     }
770
771     ObjDesc = AcpiNsGetAttachedObject (Node);
772     if (!ObjDesc)
773     {
774         return_ACPI_STATUS (AE_NOT_EXIST);
775     }
776
777     /* Resolve the operands */
778
779     Status = AcpiExResolveOperands (Op->Common.AmlOpcode,
780                     ACPI_WALK_OPERANDS, WalkState);
781
782     ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
783                     AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
784                     WalkState->NumOperands, "after AcpiExResolveOperands");
785
786     if (ACPI_FAILURE (Status))
787     {
788         ACPI_ERROR ((AE_INFO, "(%s) bad operand(s) (%X)",
789             AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Status));
790
791         return_ACPI_STATUS (Status);
792     }
793
794     /* Initialize the Buffer Field */
795
796     if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)
797     {
798         /* NOTE: Slightly different operands for this opcode */
799
800         Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc,
801                     WalkState->Operands[0], WalkState->Operands[1],
802                     WalkState->Operands[2], WalkState->Operands[3]);
803     }
804     else
805     {
806         /* All other, CreateXxxField opcodes */
807
808         Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc,
809                     WalkState->Operands[0], WalkState->Operands[1],
810                                       NULL, WalkState->Operands[2]);
811     }
812
813     return_ACPI_STATUS (Status);
814 }
815
816
817 /*******************************************************************************
818  *
819  * FUNCTION:    AcpiDsEvalRegionOperands
820  *
821  * PARAMETERS:  WalkState       - Current walk
822  *              Op              - A valid region Op object
823  *
824  * RETURN:      Status
825  *
826  * DESCRIPTION: Get region address and length
827  *              Called from AcpiDsExecEndOp during OpRegion parse tree walk
828  *
829  ******************************************************************************/
830
831 ACPI_STATUS
832 AcpiDsEvalRegionOperands (
833     ACPI_WALK_STATE         *WalkState,
834     ACPI_PARSE_OBJECT       *Op)
835 {
836     ACPI_STATUS             Status;
837     ACPI_OPERAND_OBJECT     *ObjDesc;
838     ACPI_OPERAND_OBJECT     *OperandDesc;
839     ACPI_NAMESPACE_NODE     *Node;
840     ACPI_PARSE_OBJECT       *NextOp;
841
842
843     ACPI_FUNCTION_TRACE_PTR (DsEvalRegionOperands, Op);
844
845
846     /*
847      * This is where we evaluate the address and length fields of the
848      * OpRegion declaration
849      */
850     Node =  Op->Common.Node;
851
852     /* NextOp points to the op that holds the SpaceID */
853
854     NextOp = Op->Common.Value.Arg;
855
856     /* NextOp points to address op */
857
858     NextOp = NextOp->Common.Next;
859
860     /* Evaluate/create the address and length operands */
861
862     Status = AcpiDsCreateOperands (WalkState, NextOp);
863     if (ACPI_FAILURE (Status))
864     {
865         return_ACPI_STATUS (Status);
866     }
867
868     /* Resolve the length and address operands to numbers */
869
870     Status = AcpiExResolveOperands (Op->Common.AmlOpcode,
871                 ACPI_WALK_OPERANDS, WalkState);
872     if (ACPI_FAILURE (Status))
873     {
874         return_ACPI_STATUS (Status);
875     }
876
877     ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
878                     AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
879                     1, "after AcpiExResolveOperands");
880
881     ObjDesc = AcpiNsGetAttachedObject (Node);
882     if (!ObjDesc)
883     {
884         return_ACPI_STATUS (AE_NOT_EXIST);
885     }
886
887     /*
888      * Get the length operand and save it
889      * (at Top of stack)
890      */
891     OperandDesc = WalkState->Operands[WalkState->NumOperands - 1];
892
893     ObjDesc->Region.Length = (UINT32) OperandDesc->Integer.Value;
894     AcpiUtRemoveReference (OperandDesc);
895
896     /*
897      * Get the address and save it
898      * (at top of stack - 1)
899      */
900     OperandDesc = WalkState->Operands[WalkState->NumOperands - 2];
901
902     ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS)
903                                 OperandDesc->Integer.Value;
904     AcpiUtRemoveReference (OperandDesc);
905
906     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
907         ObjDesc,
908         ACPI_FORMAT_UINT64 (ObjDesc->Region.Address),
909         ObjDesc->Region.Length));
910
911     /* Now the address and length are valid for this opregion */
912
913     ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID;
914
915     return_ACPI_STATUS (Status);
916 }
917
918
919 /*******************************************************************************
920  *
921  * FUNCTION:    AcpiDsEvalDataObjectOperands
922  *
923  * PARAMETERS:  WalkState       - Current walk
924  *              Op              - A valid DataObject Op object
925  *              ObjDesc         - DataObject
926  *
927  * RETURN:      Status
928  *
929  * DESCRIPTION: Get the operands and complete the following data object types:
930  *              Buffer, Package.
931  *
932  ******************************************************************************/
933
934 ACPI_STATUS
935 AcpiDsEvalDataObjectOperands (
936     ACPI_WALK_STATE         *WalkState,
937     ACPI_PARSE_OBJECT       *Op,
938     ACPI_OPERAND_OBJECT     *ObjDesc)
939 {
940     ACPI_STATUS             Status;
941     ACPI_OPERAND_OBJECT     *ArgDesc;
942     UINT32                  Length;
943
944
945     ACPI_FUNCTION_TRACE (DsEvalDataObjectOperands);
946
947
948     /* The first operand (for all of these data objects) is the length */
949
950     /*
951      * Set proper index into operand stack for AcpiDsObjStackPush
952      * invoked inside AcpiDsCreateOperand.
953      */
954     WalkState->OperandIndex = WalkState->NumOperands;
955
956     Status = AcpiDsCreateOperand (WalkState, Op->Common.Value.Arg, 1);
957     if (ACPI_FAILURE (Status))
958     {
959         return_ACPI_STATUS (Status);
960     }
961
962     Status = AcpiExResolveOperands (WalkState->Opcode,
963                     &(WalkState->Operands [WalkState->NumOperands -1]),
964                     WalkState);
965     if (ACPI_FAILURE (Status))
966     {
967         return_ACPI_STATUS (Status);
968     }
969
970     /* Extract length operand */
971
972     ArgDesc = WalkState->Operands [WalkState->NumOperands - 1];
973     Length = (UINT32) ArgDesc->Integer.Value;
974
975     /* Cleanup for length operand */
976
977     Status = AcpiDsObjStackPop (1, WalkState);
978     if (ACPI_FAILURE (Status))
979     {
980         return_ACPI_STATUS (Status);
981     }
982
983     AcpiUtRemoveReference (ArgDesc);
984
985     /*
986      * Create the actual data object
987      */
988     switch (Op->Common.AmlOpcode)
989     {
990     case AML_BUFFER_OP:
991
992         Status = AcpiDsBuildInternalBufferObj (WalkState, Op, Length, &ObjDesc);
993         break;
994
995     case AML_PACKAGE_OP:
996     case AML_VAR_PACKAGE_OP:
997
998         Status = AcpiDsBuildInternalPackageObj (WalkState, Op, Length, &ObjDesc);
999         break;
1000
1001     default:
1002         return_ACPI_STATUS (AE_AML_BAD_OPCODE);
1003     }
1004
1005     if (ACPI_SUCCESS (Status))
1006     {
1007         /*
1008          * Return the object in the WalkState, unless the parent is a package -
1009          * in this case, the return object will be stored in the parse tree
1010          * for the package.
1011          */
1012         if ((!Op->Common.Parent) ||
1013             ((Op->Common.Parent->Common.AmlOpcode != AML_PACKAGE_OP) &&
1014              (Op->Common.Parent->Common.AmlOpcode != AML_VAR_PACKAGE_OP) &&
1015              (Op->Common.Parent->Common.AmlOpcode != AML_NAME_OP)))
1016         {
1017             WalkState->ResultObj = ObjDesc;
1018         }
1019     }
1020
1021     return_ACPI_STATUS (Status);
1022 }
1023
1024
1025 /*******************************************************************************
1026  *
1027  * FUNCTION:    AcpiDsExecBeginControlOp
1028  *
1029  * PARAMETERS:  WalkList        - The list that owns the walk stack
1030  *              Op              - The control Op
1031  *
1032  * RETURN:      Status
1033  *
1034  * DESCRIPTION: Handles all control ops encountered during control method
1035  *              execution.
1036  *
1037  ******************************************************************************/
1038
1039 ACPI_STATUS
1040 AcpiDsExecBeginControlOp (
1041     ACPI_WALK_STATE         *WalkState,
1042     ACPI_PARSE_OBJECT       *Op)
1043 {
1044     ACPI_STATUS             Status = AE_OK;
1045     ACPI_GENERIC_STATE      *ControlState;
1046
1047
1048     ACPI_FUNCTION_NAME (DsExecBeginControlOp);
1049
1050
1051     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", Op,
1052         Op->Common.AmlOpcode, WalkState));
1053
1054     switch (Op->Common.AmlOpcode)
1055     {
1056     case AML_IF_OP:
1057     case AML_WHILE_OP:
1058
1059         /*
1060          * IF/WHILE: Create a new control state to manage these
1061          * constructs. We need to manage these as a stack, in order
1062          * to handle nesting.
1063          */
1064         ControlState = AcpiUtCreateControlState ();
1065         if (!ControlState)
1066         {
1067             Status = AE_NO_MEMORY;
1068             break;
1069         }
1070         /*
1071          * Save a pointer to the predicate for multiple executions
1072          * of a loop
1073          */
1074         ControlState->Control.AmlPredicateStart = WalkState->ParserState.Aml - 1;
1075         ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd;
1076         ControlState->Control.Opcode = Op->Common.AmlOpcode;
1077
1078
1079         /* Push the control state on this walk's control stack */
1080
1081         AcpiUtPushGenericState (&WalkState->ControlState, ControlState);
1082         break;
1083
1084     case AML_ELSE_OP:
1085
1086         /* Predicate is in the state object */
1087         /* If predicate is true, the IF was executed, ignore ELSE part */
1088
1089         if (WalkState->LastPredicate)
1090         {
1091             Status = AE_CTRL_TRUE;
1092         }
1093
1094         break;
1095
1096     case AML_RETURN_OP:
1097
1098         break;
1099
1100     default:
1101         break;
1102     }
1103
1104     return (Status);
1105 }
1106
1107
1108 /*******************************************************************************
1109  *
1110  * FUNCTION:    AcpiDsExecEndControlOp
1111  *
1112  * PARAMETERS:  WalkList        - The list that owns the walk stack
1113  *              Op              - The control Op
1114  *
1115  * RETURN:      Status
1116  *
1117  * DESCRIPTION: Handles all control ops encountered during control method
1118  *              execution.
1119  *
1120  ******************************************************************************/
1121
1122 ACPI_STATUS
1123 AcpiDsExecEndControlOp (
1124     ACPI_WALK_STATE         *WalkState,
1125     ACPI_PARSE_OBJECT       *Op)
1126 {
1127     ACPI_STATUS             Status = AE_OK;
1128     ACPI_GENERIC_STATE      *ControlState;
1129
1130
1131     ACPI_FUNCTION_NAME (DsExecEndControlOp);
1132
1133
1134     switch (Op->Common.AmlOpcode)
1135     {
1136     case AML_IF_OP:
1137
1138         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op));
1139
1140         /*
1141          * Save the result of the predicate in case there is an
1142          * ELSE to come
1143          */
1144         WalkState->LastPredicate =
1145             (BOOLEAN) WalkState->ControlState->Common.Value;
1146
1147         /*
1148          * Pop the control state that was created at the start
1149          * of the IF and free it
1150          */
1151         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
1152         AcpiUtDeleteGenericState (ControlState);
1153         break;
1154
1155
1156     case AML_ELSE_OP:
1157
1158         break;
1159
1160
1161     case AML_WHILE_OP:
1162
1163         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op));
1164
1165         if (WalkState->ControlState->Common.Value)
1166         {
1167             /* Predicate was true, go back and evaluate it again! */
1168
1169             Status = AE_CTRL_PENDING;
1170         }
1171
1172         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1173             "[WHILE_OP] termination! Op=%p\n",Op));
1174
1175         /* Pop this control state and free it */
1176
1177         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
1178
1179         WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart;
1180         AcpiUtDeleteGenericState (ControlState);
1181         break;
1182
1183
1184     case AML_RETURN_OP:
1185
1186         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1187             "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg));
1188
1189         /*
1190          * One optional operand -- the return value
1191          * It can be either an immediate operand or a result that
1192          * has been bubbled up the tree
1193          */
1194         if (Op->Common.Value.Arg)
1195         {
1196             /* Since we have a real Return(), delete any implicit return */
1197
1198             AcpiDsClearImplicitReturn (WalkState);
1199
1200             /* Return statement has an immediate operand */
1201
1202             Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
1203             if (ACPI_FAILURE (Status))
1204             {
1205                 return (Status);
1206             }
1207
1208             /*
1209              * If value being returned is a Reference (such as
1210              * an arg or local), resolve it now because it may
1211              * cease to exist at the end of the method.
1212              */
1213             Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState);
1214             if (ACPI_FAILURE (Status))
1215             {
1216                 return (Status);
1217             }
1218
1219             /*
1220              * Get the return value and save as the last result
1221              * value.  This is the only place where WalkState->ReturnDesc
1222              * is set to anything other than zero!
1223              */
1224             WalkState->ReturnDesc = WalkState->Operands[0];
1225         }
1226         else if (WalkState->ResultCount)
1227         {
1228             /* Since we have a real Return(), delete any implicit return */
1229
1230             AcpiDsClearImplicitReturn (WalkState);
1231
1232             /*
1233              * The return value has come from a previous calculation.
1234              *
1235              * If value being returned is a Reference (such as
1236              * an arg or local), resolve it now because it may
1237              * cease to exist at the end of the method.
1238              *
1239              * Allow references created by the Index operator to return unchanged.
1240              */
1241             if ((ACPI_GET_DESCRIPTOR_TYPE (WalkState->Results->Results.ObjDesc[0]) == ACPI_DESC_TYPE_OPERAND) &&
1242                 (ACPI_GET_OBJECT_TYPE (WalkState->Results->Results.ObjDesc [0]) == ACPI_TYPE_LOCAL_REFERENCE) &&
1243                 ((WalkState->Results->Results.ObjDesc [0])->Reference.Opcode != AML_INDEX_OP))
1244             {
1245                 Status = AcpiExResolveToValue (&WalkState->Results->Results.ObjDesc [0], WalkState);
1246                 if (ACPI_FAILURE (Status))
1247                 {
1248                     return (Status);
1249                 }
1250             }
1251
1252             WalkState->ReturnDesc = WalkState->Results->Results.ObjDesc [0];
1253         }
1254         else
1255         {
1256             /* No return operand */
1257
1258             if (WalkState->NumOperands)
1259             {
1260                 AcpiUtRemoveReference (WalkState->Operands [0]);
1261             }
1262
1263             WalkState->Operands [0]     = NULL;
1264             WalkState->NumOperands      = 0;
1265             WalkState->ReturnDesc       = NULL;
1266         }
1267
1268
1269         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1270             "Completed RETURN_OP State=%p, RetVal=%p\n",
1271             WalkState, WalkState->ReturnDesc));
1272
1273         /* End the control method execution right now */
1274
1275         Status = AE_CTRL_TERMINATE;
1276         break;
1277
1278
1279     case AML_NOOP_OP:
1280
1281         /* Just do nothing! */
1282         break;
1283
1284
1285     case AML_BREAK_POINT_OP:
1286
1287         /* Call up to the OS service layer to handle this */
1288
1289         Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode");
1290
1291         /* If and when it returns, all done. */
1292
1293         break;
1294
1295
1296     case AML_BREAK_OP:
1297     case AML_CONTINUE_OP: /* ACPI 2.0 */
1298
1299
1300         /* Pop and delete control states until we find a while */
1301
1302         while (WalkState->ControlState &&
1303                 (WalkState->ControlState->Control.Opcode != AML_WHILE_OP))
1304         {
1305             ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
1306             AcpiUtDeleteGenericState (ControlState);
1307         }
1308
1309         /* No while found? */
1310
1311         if (!WalkState->ControlState)
1312         {
1313             return (AE_AML_NO_WHILE);
1314         }
1315
1316         /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */
1317
1318         WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd;
1319
1320         /* Return status depending on opcode */
1321
1322         if (Op->Common.AmlOpcode == AML_BREAK_OP)
1323         {
1324             Status = AE_CTRL_BREAK;
1325         }
1326         else
1327         {
1328             Status = AE_CTRL_CONTINUE;
1329         }
1330         break;
1331
1332
1333     default:
1334
1335         ACPI_ERROR ((AE_INFO, "Unknown control opcode=%X Op=%p",
1336             Op->Common.AmlOpcode, Op));
1337
1338         Status = AE_AML_BAD_OPCODE;
1339         break;
1340     }
1341
1342     return (Status);
1343 }
1344