Home | History | Annotate | Line # | Download | only in executer
exutils.c revision 1.1.1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: exutils - interpreter/scanner utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 /*
     45  * DEFINE_AML_GLOBALS is tested in amlcode.h
     46  * to determine whether certain global names should be "defined" or only
     47  * "declared" in the current compilation. This enhances maintainability
     48  * by enabling a single header file to embody all knowledge of the names
     49  * in question.
     50  *
     51  * Exactly one module of any executable should #define DEFINE_GLOBALS
     52  * before #including the header files which use this convention. The
     53  * names in question will be defined and initialized in that module,
     54  * and declared as extern in all other modules which #include those
     55  * header files.
     56  */
     57 
     58 #define DEFINE_AML_GLOBALS
     59 
     60 #include "acpi.h"
     61 #include "accommon.h"
     62 #include "acinterp.h"
     63 #include "amlcode.h"
     64 
     65 #define _COMPONENT          ACPI_EXECUTER
     66         ACPI_MODULE_NAME    ("exutils")
     67 
     68 /* Local prototypes */
     69 
     70 static UINT32
     71 AcpiExDigitsNeeded (
     72     UINT64                  Value,
     73     UINT32                  Base);
     74 
     75 
     76 #ifndef ACPI_NO_METHOD_EXECUTION
     77 /*******************************************************************************
     78  *
     79  * FUNCTION:    AcpiExEnterInterpreter
     80  *
     81  * PARAMETERS:  None
     82  *
     83  * RETURN:      None
     84  *
     85  * DESCRIPTION: Enter the interpreter execution region. Failure to enter
     86  *              the interpreter region is a fatal system error. Used in
     87  *              conjunction with ExitInterpreter.
     88  *
     89  ******************************************************************************/
     90 
     91 void
     92 AcpiExEnterInterpreter (
     93     void)
     94 {
     95     ACPI_STATUS             Status;
     96 
     97 
     98     ACPI_FUNCTION_TRACE (ExEnterInterpreter);
     99 
    100 
    101     Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
    102     if (ACPI_FAILURE (Status))
    103     {
    104         ACPI_ERROR ((AE_INFO, "Could not acquire AML Interpreter mutex"));
    105     }
    106 
    107     return_VOID;
    108 }
    109 
    110 
    111 /*******************************************************************************
    112  *
    113  * FUNCTION:    AcpiExExitInterpreter
    114  *
    115  * PARAMETERS:  None
    116  *
    117  * RETURN:      None
    118  *
    119  * DESCRIPTION: Exit the interpreter execution region. This is the top level
    120  *              routine used to exit the interpreter when all processing has
    121  *              been completed, or when the method blocks.
    122  *
    123  * Cases where the interpreter is unlocked internally:
    124  *      1) Method will be blocked on a Sleep() AML opcode
    125  *      2) Method will be blocked on an Acquire() AML opcode
    126  *      3) Method will be blocked on a Wait() AML opcode
    127  *      4) Method will be blocked to acquire the global lock
    128  *      5) Method will be blocked waiting to execute a serialized control
    129  *          method that is currently executing
    130  *      6) About to invoke a user-installed opregion handler
    131  *
    132  ******************************************************************************/
    133 
    134 void
    135 AcpiExExitInterpreter (
    136     void)
    137 {
    138     ACPI_STATUS             Status;
    139 
    140 
    141     ACPI_FUNCTION_TRACE (ExExitInterpreter);
    142 
    143 
    144     Status = AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
    145     if (ACPI_FAILURE (Status))
    146     {
    147         ACPI_ERROR ((AE_INFO, "Could not release AML Interpreter mutex"));
    148     }
    149 
    150     return_VOID;
    151 }
    152 
    153 
    154 /*******************************************************************************
    155  *
    156  * FUNCTION:    AcpiExTruncateFor32bitTable
    157  *
    158  * PARAMETERS:  ObjDesc         - Object to be truncated
    159  *
    160  * RETURN:      TRUE if a truncation was performed, FALSE otherwise.
    161  *
    162  * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
    163  *              32-bit, as determined by the revision of the DSDT.
    164  *
    165  ******************************************************************************/
    166 
    167 BOOLEAN
    168 AcpiExTruncateFor32bitTable (
    169     ACPI_OPERAND_OBJECT     *ObjDesc)
    170 {
    171 
    172     ACPI_FUNCTION_ENTRY ();
    173 
    174 
    175     /*
    176      * Object must be a valid number and we must be executing
    177      * a control method. Object could be NS node for AML_INT_NAMEPATH_OP.
    178      */
    179     if ((!ObjDesc) ||
    180         (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) ||
    181         (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
    182     {
    183         return (FALSE);
    184     }
    185 
    186     if ((AcpiGbl_IntegerByteWidth == 4) &&
    187         (ObjDesc->Integer.Value > (UINT64) ACPI_UINT32_MAX))
    188     {
    189         /*
    190          * We are executing in a 32-bit ACPI table. Truncate
    191          * the value to 32 bits by zeroing out the upper 32-bit field
    192          */
    193         ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX;
    194         return (TRUE);
    195     }
    196 
    197     return (FALSE);
    198 }
    199 
    200 
    201 /*******************************************************************************
    202  *
    203  * FUNCTION:    AcpiExAcquireGlobalLock
    204  *
    205  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
    206  *                                      AlwaysLock or NeverLock
    207  *
    208  * RETURN:      None
    209  *
    210  * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
    211  *              flags specifiy that it is to be obtained before field access.
    212  *
    213  ******************************************************************************/
    214 
    215 void
    216 AcpiExAcquireGlobalLock (
    217     UINT32                  FieldFlags)
    218 {
    219     ACPI_STATUS             Status;
    220 
    221 
    222     ACPI_FUNCTION_TRACE (ExAcquireGlobalLock);
    223 
    224 
    225     /* Only use the lock if the AlwaysLock bit is set */
    226 
    227     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
    228     {
    229         return_VOID;
    230     }
    231 
    232     /* Attempt to get the global lock, wait forever */
    233 
    234     Status = AcpiExAcquireMutexObject (ACPI_WAIT_FOREVER,
    235         AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
    236 
    237     if (ACPI_FAILURE (Status))
    238     {
    239         ACPI_EXCEPTION ((AE_INFO, Status,
    240             "Could not acquire Global Lock"));
    241     }
    242 
    243     return_VOID;
    244 }
    245 
    246 
    247 /*******************************************************************************
    248  *
    249  * FUNCTION:    AcpiExReleaseGlobalLock
    250  *
    251  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
    252  *                                      AlwaysLock or NeverLock
    253  *
    254  * RETURN:      None
    255  *
    256  * DESCRIPTION: Release the ACPI hardware Global Lock
    257  *
    258  ******************************************************************************/
    259 
    260 void
    261 AcpiExReleaseGlobalLock (
    262     UINT32                  FieldFlags)
    263 {
    264     ACPI_STATUS             Status;
    265 
    266 
    267     ACPI_FUNCTION_TRACE (ExReleaseGlobalLock);
    268 
    269 
    270     /* Only use the lock if the AlwaysLock bit is set */
    271 
    272     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
    273     {
    274         return_VOID;
    275     }
    276 
    277     /* Release the global lock */
    278 
    279     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
    280     if (ACPI_FAILURE (Status))
    281     {
    282         /* Report the error, but there isn't much else we can do */
    283 
    284         ACPI_EXCEPTION ((AE_INFO, Status,
    285             "Could not release Global Lock"));
    286     }
    287 
    288     return_VOID;
    289 }
    290 
    291 
    292 /*******************************************************************************
    293  *
    294  * FUNCTION:    AcpiExDigitsNeeded
    295  *
    296  * PARAMETERS:  Value           - Value to be represented
    297  *              Base            - Base of representation
    298  *
    299  * RETURN:      The number of digits.
    300  *
    301  * DESCRIPTION: Calculate the number of digits needed to represent the Value
    302  *              in the given Base (Radix)
    303  *
    304  ******************************************************************************/
    305 
    306 static UINT32
    307 AcpiExDigitsNeeded (
    308     UINT64                  Value,
    309     UINT32                  Base)
    310 {
    311     UINT32                  NumDigits;
    312     UINT64                  CurrentValue;
    313 
    314 
    315     ACPI_FUNCTION_TRACE (ExDigitsNeeded);
    316 
    317 
    318     /* UINT64 is unsigned, so we don't worry about a '-' prefix */
    319 
    320     if (Value == 0)
    321     {
    322         return_UINT32 (1);
    323     }
    324 
    325     CurrentValue = Value;
    326     NumDigits = 0;
    327 
    328     /* Count the digits in the requested base */
    329 
    330     while (CurrentValue)
    331     {
    332         (void) AcpiUtShortDivide (CurrentValue, Base, &CurrentValue, NULL);
    333         NumDigits++;
    334     }
    335 
    336     return_UINT32 (NumDigits);
    337 }
    338 
    339 
    340 /*******************************************************************************
    341  *
    342  * FUNCTION:    AcpiExEisaIdToString
    343  *
    344  * PARAMETERS:  CompressedId    - EISAID to be converted
    345  *              OutString       - Where to put the converted string (8 bytes)
    346  *
    347  * RETURN:      None
    348  *
    349  * DESCRIPTION: Convert a numeric EISAID to string representation. Return
    350  *              buffer must be large enough to hold the string. The string
    351  *              returned is always exactly of length ACPI_EISAID_STRING_SIZE
    352  *              (includes null terminator). The EISAID is always 32 bits.
    353  *
    354  ******************************************************************************/
    355 
    356 void
    357 AcpiExEisaIdToString (
    358     char                    *OutString,
    359     UINT64                  CompressedId)
    360 {
    361     UINT32                  SwappedId;
    362 
    363 
    364     ACPI_FUNCTION_ENTRY ();
    365 
    366 
    367     /* The EISAID should be a 32-bit integer */
    368 
    369     if (CompressedId > ACPI_UINT32_MAX)
    370     {
    371         ACPI_WARNING ((AE_INFO,
    372             "Expected EISAID is larger than 32 bits: "
    373             "0x%8.8X%8.8X, truncating",
    374             ACPI_FORMAT_UINT64 (CompressedId)));
    375     }
    376 
    377     /* Swap ID to big-endian to get contiguous bits */
    378 
    379     SwappedId = AcpiUtDwordByteSwap ((UINT32) CompressedId);
    380 
    381     /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
    382 
    383     OutString[0] = (char) (0x40 + (((unsigned long) SwappedId >> 26) & 0x1F));
    384     OutString[1] = (char) (0x40 + ((SwappedId >> 21) & 0x1F));
    385     OutString[2] = (char) (0x40 + ((SwappedId >> 16) & 0x1F));
    386     OutString[3] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 12);
    387     OutString[4] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 8);
    388     OutString[5] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 4);
    389     OutString[6] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 0);
    390     OutString[7] = 0;
    391 }
    392 
    393 
    394 /*******************************************************************************
    395  *
    396  * FUNCTION:    AcpiExIntegerToString
    397  *
    398  * PARAMETERS:  OutString       - Where to put the converted string. At least
    399  *                                21 bytes are needed to hold the largest
    400  *                                possible 64-bit integer.
    401  *              Value           - Value to be converted
    402  *
    403  * RETURN:      None, string
    404  *
    405  * DESCRIPTION: Convert a 64-bit integer to decimal string representation.
    406  *              Assumes string buffer is large enough to hold the string. The
    407  *              largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
    408  *
    409  ******************************************************************************/
    410 
    411 void
    412 AcpiExIntegerToString (
    413     char                    *OutString,
    414     UINT64                  Value)
    415 {
    416     UINT32                  Count;
    417     UINT32                  DigitsNeeded;
    418     UINT32                  Remainder;
    419 
    420 
    421     ACPI_FUNCTION_ENTRY ();
    422 
    423 
    424     DigitsNeeded = AcpiExDigitsNeeded (Value, 10);
    425     OutString[DigitsNeeded] = 0;
    426 
    427     for (Count = DigitsNeeded; Count > 0; Count--)
    428     {
    429         (void) AcpiUtShortDivide (Value, 10, &Value, &Remainder);
    430         OutString[Count-1] = (char) ('0' + Remainder);\
    431     }
    432 }
    433 
    434 
    435 /*******************************************************************************
    436  *
    437  * FUNCTION:    AcpiExPciClsToString
    438  *
    439  * PARAMETERS:  OutString       - Where to put the converted string (7 bytes)
    440  * PARAMETERS:  ClassCode       - PCI class code to be converted (3 bytes)
    441  *
    442  * RETURN:      None
    443  *
    444  * DESCRIPTION: Convert 3-bytes PCI class code to string representation.
    445  *              Return buffer must be large enough to hold the string. The
    446  *              string returned is always exactly of length
    447  *              ACPI_PCICLS_STRING_SIZE (includes null terminator).
    448  *
    449  ******************************************************************************/
    450 
    451 void
    452 AcpiExPciClsToString (
    453     char                    *OutString,
    454     UINT8                   ClassCode[3])
    455 {
    456 
    457     ACPI_FUNCTION_ENTRY ();
    458 
    459 
    460     /* All 3 bytes are hexadecimal */
    461 
    462     OutString[0] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 4);
    463     OutString[1] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 0);
    464     OutString[2] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 4);
    465     OutString[3] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 0);
    466     OutString[4] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 4);
    467     OutString[5] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 0);
    468     OutString[6] = 0;
    469 }
    470 
    471 
    472 /*******************************************************************************
    473  *
    474  * FUNCTION:    AcpiIsValidSpaceId
    475  *
    476  * PARAMETERS:  SpaceId             - ID to be validated
    477  *
    478  * RETURN:      TRUE if valid/supported ID.
    479  *
    480  * DESCRIPTION: Validate an operation region SpaceID.
    481  *
    482  ******************************************************************************/
    483 
    484 BOOLEAN
    485 AcpiIsValidSpaceId (
    486     UINT8                   SpaceId)
    487 {
    488 
    489     if ((SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) &&
    490         (SpaceId < ACPI_USER_REGION_BEGIN) &&
    491         (SpaceId != ACPI_ADR_SPACE_DATA_TABLE) &&
    492         (SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE))
    493     {
    494         return (FALSE);
    495     }
    496 
    497     return (TRUE);
    498 }
    499 
    500 #endif
    501