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