exutils.c revision 69450
1
2/******************************************************************************
3 *
4 * Module Name: amutils - interpreter/scanner utilities
5 *              $Revision: 63 $
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 * 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 __AMUTILS_C__
119
120#include "acpi.h"
121#include "acparser.h"
122#include "acinterp.h"
123#include "amlcode.h"
124#include "acnamesp.h"
125#include "acevents.h"
126
127#define _COMPONENT          INTERPRETER
128        MODULE_NAME         ("amutils")
129
130
131typedef struct Internal_Search_st
132{
133    ACPI_OPERAND_OBJECT         *DestObj;
134    UINT32                      Index;
135    ACPI_OPERAND_OBJECT         *SourceObj;
136
137} INTERNAL_PKG_SEARCH_INFO;
138
139
140/* Used to traverse nested packages when copying*/
141
142INTERNAL_PKG_SEARCH_INFO        CopyLevel[MAX_PACKAGE_DEPTH];
143
144
145static NATIVE_CHAR          hex[] =
146    {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
147
148
149/*******************************************************************************
150 *
151 * FUNCTION:    AcpiAmlEnterInterpreter
152 *
153 * PARAMETERS:  None
154 *
155 * DESCRIPTION: Enter the interpreter execution region
156 *
157 ******************************************************************************/
158
159void
160AcpiAmlEnterInterpreter (void)
161{
162    FUNCTION_TRACE ("AmlEnterInterpreter");
163
164
165    AcpiCmAcquireMutex (ACPI_MTX_EXECUTE);
166
167    return_VOID;
168}
169
170
171/*******************************************************************************
172 *
173 * FUNCTION:    AcpiAmlExitInterpreter
174 *
175 * PARAMETERS:  None
176 *
177 * DESCRIPTION: Exit the interpreter execution region
178 *
179 * Cases where the interpreter is unlocked:
180 *      1) Completion of the execution of a control method
181 *      2) Method blocked on a Sleep() AML opcode
182 *      3) Method blocked on an Acquire() AML opcode
183 *      4) Method blocked on a Wait() AML opcode
184 *      5) Method blocked to acquire the global lock
185 *      6) Method blocked to execute a serialized control method that is
186 *          already executing
187 *      7) About to invoke a user-installed opregion handler
188 *
189 ******************************************************************************/
190
191void
192AcpiAmlExitInterpreter (void)
193{
194    FUNCTION_TRACE ("AmlExitInterpreter");
195
196
197    AcpiCmReleaseMutex (ACPI_MTX_EXECUTE);
198
199    return_VOID;
200}
201
202
203/*******************************************************************************
204 *
205 * FUNCTION:    AcpiAmlValidateObjectType
206 *
207 * PARAMETERS:  Type            Object type to validate
208 *
209 * DESCRIPTION: Determine if a type is a valid ACPI object type
210 *
211 ******************************************************************************/
212
213BOOLEAN
214AcpiAmlValidateObjectType (
215    ACPI_OBJECT_TYPE        Type)
216{
217
218    if ((Type > ACPI_TYPE_MAX && Type < INTERNAL_TYPE_BEGIN) ||
219        (Type > INTERNAL_TYPE_MAX))
220    {
221        return (FALSE);
222    }
223
224    return (TRUE);
225}
226
227
228/*******************************************************************************
229 *
230 * FUNCTION:    AcpiAmlTruncateFor32bitTable
231 *
232 * PARAMETERS:  ObjDesc         - Object to be truncated
233 *              WalkState       - Current walk state
234 *                                (A method must be executing)
235 *
236 * RETURN:      none
237 *
238 * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
239 *              belongs to a 32-bit ACPI table.
240 *
241 ******************************************************************************/
242
243void
244AcpiAmlTruncateFor32bitTable (
245    ACPI_OPERAND_OBJECT     *ObjDesc,
246    ACPI_WALK_STATE         *WalkState)
247{
248
249    /*
250     * Object must be a valid number and we must be executing
251     * a control method
252     */
253
254    if ((!ObjDesc) ||
255        (ObjDesc->Common.Type != ACPI_TYPE_NUMBER) ||
256        (!WalkState->MethodNode))
257    {
258        return;
259    }
260
261    if (WalkState->MethodNode->Flags & ANOBJ_DATA_WIDTH_32)
262    {
263        /*
264         * We are running a method that exists in a 32-bit ACPI table.
265         * Truncate the value to 32 bits by zeroing out the upper 32-bit field
266         */
267        ObjDesc->Number.Value &= (UINT64) ACPI_UINT32_MAX;
268    }
269}
270
271
272/*******************************************************************************
273 *
274 * FUNCTION:    AcpiAmlAcquireGlobalLock
275 *
276 * PARAMETERS:  Rule            - Lock rule: AlwaysLock, NeverLock
277 *
278 * RETURN:      TRUE/FALSE indicating whether the lock was actually acquired
279 *
280 * DESCRIPTION: Obtain the global lock and keep track of this fact via two
281 *              methods.  A global variable keeps the state of the lock, and
282 *              the state is returned to the caller.
283 *
284 ******************************************************************************/
285
286BOOLEAN
287AcpiAmlAcquireGlobalLock (
288    UINT32                  Rule)
289{
290    BOOLEAN                 Locked = FALSE;
291    ACPI_STATUS             Status;
292
293
294    FUNCTION_TRACE ("AmlAcquireGlobalLock");
295
296
297    /*  Only attempt lock if the Rule says so */
298
299    if (Rule == (UINT32) GLOCK_ALWAYS_LOCK)
300    {
301        /*  OK to get the lock   */
302
303        Status = AcpiEvAcquireGlobalLock ();
304        if (ACPI_FAILURE (Status))
305        {
306            DEBUG_PRINT (ACPI_ERROR, ("Get Global Lock Failed!!\n"));
307        }
308
309        if (ACPI_SUCCESS (Status))
310        {
311            AcpiGbl_GlobalLockSet = TRUE;
312            Locked = TRUE;
313        }
314    }
315
316    return_VALUE (Locked);
317}
318
319
320/*******************************************************************************
321 *
322 * FUNCTION:    AcpiAmlReleaseGlobalLock
323 *
324 * PARAMETERS:  LockedByMe      - Return value from corresponding call to
325 *                                AcquireGlobalLock.
326 *
327 * RETURN:      Status
328 *
329 * DESCRIPTION: Release the global lock if it is locked.
330 *
331 ******************************************************************************/
332
333ACPI_STATUS
334AcpiAmlReleaseGlobalLock (
335    BOOLEAN                 LockedByMe)
336{
337
338    FUNCTION_TRACE ("AmlReleaseGlobalLock");
339
340
341    /* Only attempt unlock if the caller locked it */
342
343    if (LockedByMe)
344    {
345        /* Double check against the global flag */
346
347        if (AcpiGbl_GlobalLockSet)
348        {
349            /* OK, now release the lock */
350
351            AcpiEvReleaseGlobalLock ();
352            AcpiGbl_GlobalLockSet = FALSE;
353        }
354
355        else
356        {
357            DEBUG_PRINT (ACPI_ERROR, ("Global lock was not set\n"));
358        }
359    }
360
361
362    return_ACPI_STATUS (AE_OK);
363}
364
365
366/*******************************************************************************
367 *
368 * FUNCTION:    AcpiAmlDigitsNeeded
369 *
370 * PARAMETERS:  val             - Value to be represented
371 *              base            - Base of representation
372 *
373 * RETURN:      the number of digits needed to represent val in base
374 *
375 ******************************************************************************/
376
377UINT32
378AcpiAmlDigitsNeeded (
379    ACPI_INTEGER            val,
380    UINT32                  base)
381{
382    UINT32                  NumDigits = 0;
383
384
385    FUNCTION_TRACE ("AmlDigitsNeeded");
386
387
388    if (base < 1)
389    {
390        REPORT_ERROR (("AmlDigitsNeeded: Internal error - Invalid base\n"));
391    }
392
393    else
394    {
395        for (NumDigits = 1 + (val < 0); (val = ACPI_DIVIDE (val,base)); ++NumDigits)
396        { ; }
397    }
398
399    return_VALUE (NumDigits);
400}
401
402
403/*******************************************************************************
404 *
405 * FUNCTION:    ntohl
406 *
407 * PARAMETERS:  Value           - Value to be converted
408 *
409 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
410 *
411 ******************************************************************************/
412
413static UINT32
414_ntohl (
415    UINT32                  Value)
416{
417    union
418    {
419        UINT32              Value;
420        UINT8               Bytes[4];
421    } Out;
422
423    union
424    {
425        UINT32              Value;
426        UINT8               Bytes[4];
427    } In;
428
429
430    In.Value = Value;
431
432    Out.Bytes[0] = In.Bytes[3];
433    Out.Bytes[1] = In.Bytes[2];
434    Out.Bytes[2] = In.Bytes[1];
435    Out.Bytes[3] = In.Bytes[0];
436
437    return (Out.Value);
438}
439
440
441/*******************************************************************************
442 *
443 * FUNCTION:    AcpiAmlEisaIdToString
444 *
445 * PARAMETERS:  NumericId       - EISA ID to be converted
446 *              OutString       - Where to put the converted string (8 bytes)
447 *
448 * DESCRIPTION: Convert a numeric EISA ID to string representation
449 *
450 ******************************************************************************/
451
452ACPI_STATUS
453AcpiAmlEisaIdToString (
454    UINT32                  NumericId,
455    NATIVE_CHAR             *OutString)
456{
457    UINT32                  id;
458
459    /* swap to big-endian to get contiguous bits */
460
461    id = _ntohl (NumericId);
462
463    OutString[0] = (char) ('@' + ((id >> 26) & 0x1f));
464    OutString[1] = (char) ('@' + ((id >> 21) & 0x1f));
465    OutString[2] = (char) ('@' + ((id >> 16) & 0x1f));
466    OutString[3] = hex[(id >> 12) & 0xf];
467    OutString[4] = hex[(id >> 8) & 0xf];
468    OutString[5] = hex[(id >> 4) & 0xf];
469    OutString[6] = hex[id & 0xf];
470    OutString[7] = 0;
471
472    return (AE_OK);
473}
474
475
476/*******************************************************************************
477 *
478 * FUNCTION:    AcpiAmlUnsignedIntegerToString
479 *
480 * PARAMETERS:  Value           - Value to be converted
481 *              OutString       - Where to put the converted string (8 bytes)
482 *
483 * RETURN:      Convert a number to string representation
484 *
485 ******************************************************************************/
486
487ACPI_STATUS
488AcpiAmlUnsignedIntegerToString (
489    ACPI_INTEGER            Value,
490    NATIVE_CHAR             *OutString)
491{
492    UINT32                  Count;
493    UINT32                  DigitsNeeded;
494
495
496    DigitsNeeded = AcpiAmlDigitsNeeded (Value, 10);
497
498    OutString[DigitsNeeded] = '\0';
499
500    for (Count = DigitsNeeded; Count > 0; Count--)
501    {
502        OutString[Count-1] = (NATIVE_CHAR) ('0' + (ACPI_MODULO (Value, 10)));
503        Value = ACPI_DIVIDE (Value, 10);
504    }
505
506    return (AE_OK);
507}
508
509
510/*******************************************************************************
511 *
512 * FUNCTION:    AcpiAmlBuildCopyInternalPackageObject
513 *
514 * PARAMETERS:  *SourceObj      - Pointer to the source package object
515 *              *DestObj        - Where the internal object is returned
516 *
517 * RETURN:      Status          - the status of the call
518 *
519 * DESCRIPTION: This function is called to copy an internal package object
520 *              into another internal package object.
521 *
522 ******************************************************************************/
523
524ACPI_STATUS
525AcpiAmlBuildCopyInternalPackageObject (
526    ACPI_OPERAND_OBJECT     *SourceObj,
527    ACPI_OPERAND_OBJECT     *DestObj,
528    ACPI_WALK_STATE         *WalkState)
529{
530    UINT32                      CurrentDepth = 0;
531    ACPI_STATUS                 Status = AE_OK;
532    UINT32                      Length = 0;
533    UINT32                      ThisIndex;
534    UINT32                      ObjectSpace = 0;
535    ACPI_OPERAND_OBJECT         *ThisDestObj;
536    ACPI_OPERAND_OBJECT         *ThisSourceObj;
537    INTERNAL_PKG_SEARCH_INFO    *LevelPtr;
538
539
540    FUNCTION_TRACE ("AmlBuildCopyInternalPackageObject");
541
542
543    /*
544     * Initialize the working variables
545     */
546
547    MEMSET ((void *) CopyLevel, 0, sizeof(CopyLevel));
548
549    CopyLevel[0].DestObj    = DestObj;
550    CopyLevel[0].SourceObj  = SourceObj;
551    LevelPtr                = &CopyLevel[0];
552    CurrentDepth            = 0;
553
554    DestObj->Common.Type    = SourceObj->Common.Type;
555    DestObj->Package.Count  = SourceObj->Package.Count;
556
557
558    /*
559     * Build an array of ACPI_OBJECTS in the buffer
560     * and move the free space past it
561     */
562
563    DestObj->Package.Elements   = AcpiCmCallocate (
564                                        (DestObj->Package.Count + 1) *
565                                        sizeof (void *));
566    if (!DestObj->Package.Elements)
567    {
568        /* Package vector allocation failure   */
569
570        REPORT_ERROR (("AmlBuildCopyInternalPackageObject: Package vector allocation failure\n"));
571        return_ACPI_STATUS (AE_NO_MEMORY);
572    }
573
574    DestObj->Package.NextElement = DestObj->Package.Elements;
575
576
577    while (1)
578    {
579        ThisIndex       = LevelPtr->Index;
580        ThisDestObj     = (ACPI_OPERAND_OBJECT *) LevelPtr->DestObj->Package.Elements[ThisIndex];
581        ThisSourceObj   = (ACPI_OPERAND_OBJECT *) LevelPtr->SourceObj->Package.Elements[ThisIndex];
582
583        if (IS_THIS_OBJECT_TYPE (ThisSourceObj, ACPI_TYPE_PACKAGE))
584        {
585            /*
586             * If this object is a package then we go one deeper
587             */
588            if (CurrentDepth >= MAX_PACKAGE_DEPTH-1)
589            {
590                /*
591                 * Too many nested levels of packages for us to handle
592                 */
593                DEBUG_PRINT (ACPI_ERROR,
594                    ("AmlBuildCopyInternalPackageObject: Pkg nested too deep (max %d)\n",
595                    MAX_PACKAGE_DEPTH));
596                return_ACPI_STATUS (AE_LIMIT);
597            }
598
599            /*
600             * Build the package object
601             */
602            ThisDestObj = AcpiCmCreateInternalObject (ACPI_TYPE_PACKAGE);
603            LevelPtr->DestObj->Package.Elements[ThisIndex] = ThisDestObj;
604
605
606            ThisDestObj->Common.Type        = ACPI_TYPE_PACKAGE;
607            ThisDestObj->Package.Count      = ThisDestObj->Package.Count;
608
609            /*
610             * Save space for the array of objects (Package elements)
611             * update the buffer length counter
612             */
613            ObjectSpace             = ThisDestObj->Package.Count *
614                                        sizeof (ACPI_OPERAND_OBJECT);
615            Length                  += ObjectSpace;
616            CurrentDepth++;
617            LevelPtr                = &CopyLevel[CurrentDepth];
618            LevelPtr->DestObj       = ThisDestObj;
619            LevelPtr->SourceObj     = ThisSourceObj;
620            LevelPtr->Index         = 0;
621
622        }   /* if object is a package */
623
624        else
625        {
626
627            ThisDestObj = AcpiCmCreateInternalObject (
628                                ThisSourceObj->Common.Type);
629            LevelPtr->DestObj->Package.Elements[ThisIndex] = ThisDestObj;
630
631            Status = AcpiAmlStoreObjectToObject(ThisSourceObj, ThisDestObj, WalkState);
632
633            if (ACPI_FAILURE (Status))
634            {
635                /*
636                 * Failure get out
637                 */
638                return_ACPI_STATUS (Status);
639            }
640
641            Length      +=ObjectSpace;
642
643            LevelPtr->Index++;
644            while (LevelPtr->Index >= LevelPtr->DestObj->Package.Count)
645            {
646                /*
647                 * We've handled all of the objects at this level,  This means
648                 * that we have just completed a package.  That package may
649                 * have contained one or more packages itself
650                 */
651                if (CurrentDepth == 0)
652                {
653                    /*
654                     * We have handled all of the objects in the top level
655                     * package just add the length of the package objects
656                     * and exit
657                     */
658                    return_ACPI_STATUS (AE_OK);
659                }
660
661                /*
662                 * Go back up a level and move the index past the just
663                 * completed package object.
664                 */
665                CurrentDepth--;
666                LevelPtr = &CopyLevel[CurrentDepth];
667                LevelPtr->Index++;
668            }
669        }   /* else object is NOT a package */
670    }   /* while (1)  */
671}
672
673
674