![]() |
|
|||
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, ¤t_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 }
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |