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