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