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