Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exutils - interpreter/scanner utilities
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 /*
0011  * DEFINE_AML_GLOBALS is tested in amlcode.h
0012  * to determine whether certain global names should be "defined" or only
0013  * "declared" in the current compilation. This enhances maintainability
0014  * by enabling a single header file to embody all knowledge of the names
0015  * in question.
0016  *
0017  * Exactly one module of any executable should #define DEFINE_GLOBALS
0018  * before #including the header files which use this convention. The
0019  * names in question will be defined and initialized in that module,
0020  * and declared as extern in all other modules which #include those
0021  * header files.
0022  */
0023 
0024 #define DEFINE_AML_GLOBALS
0025 
0026 #include <acpi/acpi.h>
0027 #include "accommon.h"
0028 #include "acinterp.h"
0029 #include "amlcode.h"
0030 
0031 #define _COMPONENT          ACPI_EXECUTER
0032 ACPI_MODULE_NAME("exutils")
0033 
0034 /* Local prototypes */
0035 static u32 acpi_ex_digits_needed(u64 value, u32 base);
0036 
0037 /*******************************************************************************
0038  *
0039  * FUNCTION:    acpi_ex_enter_interpreter
0040  *
0041  * PARAMETERS:  None
0042  *
0043  * RETURN:      None
0044  *
0045  * DESCRIPTION: Enter the interpreter execution region. Failure to enter
0046  *              the interpreter region is a fatal system error. Used in
0047  *              conjunction with exit_interpreter.
0048  *
0049  ******************************************************************************/
0050 
0051 void acpi_ex_enter_interpreter(void)
0052 {
0053     acpi_status status;
0054 
0055     ACPI_FUNCTION_TRACE(ex_enter_interpreter);
0056 
0057     status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
0058     if (ACPI_FAILURE(status)) {
0059         ACPI_ERROR((AE_INFO,
0060                 "Could not acquire AML Interpreter mutex"));
0061     }
0062     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0063     if (ACPI_FAILURE(status)) {
0064         ACPI_ERROR((AE_INFO, "Could not acquire AML Namespace mutex"));
0065     }
0066 
0067     return_VOID;
0068 }
0069 
0070 /*******************************************************************************
0071  *
0072  * FUNCTION:    acpi_ex_exit_interpreter
0073  *
0074  * PARAMETERS:  None
0075  *
0076  * RETURN:      None
0077  *
0078  * DESCRIPTION: Exit the interpreter execution region. This is the top level
0079  *              routine used to exit the interpreter when all processing has
0080  *              been completed, or when the method blocks.
0081  *
0082  * Cases where the interpreter is unlocked internally:
0083  *      1) Method will be blocked on a Sleep() AML opcode
0084  *      2) Method will be blocked on an Acquire() AML opcode
0085  *      3) Method will be blocked on a Wait() AML opcode
0086  *      4) Method will be blocked to acquire the global lock
0087  *      5) Method will be blocked waiting to execute a serialized control
0088  *          method that is currently executing
0089  *      6) About to invoke a user-installed opregion handler
0090  *
0091  ******************************************************************************/
0092 
0093 void acpi_ex_exit_interpreter(void)
0094 {
0095     acpi_status status;
0096 
0097     ACPI_FUNCTION_TRACE(ex_exit_interpreter);
0098 
0099     status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0100     if (ACPI_FAILURE(status)) {
0101         ACPI_ERROR((AE_INFO, "Could not release AML Namespace mutex"));
0102     }
0103     status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
0104     if (ACPI_FAILURE(status)) {
0105         ACPI_ERROR((AE_INFO,
0106                 "Could not release AML Interpreter mutex"));
0107     }
0108 
0109     return_VOID;
0110 }
0111 
0112 /*******************************************************************************
0113  *
0114  * FUNCTION:    acpi_ex_truncate_for32bit_table
0115  *
0116  * PARAMETERS:  obj_desc        - Object to be truncated
0117  *
0118  * RETURN:      TRUE if a truncation was performed, FALSE otherwise.
0119  *
0120  * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
0121  *              32-bit, as determined by the revision of the DSDT.
0122  *
0123  ******************************************************************************/
0124 
0125 u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
0126 {
0127 
0128     ACPI_FUNCTION_ENTRY();
0129 
0130     /*
0131      * Object must be a valid number and we must be executing
0132      * a control method. Object could be NS node for AML_INT_NAMEPATH_OP.
0133      */
0134     if ((!obj_desc) ||
0135         (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) ||
0136         (obj_desc->common.type != ACPI_TYPE_INTEGER)) {
0137         return (FALSE);
0138     }
0139 
0140     if ((acpi_gbl_integer_byte_width == 4) &&
0141         (obj_desc->integer.value > (u64)ACPI_UINT32_MAX)) {
0142         /*
0143          * We are executing in a 32-bit ACPI table. Truncate
0144          * the value to 32 bits by zeroing out the upper 32-bit field
0145          */
0146         obj_desc->integer.value &= (u64)ACPI_UINT32_MAX;
0147         return (TRUE);
0148     }
0149 
0150     return (FALSE);
0151 }
0152 
0153 /*******************************************************************************
0154  *
0155  * FUNCTION:    acpi_ex_acquire_global_lock
0156  *
0157  * PARAMETERS:  field_flags           - Flags with Lock rule:
0158  *                                      always_lock or never_lock
0159  *
0160  * RETURN:      None
0161  *
0162  * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
0163  *              flags specify that it is to be obtained before field access.
0164  *
0165  ******************************************************************************/
0166 
0167 void acpi_ex_acquire_global_lock(u32 field_flags)
0168 {
0169     acpi_status status;
0170 
0171     ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
0172 
0173     /* Only use the lock if the always_lock bit is set */
0174 
0175     if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
0176         return_VOID;
0177     }
0178 
0179     /* Attempt to get the global lock, wait forever */
0180 
0181     status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER,
0182                           acpi_gbl_global_lock_mutex,
0183                           acpi_os_get_thread_id());
0184 
0185     if (ACPI_FAILURE(status)) {
0186         ACPI_EXCEPTION((AE_INFO, status,
0187                 "Could not acquire Global Lock"));
0188     }
0189 
0190     return_VOID;
0191 }
0192 
0193 /*******************************************************************************
0194  *
0195  * FUNCTION:    acpi_ex_release_global_lock
0196  *
0197  * PARAMETERS:  field_flags           - Flags with Lock rule:
0198  *                                      always_lock or never_lock
0199  *
0200  * RETURN:      None
0201  *
0202  * DESCRIPTION: Release the ACPI hardware Global Lock
0203  *
0204  ******************************************************************************/
0205 
0206 void acpi_ex_release_global_lock(u32 field_flags)
0207 {
0208     acpi_status status;
0209 
0210     ACPI_FUNCTION_TRACE(ex_release_global_lock);
0211 
0212     /* Only use the lock if the always_lock bit is set */
0213 
0214     if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
0215         return_VOID;
0216     }
0217 
0218     /* Release the global lock */
0219 
0220     status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
0221     if (ACPI_FAILURE(status)) {
0222 
0223         /* Report the error, but there isn't much else we can do */
0224 
0225         ACPI_EXCEPTION((AE_INFO, status,
0226                 "Could not release Global Lock"));
0227     }
0228 
0229     return_VOID;
0230 }
0231 
0232 /*******************************************************************************
0233  *
0234  * FUNCTION:    acpi_ex_digits_needed
0235  *
0236  * PARAMETERS:  value           - Value to be represented
0237  *              base            - Base of representation
0238  *
0239  * RETURN:      The number of digits.
0240  *
0241  * DESCRIPTION: Calculate the number of digits needed to represent the Value
0242  *              in the given Base (Radix)
0243  *
0244  ******************************************************************************/
0245 
0246 static u32 acpi_ex_digits_needed(u64 value, u32 base)
0247 {
0248     u32 num_digits;
0249     u64 current_value;
0250 
0251     ACPI_FUNCTION_TRACE(ex_digits_needed);
0252 
0253     /* u64 is unsigned, so we don't worry about a '-' prefix */
0254 
0255     if (value == 0) {
0256         return_UINT32(1);
0257     }
0258 
0259     current_value = value;
0260     num_digits = 0;
0261 
0262     /* Count the digits in the requested base */
0263 
0264     while (current_value) {
0265         (void)acpi_ut_short_divide(current_value, base, &current_value,
0266                        NULL);
0267         num_digits++;
0268     }
0269 
0270     return_UINT32(num_digits);
0271 }
0272 
0273 /*******************************************************************************
0274  *
0275  * FUNCTION:    acpi_ex_eisa_id_to_string
0276  *
0277  * PARAMETERS:  out_string      - Where to put the converted string (8 bytes)
0278  *              compressed_id   - EISAID to be converted
0279  *
0280  * RETURN:      None
0281  *
0282  * DESCRIPTION: Convert a numeric EISAID to string representation. Return
0283  *              buffer must be large enough to hold the string. The string
0284  *              returned is always exactly of length ACPI_EISAID_STRING_SIZE
0285  *              (includes null terminator). The EISAID is always 32 bits.
0286  *
0287  ******************************************************************************/
0288 
0289 void acpi_ex_eisa_id_to_string(char *out_string, u64 compressed_id)
0290 {
0291     u32 swapped_id;
0292 
0293     ACPI_FUNCTION_ENTRY();
0294 
0295     /* The EISAID should be a 32-bit integer */
0296 
0297     if (compressed_id > ACPI_UINT32_MAX) {
0298         ACPI_WARNING((AE_INFO,
0299                   "Expected EISAID is larger than 32 bits: "
0300                   "0x%8.8X%8.8X, truncating",
0301                   ACPI_FORMAT_UINT64(compressed_id)));
0302     }
0303 
0304     /* Swap ID to big-endian to get contiguous bits */
0305 
0306     swapped_id = acpi_ut_dword_byte_swap((u32)compressed_id);
0307 
0308     /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
0309 
0310     out_string[0] =
0311         (char)(0x40 + (((unsigned long)swapped_id >> 26) & 0x1F));
0312     out_string[1] = (char)(0x40 + ((swapped_id >> 21) & 0x1F));
0313     out_string[2] = (char)(0x40 + ((swapped_id >> 16) & 0x1F));
0314     out_string[3] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 12);
0315     out_string[4] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 8);
0316     out_string[5] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 4);
0317     out_string[6] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 0);
0318     out_string[7] = 0;
0319 }
0320 
0321 /*******************************************************************************
0322  *
0323  * FUNCTION:    acpi_ex_integer_to_string
0324  *
0325  * PARAMETERS:  out_string      - Where to put the converted string. At least
0326  *                                21 bytes are needed to hold the largest
0327  *                                possible 64-bit integer.
0328  *              value           - Value to be converted
0329  *
0330  * RETURN:      Converted string in out_string
0331  *
0332  * DESCRIPTION: Convert a 64-bit integer to decimal string representation.
0333  *              Assumes string buffer is large enough to hold the string. The
0334  *              largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
0335  *
0336  ******************************************************************************/
0337 
0338 void acpi_ex_integer_to_string(char *out_string, u64 value)
0339 {
0340     u32 count;
0341     u32 digits_needed;
0342     u32 remainder;
0343 
0344     ACPI_FUNCTION_ENTRY();
0345 
0346     digits_needed = acpi_ex_digits_needed(value, 10);
0347     out_string[digits_needed] = 0;
0348 
0349     for (count = digits_needed; count > 0; count--) {
0350         (void)acpi_ut_short_divide(value, 10, &value, &remainder);
0351         out_string[count - 1] = (char)('0' + remainder);
0352     }
0353 }
0354 
0355 /*******************************************************************************
0356  *
0357  * FUNCTION:    acpi_ex_pci_cls_to_string
0358  *
0359  * PARAMETERS:  out_string      - Where to put the converted string (7 bytes)
0360  *              class_code      - PCI class code to be converted (3 bytes)
0361  *
0362  * RETURN:      Converted string in out_string
0363  *
0364  * DESCRIPTION: Convert 3-bytes PCI class code to string representation.
0365  *              Return buffer must be large enough to hold the string. The
0366  *              string returned is always exactly of length
0367  *              ACPI_PCICLS_STRING_SIZE (includes null terminator).
0368  *
0369  ******************************************************************************/
0370 
0371 void acpi_ex_pci_cls_to_string(char *out_string, u8 class_code[3])
0372 {
0373 
0374     ACPI_FUNCTION_ENTRY();
0375 
0376     /* All 3 bytes are hexadecimal */
0377 
0378     out_string[0] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 4);
0379     out_string[1] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 0);
0380     out_string[2] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 4);
0381     out_string[3] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 0);
0382     out_string[4] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 4);
0383     out_string[5] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 0);
0384     out_string[6] = 0;
0385 }
0386 
0387 /*******************************************************************************
0388  *
0389  * FUNCTION:    acpi_is_valid_space_id
0390  *
0391  * PARAMETERS:  space_id            - ID to be validated
0392  *
0393  * RETURN:      TRUE if space_id is a valid/supported ID.
0394  *
0395  * DESCRIPTION: Validate an operation region space_ID.
0396  *
0397  ******************************************************************************/
0398 
0399 u8 acpi_is_valid_space_id(u8 space_id)
0400 {
0401 
0402     if ((space_id >= ACPI_NUM_PREDEFINED_REGIONS) &&
0403         (space_id < ACPI_USER_REGION_BEGIN) &&
0404         (space_id != ACPI_ADR_SPACE_DATA_TABLE) &&
0405         (space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
0406         return (FALSE);
0407     }
0408 
0409     return (TRUE);
0410 }