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