1 /****************************************************************************** 2 * 3 * Module Name: exutils - interpreter/scanner utilities 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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. 191 * Truncate 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: CompressedId - EISAID to be converted 345 * OutString - Where to put the converted string (8 bytes) 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: 0x%8.8X%8.8X, truncating", 373 ACPI_FORMAT_UINT64 (CompressedId))); 374 } 375 376 /* Swap ID to big-endian to get contiguous bits */ 377 378 SwappedId = AcpiUtDwordByteSwap ((UINT32) CompressedId); 379 380 /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */ 381 382 OutString[0] = (char) (0x40 + (((unsigned long) SwappedId >> 26) & 0x1F)); 383 OutString[1] = (char) (0x40 + ((SwappedId >> 21) & 0x1F)); 384 OutString[2] = (char) (0x40 + ((SwappedId >> 16) & 0x1F)); 385 OutString[3] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 12); 386 OutString[4] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 8); 387 OutString[5] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 4); 388 OutString[6] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 0); 389 OutString[7] = 0; 390 } 391 392 393 /******************************************************************************* 394 * 395 * FUNCTION: AcpiExIntegerToString 396 * 397 * PARAMETERS: OutString - Where to put the converted string. At least 398 * 21 bytes are needed to hold the largest 399 * possible 64-bit integer. 400 * Value - Value to be converted 401 * 402 * RETURN: None, string 403 * 404 * DESCRIPTION: Convert a 64-bit integer to decimal string representation. 405 * Assumes string buffer is large enough to hold the string. The 406 * largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1). 407 * 408 ******************************************************************************/ 409 410 void 411 AcpiExIntegerToString ( 412 char *OutString, 413 UINT64 Value) 414 { 415 UINT32 Count; 416 UINT32 DigitsNeeded; 417 UINT32 Remainder; 418 419 420 ACPI_FUNCTION_ENTRY (); 421 422 423 DigitsNeeded = AcpiExDigitsNeeded (Value, 10); 424 OutString[DigitsNeeded] = 0; 425 426 for (Count = DigitsNeeded; Count > 0; Count--) 427 { 428 (void) AcpiUtShortDivide (Value, 10, &Value, &Remainder); 429 OutString[Count-1] = (char) ('0' + Remainder);\ 430 } 431 } 432 433 434 /******************************************************************************* 435 * 436 * FUNCTION: AcpiExPciClsToString 437 * 438 * PARAMETERS: OutString - Where to put the converted string (7 bytes) 439 * PARAMETERS: ClassCode - PCI class code to be converted (3 bytes) 440 * 441 * RETURN: None 442 * 443 * DESCRIPTION: Convert 3-bytes PCI class code to string representation. 444 * Return buffer must be large enough to hold the string. The 445 * string returned is always exactly of length 446 * ACPI_PCICLS_STRING_SIZE (includes null terminator). 447 * 448 ******************************************************************************/ 449 450 void 451 AcpiExPciClsToString ( 452 char *OutString, 453 UINT8 ClassCode[3]) 454 { 455 456 ACPI_FUNCTION_ENTRY (); 457 458 459 /* All 3 bytes are hexadecimal */ 460 461 OutString[0] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 4); 462 OutString[1] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 0); 463 OutString[2] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 4); 464 OutString[3] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 0); 465 OutString[4] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 4); 466 OutString[5] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 0); 467 OutString[6] = 0; 468 } 469 470 471 /******************************************************************************* 472 * 473 * FUNCTION: AcpiIsValidSpaceId 474 * 475 * PARAMETERS: SpaceId - ID to be validated 476 * 477 * RETURN: TRUE if valid/supported ID. 478 * 479 * DESCRIPTION: Validate an operation region SpaceID. 480 * 481 ******************************************************************************/ 482 483 BOOLEAN 484 AcpiIsValidSpaceId ( 485 UINT8 SpaceId) 486 { 487 488 if ((SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) && 489 (SpaceId < ACPI_USER_REGION_BEGIN) && 490 (SpaceId != ACPI_ADR_SPACE_DATA_TABLE) && 491 (SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE)) 492 { 493 return (FALSE); 494 } 495 496 return (TRUE); 497 } 498 499 500 #endif 501