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