exmisc.c revision 67754
1
2/******************************************************************************
3 *
4 * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes
5 *              $Revision: 70 $
6 *
7 *****************************************************************************/
8
9/******************************************************************************
10 *
11 * 1. Copyright Notice
12 *
13 * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
14 * 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
89 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
90 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
91 * PARTICULAR PURPOSE.
92 *
93 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
94 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
95 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
96 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
97 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
98 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
99 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
100 * LIMITED REMEDY.
101 *
102 * 4.3. Licensee shall not export, either directly or indirectly, any of this
103 * software or system incorporating such software without first obtaining any
104 * required license or other approval from the U. S. Department of Commerce or
105 * any other agency or department of the United States Government.  In the
106 * event Licensee exports any such software from the United States or
107 * re-exports any such software from a foreign destination, Licensee shall
108 * ensure that the distribution and export/re-export of the software is in
109 * compliance with all laws, regulations, orders, or other restrictions of the
110 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
111 * any of its subsidiaries will export/re-export any technical data, process,
112 * software, or service, directly or indirectly, to any country for which the
113 * United States government or any agency thereof requires an export license,
114 * other governmental approval, or letter of assurance, without first obtaining
115 * such license, approval or letter.
116 *
117 *****************************************************************************/
118
119#define __AMMISC_C__
120
121#include "acpi.h"
122#include "acparser.h"
123#include "acinterp.h"
124#include "amlcode.h"
125#include "acdispat.h"
126
127
128#define _COMPONENT          INTERPRETER
129        MODULE_NAME         ("ammisc")
130
131
132/*******************************************************************************
133 *
134 * FUNCTION:    AcpiAmlExecFatal
135 *
136 * PARAMETERS:  none
137 *
138 * RETURN:      Status.  If the OS returns from the OSD call, we just keep
139 *              on going.
140 *
141 * DESCRIPTION: Execute Fatal operator
142 *
143 * ACPI SPECIFICATION REFERENCES:
144 *  DefFatal    :=  FatalOp FatalType   FatalCode   FatalArg
145 *  FatalType   :=  ByteData
146 *  FatalCode   :=  DWordData
147 *  FatalArg    :=  TermArg=>Integer
148 *
149 ******************************************************************************/
150
151ACPI_STATUS
152AcpiAmlExecFatal (
153    ACPI_WALK_STATE         *WalkState)
154{
155    ACPI_OPERAND_OBJECT     *TypeDesc;
156    ACPI_OPERAND_OBJECT     *CodeDesc;
157    ACPI_OPERAND_OBJECT     *ArgDesc;
158    ACPI_STATUS             Status;
159
160
161    FUNCTION_TRACE ("AmlExecFatal");
162
163
164    /* Resolve operands */
165
166    Status = AcpiAmlResolveOperands (AML_FATAL_OP, WALK_OPERANDS, WalkState);
167    DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE,
168                    AcpiPsGetOpcodeName (AML_FATAL_OP),
169                    3, "after AcpiAmlResolveOperands");
170
171    /* Get operands */
172
173    Status |= AcpiDsObjStackPopObject (&ArgDesc, WalkState);
174    Status |= AcpiDsObjStackPopObject (&CodeDesc, WalkState);
175    Status |= AcpiDsObjStackPopObject (&TypeDesc, WalkState);
176    if (ACPI_FAILURE (Status))
177    {
178        /* Invalid parameters on object stack  */
179
180        DEBUG_PRINT (ACPI_ERROR,
181            ("AcpiAmlExecFatal/AML_FATAL_OP: bad operand(s) (0x%X)\n",
182            Status));
183
184        goto Cleanup;
185    }
186
187
188    /* DefFatal    :=  FatalOp FatalType   FatalCode   FatalArg    */
189
190
191    DEBUG_PRINT (ACPI_INFO,
192        ("FatalOp: Type %x Code %x Arg %x <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
193        TypeDesc->Number.Value, CodeDesc->Number.Value, ArgDesc->Number.Value));
194
195
196    /*
197     * TBD: [Unhandled] call OSD interface to notify OS of fatal error
198     * requiring shutdown!
199     */
200
201
202Cleanup:
203
204    /* Free the operands */
205
206    AcpiCmRemoveReference (ArgDesc);
207    AcpiCmRemoveReference (CodeDesc);
208    AcpiCmRemoveReference (TypeDesc);
209
210
211    /* If we get back from the OS call, we might as well keep going. */
212
213    REPORT_WARNING (("An AML \"Fatal\" Opcode (FatalOp) was executed\n"));
214    return_ACPI_STATUS (AE_OK);
215}
216
217
218/*******************************************************************************
219 *
220 * FUNCTION:    AcpiAmlExecIndex
221 *
222 * PARAMETERS:  none
223 *
224 * RETURN:      Status
225 *
226 * DESCRIPTION: Execute Index operator
227 *
228 * ALLOCATION:  Deletes one operand descriptor -- other remains on stack
229 *
230 *  ACPI SPECIFICATION REFERENCES:
231 *  DefIndex    :=  IndexOp BuffPkgObj IndexValue Result
232 *  IndexValue  :=  TermArg=>Integer
233 *  NameString  :=  <RootChar NamePath> | <PrefixPath NamePath>
234 *  Result      :=  SuperName
235 *  SuperName   :=  NameString | ArgObj | LocalObj | DebugObj | DefIndex
236 *                             Local4Op | Local5Op | Local6Op | Local7Op
237 *
238 ******************************************************************************/
239
240ACPI_STATUS
241AcpiAmlExecIndex (
242    ACPI_WALK_STATE         *WalkState,
243    ACPI_OPERAND_OBJECT     **ReturnDesc)
244{
245    ACPI_OPERAND_OBJECT     *ObjDesc;
246    ACPI_OPERAND_OBJECT     *IdxDesc;
247    ACPI_OPERAND_OBJECT     *ResDesc;
248    ACPI_OPERAND_OBJECT     *RetDesc = NULL;
249    ACPI_OPERAND_OBJECT     *TmpDesc;
250    ACPI_STATUS             Status;
251
252
253    FUNCTION_TRACE ("AmlExecIndex");
254
255
256    /* Resolve operands */
257    /* First operand can be either a package or a buffer */
258
259    Status = AcpiAmlResolveOperands (AML_INDEX_OP, WALK_OPERANDS, WalkState);
260    DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE,
261                    AcpiPsGetOpcodeName (AML_INDEX_OP),
262                    3, "after AcpiAmlResolveOperands");
263
264    /* Get all operands */
265
266    Status |= AcpiDsObjStackPopObject (&ResDesc, WalkState);
267    Status |= AcpiDsObjStackPopObject (&IdxDesc, WalkState);
268    Status |= AcpiDsObjStackPopObject (&ObjDesc, WalkState);
269    if (ACPI_FAILURE (Status))
270    {
271        /* Invalid parameters on object stack  */
272
273        DEBUG_PRINT (ACPI_ERROR,
274            ("AcpiAmlExecIndex/AML_INDEX_OP: bad operand(s) (0x%X)\n",
275            Status));
276
277        goto Cleanup;
278    }
279
280
281    /* Create the internal return object */
282
283    RetDesc = AcpiCmCreateInternalObject (INTERNAL_TYPE_REFERENCE);
284    if (!RetDesc)
285    {
286        Status = AE_NO_MEMORY;
287        goto Cleanup;
288    }
289
290
291    /*
292     * At this point, the ObjDesc operand is either a Package or a Buffer
293     */
294
295    if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
296    {
297        /* Object to be indexed is a Package */
298
299        if (IdxDesc->Number.Value >= ObjDesc->Package.Count)
300        {
301            DEBUG_PRINT (ACPI_ERROR,
302                ("AmlExecIndex: Index value out of range\n"));
303            Status = AE_AML_PACKAGE_LIMIT;
304            goto Cleanup;
305        }
306
307        if ((ResDesc->Common.Type == INTERNAL_TYPE_REFERENCE) &&
308            (ResDesc->Reference.OpCode == AML_ZERO_OP))
309        {
310            /*
311             * There is no actual result descriptor (the ZeroOp Result
312             * descriptor is a placeholder), so just delete the placeholder and
313             * return a reference to the package element
314             */
315
316            AcpiCmRemoveReference (ResDesc);
317        }
318
319        else
320        {
321            /*
322             * Each element of the package is an internal object.  Get the one
323             * we are after.
324             */
325
326            TmpDesc                       = ObjDesc->Package.Elements[IdxDesc->Number.Value];
327            RetDesc->Reference.OpCode     = AML_INDEX_OP;
328            RetDesc->Reference.TargetType = TmpDesc->Common.Type;
329            RetDesc->Reference.Object     = TmpDesc;
330
331            Status = AcpiAmlExecStore (RetDesc, ResDesc, WalkState);
332            RetDesc->Reference.Object     = NULL;
333        }
334
335        /*
336         * The local return object must always be a reference to the package element,
337         * not the element itself.
338         */
339        RetDesc->Reference.OpCode     = AML_INDEX_OP;
340        RetDesc->Reference.TargetType = ACPI_TYPE_PACKAGE;
341        RetDesc->Reference.Where      = &ObjDesc->Package.Elements[IdxDesc->Number.Value];
342    }
343
344    else
345    {
346        /* Object to be indexed is a Buffer */
347
348        if (IdxDesc->Number.Value >= ObjDesc->Buffer.Length)
349        {
350            DEBUG_PRINT (ACPI_ERROR,
351                ("AmlExecIndex: Index value out of range\n"));
352            Status = AE_AML_BUFFER_LIMIT;
353            goto Cleanup;
354        }
355
356        RetDesc->Reference.OpCode       = AML_INDEX_OP;
357        RetDesc->Reference.TargetType   = ACPI_TYPE_BUFFER_FIELD;
358        RetDesc->Reference.Object       = ObjDesc;
359        RetDesc->Reference.Offset       = (UINT32) IdxDesc->Number.Value;
360
361        Status = AcpiAmlExecStore (RetDesc, ResDesc, WalkState);
362    }
363
364
365Cleanup:
366
367    /* Always delete operands */
368
369    AcpiCmRemoveReference (ObjDesc);
370    AcpiCmRemoveReference (IdxDesc);
371
372    /* Delete return object on error */
373
374    if (ACPI_FAILURE (Status))
375    {
376        AcpiCmRemoveReference (ResDesc);
377
378        if (RetDesc)
379        {
380            AcpiCmRemoveReference (RetDesc);
381            RetDesc = NULL;
382        }
383    }
384
385    /* Set the return object and exit */
386
387    *ReturnDesc = RetDesc;
388    return_ACPI_STATUS (Status);
389}
390
391
392/*******************************************************************************
393 *
394 * FUNCTION:    AcpiAmlExecMatch
395 *
396 * PARAMETERS:  none
397 *
398 * RETURN:      Status
399 *
400 * DESCRIPTION: Execute Match operator
401 *
402 * ACPI SPECIFICATION REFERENCES:
403 *  DefMatch    :=  MatchOp SearchPkg   Opcode1     Operand1
404 *                              Opcode2 Operand2    StartIndex
405 *  Opcode1     :=  ByteData: MTR, MEQ, MLE, MLT, MGE, or MGT
406 *  Opcode2     :=  ByteData: MTR, MEQ, MLE, MLT, MGE, or MGT
407 *  Operand1    :=  TermArg=>Integer
408 *  Operand2    :=  TermArg=>Integer
409 *  SearchPkg   :=  TermArg=>PackageObject
410 *  StartIndex  :=  TermArg=>Integer
411 *
412 ******************************************************************************/
413
414ACPI_STATUS
415AcpiAmlExecMatch (
416    ACPI_WALK_STATE         *WalkState,
417    ACPI_OPERAND_OBJECT     **ReturnDesc)
418{
419    ACPI_OPERAND_OBJECT     *PkgDesc;
420    ACPI_OPERAND_OBJECT     *Op1Desc;
421    ACPI_OPERAND_OBJECT     *V1Desc;
422    ACPI_OPERAND_OBJECT     *Op2Desc;
423    ACPI_OPERAND_OBJECT     *V2Desc;
424    ACPI_OPERAND_OBJECT     *StartDesc;
425    ACPI_OPERAND_OBJECT     *RetDesc = NULL;
426    ACPI_STATUS             Status;
427    UINT32                  Index;
428    UINT32                  MatchValue = (UINT32) -1;
429
430
431    FUNCTION_TRACE ("AmlExecMatch");
432
433
434    /* Resolve all operands */
435
436    Status = AcpiAmlResolveOperands (AML_MATCH_OP, WALK_OPERANDS, WalkState);
437    DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE,
438                    AcpiPsGetOpcodeName (AML_MATCH_OP),
439                    6, "after AcpiAmlResolveOperands");
440
441    /* Get all operands */
442
443    Status |= AcpiDsObjStackPopObject (&StartDesc, WalkState);
444    Status |= AcpiDsObjStackPopObject (&V2Desc, WalkState);
445    Status |= AcpiDsObjStackPopObject (&Op2Desc, WalkState);
446    Status |= AcpiDsObjStackPopObject (&V1Desc, WalkState);
447    Status |= AcpiDsObjStackPopObject (&Op1Desc, WalkState);
448    Status |= AcpiDsObjStackPopObject (&PkgDesc, WalkState);
449
450    if (ACPI_FAILURE (Status))
451    {
452        /* Invalid parameters on object stack  */
453
454        DEBUG_PRINT (ACPI_ERROR,
455            ("ExecMatch/AML_MATCH_OP: bad operand(s) (0x%X)\n",
456            Status));
457
458        goto Cleanup;
459    }
460
461    /* Validate match comparison sub-opcodes */
462
463    if ((Op1Desc->Number.Value > MAX_MATCH_OPERATOR) ||
464        (Op2Desc->Number.Value > MAX_MATCH_OPERATOR))
465    {
466        DEBUG_PRINT (ACPI_ERROR,
467            ("AmlExecMatch: operation encoding out of range\n"));
468        Status = AE_AML_OPERAND_VALUE;
469        goto Cleanup;
470    }
471
472    Index = (UINT32) StartDesc->Number.Value;
473    if (Index >= (UINT32) PkgDesc->Package.Count)
474    {
475        DEBUG_PRINT (ACPI_ERROR,
476            ("AmlExecMatch: start position value out of range\n"));
477        Status = AE_AML_PACKAGE_LIMIT;
478        goto Cleanup;
479    }
480
481    RetDesc = AcpiCmCreateInternalObject (ACPI_TYPE_NUMBER);
482    if (!RetDesc)
483    {
484        Status = AE_NO_MEMORY;
485        goto Cleanup;
486
487    }
488
489    /*
490     * Examine each element until a match is found.  Within the loop,
491     * "continue" signifies that the current element does not match
492     * and the next should be examined.
493     * Upon finding a match, the loop will terminate via "break" at
494     * the bottom.  If it terminates "normally", MatchValue will be -1
495     * (its initial value) indicating that no match was found.  When
496     * returned as a Number, this will produce the Ones value as specified.
497     */
498
499    for ( ; Index < PkgDesc->Package.Count; ++Index)
500    {
501        /*
502         * Treat any NULL or non-numeric elements as non-matching.
503         * TBD [Unhandled] - if an element is a Name,
504         *      should we examine its value?
505         */
506        if (!PkgDesc->Package.Elements[Index] ||
507            ACPI_TYPE_NUMBER != PkgDesc->Package.Elements[Index]->Common.Type)
508        {
509            continue;
510        }
511
512        /*
513         * Within these switch statements:
514         *      "break" (exit from the switch) signifies a match;
515         *      "continue" (proceed to next iteration of enclosing
516         *          "for" loop) signifies a non-match.
517         */
518        switch (Op1Desc->Number.Value)
519        {
520
521        case MATCH_MTR:   /* always true */
522
523            break;
524
525
526        case MATCH_MEQ:   /* true if equal   */
527
528            if (PkgDesc->Package.Elements[Index]->Number.Value
529                 != V1Desc->Number.Value)
530            {
531                continue;
532            }
533            break;
534
535
536        case MATCH_MLE:   /* true if less than or equal  */
537
538            if (PkgDesc->Package.Elements[Index]->Number.Value
539                 > V1Desc->Number.Value)
540            {
541                continue;
542            }
543            break;
544
545
546        case MATCH_MLT:   /* true if less than   */
547
548            if (PkgDesc->Package.Elements[Index]->Number.Value
549                 >= V1Desc->Number.Value)
550            {
551                continue;
552            }
553            break;
554
555
556        case MATCH_MGE:   /* true if greater than or equal   */
557
558            if (PkgDesc->Package.Elements[Index]->Number.Value
559                 < V1Desc->Number.Value)
560            {
561                continue;
562            }
563            break;
564
565
566        case MATCH_MGT:   /* true if greater than    */
567
568            if (PkgDesc->Package.Elements[Index]->Number.Value
569                 <= V1Desc->Number.Value)
570            {
571                continue;
572            }
573            break;
574
575
576        default:    /* undefined   */
577
578            continue;
579        }
580
581
582        switch(Op2Desc->Number.Value)
583        {
584
585        case MATCH_MTR:
586
587            break;
588
589
590        case MATCH_MEQ:
591
592            if (PkgDesc->Package.Elements[Index]->Number.Value
593                 != V2Desc->Number.Value)
594            {
595                continue;
596            }
597            break;
598
599
600        case MATCH_MLE:
601
602            if (PkgDesc->Package.Elements[Index]->Number.Value
603                 > V2Desc->Number.Value)
604            {
605                continue;
606            }
607            break;
608
609
610        case MATCH_MLT:
611
612            if (PkgDesc->Package.Elements[Index]->Number.Value
613                 >= V2Desc->Number.Value)
614            {
615                continue;
616            }
617            break;
618
619
620        case MATCH_MGE:
621
622            if (PkgDesc->Package.Elements[Index]->Number.Value
623                 < V2Desc->Number.Value)
624            {
625                continue;
626            }
627            break;
628
629
630        case MATCH_MGT:
631
632            if (PkgDesc->Package.Elements[Index]->Number.Value
633                 <= V2Desc->Number.Value)
634            {
635                continue;
636            }
637            break;
638
639
640        default:
641
642            continue;
643        }
644
645        /* Match found: exit from loop */
646
647        MatchValue = Index;
648        break;
649    }
650
651    /* MatchValue is the return value */
652
653    RetDesc->Number.Value = MatchValue;
654
655
656Cleanup:
657
658    /* Free the operands */
659
660    AcpiCmRemoveReference (StartDesc);
661    AcpiCmRemoveReference (V2Desc);
662    AcpiCmRemoveReference (Op2Desc);
663    AcpiCmRemoveReference (V1Desc);
664    AcpiCmRemoveReference (Op1Desc);
665    AcpiCmRemoveReference (PkgDesc);
666
667
668    /* Delete return object on error */
669
670    if (ACPI_FAILURE (Status) &&
671        (RetDesc))
672    {
673        AcpiCmRemoveReference (RetDesc);
674        RetDesc = NULL;
675    }
676
677
678    /* Set the return object and exit */
679
680    *ReturnDesc = RetDesc;
681    return_ACPI_STATUS (Status);
682}
683