Home | History | Annotate | Line # | Download | only in executer
exutils.c revision 1.1.1.2
      1 
      2 /******************************************************************************
      3  *
      4  * Module Name: exutils - interpreter/scanner utilities
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2011, Intel Corp.
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions, and the following disclaimer,
     17  *    without modification.
     18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     19  *    substantially similar to the "NO WARRANTY" disclaimer below
     20  *    ("Disclaimer") and any redistribution must be conditioned upon
     21  *    including a substantially similar Disclaimer requirement for further
     22  *    binary redistribution.
     23  * 3. Neither the names of the above-listed copyright holders nor the names
     24  *    of any contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * Alternatively, this software may be distributed under the terms of the
     28  * GNU General Public License ("GPL") version 2 as published by the Free
     29  * Software Foundation.
     30  *
     31  * NO WARRANTY
     32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     42  * POSSIBILITY OF SUCH DAMAGES.
     43  */
     44 
     45 #define __EXUTILS_C__
     46 
     47 /*
     48  * DEFINE_AML_GLOBALS is tested in amlcode.h
     49  * to determine whether certain global names should be "defined" or only
     50  * "declared" in the current compilation.  This enhances maintainability
     51  * by enabling a single header file to embody all knowledge of the names
     52  * in question.
     53  *
     54  * Exactly one module of any executable should #define DEFINE_GLOBALS
     55  * before #including the header files which use this convention.  The
     56  * names in question will be defined and initialized in that module,
     57  * and declared as extern in all other modules which #include those
     58  * header files.
     59  */
     60 
     61 #define DEFINE_AML_GLOBALS
     62 
     63 #include "acpi.h"
     64 #include "accommon.h"
     65 #include "acinterp.h"
     66 #include "amlcode.h"
     67 
     68 #define _COMPONENT          ACPI_EXECUTER
     69         ACPI_MODULE_NAME    ("exutils")
     70 
     71 /* Local prototypes */
     72 
     73 static UINT32
     74 AcpiExDigitsNeeded (
     75     UINT64                  Value,
     76     UINT32                  Base);
     77 
     78 
     79 #ifndef ACPI_NO_METHOD_EXECUTION
     80 /*******************************************************************************
     81  *
     82  * FUNCTION:    AcpiExEnterInterpreter
     83  *
     84  * PARAMETERS:  None
     85  *
     86  * RETURN:      None
     87  *
     88  * DESCRIPTION: Enter the interpreter execution region. Failure to enter
     89  *              the interpreter region is a fatal system error. Used in
     90  *              conjunction with ExitInterpreter.
     91  *
     92  ******************************************************************************/
     93 
     94 void
     95 AcpiExEnterInterpreter (
     96     void)
     97 {
     98     ACPI_STATUS             Status;
     99 
    100 
    101     ACPI_FUNCTION_TRACE (ExEnterInterpreter);
    102 
    103 
    104     Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
    105     if (ACPI_FAILURE (Status))
    106     {
    107         ACPI_ERROR ((AE_INFO, "Could not acquire AML Interpreter mutex"));
    108     }
    109 
    110     return_VOID;
    111 }
    112 
    113 
    114 /*******************************************************************************
    115  *
    116  * FUNCTION:    AcpiExReacquireInterpreter
    117  *
    118  * PARAMETERS:  None
    119  *
    120  * RETURN:      None
    121  *
    122  * DESCRIPTION: Reacquire the interpreter execution region from within the
    123  *              interpreter code. Failure to enter the interpreter region is a
    124  *              fatal system error. Used in  conjuction with
    125  *              RelinquishInterpreter
    126  *
    127  ******************************************************************************/
    128 
    129 void
    130 AcpiExReacquireInterpreter (
    131     void)
    132 {
    133     ACPI_FUNCTION_TRACE (ExReacquireInterpreter);
    134 
    135 
    136     /*
    137      * If the global serialized flag is set, do not release the interpreter,
    138      * since it was not actually released by AcpiExRelinquishInterpreter.
    139      * This forces the interpreter to be single threaded.
    140      */
    141     if (!AcpiGbl_AllMethodsSerialized)
    142     {
    143         AcpiExEnterInterpreter ();
    144     }
    145 
    146     return_VOID;
    147 }
    148 
    149 
    150 /*******************************************************************************
    151  *
    152  * FUNCTION:    AcpiExExitInterpreter
    153  *
    154  * PARAMETERS:  None
    155  *
    156  * RETURN:      None
    157  *
    158  * DESCRIPTION: Exit the interpreter execution region. This is the top level
    159  *              routine used to exit the interpreter when all processing has
    160  *              been completed.
    161  *
    162  ******************************************************************************/
    163 
    164 void
    165 AcpiExExitInterpreter (
    166     void)
    167 {
    168     ACPI_STATUS             Status;
    169 
    170 
    171     ACPI_FUNCTION_TRACE (ExExitInterpreter);
    172 
    173 
    174     Status = AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
    175     if (ACPI_FAILURE (Status))
    176     {
    177         ACPI_ERROR ((AE_INFO, "Could not release AML Interpreter mutex"));
    178     }
    179 
    180     return_VOID;
    181 }
    182 
    183 
    184 /*******************************************************************************
    185  *
    186  * FUNCTION:    AcpiExRelinquishInterpreter
    187  *
    188  * PARAMETERS:  None
    189  *
    190  * RETURN:      None
    191  *
    192  * DESCRIPTION: Exit the interpreter execution region, from within the
    193  *              interpreter - before attempting an operation that will possibly
    194  *              block the running thread.
    195  *
    196  * Cases where the interpreter is unlocked internally
    197  *      1) Method to be blocked on a Sleep() AML opcode
    198  *      2) Method to be blocked on an Acquire() AML opcode
    199  *      3) Method to be blocked on a Wait() AML opcode
    200  *      4) Method to be blocked to acquire the global lock
    201  *      5) Method to be blocked waiting to execute a serialized control method
    202  *          that is currently executing
    203  *      6) About to invoke a user-installed opregion handler
    204  *
    205  ******************************************************************************/
    206 
    207 void
    208 AcpiExRelinquishInterpreter (
    209     void)
    210 {
    211     ACPI_FUNCTION_TRACE (ExRelinquishInterpreter);
    212 
    213 
    214     /*
    215      * If the global serialized flag is set, do not release the interpreter.
    216      * This forces the interpreter to be single threaded.
    217      */
    218     if (!AcpiGbl_AllMethodsSerialized)
    219     {
    220         AcpiExExitInterpreter ();
    221     }
    222 
    223     return_VOID;
    224 }
    225 
    226 
    227 /*******************************************************************************
    228  *
    229  * FUNCTION:    AcpiExTruncateFor32bitTable
    230  *
    231  * PARAMETERS:  ObjDesc         - Object to be truncated
    232  *
    233  * RETURN:      none
    234  *
    235  * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
    236  *              32-bit, as determined by the revision of the DSDT.
    237  *
    238  ******************************************************************************/
    239 
    240 void
    241 AcpiExTruncateFor32bitTable (
    242     ACPI_OPERAND_OBJECT     *ObjDesc)
    243 {
    244 
    245     ACPI_FUNCTION_ENTRY ();
    246 
    247 
    248     /*
    249      * Object must be a valid number and we must be executing
    250      * a control method. NS node could be there for AML_INT_NAMEPATH_OP.
    251      */
    252     if ((!ObjDesc) ||
    253         (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) ||
    254         (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
    255     {
    256         return;
    257     }
    258 
    259     if (AcpiGbl_IntegerByteWidth == 4)
    260     {
    261         /*
    262          * We are running a method that exists in a 32-bit ACPI table.
    263          * Truncate the value to 32 bits by zeroing out the upper 32-bit field
    264          */
    265         ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX;
    266     }
    267 }
    268 
    269 
    270 /*******************************************************************************
    271  *
    272  * FUNCTION:    AcpiExAcquireGlobalLock
    273  *
    274  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
    275  *                                      AlwaysLock or NeverLock
    276  *
    277  * RETURN:      None
    278  *
    279  * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
    280  *              flags specifiy that it is to be obtained before field access.
    281  *
    282  ******************************************************************************/
    283 
    284 void
    285 AcpiExAcquireGlobalLock (
    286     UINT32                  FieldFlags)
    287 {
    288     ACPI_STATUS             Status;
    289 
    290 
    291     ACPI_FUNCTION_TRACE (ExAcquireGlobalLock);
    292 
    293 
    294     /* Only use the lock if the AlwaysLock bit is set */
    295 
    296     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
    297     {
    298         return_VOID;
    299     }
    300 
    301     /* Attempt to get the global lock, wait forever */
    302 
    303     Status = AcpiExAcquireMutexObject (ACPI_WAIT_FOREVER,
    304                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
    305 
    306     if (ACPI_FAILURE (Status))
    307     {
    308         ACPI_EXCEPTION ((AE_INFO, Status,
    309             "Could not acquire Global Lock"));
    310     }
    311 
    312     return_VOID;
    313 }
    314 
    315 
    316 /*******************************************************************************
    317  *
    318  * FUNCTION:    AcpiExReleaseGlobalLock
    319  *
    320  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
    321  *                                      AlwaysLock or NeverLock
    322  *
    323  * RETURN:      None
    324  *
    325  * DESCRIPTION: Release the ACPI hardware Global Lock
    326  *
    327  ******************************************************************************/
    328 
    329 void
    330 AcpiExReleaseGlobalLock (
    331     UINT32                  FieldFlags)
    332 {
    333     ACPI_STATUS             Status;
    334 
    335 
    336     ACPI_FUNCTION_TRACE (ExReleaseGlobalLock);
    337 
    338 
    339     /* Only use the lock if the AlwaysLock bit is set */
    340 
    341     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
    342     {
    343         return_VOID;
    344     }
    345 
    346     /* Release the global lock */
    347 
    348     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
    349     if (ACPI_FAILURE (Status))
    350     {
    351         /* Report the error, but there isn't much else we can do */
    352 
    353         ACPI_EXCEPTION ((AE_INFO, Status,
    354             "Could not release Global Lock"));
    355     }
    356 
    357     return_VOID;
    358 }
    359 
    360 
    361 /*******************************************************************************
    362  *
    363  * FUNCTION:    AcpiExDigitsNeeded
    364  *
    365  * PARAMETERS:  Value           - Value to be represented
    366  *              Base            - Base of representation
    367  *
    368  * RETURN:      The number of digits.
    369  *
    370  * DESCRIPTION: Calculate the number of digits needed to represent the Value
    371  *              in the given Base (Radix)
    372  *
    373  ******************************************************************************/
    374 
    375 static UINT32
    376 AcpiExDigitsNeeded (
    377     UINT64                  Value,
    378     UINT32                  Base)
    379 {
    380     UINT32                  NumDigits;
    381     UINT64                  CurrentValue;
    382 
    383 
    384     ACPI_FUNCTION_TRACE (ExDigitsNeeded);
    385 
    386 
    387     /* UINT64 is unsigned, so we don't worry about a '-' prefix */
    388 
    389     if (Value == 0)
    390     {
    391         return_UINT32 (1);
    392     }
    393 
    394     CurrentValue = Value;
    395     NumDigits = 0;
    396 
    397     /* Count the digits in the requested base */
    398 
    399     while (CurrentValue)
    400     {
    401         (void) AcpiUtShortDivide (CurrentValue, Base, &CurrentValue, NULL);
    402         NumDigits++;
    403     }
    404 
    405     return_UINT32 (NumDigits);
    406 }
    407 
    408 
    409 /*******************************************************************************
    410  *
    411  * FUNCTION:    AcpiExEisaIdToString
    412  *
    413  * PARAMETERS:  CompressedId    - EISAID to be converted
    414  *              OutString       - Where to put the converted string (8 bytes)
    415  *
    416  * RETURN:      None
    417  *
    418  * DESCRIPTION: Convert a numeric EISAID to string representation. Return
    419  *              buffer must be large enough to hold the string. The string
    420  *              returned is always exactly of length ACPI_EISAID_STRING_SIZE
    421  *              (includes null terminator). The EISAID is always 32 bits.
    422  *
    423  ******************************************************************************/
    424 
    425 void
    426 AcpiExEisaIdToString (
    427     char                    *OutString,
    428     UINT64                  CompressedId)
    429 {
    430     UINT32                  SwappedId;
    431 
    432 
    433     ACPI_FUNCTION_ENTRY ();
    434 
    435 
    436     /* The EISAID should be a 32-bit integer */
    437 
    438     if (CompressedId > ACPI_UINT32_MAX)
    439     {
    440         ACPI_WARNING ((AE_INFO,
    441             "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
    442             ACPI_FORMAT_UINT64 (CompressedId)));
    443     }
    444 
    445     /* Swap ID to big-endian to get contiguous bits */
    446 
    447     SwappedId = AcpiUtDwordByteSwap ((UINT32) CompressedId);
    448 
    449     /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
    450 
    451     OutString[0] = (char) (0x40 + (((unsigned long) SwappedId >> 26) & 0x1F));
    452     OutString[1] = (char) (0x40 + ((SwappedId >> 21) & 0x1F));
    453     OutString[2] = (char) (0x40 + ((SwappedId >> 16) & 0x1F));
    454     OutString[3] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 12);
    455     OutString[4] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 8);
    456     OutString[5] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 4);
    457     OutString[6] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 0);
    458     OutString[7] = 0;
    459 }
    460 
    461 
    462 /*******************************************************************************
    463  *
    464  * FUNCTION:    AcpiExIntegerToString
    465  *
    466  * PARAMETERS:  OutString       - Where to put the converted string. At least
    467  *                                21 bytes are needed to hold the largest
    468  *                                possible 64-bit integer.
    469  *              Value           - Value to be converted
    470  *
    471  * RETURN:      None, string
    472  *
    473  * DESCRIPTION: Convert a 64-bit integer to decimal string representation.
    474  *              Assumes string buffer is large enough to hold the string. The
    475  *              largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
    476  *
    477  ******************************************************************************/
    478 
    479 void
    480 AcpiExIntegerToString (
    481     char                    *OutString,
    482     UINT64                  Value)
    483 {
    484     UINT32                  Count;
    485     UINT32                  DigitsNeeded;
    486     UINT32                  Remainder;
    487 
    488 
    489     ACPI_FUNCTION_ENTRY ();
    490 
    491 
    492     DigitsNeeded = AcpiExDigitsNeeded (Value, 10);
    493     OutString[DigitsNeeded] = 0;
    494 
    495     for (Count = DigitsNeeded; Count > 0; Count--)
    496     {
    497         (void) AcpiUtShortDivide (Value, 10, &Value, &Remainder);
    498         OutString[Count-1] = (char) ('0' + Remainder);\
    499     }
    500 }
    501 
    502 #endif
    503