Home | History | Annotate | Line # | Download | only in executer
exutils.c revision 1.1.1.4
      1 /******************************************************************************
      2  *
      3  * Module Name: exutils - interpreter/scanner utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2014, 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:    AcpiExExitInterpreter
    116  *
    117  * PARAMETERS:  None
    118  *
    119  * RETURN:      None
    120  *
    121  * DESCRIPTION: Exit the interpreter execution region. This is the top level
    122  *              routine used to exit the interpreter when all processing has
    123  *              been completed, or when the method blocks.
    124  *
    125  * Cases where the interpreter is unlocked internally:
    126  *      1) Method will be blocked on a Sleep() AML opcode
    127  *      2) Method will be blocked on an Acquire() AML opcode
    128  *      3) Method will be blocked on a Wait() AML opcode
    129  *      4) Method will be blocked to acquire the global lock
    130  *      5) Method will be blocked waiting to execute a serialized control
    131  *          method that is currently executing
    132  *      6) About to invoke a user-installed opregion handler
    133  *
    134  ******************************************************************************/
    135 
    136 void
    137 AcpiExExitInterpreter (
    138     void)
    139 {
    140     ACPI_STATUS             Status;
    141 
    142 
    143     ACPI_FUNCTION_TRACE (ExExitInterpreter);
    144 
    145 
    146     Status = AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
    147     if (ACPI_FAILURE (Status))
    148     {
    149         ACPI_ERROR ((AE_INFO, "Could not release AML Interpreter mutex"));
    150     }
    151 
    152     return_VOID;
    153 }
    154 
    155 
    156 /*******************************************************************************
    157  *
    158  * FUNCTION:    AcpiExTruncateFor32bitTable
    159  *
    160  * PARAMETERS:  ObjDesc         - Object to be truncated
    161  *
    162  * RETURN:      TRUE if a truncation was performed, FALSE otherwise.
    163  *
    164  * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
    165  *              32-bit, as determined by the revision of the DSDT.
    166  *
    167  ******************************************************************************/
    168 
    169 BOOLEAN
    170 AcpiExTruncateFor32bitTable (
    171     ACPI_OPERAND_OBJECT     *ObjDesc)
    172 {
    173 
    174     ACPI_FUNCTION_ENTRY ();
    175 
    176 
    177     /*
    178      * Object must be a valid number and we must be executing
    179      * a control method. Object could be NS node for AML_INT_NAMEPATH_OP.
    180      */
    181     if ((!ObjDesc) ||
    182         (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) ||
    183         (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
    184     {
    185         return (FALSE);
    186     }
    187 
    188     if ((AcpiGbl_IntegerByteWidth == 4) &&
    189         (ObjDesc->Integer.Value > (UINT64) ACPI_UINT32_MAX))
    190     {
    191         /*
    192          * We are executing in a 32-bit ACPI table.
    193          * Truncate the value to 32 bits by zeroing out the upper 32-bit field
    194          */
    195         ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX;
    196         return (TRUE);
    197     }
    198 
    199     return (FALSE);
    200 }
    201 
    202 
    203 /*******************************************************************************
    204  *
    205  * FUNCTION:    AcpiExAcquireGlobalLock
    206  *
    207  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
    208  *                                      AlwaysLock or NeverLock
    209  *
    210  * RETURN:      None
    211  *
    212  * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
    213  *              flags specifiy that it is to be obtained before field access.
    214  *
    215  ******************************************************************************/
    216 
    217 void
    218 AcpiExAcquireGlobalLock (
    219     UINT32                  FieldFlags)
    220 {
    221     ACPI_STATUS             Status;
    222 
    223 
    224     ACPI_FUNCTION_TRACE (ExAcquireGlobalLock);
    225 
    226 
    227     /* Only use the lock if the AlwaysLock bit is set */
    228 
    229     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
    230     {
    231         return_VOID;
    232     }
    233 
    234     /* Attempt to get the global lock, wait forever */
    235 
    236     Status = AcpiExAcquireMutexObject (ACPI_WAIT_FOREVER,
    237                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
    238 
    239     if (ACPI_FAILURE (Status))
    240     {
    241         ACPI_EXCEPTION ((AE_INFO, Status,
    242             "Could not acquire Global Lock"));
    243     }
    244 
    245     return_VOID;
    246 }
    247 
    248 
    249 /*******************************************************************************
    250  *
    251  * FUNCTION:    AcpiExReleaseGlobalLock
    252  *
    253  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
    254  *                                      AlwaysLock or NeverLock
    255  *
    256  * RETURN:      None
    257  *
    258  * DESCRIPTION: Release the ACPI hardware Global Lock
    259  *
    260  ******************************************************************************/
    261 
    262 void
    263 AcpiExReleaseGlobalLock (
    264     UINT32                  FieldFlags)
    265 {
    266     ACPI_STATUS             Status;
    267 
    268 
    269     ACPI_FUNCTION_TRACE (ExReleaseGlobalLock);
    270 
    271 
    272     /* Only use the lock if the AlwaysLock bit is set */
    273 
    274     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
    275     {
    276         return_VOID;
    277     }
    278 
    279     /* Release the global lock */
    280 
    281     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
    282     if (ACPI_FAILURE (Status))
    283     {
    284         /* Report the error, but there isn't much else we can do */
    285 
    286         ACPI_EXCEPTION ((AE_INFO, Status,
    287             "Could not release Global Lock"));
    288     }
    289 
    290     return_VOID;
    291 }
    292 
    293 
    294 /*******************************************************************************
    295  *
    296  * FUNCTION:    AcpiExDigitsNeeded
    297  *
    298  * PARAMETERS:  Value           - Value to be represented
    299  *              Base            - Base of representation
    300  *
    301  * RETURN:      The number of digits.
    302  *
    303  * DESCRIPTION: Calculate the number of digits needed to represent the Value
    304  *              in the given Base (Radix)
    305  *
    306  ******************************************************************************/
    307 
    308 static UINT32
    309 AcpiExDigitsNeeded (
    310     UINT64                  Value,
    311     UINT32                  Base)
    312 {
    313     UINT32                  NumDigits;
    314     UINT64                  CurrentValue;
    315 
    316 
    317     ACPI_FUNCTION_TRACE (ExDigitsNeeded);
    318 
    319 
    320     /* UINT64 is unsigned, so we don't worry about a '-' prefix */
    321 
    322     if (Value == 0)
    323     {
    324         return_UINT32 (1);
    325     }
    326 
    327     CurrentValue = Value;
    328     NumDigits = 0;
    329 
    330     /* Count the digits in the requested base */
    331 
    332     while (CurrentValue)
    333     {
    334         (void) AcpiUtShortDivide (CurrentValue, Base, &CurrentValue, NULL);
    335         NumDigits++;
    336     }
    337 
    338     return_UINT32 (NumDigits);
    339 }
    340 
    341 
    342 /*******************************************************************************
    343  *
    344  * FUNCTION:    AcpiExEisaIdToString
    345  *
    346  * PARAMETERS:  CompressedId    - EISAID to be converted
    347  *              OutString       - Where to put the converted string (8 bytes)
    348  *
    349  * RETURN:      None
    350  *
    351  * DESCRIPTION: Convert a numeric EISAID to string representation. Return
    352  *              buffer must be large enough to hold the string. The string
    353  *              returned is always exactly of length ACPI_EISAID_STRING_SIZE
    354  *              (includes null terminator). The EISAID is always 32 bits.
    355  *
    356  ******************************************************************************/
    357 
    358 void
    359 AcpiExEisaIdToString (
    360     char                    *OutString,
    361     UINT64                  CompressedId)
    362 {
    363     UINT32                  SwappedId;
    364 
    365 
    366     ACPI_FUNCTION_ENTRY ();
    367 
    368 
    369     /* The EISAID should be a 32-bit integer */
    370 
    371     if (CompressedId > ACPI_UINT32_MAX)
    372     {
    373         ACPI_WARNING ((AE_INFO,
    374             "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
    375             ACPI_FORMAT_UINT64 (CompressedId)));
    376     }
    377 
    378     /* Swap ID to big-endian to get contiguous bits */
    379 
    380     SwappedId = AcpiUtDwordByteSwap ((UINT32) CompressedId);
    381 
    382     /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
    383 
    384     OutString[0] = (char) (0x40 + (((unsigned long) SwappedId >> 26) & 0x1F));
    385     OutString[1] = (char) (0x40 + ((SwappedId >> 21) & 0x1F));
    386     OutString[2] = (char) (0x40 + ((SwappedId >> 16) & 0x1F));
    387     OutString[3] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 12);
    388     OutString[4] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 8);
    389     OutString[5] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 4);
    390     OutString[6] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 0);
    391     OutString[7] = 0;
    392 }
    393 
    394 
    395 /*******************************************************************************
    396  *
    397  * FUNCTION:    AcpiExIntegerToString
    398  *
    399  * PARAMETERS:  OutString       - Where to put the converted string. At least
    400  *                                21 bytes are needed to hold the largest
    401  *                                possible 64-bit integer.
    402  *              Value           - Value to be converted
    403  *
    404  * RETURN:      None, string
    405  *
    406  * DESCRIPTION: Convert a 64-bit integer to decimal string representation.
    407  *              Assumes string buffer is large enough to hold the string. The
    408  *              largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
    409  *
    410  ******************************************************************************/
    411 
    412 void
    413 AcpiExIntegerToString (
    414     char                    *OutString,
    415     UINT64                  Value)
    416 {
    417     UINT32                  Count;
    418     UINT32                  DigitsNeeded;
    419     UINT32                  Remainder;
    420 
    421 
    422     ACPI_FUNCTION_ENTRY ();
    423 
    424 
    425     DigitsNeeded = AcpiExDigitsNeeded (Value, 10);
    426     OutString[DigitsNeeded] = 0;
    427 
    428     for (Count = DigitsNeeded; Count > 0; Count--)
    429     {
    430         (void) AcpiUtShortDivide (Value, 10, &Value, &Remainder);
    431         OutString[Count-1] = (char) ('0' + Remainder);\
    432     }
    433 }
    434 
    435 
    436 /*******************************************************************************
    437  *
    438  * FUNCTION:    AcpiIsValidSpaceId
    439  *
    440  * PARAMETERS:  SpaceId             - ID to be validated
    441  *
    442  * RETURN:      TRUE if valid/supported ID.
    443  *
    444  * DESCRIPTION: Validate an operation region SpaceID.
    445  *
    446  ******************************************************************************/
    447 
    448 BOOLEAN
    449 AcpiIsValidSpaceId (
    450     UINT8                   SpaceId)
    451 {
    452 
    453     if ((SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) &&
    454         (SpaceId < ACPI_USER_REGION_BEGIN) &&
    455         (SpaceId != ACPI_ADR_SPACE_DATA_TABLE) &&
    456         (SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE))
    457     {
    458         return (FALSE);
    459     }
    460 
    461     return (TRUE);
    462 }
    463 
    464 
    465 #endif
    466