1 /****************************************************************************** 2 * 3 * Module Name: psxface - Parser external interfaces 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 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acparser.h> 47 #include <contrib/dev/acpica/include/acdispat.h> 48 #include <contrib/dev/acpica/include/acinterp.h> 49 #include <contrib/dev/acpica/include/actables.h> 50 51 52 #define _COMPONENT ACPI_PARSER 53 ACPI_MODULE_NAME ("psxface") 54 55 /* Local Prototypes */ 56 57 static void 58 AcpiPsStartTrace ( 59 ACPI_EVALUATE_INFO *Info); 60 61 static void 62 AcpiPsStopTrace ( 63 ACPI_EVALUATE_INFO *Info); 64 65 static void 66 AcpiPsUpdateParameterList ( 67 ACPI_EVALUATE_INFO *Info, 68 UINT16 Action); 69 70 71 /******************************************************************************* 72 * 73 * FUNCTION: AcpiDebugTrace 74 * 75 * PARAMETERS: MethodName - Valid ACPI name string 76 * DebugLevel - Optional level mask. 0 to use default 77 * DebugLayer - Optional layer mask. 0 to use default 78 * Flags - bit 1: one shot(1) or persistent(0) 79 * 80 * RETURN: Status 81 * 82 * DESCRIPTION: External interface to enable debug tracing during control 83 * method execution 84 * 85 ******************************************************************************/ 86 87 ACPI_STATUS 88 AcpiDebugTrace ( 89 char *Name, 90 UINT32 DebugLevel, 91 UINT32 DebugLayer, 92 UINT32 Flags) 93 { 94 ACPI_STATUS Status; 95 96 97 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 98 if (ACPI_FAILURE (Status)) 99 { 100 return (Status); 101 } 102 103 /* TBDs: Validate name, allow full path or just nameseg */ 104 105 AcpiGbl_TraceMethodName = *ACPI_CAST_PTR (UINT32, Name); 106 AcpiGbl_TraceFlags = Flags; 107 108 if (DebugLevel) 109 { 110 AcpiGbl_TraceDbgLevel = DebugLevel; 111 } 112 if (DebugLayer) 113 { 114 AcpiGbl_TraceDbgLayer = DebugLayer; 115 } 116 117 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 118 return (AE_OK); 119 } 120 121 122 /******************************************************************************* 123 * 124 * FUNCTION: AcpiPsStartTrace 125 * 126 * PARAMETERS: Info - Method info struct 127 * 128 * RETURN: None 129 * 130 * DESCRIPTION: Start control method execution trace 131 * 132 ******************************************************************************/ 133 134 static void 135 AcpiPsStartTrace ( 136 ACPI_EVALUATE_INFO *Info) 137 { 138 ACPI_STATUS Status; 139 140 141 ACPI_FUNCTION_ENTRY (); 142 143 144 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 145 if (ACPI_FAILURE (Status)) 146 { 147 return; 148 } 149 150 if ((!AcpiGbl_TraceMethodName) || 151 (AcpiGbl_TraceMethodName != Info->Node->Name.Integer)) 152 { 153 goto Exit; 154 } 155 156 AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; 157 AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; 158 159 AcpiDbgLevel = 0x00FFFFFF; 160 AcpiDbgLayer = ACPI_UINT32_MAX; 161 162 if (AcpiGbl_TraceDbgLevel) 163 { 164 AcpiDbgLevel = AcpiGbl_TraceDbgLevel; 165 } 166 if (AcpiGbl_TraceDbgLayer) 167 { 168 AcpiDbgLayer = AcpiGbl_TraceDbgLayer; 169 } 170 171 172 Exit: 173 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 174 } 175 176 177 /******************************************************************************* 178 * 179 * FUNCTION: AcpiPsStopTrace 180 * 181 * PARAMETERS: Info - Method info struct 182 * 183 * RETURN: None 184 * 185 * DESCRIPTION: Stop control method execution trace 186 * 187 ******************************************************************************/ 188 189 static void 190 AcpiPsStopTrace ( 191 ACPI_EVALUATE_INFO *Info) 192 { 193 ACPI_STATUS Status; 194 195 196 ACPI_FUNCTION_ENTRY (); 197 198 199 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 200 if (ACPI_FAILURE (Status)) 201 { 202 return; 203 } 204 205 if ((!AcpiGbl_TraceMethodName) || 206 (AcpiGbl_TraceMethodName != Info->Node->Name.Integer)) 207 { 208 goto Exit; 209 } 210 211 /* Disable further tracing if type is one-shot */ 212 213 if (AcpiGbl_TraceFlags & 1) 214 { 215 AcpiGbl_TraceMethodName = 0; 216 AcpiGbl_TraceDbgLevel = 0; 217 AcpiGbl_TraceDbgLayer = 0; 218 } 219 220 AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; 221 AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; 222 223 Exit: 224 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 225 } 226 227 228 /******************************************************************************* 229 * 230 * FUNCTION: AcpiPsExecuteMethod 231 * 232 * PARAMETERS: Info - Method info block, contains: 233 * Node - Method Node to execute 234 * ObjDesc - Method object 235 * Parameters - List of parameters to pass to the method, 236 * terminated by NULL. Params itself may be 237 * NULL if no parameters are being passed. 238 * ReturnObject - Where to put method's return value (if 239 * any). If NULL, no value is returned. 240 * ParameterType - Type of Parameter list 241 * ReturnObject - Where to put method's return value (if 242 * any). If NULL, no value is returned. 243 * PassNumber - Parse or execute pass 244 * 245 * RETURN: Status 246 * 247 * DESCRIPTION: Execute a control method 248 * 249 ******************************************************************************/ 250 251 ACPI_STATUS 252 AcpiPsExecuteMethod ( 253 ACPI_EVALUATE_INFO *Info) 254 { 255 ACPI_STATUS Status; 256 ACPI_PARSE_OBJECT *Op; 257 ACPI_WALK_STATE *WalkState; 258 259 260 ACPI_FUNCTION_TRACE (PsExecuteMethod); 261 262 263 /* Quick validation of DSDT header */ 264 265 AcpiTbCheckDsdtHeader (); 266 267 /* Validate the Info and method Node */ 268 269 if (!Info || !Info->Node) 270 { 271 return_ACPI_STATUS (AE_NULL_ENTRY); 272 } 273 274 /* Init for new method, wait on concurrency semaphore */ 275 276 Status = AcpiDsBeginMethodExecution (Info->Node, Info->ObjDesc, NULL); 277 if (ACPI_FAILURE (Status)) 278 { 279 return_ACPI_STATUS (Status); 280 } 281 282 /* 283 * The caller "owns" the parameters, so give each one an extra reference 284 */ 285 AcpiPsUpdateParameterList (Info, REF_INCREMENT); 286 287 /* Begin tracing if requested */ 288 289 AcpiPsStartTrace (Info); 290 291 /* 292 * Execute the method. Performs parse simultaneously 293 */ 294 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 295 "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", 296 Info->Node->Name.Ascii, Info->Node, Info->ObjDesc)); 297 298 /* Create and init a Root Node */ 299 300 Op = AcpiPsCreateScopeOp (); 301 if (!Op) 302 { 303 Status = AE_NO_MEMORY; 304 goto Cleanup; 305 } 306 307 /* Create and initialize a new walk state */ 308 309 Info->PassNumber = ACPI_IMODE_EXECUTE; 310 WalkState = AcpiDsCreateWalkState ( 311 Info->ObjDesc->Method.OwnerId, NULL, NULL, NULL); 312 if (!WalkState) 313 { 314 Status = AE_NO_MEMORY; 315 goto Cleanup; 316 } 317 318 Status = AcpiDsInitAmlWalk (WalkState, Op, Info->Node, 319 Info->ObjDesc->Method.AmlStart, 320 Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber); 321 if (ACPI_FAILURE (Status)) 322 { 323 AcpiDsDeleteWalkState (WalkState); 324 goto Cleanup; 325 } 326 327 if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) 328 { 329 WalkState->ParseFlags |= ACPI_PARSE_MODULE_LEVEL; 330 } 331 332 /* Invoke an internal method if necessary */ 333 334 if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY) 335 { 336 Status = Info->ObjDesc->Method.Dispatch.Implementation (WalkState); 337 Info->ReturnObject = WalkState->ReturnDesc; 338 339 /* Cleanup states */ 340 341 AcpiDsScopeStackClear (WalkState); 342 AcpiPsCleanupScope (&WalkState->ParserState); 343 AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); 344 AcpiDsDeleteWalkState (WalkState); 345 goto Cleanup; 346 } 347 348 /* 349 * Start method evaluation with an implicit return of zero. 350 * This is done for Windows compatibility. 351 */ 352 if (AcpiGbl_EnableInterpreterSlack) 353 { 354 WalkState->ImplicitReturnObj = 355 AcpiUtCreateIntegerObject ((UINT64) 0); 356 if (!WalkState->ImplicitReturnObj) 357 { 358 Status = AE_NO_MEMORY; 359 AcpiDsDeleteWalkState (WalkState); 360 goto Cleanup; 361 } 362 } 363 364 /* Parse the AML */ 365 366 Status = AcpiPsParseAml (WalkState); 367 368 /* WalkState was deleted by ParseAml */ 369 370 Cleanup: 371 AcpiPsDeleteParseTree (Op); 372 373 /* End optional tracing */ 374 375 AcpiPsStopTrace (Info); 376 377 /* Take away the extra reference that we gave the parameters above */ 378 379 AcpiPsUpdateParameterList (Info, REF_DECREMENT); 380 381 /* Exit now if error above */ 382 383 if (ACPI_FAILURE (Status)) 384 { 385 return_ACPI_STATUS (Status); 386 } 387 388 /* 389 * If the method has returned an object, signal this to the caller with 390 * a control exception code 391 */ 392 if (Info->ReturnObject) 393 { 394 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", 395 Info->ReturnObject)); 396 ACPI_DUMP_STACK_ENTRY (Info->ReturnObject); 397 398 Status = AE_CTRL_RETURN_VALUE; 399 } 400 401 return_ACPI_STATUS (Status); 402 } 403 404 405 /******************************************************************************* 406 * 407 * FUNCTION: AcpiPsUpdateParameterList 408 * 409 * PARAMETERS: Info - See ACPI_EVALUATE_INFO 410 * (Used: ParameterType and Parameters) 411 * Action - Add or Remove reference 412 * 413 * RETURN: Status 414 * 415 * DESCRIPTION: Update reference count on all method parameter objects 416 * 417 ******************************************************************************/ 418 419 static void 420 AcpiPsUpdateParameterList ( 421 ACPI_EVALUATE_INFO *Info, 422 UINT16 Action) 423 { 424 UINT32 i; 425 426 427 if (Info->Parameters) 428 { 429 /* Update reference count for each parameter */ 430 431 for (i = 0; Info->Parameters[i]; i++) 432 { 433 /* Ignore errors, just do them all */ 434 435 (void) AcpiUtUpdateObjectReference (Info->Parameters[i], Action); 436 } 437 } 438 } 439