167754Smsmith/****************************************************************************** 267754Smsmith * 377424Smsmith * Module Name: exutils - interpreter/scanner utilities 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8298714Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 4483174Smsmith/* 4583174Smsmith * DEFINE_AML_GLOBALS is tested in amlcode.h 4683174Smsmith * to determine whether certain global names should be "defined" or only 47241973Sjkim * "declared" in the current compilation. This enhances maintainability 4883174Smsmith * by enabling a single header file to embody all knowledge of the names 4983174Smsmith * in question. 5083174Smsmith * 5183174Smsmith * Exactly one module of any executable should #define DEFINE_GLOBALS 52241973Sjkim * before #including the header files which use this convention. The 5383174Smsmith * names in question will be defined and initialized in that module, 5483174Smsmith * and declared as extern in all other modules which #include those 5583174Smsmith * header files. 5683174Smsmith */ 5783174Smsmith 5883174Smsmith#define DEFINE_AML_GLOBALS 5983174Smsmith 60193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 61193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 62193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 63193341Sjkim#include <contrib/dev/acpica/include/amlcode.h> 6467754Smsmith 6577424Smsmith#define _COMPONENT ACPI_EXECUTER 6691116Smsmith ACPI_MODULE_NAME ("exutils") 6767754Smsmith 68151937Sjkim/* Local prototypes */ 6967754Smsmith 70151937Sjkimstatic UINT32 71151937SjkimAcpiExDigitsNeeded ( 72202771Sjkim UINT64 Value, 73151937Sjkim UINT32 Base); 74151937Sjkim 75151937Sjkim 76100966Siwasaki#ifndef ACPI_NO_METHOD_EXECUTION 77100966Siwasaki/******************************************************************************* 78100966Siwasaki * 7977424Smsmith * FUNCTION: AcpiExEnterInterpreter 8067754Smsmith * 8167754Smsmith * PARAMETERS: None 8267754Smsmith * 83167802Sjkim * RETURN: None 84151937Sjkim * 85167802Sjkim * DESCRIPTION: Enter the interpreter execution region. Failure to enter 86167802Sjkim * the interpreter region is a fatal system error. Used in 87167802Sjkim * conjunction with ExitInterpreter. 8867754Smsmith * 8967754Smsmith ******************************************************************************/ 9067754Smsmith 91167802Sjkimvoid 92151937SjkimAcpiExEnterInterpreter ( 93151937Sjkim void) 9467754Smsmith{ 9577424Smsmith ACPI_STATUS Status; 9667754Smsmith 9767754Smsmith 98167802Sjkim ACPI_FUNCTION_TRACE (ExEnterInterpreter); 9967754Smsmith 100167802Sjkim 101167802Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 10291116Smsmith if (ACPI_FAILURE (Status)) 10391116Smsmith { 104167802Sjkim ACPI_ERROR ((AE_INFO, "Could not acquire AML Interpreter mutex")); 10591116Smsmith } 10691116Smsmith 107167802Sjkim return_VOID; 10867754Smsmith} 10967754Smsmith 11067754Smsmith 11167754Smsmith/******************************************************************************* 11267754Smsmith * 11377424Smsmith * FUNCTION: AcpiExExitInterpreter 11467754Smsmith * 11567754Smsmith * PARAMETERS: None 11667754Smsmith * 117151937Sjkim * RETURN: None 118151937Sjkim * 119167802Sjkim * DESCRIPTION: Exit the interpreter execution region. This is the top level 120167802Sjkim * routine used to exit the interpreter when all processing has 121272444Sjkim * been completed, or when the method blocks. 12267754Smsmith * 123272444Sjkim * Cases where the interpreter is unlocked internally: 124272444Sjkim * 1) Method will be blocked on a Sleep() AML opcode 125272444Sjkim * 2) Method will be blocked on an Acquire() AML opcode 126272444Sjkim * 3) Method will be blocked on a Wait() AML opcode 127272444Sjkim * 4) Method will be blocked to acquire the global lock 128272444Sjkim * 5) Method will be blocked waiting to execute a serialized control 129272444Sjkim * method that is currently executing 130272444Sjkim * 6) About to invoke a user-installed opregion handler 131272444Sjkim * 13267754Smsmith ******************************************************************************/ 13367754Smsmith 13467754Smsmithvoid 135151937SjkimAcpiExExitInterpreter ( 136151937Sjkim void) 13767754Smsmith{ 13891116Smsmith ACPI_STATUS Status; 13967754Smsmith 14067754Smsmith 141167802Sjkim ACPI_FUNCTION_TRACE (ExExitInterpreter); 14267754Smsmith 14391116Smsmith 144167802Sjkim Status = AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 14599679Siwasaki if (ACPI_FAILURE (Status)) 14699679Siwasaki { 147167802Sjkim ACPI_ERROR ((AE_INFO, "Could not release AML Interpreter mutex")); 14899679Siwasaki } 14991116Smsmith 15067754Smsmith return_VOID; 15167754Smsmith} 15267754Smsmith 15367754Smsmith 15467754Smsmith/******************************************************************************* 15567754Smsmith * 15677424Smsmith * FUNCTION: AcpiExTruncateFor32bitTable 15767754Smsmith * 15869450Smsmith * PARAMETERS: ObjDesc - Object to be truncated 15967754Smsmith * 160245582Sjkim * RETURN: TRUE if a truncation was performed, FALSE otherwise. 16167754Smsmith * 162167802Sjkim * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is 163167802Sjkim * 32-bit, as determined by the revision of the DSDT. 16467754Smsmith * 16567754Smsmith ******************************************************************************/ 16667754Smsmith 167245582SjkimBOOLEAN 16877424SmsmithAcpiExTruncateFor32bitTable ( 16999679Siwasaki ACPI_OPERAND_OBJECT *ObjDesc) 17067754Smsmith{ 17167754Smsmith 17291116Smsmith ACPI_FUNCTION_ENTRY (); 17383174Smsmith 17483174Smsmith 17569450Smsmith /* 17669450Smsmith * Object must be a valid number and we must be executing 177245582Sjkim * a control method. Object could be NS node for AML_INT_NAMEPATH_OP. 17869450Smsmith */ 17969450Smsmith if ((!ObjDesc) || 180167802Sjkim (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) || 181193267Sjkim (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) 18269450Smsmith { 183245582Sjkim return (FALSE); 18469450Smsmith } 18569450Smsmith 186245582Sjkim if ((AcpiGbl_IntegerByteWidth == 4) && 187245582Sjkim (ObjDesc->Integer.Value > (UINT64) ACPI_UINT32_MAX)) 18869450Smsmith { 18969450Smsmith /* 190298714Sjkim * We are executing in a 32-bit ACPI table. Truncate 191298714Sjkim * the value to 32 bits by zeroing out the upper 32-bit field 19269450Smsmith */ 193202771Sjkim ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX; 194245582Sjkim return (TRUE); 19569450Smsmith } 196245582Sjkim 197245582Sjkim return (FALSE); 19867754Smsmith} 19967754Smsmith 20067754Smsmith 20167754Smsmith/******************************************************************************* 20267754Smsmith * 20377424Smsmith * FUNCTION: AcpiExAcquireGlobalLock 20467754Smsmith * 20591116Smsmith * PARAMETERS: FieldFlags - Flags with Lock rule: 20687031Smsmith * AlwaysLock or NeverLock 20767754Smsmith * 208167802Sjkim * RETURN: None 20967754Smsmith * 210167802Sjkim * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field 211167802Sjkim * flags specifiy that it is to be obtained before field access. 21267754Smsmith * 21367754Smsmith ******************************************************************************/ 21467754Smsmith 215167802Sjkimvoid 21677424SmsmithAcpiExAcquireGlobalLock ( 21787031Smsmith UINT32 FieldFlags) 21867754Smsmith{ 21967754Smsmith ACPI_STATUS Status; 22067754Smsmith 22167754Smsmith 222167802Sjkim ACPI_FUNCTION_TRACE (ExAcquireGlobalLock); 22367754Smsmith 22467754Smsmith 225167802Sjkim /* Only use the lock if the AlwaysLock bit is set */ 22667754Smsmith 227167802Sjkim if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK)) 22867754Smsmith { 229167802Sjkim return_VOID; 230167802Sjkim } 23167754Smsmith 232167802Sjkim /* Attempt to get the global lock, wait forever */ 233167802Sjkim 234167802Sjkim Status = AcpiExAcquireMutexObject (ACPI_WAIT_FOREVER, 235298714Sjkim AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); 236167802Sjkim 237167802Sjkim if (ACPI_FAILURE (Status)) 238167802Sjkim { 239167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 240167802Sjkim "Could not acquire Global Lock")); 24167754Smsmith } 24267754Smsmith 243167802Sjkim return_VOID; 24467754Smsmith} 24567754Smsmith 24667754Smsmith 24767754Smsmith/******************************************************************************* 24867754Smsmith * 24977424Smsmith * FUNCTION: AcpiExReleaseGlobalLock 25067754Smsmith * 251167802Sjkim * PARAMETERS: FieldFlags - Flags with Lock rule: 252167802Sjkim * AlwaysLock or NeverLock 25367754Smsmith * 254151937Sjkim * RETURN: None 25567754Smsmith * 256167802Sjkim * DESCRIPTION: Release the ACPI hardware Global Lock 25767754Smsmith * 25867754Smsmith ******************************************************************************/ 25967754Smsmith 26099679Siwasakivoid 26177424SmsmithAcpiExReleaseGlobalLock ( 262167802Sjkim UINT32 FieldFlags) 26367754Smsmith{ 26499679Siwasaki ACPI_STATUS Status; 26567754Smsmith 26699679Siwasaki 267167802Sjkim ACPI_FUNCTION_TRACE (ExReleaseGlobalLock); 26867754Smsmith 26967754Smsmith 270167802Sjkim /* Only use the lock if the AlwaysLock bit is set */ 27167754Smsmith 272167802Sjkim if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK)) 27367754Smsmith { 274167802Sjkim return_VOID; 275167802Sjkim } 27667754Smsmith 277167802Sjkim /* Release the global lock */ 27899679Siwasaki 279167802Sjkim Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); 280167802Sjkim if (ACPI_FAILURE (Status)) 281167802Sjkim { 282167802Sjkim /* Report the error, but there isn't much else we can do */ 283167802Sjkim 284167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 285167802Sjkim "Could not release Global Lock")); 28667754Smsmith } 287100966Siwasaki 288100966Siwasaki return_VOID; 28967754Smsmith} 29067754Smsmith 29167754Smsmith 29267754Smsmith/******************************************************************************* 29367754Smsmith * 29477424Smsmith * FUNCTION: AcpiExDigitsNeeded 29567754Smsmith * 29684491Smsmith * PARAMETERS: Value - Value to be represented 29784491Smsmith * Base - Base of representation 29867754Smsmith * 299151937Sjkim * RETURN: The number of digits. 30067754Smsmith * 301151937Sjkim * DESCRIPTION: Calculate the number of digits needed to represent the Value 302151937Sjkim * in the given Base (Radix) 303151937Sjkim * 30467754Smsmith ******************************************************************************/ 30567754Smsmith 306151937Sjkimstatic UINT32 30777424SmsmithAcpiExDigitsNeeded ( 308202771Sjkim UINT64 Value, 30984491Smsmith UINT32 Base) 31067754Smsmith{ 31199679Siwasaki UINT32 NumDigits; 312202771Sjkim UINT64 CurrentValue; 31367754Smsmith 31467754Smsmith 315167802Sjkim ACPI_FUNCTION_TRACE (ExDigitsNeeded); 31667754Smsmith 31767754Smsmith 318202771Sjkim /* UINT64 is unsigned, so we don't worry about a '-' prefix */ 319138287Smarks 320138287Smarks if (Value == 0) 321117521Snjl { 322246849Sjkim return_UINT32 (1); 323117521Snjl } 324117521Snjl 325138287Smarks CurrentValue = Value; 32699679Siwasaki NumDigits = 0; 32799679Siwasaki 328138287Smarks /* Count the digits in the requested base */ 329138287Smarks 33099679Siwasaki while (CurrentValue) 33167754Smsmith { 332138287Smarks (void) AcpiUtShortDivide (CurrentValue, Base, &CurrentValue, NULL); 33399679Siwasaki NumDigits++; 33467754Smsmith } 33567754Smsmith 336246849Sjkim return_UINT32 (NumDigits); 33767754Smsmith} 33867754Smsmith 33967754Smsmith 34067754Smsmith/******************************************************************************* 34167754Smsmith * 34277424Smsmith * FUNCTION: AcpiExEisaIdToString 34367754Smsmith * 344298714Sjkim * PARAMETERS: OutString - Where to put the converted string (8 bytes) 345298714Sjkim * CompressedId - EISAID to be converted 34667754Smsmith * 347151937Sjkim * RETURN: None 348151937Sjkim * 349197104Sjkim * DESCRIPTION: Convert a numeric EISAID to string representation. Return 350197104Sjkim * buffer must be large enough to hold the string. The string 351197104Sjkim * returned is always exactly of length ACPI_EISAID_STRING_SIZE 352197104Sjkim * (includes null terminator). The EISAID is always 32 bits. 35367754Smsmith * 35467754Smsmith ******************************************************************************/ 35567754Smsmith 35699679Siwasakivoid 35777424SmsmithAcpiExEisaIdToString ( 358197104Sjkim char *OutString, 359202771Sjkim UINT64 CompressedId) 36067754Smsmith{ 361197104Sjkim UINT32 SwappedId; 36267754Smsmith 36383174Smsmith 36491116Smsmith ACPI_FUNCTION_ENTRY (); 36583174Smsmith 36683174Smsmith 367197104Sjkim /* The EISAID should be a 32-bit integer */ 368197104Sjkim 369197104Sjkim if (CompressedId > ACPI_UINT32_MAX) 370197104Sjkim { 371197104Sjkim ACPI_WARNING ((AE_INFO, 372298714Sjkim "Expected EISAID is larger than 32 bits: " 373298714Sjkim "0x%8.8X%8.8X, truncating", 374197104Sjkim ACPI_FORMAT_UINT64 (CompressedId))); 375197104Sjkim } 376197104Sjkim 37799679Siwasaki /* Swap ID to big-endian to get contiguous bits */ 37867754Smsmith 379197104Sjkim SwappedId = AcpiUtDwordByteSwap ((UINT32) CompressedId); 38067754Smsmith 381197104Sjkim /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */ 382197104Sjkim 383197104Sjkim OutString[0] = (char) (0x40 + (((unsigned long) SwappedId >> 26) & 0x1F)); 384197104Sjkim OutString[1] = (char) (0x40 + ((SwappedId >> 21) & 0x1F)); 385197104Sjkim OutString[2] = (char) (0x40 + ((SwappedId >> 16) & 0x1F)); 386202771Sjkim OutString[3] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 12); 387202771Sjkim OutString[4] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 8); 388202771Sjkim OutString[5] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 4); 389202771Sjkim OutString[6] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 0); 39067754Smsmith OutString[7] = 0; 39167754Smsmith} 39267754Smsmith 39367754Smsmith 39467754Smsmith/******************************************************************************* 39567754Smsmith * 396197104Sjkim * FUNCTION: AcpiExIntegerToString 39767754Smsmith * 398197104Sjkim * PARAMETERS: OutString - Where to put the converted string. At least 399197104Sjkim * 21 bytes are needed to hold the largest 400197104Sjkim * possible 64-bit integer. 401197104Sjkim * Value - Value to be converted 40267754Smsmith * 403298714Sjkim * RETURN: Converted string in OutString 40467754Smsmith * 405197104Sjkim * DESCRIPTION: Convert a 64-bit integer to decimal string representation. 406197104Sjkim * Assumes string buffer is large enough to hold the string. The 407197104Sjkim * largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1). 408151937Sjkim * 40967754Smsmith ******************************************************************************/ 41067754Smsmith 41199679Siwasakivoid 412197104SjkimAcpiExIntegerToString ( 413197104Sjkim char *OutString, 414202771Sjkim UINT64 Value) 41567754Smsmith{ 41667754Smsmith UINT32 Count; 41767754Smsmith UINT32 DigitsNeeded; 41884491Smsmith UINT32 Remainder; 41967754Smsmith 42067754Smsmith 42191116Smsmith ACPI_FUNCTION_ENTRY (); 42283174Smsmith 42383174Smsmith 42477424Smsmith DigitsNeeded = AcpiExDigitsNeeded (Value, 10); 42584491Smsmith OutString[DigitsNeeded] = 0; 42667754Smsmith 42767754Smsmith for (Count = DigitsNeeded; Count > 0; Count--) 42867754Smsmith { 429138287Smarks (void) AcpiUtShortDivide (Value, 10, &Value, &Remainder); 430114237Snjl OutString[Count-1] = (char) ('0' + Remainder);\ 43167754Smsmith } 43267754Smsmith} 43367754Smsmith 434228110Sjkim 435228110Sjkim/******************************************************************************* 436228110Sjkim * 437284583Sjkim * FUNCTION: AcpiExPciClsToString 438284583Sjkim * 439284583Sjkim * PARAMETERS: OutString - Where to put the converted string (7 bytes) 440298714Sjkim * ClassCode - PCI class code to be converted (3 bytes) 441284583Sjkim * 442298714Sjkim * RETURN: Converted string in OutString 443284583Sjkim * 444284583Sjkim * DESCRIPTION: Convert 3-bytes PCI class code to string representation. 445284583Sjkim * Return buffer must be large enough to hold the string. The 446284583Sjkim * string returned is always exactly of length 447284583Sjkim * ACPI_PCICLS_STRING_SIZE (includes null terminator). 448284583Sjkim * 449284583Sjkim ******************************************************************************/ 450284583Sjkim 451284583Sjkimvoid 452284583SjkimAcpiExPciClsToString ( 453284583Sjkim char *OutString, 454284583Sjkim UINT8 ClassCode[3]) 455284583Sjkim{ 456284583Sjkim 457284583Sjkim ACPI_FUNCTION_ENTRY (); 458284583Sjkim 459284583Sjkim 460284583Sjkim /* All 3 bytes are hexadecimal */ 461284583Sjkim 462284583Sjkim OutString[0] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 4); 463284583Sjkim OutString[1] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 0); 464284583Sjkim OutString[2] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 4); 465284583Sjkim OutString[3] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 0); 466284583Sjkim OutString[4] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 4); 467284583Sjkim OutString[5] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 0); 468284583Sjkim OutString[6] = 0; 469284583Sjkim} 470284583Sjkim 471284583Sjkim 472284583Sjkim/******************************************************************************* 473284583Sjkim * 474228110Sjkim * FUNCTION: AcpiIsValidSpaceId 475228110Sjkim * 476228110Sjkim * PARAMETERS: SpaceId - ID to be validated 477228110Sjkim * 478298714Sjkim * RETURN: TRUE if SpaceId is a valid/supported ID. 479228110Sjkim * 480228110Sjkim * DESCRIPTION: Validate an operation region SpaceID. 481228110Sjkim * 482228110Sjkim ******************************************************************************/ 483228110Sjkim 484228110SjkimBOOLEAN 485228110SjkimAcpiIsValidSpaceId ( 486228110Sjkim UINT8 SpaceId) 487228110Sjkim{ 488228110Sjkim 489228110Sjkim if ((SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) && 490228110Sjkim (SpaceId < ACPI_USER_REGION_BEGIN) && 491228110Sjkim (SpaceId != ACPI_ADR_SPACE_DATA_TABLE) && 492228110Sjkim (SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE)) 493228110Sjkim { 494228110Sjkim return (FALSE); 495228110Sjkim } 496228110Sjkim 497228110Sjkim return (TRUE); 498228110Sjkim} 499228110Sjkim 500100966Siwasaki#endif 501