1 /****************************************************************************** 2 * 3 * Module Name: dswload - Dispatcher first pass namespace load callbacks 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2020, 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 "acpi.h" 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 #include "acdispat.h" 49 #include "acinterp.h" 50 #include "acnamesp.h" 51 #ifdef ACPI_ASL_COMPILER 52 #include "acdisasm.h" 53 #endif 54 55 #define _COMPONENT ACPI_DISPATCHER 56 ACPI_MODULE_NAME ("dswload") 57 58 59 /******************************************************************************* 60 * 61 * FUNCTION: AcpiDsInitCallbacks 62 * 63 * PARAMETERS: WalkState - Current state of the parse tree walk 64 * PassNumber - 1, 2, or 3 65 * 66 * RETURN: Status 67 * 68 * DESCRIPTION: Init walk state callbacks 69 * 70 ******************************************************************************/ 71 72 ACPI_STATUS 73 AcpiDsInitCallbacks ( 74 ACPI_WALK_STATE *WalkState, 75 UINT32 PassNumber) 76 { 77 78 switch (PassNumber) 79 { 80 case 0: 81 82 /* Parse only - caller will setup callbacks */ 83 84 WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | 85 ACPI_PARSE_DELETE_TREE | 86 ACPI_PARSE_DISASSEMBLE; 87 WalkState->DescendingCallback = NULL; 88 WalkState->AscendingCallback = NULL; 89 break; 90 91 case 1: 92 93 /* Load pass 1 */ 94 95 WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | 96 ACPI_PARSE_DELETE_TREE; 97 WalkState->DescendingCallback = AcpiDsLoad1BeginOp; 98 WalkState->AscendingCallback = AcpiDsLoad1EndOp; 99 break; 100 101 case 2: 102 103 /* Load pass 2 */ 104 105 WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | 106 ACPI_PARSE_DELETE_TREE; 107 WalkState->DescendingCallback = AcpiDsLoad2BeginOp; 108 WalkState->AscendingCallback = AcpiDsLoad2EndOp; 109 break; 110 111 case 3: 112 113 /* Execution pass */ 114 115 WalkState->ParseFlags |= ACPI_PARSE_EXECUTE | 116 ACPI_PARSE_DELETE_TREE; 117 WalkState->DescendingCallback = AcpiDsExecBeginOp; 118 WalkState->AscendingCallback = AcpiDsExecEndOp; 119 break; 120 121 default: 122 123 return (AE_BAD_PARAMETER); 124 } 125 126 return (AE_OK); 127 } 128 129 130 /******************************************************************************* 131 * 132 * FUNCTION: AcpiDsLoad1BeginOp 133 * 134 * PARAMETERS: WalkState - Current state of the parse tree walk 135 * OutOp - Where to return op if a new one is created 136 * 137 * RETURN: Status 138 * 139 * DESCRIPTION: Descending callback used during the loading of ACPI tables. 140 * 141 ******************************************************************************/ 142 143 ACPI_STATUS 144 AcpiDsLoad1BeginOp ( 145 ACPI_WALK_STATE *WalkState, 146 ACPI_PARSE_OBJECT **OutOp) 147 { 148 ACPI_PARSE_OBJECT *Op; 149 ACPI_NAMESPACE_NODE *Node; 150 ACPI_STATUS Status; 151 ACPI_OBJECT_TYPE ObjectType; 152 char *Path; 153 UINT32 Flags; 154 155 156 ACPI_FUNCTION_TRACE_PTR (DsLoad1BeginOp, WalkState->Op); 157 158 159 Op = WalkState->Op; 160 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); 161 162 /* We are only interested in opcodes that have an associated name */ 163 164 if (Op) 165 { 166 if (!(WalkState->OpInfo->Flags & AML_NAMED)) 167 { 168 *OutOp = Op; 169 return_ACPI_STATUS (AE_OK); 170 } 171 172 /* Check if this object has already been installed in the namespace */ 173 174 if (Op->Common.Node) 175 { 176 *OutOp = Op; 177 return_ACPI_STATUS (AE_OK); 178 } 179 } 180 181 Path = AcpiPsGetNextNamestring (&WalkState->ParserState); 182 183 /* Map the raw opcode into an internal object type */ 184 185 ObjectType = WalkState->OpInfo->ObjectType; 186 187 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 188 "State=%p Op=%p [%s]\n", WalkState, Op, 189 AcpiUtGetTypeName (ObjectType))); 190 191 switch (WalkState->Opcode) 192 { 193 case AML_SCOPE_OP: 194 /* 195 * The target name of the Scope() operator must exist at this point so 196 * that we can actually open the scope to enter new names underneath it. 197 * Allow search-to-root for single namesegs. 198 */ 199 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 200 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); 201 #ifdef ACPI_ASL_COMPILER 202 if (Status == AE_NOT_FOUND) 203 { 204 /* 205 * Table disassembly: 206 * Target of Scope() not found. Generate an External for it, and 207 * insert the name into the namespace. 208 */ 209 AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_DEVICE, 0, 0); 210 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 211 ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, 212 WalkState, &Node); 213 } 214 #endif 215 if (ACPI_FAILURE (Status)) 216 { 217 ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, Path, Status); 218 return_ACPI_STATUS (Status); 219 } 220 221 /* 222 * Check to make sure that the target is 223 * one of the opcodes that actually opens a scope 224 */ 225 switch (Node->Type) 226 { 227 case ACPI_TYPE_ANY: 228 case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ 229 case ACPI_TYPE_DEVICE: 230 case ACPI_TYPE_POWER: 231 case ACPI_TYPE_PROCESSOR: 232 case ACPI_TYPE_THERMAL: 233 234 /* These are acceptable types */ 235 break; 236 237 case ACPI_TYPE_INTEGER: 238 case ACPI_TYPE_STRING: 239 case ACPI_TYPE_BUFFER: 240 /* 241 * These types we will allow, but we will change the type. 242 * This enables some existing code of the form: 243 * 244 * Name (DEB, 0) 245 * Scope (DEB) { ... } 246 * 247 * Note: silently change the type here. On the second pass, 248 * we will report a warning 249 */ 250 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 251 "Type override - [%4.4s] had invalid type (%s) " 252 "for Scope operator, changed to type ANY\n", 253 AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); 254 255 Node->Type = ACPI_TYPE_ANY; 256 WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; 257 break; 258 259 case ACPI_TYPE_METHOD: 260 /* 261 * Allow scope change to root during execution of module-level 262 * code. Root is typed METHOD during this time. 263 */ 264 if ((Node == AcpiGbl_RootNode) && 265 (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) 266 { 267 break; 268 } 269 270 ACPI_FALLTHROUGH; 271 272 default: 273 274 /* All other types are an error */ 275 276 ACPI_ERROR ((AE_INFO, 277 "Invalid type (%s) for target of " 278 "Scope operator [%4.4s] (Cannot override)", 279 AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node))); 280 281 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 282 } 283 break; 284 285 default: 286 /* 287 * For all other named opcodes, we will enter the name into 288 * the namespace. 289 * 290 * Setup the search flags. 291 * Since we are entering a name into the namespace, we do not want to 292 * enable the search-to-root upsearch. 293 * 294 * There are only two conditions where it is acceptable that the name 295 * already exists: 296 * 1) the Scope() operator can reopen a scoping object that was 297 * previously defined (Scope, Method, Device, etc.) 298 * 2) Whenever we are parsing a deferred opcode (OpRegion, Buffer, 299 * BufferField, or Package), the name of the object is already 300 * in the namespace. 301 */ 302 if (WalkState->DeferredNode) 303 { 304 /* This name is already in the namespace, get the node */ 305 306 Node = WalkState->DeferredNode; 307 Status = AE_OK; 308 break; 309 } 310 311 /* 312 * If we are executing a method, do not create any namespace objects 313 * during the load phase, only during execution. 314 */ 315 if (WalkState->MethodNode) 316 { 317 Node = NULL; 318 Status = AE_OK; 319 break; 320 } 321 322 Flags = ACPI_NS_NO_UPSEARCH; 323 if ((WalkState->Opcode != AML_SCOPE_OP) && 324 (!(WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP))) 325 { 326 if (WalkState->NamespaceOverride) 327 { 328 Flags |= ACPI_NS_OVERRIDE_IF_FOUND; 329 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Override allowed\n", 330 AcpiUtGetTypeName (ObjectType))); 331 } 332 else 333 { 334 Flags |= ACPI_NS_ERROR_IF_FOUND; 335 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", 336 AcpiUtGetTypeName (ObjectType))); 337 } 338 } 339 else 340 { 341 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 342 "[%s] Both Find or Create allowed\n", 343 AcpiUtGetTypeName (ObjectType))); 344 } 345 346 /* 347 * Enter the named type into the internal namespace. We enter the name 348 * as we go downward in the parse tree. Any necessary subobjects that 349 * involve arguments to the opcode must be created as we go back up the 350 * parse tree later. 351 */ 352 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 353 ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); 354 if (ACPI_FAILURE (Status)) 355 { 356 if (Status == AE_ALREADY_EXISTS) 357 { 358 /* The name already exists in this scope */ 359 360 if (Node->Flags & ANOBJ_IS_EXTERNAL) 361 { 362 /* 363 * Allow one create on an object or segment that was 364 * previously declared External 365 */ 366 Node->Flags &= ~ANOBJ_IS_EXTERNAL; 367 Node->Type = (UINT8) ObjectType; 368 369 /* Just retyped a node, probably will need to open a scope */ 370 371 if (AcpiNsOpensScope (ObjectType)) 372 { 373 Status = AcpiDsScopeStackPush ( 374 Node, ObjectType, WalkState); 375 if (ACPI_FAILURE (Status)) 376 { 377 return_ACPI_STATUS (Status); 378 } 379 } 380 381 Status = AE_OK; 382 } 383 } 384 385 if (ACPI_FAILURE (Status)) 386 { 387 ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, Path, Status); 388 return_ACPI_STATUS (Status); 389 } 390 } 391 break; 392 } 393 394 /* Common exit */ 395 396 if (!Op) 397 { 398 /* Create a new op */ 399 400 Op = AcpiPsAllocOp (WalkState->Opcode, WalkState->Aml); 401 if (!Op) 402 { 403 return_ACPI_STATUS (AE_NO_MEMORY); 404 } 405 } 406 407 /* Initialize the op */ 408 409 #ifdef ACPI_CONSTANT_EVAL_ONLY 410 Op->Named.Path = Path; 411 #endif 412 413 if (Node) 414 { 415 /* 416 * Put the Node in the "op" object that the parser uses, so we 417 * can get it again quickly when this scope is closed 418 */ 419 Op->Common.Node = Node; 420 Op->Named.Name = Node->Name.Integer; 421 } 422 423 AcpiPsAppendArg (AcpiPsGetParentScope (&WalkState->ParserState), Op); 424 *OutOp = Op; 425 return_ACPI_STATUS (Status); 426 } 427 428 429 /******************************************************************************* 430 * 431 * FUNCTION: AcpiDsLoad1EndOp 432 * 433 * PARAMETERS: WalkState - Current state of the parse tree walk 434 * 435 * RETURN: Status 436 * 437 * DESCRIPTION: Ascending callback used during the loading of the namespace, 438 * both control methods and everything else. 439 * 440 ******************************************************************************/ 441 442 ACPI_STATUS 443 AcpiDsLoad1EndOp ( 444 ACPI_WALK_STATE *WalkState) 445 { 446 ACPI_PARSE_OBJECT *Op; 447 ACPI_OBJECT_TYPE ObjectType; 448 ACPI_STATUS Status = AE_OK; 449 #ifdef ACPI_ASL_COMPILER 450 UINT8 ParamCount; 451 #endif 452 453 454 ACPI_FUNCTION_TRACE (DsLoad1EndOp); 455 456 457 Op = WalkState->Op; 458 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); 459 460 /* 461 * Disassembler: handle create field operators here. 462 * 463 * CreateBufferField is a deferred op that is typically processed in load 464 * pass 2. However, disassembly of control method contents walk the parse 465 * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed 466 * in a later walk. This is a problem when there is a control method that 467 * has the same name as the AML_CREATE object. In this case, any use of the 468 * name segment will be detected as a method call rather than a reference 469 * to a buffer field. 470 * 471 * This earlier creation during disassembly solves this issue by inserting 472 * the named object in the ACPI namespace so that references to this name 473 * would be a name string rather than a method call. 474 */ 475 if ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) && 476 (WalkState->OpInfo->Flags & AML_CREATE)) 477 { 478 Status = AcpiDsCreateBufferField (Op, WalkState); 479 return_ACPI_STATUS (Status); 480 } 481 482 /* We are only interested in opcodes that have an associated name */ 483 484 if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_FIELD))) 485 { 486 return_ACPI_STATUS (AE_OK); 487 } 488 489 /* Get the object type to determine if we should pop the scope */ 490 491 ObjectType = WalkState->OpInfo->ObjectType; 492 493 if (WalkState->OpInfo->Flags & AML_FIELD) 494 { 495 /* 496 * If we are executing a method, do not create any namespace objects 497 * during the load phase, only during execution. 498 */ 499 if (!WalkState->MethodNode) 500 { 501 if (WalkState->Opcode == AML_FIELD_OP || 502 WalkState->Opcode == AML_BANK_FIELD_OP || 503 WalkState->Opcode == AML_INDEX_FIELD_OP) 504 { 505 Status = AcpiDsInitFieldObjects (Op, WalkState); 506 } 507 } 508 return_ACPI_STATUS (Status); 509 } 510 511 /* 512 * If we are executing a method, do not create any namespace objects 513 * during the load phase, only during execution. 514 */ 515 if (!WalkState->MethodNode) 516 { 517 if (Op->Common.AmlOpcode == AML_REGION_OP) 518 { 519 Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length, 520 (ACPI_ADR_SPACE_TYPE) 521 ((Op->Common.Value.Arg)->Common.Value.Integer), 522 WalkState); 523 if (ACPI_FAILURE (Status)) 524 { 525 return_ACPI_STATUS (Status); 526 } 527 } 528 else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP) 529 { 530 Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length, 531 ACPI_ADR_SPACE_DATA_TABLE, WalkState); 532 if (ACPI_FAILURE (Status)) 533 { 534 return_ACPI_STATUS (Status); 535 } 536 } 537 } 538 539 if (Op->Common.AmlOpcode == AML_NAME_OP) 540 { 541 /* For Name opcode, get the object type from the argument */ 542 543 if (Op->Common.Value.Arg) 544 { 545 ObjectType = (AcpiPsGetOpcodeInfo ( 546 (Op->Common.Value.Arg)->Common.AmlOpcode))->ObjectType; 547 548 /* Set node type if we have a namespace node */ 549 550 if (Op->Common.Node) 551 { 552 Op->Common.Node->Type = (UINT8) ObjectType; 553 } 554 } 555 } 556 557 #ifdef ACPI_ASL_COMPILER 558 /* 559 * For external opcode, get the object type from the argument and 560 * get the parameter count from the argument's next. 561 */ 562 if (AcpiGbl_DisasmFlag && 563 Op->Common.Node && 564 Op->Common.AmlOpcode == AML_EXTERNAL_OP) 565 { 566 /* 567 * Note, if this external is not a method 568 * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0 569 * Therefore, ParamCount will be 0. 570 */ 571 ParamCount = (UINT8) Op->Common.Value.Arg->Common.Next->Common.Value.Integer; 572 ObjectType = (UINT8) Op->Common.Value.Arg->Common.Value.Integer; 573 Op->Common.Node->Flags |= ANOBJ_IS_EXTERNAL; 574 Op->Common.Node->Type = (UINT8) ObjectType; 575 576 AcpiDmCreateSubobjectForExternal ((UINT8)ObjectType, 577 &Op->Common.Node, ParamCount); 578 579 /* 580 * Add the external to the external list because we may be 581 * emitting code based off of the items within the external list. 582 */ 583 AcpiDmAddOpToExternalList (Op, Op->Named.Path, (UINT8)ObjectType, ParamCount, 584 ACPI_EXT_ORIGIN_FROM_OPCODE | ACPI_EXT_RESOLVED_REFERENCE); 585 } 586 #endif 587 588 /* 589 * If we are executing a method, do not create any namespace objects 590 * during the load phase, only during execution. 591 */ 592 if (!WalkState->MethodNode) 593 { 594 if (Op->Common.AmlOpcode == AML_METHOD_OP) 595 { 596 /* 597 * MethodOp PkgLength NameString MethodFlags TermList 598 * 599 * Note: We must create the method node/object pair as soon as we 600 * see the method declaration. This allows later pass1 parsing 601 * of invocations of the method (need to know the number of 602 * arguments.) 603 */ 604 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 605 "LOADING-Method: State=%p Op=%p NamedObj=%p\n", 606 WalkState, Op, Op->Named.Node)); 607 608 if (!AcpiNsGetAttachedObject (Op->Named.Node)) 609 { 610 WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node); 611 WalkState->NumOperands = 1; 612 613 Status = AcpiDsCreateOperands ( 614 WalkState, Op->Common.Value.Arg); 615 if (ACPI_SUCCESS (Status)) 616 { 617 Status = AcpiExCreateMethod (Op->Named.Data, 618 Op->Named.Length, WalkState); 619 } 620 621 WalkState->Operands[0] = NULL; 622 WalkState->NumOperands = 0; 623 624 if (ACPI_FAILURE (Status)) 625 { 626 return_ACPI_STATUS (Status); 627 } 628 } 629 } 630 } 631 632 /* Pop the scope stack (only if loading a table) */ 633 634 if (!WalkState->MethodNode && 635 Op->Common.AmlOpcode != AML_EXTERNAL_OP && 636 AcpiNsOpensScope (ObjectType)) 637 { 638 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", 639 AcpiUtGetTypeName (ObjectType), Op)); 640 641 Status = AcpiDsScopeStackPop (WalkState); 642 } 643 644 return_ACPI_STATUS (Status); 645 } 646