1 /****************************************************************************** 2 * 3 * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 "acevents.h" 47 #include "acnamesp.h" 48 #include "acinterp.h" 49 50 #define _COMPONENT ACPI_EVENTS 51 ACPI_MODULE_NAME ("evrgnini") 52 53 54 /******************************************************************************* 55 * 56 * FUNCTION: AcpiEvSystemMemoryRegionSetup 57 * 58 * PARAMETERS: Handle - Region we are interested in 59 * Function - Start or stop 60 * HandlerContext - Address space handler context 61 * RegionContext - Region specific context 62 * 63 * RETURN: Status 64 * 65 * DESCRIPTION: Setup a SystemMemory operation region 66 * 67 ******************************************************************************/ 68 69 ACPI_STATUS 70 AcpiEvSystemMemoryRegionSetup ( 71 ACPI_HANDLE Handle, 72 UINT32 Function, 73 void *HandlerContext, 74 void **RegionContext) 75 { 76 ACPI_OPERAND_OBJECT *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle; 77 ACPI_MEM_SPACE_CONTEXT *LocalRegionContext; 78 ACPI_MEM_MAPPING *Mm; 79 80 81 ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup); 82 83 84 if (Function == ACPI_REGION_DEACTIVATE) 85 { 86 if (*RegionContext) 87 { 88 LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext; 89 90 /* Delete memory mappings if present */ 91 92 while (LocalRegionContext->FirstMm) 93 { 94 Mm = LocalRegionContext->FirstMm; 95 LocalRegionContext->FirstMm = Mm->NextMm; 96 AcpiOsUnmapMemory(Mm->LogicalAddress, Mm->Length); 97 ACPI_FREE(Mm); 98 } 99 ACPI_FREE (LocalRegionContext); 100 *RegionContext = NULL; 101 } 102 return_ACPI_STATUS (AE_OK); 103 } 104 105 /* Create a new context */ 106 107 LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT)); 108 if (!(LocalRegionContext)) 109 { 110 return_ACPI_STATUS (AE_NO_MEMORY); 111 } 112 113 /* Save the region length and address for use in the handler */ 114 115 LocalRegionContext->Length = RegionDesc->Region.Length; 116 LocalRegionContext->Address = RegionDesc->Region.Address; 117 118 *RegionContext = LocalRegionContext; 119 return_ACPI_STATUS (AE_OK); 120 } 121 122 123 /******************************************************************************* 124 * 125 * FUNCTION: AcpiEvIoSpaceRegionSetup 126 * 127 * PARAMETERS: Handle - Region we are interested in 128 * Function - Start or stop 129 * HandlerContext - Address space handler context 130 * RegionContext - Region specific context 131 * 132 * RETURN: Status 133 * 134 * DESCRIPTION: Setup a IO operation region 135 * 136 ******************************************************************************/ 137 138 ACPI_STATUS 139 AcpiEvIoSpaceRegionSetup ( 140 ACPI_HANDLE Handle, 141 UINT32 Function, 142 void *HandlerContext, 143 void **RegionContext) 144 { 145 ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup); 146 147 148 if (Function == ACPI_REGION_DEACTIVATE) 149 { 150 *RegionContext = NULL; 151 } 152 else 153 { 154 *RegionContext = HandlerContext; 155 } 156 157 return_ACPI_STATUS (AE_OK); 158 } 159 160 161 /******************************************************************************* 162 * 163 * FUNCTION: AcpiEvPciConfigRegionSetup 164 * 165 * PARAMETERS: Handle - Region we are interested in 166 * Function - Start or stop 167 * HandlerContext - Address space handler context 168 * RegionContext - Region specific context 169 * 170 * RETURN: Status 171 * 172 * DESCRIPTION: Setup a PCI_Config operation region 173 * 174 * MUTEX: Assumes namespace is not locked 175 * 176 ******************************************************************************/ 177 178 ACPI_STATUS 179 AcpiEvPciConfigRegionSetup ( 180 ACPI_HANDLE Handle, 181 UINT32 Function, 182 void *HandlerContext, 183 void **RegionContext) 184 { 185 ACPI_STATUS Status = AE_OK; 186 UINT64 PciValue; 187 ACPI_PCI_ID *PciId = *RegionContext; 188 ACPI_OPERAND_OBJECT *HandlerObj; 189 ACPI_NAMESPACE_NODE *ParentNode; 190 ACPI_NAMESPACE_NODE *PciRootNode; 191 ACPI_NAMESPACE_NODE *PciDeviceNode; 192 ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; 193 194 195 ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup); 196 197 198 HandlerObj = RegionObj->Region.Handler; 199 if (!HandlerObj) 200 { 201 /* 202 * No installed handler. This shouldn't happen because the dispatch 203 * routine checks before we get here, but we check again just in case. 204 */ 205 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 206 "Attempting to init a region %p, with no handler\n", RegionObj)); 207 return_ACPI_STATUS (AE_NOT_EXIST); 208 } 209 210 *RegionContext = NULL; 211 if (Function == ACPI_REGION_DEACTIVATE) 212 { 213 if (PciId) 214 { 215 ACPI_FREE (PciId); 216 } 217 return_ACPI_STATUS (Status); 218 } 219 220 ParentNode = RegionObj->Region.Node->Parent; 221 222 /* 223 * Get the _SEG and _BBN values from the device upon which the handler 224 * is installed. 225 * 226 * We need to get the _SEG and _BBN objects relative to the PCI BUS device. 227 * This is the device the handler has been registered to handle. 228 */ 229 230 /* 231 * If the AddressSpace.Node is still pointing to the root, we need 232 * to scan upward for a PCI Root bridge and re-associate the OpRegion 233 * handlers with that device. 234 */ 235 if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode) 236 { 237 /* Start search from the parent object */ 238 239 PciRootNode = ParentNode; 240 while (PciRootNode != AcpiGbl_RootNode) 241 { 242 /* Get the _HID/_CID in order to detect a RootBridge */ 243 244 if (AcpiEvIsPciRootBridge (PciRootNode)) 245 { 246 /* Install a handler for this PCI root bridge */ 247 248 Status = AcpiInstallAddressSpaceHandler ( 249 (ACPI_HANDLE) PciRootNode, 250 ACPI_ADR_SPACE_PCI_CONFIG, 251 ACPI_DEFAULT_HANDLER, NULL, NULL); 252 if (ACPI_FAILURE (Status)) 253 { 254 if (Status == AE_SAME_HANDLER) 255 { 256 /* 257 * It is OK if the handler is already installed on the 258 * root bridge. Still need to return a context object 259 * for the new PCI_Config operation region, however. 260 */ 261 } 262 else 263 { 264 ACPI_EXCEPTION ((AE_INFO, Status, 265 "Could not install PciConfig handler " 266 "for Root Bridge %4.4s", 267 AcpiUtGetNodeName (PciRootNode))); 268 } 269 } 270 break; 271 } 272 273 PciRootNode = PciRootNode->Parent; 274 } 275 276 /* PCI root bridge not found, use namespace root node */ 277 } 278 else 279 { 280 PciRootNode = HandlerObj->AddressSpace.Node; 281 } 282 283 /* 284 * If this region is now initialized, we are done. 285 * (InstallAddressSpaceHandler could have initialized it) 286 */ 287 if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 288 { 289 return_ACPI_STATUS (AE_OK); 290 } 291 292 /* Region is still not initialized. Create a new context */ 293 294 PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID)); 295 if (!PciId) 296 { 297 return_ACPI_STATUS (AE_NO_MEMORY); 298 } 299 300 /* 301 * For PCI_Config space access, we need the segment, bus, device and 302 * function numbers. Acquire them here. 303 * 304 * Find the parent device object. (This allows the operation region to be 305 * within a subscope under the device, such as a control method.) 306 */ 307 PciDeviceNode = RegionObj->Region.Node; 308 while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE)) 309 { 310 PciDeviceNode = PciDeviceNode->Parent; 311 } 312 313 if (!PciDeviceNode) 314 { 315 ACPI_FREE (PciId); 316 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 317 } 318 319 /* 320 * Get the PCI device and function numbers from the _ADR object 321 * contained in the parent's scope. 322 */ 323 Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, 324 PciDeviceNode, &PciValue); 325 326 /* 327 * The default is zero, and since the allocation above zeroed the data, 328 * just do nothing on failure. 329 */ 330 if (ACPI_SUCCESS (Status)) 331 { 332 PciId->Device = ACPI_HIWORD (ACPI_LODWORD (PciValue)); 333 PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue)); 334 } 335 336 /* The PCI segment number comes from the _SEG method */ 337 338 Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, 339 PciRootNode, &PciValue); 340 if (ACPI_SUCCESS (Status)) 341 { 342 PciId->Segment = ACPI_LOWORD (PciValue); 343 } 344 345 /* The PCI bus number comes from the _BBN method */ 346 347 Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, 348 PciRootNode, &PciValue); 349 if (ACPI_SUCCESS (Status)) 350 { 351 PciId->Bus = ACPI_LOWORD (PciValue); 352 } 353 354 /* Complete/update the PCI ID for this device */ 355 356 Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node); 357 if (ACPI_FAILURE (Status)) 358 { 359 ACPI_FREE (PciId); 360 return_ACPI_STATUS (Status); 361 } 362 363 *RegionContext = PciId; 364 return_ACPI_STATUS (AE_OK); 365 } 366 367 368 /******************************************************************************* 369 * 370 * FUNCTION: AcpiEvIsPciRootBridge 371 * 372 * PARAMETERS: Node - Device node being examined 373 * 374 * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge 375 * 376 * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by 377 * examining the _HID and _CID for the device. 378 * 379 ******************************************************************************/ 380 381 BOOLEAN 382 AcpiEvIsPciRootBridge ( 383 ACPI_NAMESPACE_NODE *Node) 384 { 385 ACPI_STATUS Status; 386 ACPI_PNP_DEVICE_ID *Hid; 387 ACPI_PNP_DEVICE_ID_LIST *Cid; 388 UINT32 i; 389 BOOLEAN Match; 390 391 392 /* Get the _HID and check for a PCI Root Bridge */ 393 394 Status = AcpiUtExecute_HID (Node, &Hid); 395 if (ACPI_FAILURE (Status)) 396 { 397 return (FALSE); 398 } 399 400 Match = AcpiUtIsPciRootBridge (Hid->String); 401 ACPI_FREE (Hid); 402 403 if (Match) 404 { 405 return (TRUE); 406 } 407 408 /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ 409 410 Status = AcpiUtExecute_CID (Node, &Cid); 411 if (ACPI_FAILURE (Status)) 412 { 413 return (FALSE); 414 } 415 416 /* Check all _CIDs in the returned list */ 417 418 for (i = 0; i < Cid->Count; i++) 419 { 420 if (AcpiUtIsPciRootBridge (Cid->Ids[i].String)) 421 { 422 ACPI_FREE (Cid); 423 return (TRUE); 424 } 425 } 426 427 ACPI_FREE (Cid); 428 return (FALSE); 429 } 430 431 432 /******************************************************************************* 433 * 434 * FUNCTION: AcpiEvPciBarRegionSetup 435 * 436 * PARAMETERS: Handle - Region we are interested in 437 * Function - Start or stop 438 * HandlerContext - Address space handler context 439 * RegionContext - Region specific context 440 * 441 * RETURN: Status 442 * 443 * DESCRIPTION: Setup a PciBAR operation region 444 * 445 * MUTEX: Assumes namespace is not locked 446 * 447 ******************************************************************************/ 448 449 ACPI_STATUS 450 AcpiEvPciBarRegionSetup ( 451 ACPI_HANDLE Handle, 452 UINT32 Function, 453 void *HandlerContext, 454 void **RegionContext) 455 { 456 ACPI_FUNCTION_TRACE (EvPciBarRegionSetup); 457 458 459 return_ACPI_STATUS (AE_OK); 460 } 461 462 463 /******************************************************************************* 464 * 465 * FUNCTION: AcpiEvCmosRegionSetup 466 * 467 * PARAMETERS: Handle - Region we are interested in 468 * Function - Start or stop 469 * HandlerContext - Address space handler context 470 * RegionContext - Region specific context 471 * 472 * RETURN: Status 473 * 474 * DESCRIPTION: Setup a CMOS operation region 475 * 476 * MUTEX: Assumes namespace is not locked 477 * 478 ******************************************************************************/ 479 480 ACPI_STATUS 481 AcpiEvCmosRegionSetup ( 482 ACPI_HANDLE Handle, 483 UINT32 Function, 484 void *HandlerContext, 485 void **RegionContext) 486 { 487 ACPI_FUNCTION_TRACE (EvCmosRegionSetup); 488 489 490 return_ACPI_STATUS (AE_OK); 491 } 492 493 494 /******************************************************************************* 495 * 496 * FUNCTION: AcpiEvDataTableRegionSetup 497 * 498 * PARAMETERS: Handle - Region we are interested in 499 * Function - Start or stop 500 * HandlerContext - Address space handler context 501 * RegionContext - Region specific context 502 * 503 * RETURN: Status 504 * 505 * DESCRIPTION: Setup a DataTableRegion 506 * 507 * MUTEX: Assumes namespace is not locked 508 * 509 ******************************************************************************/ 510 511 ACPI_STATUS 512 AcpiEvDataTableRegionSetup ( 513 ACPI_HANDLE Handle, 514 UINT32 Function, 515 void *HandlerContext, 516 void **RegionContext) 517 { 518 ACPI_OPERAND_OBJECT *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle; 519 ACPI_DATA_TABLE_MAPPING *LocalRegionContext; 520 521 522 ACPI_FUNCTION_TRACE (EvDataTableRegionSetup); 523 524 525 if (Function == ACPI_REGION_DEACTIVATE) 526 { 527 if (*RegionContext) 528 { 529 ACPI_FREE (*RegionContext); 530 *RegionContext = NULL; 531 } 532 return_ACPI_STATUS (AE_OK); 533 } 534 535 /* Create a new context */ 536 537 LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DATA_TABLE_MAPPING)); 538 if (!(LocalRegionContext)) 539 { 540 return_ACPI_STATUS (AE_NO_MEMORY); 541 } 542 543 /* Save the data table pointer for use in the handler */ 544 545 LocalRegionContext->Pointer = RegionDesc->Region.Pointer; 546 547 *RegionContext = LocalRegionContext; 548 return_ACPI_STATUS (AE_OK); 549 } 550 551 552 /******************************************************************************* 553 * 554 * FUNCTION: AcpiEvDefaultRegionSetup 555 * 556 * PARAMETERS: Handle - Region we are interested in 557 * Function - Start or stop 558 * HandlerContext - Address space handler context 559 * RegionContext - Region specific context 560 * 561 * RETURN: Status 562 * 563 * DESCRIPTION: Default region initialization 564 * 565 ******************************************************************************/ 566 567 ACPI_STATUS 568 AcpiEvDefaultRegionSetup ( 569 ACPI_HANDLE Handle, 570 UINT32 Function, 571 void *HandlerContext, 572 void **RegionContext) 573 { 574 ACPI_FUNCTION_TRACE (EvDefaultRegionSetup); 575 576 577 if (Function == ACPI_REGION_DEACTIVATE) 578 { 579 *RegionContext = NULL; 580 } 581 else 582 { 583 *RegionContext = HandlerContext; 584 } 585 586 return_ACPI_STATUS (AE_OK); 587 } 588 589 590 /******************************************************************************* 591 * 592 * FUNCTION: AcpiEvInitializeRegion 593 * 594 * PARAMETERS: RegionObj - Region we are initializing 595 * 596 * RETURN: Status 597 * 598 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them 599 * for execution at a later time 600 * 601 * Get the appropriate address space handler for a newly 602 * created region. 603 * 604 * This also performs address space specific initialization. For 605 * example, PCI regions must have an _ADR object that contains 606 * a PCI address in the scope of the definition. This address is 607 * required to perform an access to PCI config space. 608 * 609 * MUTEX: Interpreter should be unlocked, because we may run the _REG 610 * method for this region. 611 * 612 * NOTE: Possible incompliance: 613 * There is a behavior conflict in automatic _REG execution: 614 * 1. When the interpreter is evaluating a method, we can only 615 * automatically run _REG for the following case: 616 * Method(_REG, 2) {} 617 * OperationRegion (OPR1, 0x80, 0x1000010, 0x4) 618 * 2. When the interpreter is loading a table, we can also 619 * automatically run _REG for the following case: 620 * OperationRegion (OPR1, 0x80, 0x1000010, 0x4) 621 * Method(_REG, 2) {} 622 * Though this may not be compliant to the de-facto standard, the 623 * logic is kept in order not to trigger regressions. And keeping 624 * this logic should be taken care by the caller of this function. 625 * 626 ******************************************************************************/ 627 628 ACPI_STATUS 629 AcpiEvInitializeRegion ( 630 ACPI_OPERAND_OBJECT *RegionObj) 631 { 632 ACPI_OPERAND_OBJECT *HandlerObj; 633 ACPI_OPERAND_OBJECT *ObjDesc; 634 ACPI_ADR_SPACE_TYPE SpaceId; 635 ACPI_NAMESPACE_NODE *Node; 636 637 638 ACPI_FUNCTION_TRACE (EvInitializeRegion); 639 640 641 if (!RegionObj) 642 { 643 return_ACPI_STATUS (AE_BAD_PARAMETER); 644 } 645 646 if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) 647 { 648 return_ACPI_STATUS (AE_OK); 649 } 650 651 RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; 652 653 Node = RegionObj->Region.Node->Parent; 654 SpaceId = RegionObj->Region.SpaceId; 655 656 /* 657 * The following loop depends upon the root Node having no parent 658 * ie: AcpiGbl_RootNode->Parent being set to NULL 659 */ 660 while (Node) 661 { 662 /* Check to see if a handler exists */ 663 664 HandlerObj = NULL; 665 ObjDesc = AcpiNsGetAttachedObject (Node); 666 if (ObjDesc) 667 { 668 /* Can only be a handler if the object exists */ 669 670 switch (Node->Type) 671 { 672 case ACPI_TYPE_DEVICE: 673 case ACPI_TYPE_PROCESSOR: 674 case ACPI_TYPE_THERMAL: 675 676 HandlerObj = ObjDesc->CommonNotify.Handler; 677 break; 678 679 default: 680 681 /* Ignore other objects */ 682 683 break; 684 } 685 686 HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj); 687 if (HandlerObj) 688 { 689 /* Found correct handler */ 690 691 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 692 "Found handler %p for region %p in obj %p\n", 693 HandlerObj, RegionObj, ObjDesc)); 694 695 (void) AcpiEvAttachRegion (HandlerObj, RegionObj, FALSE); 696 697 /* 698 * Tell all users that this region is usable by 699 * running the _REG method 700 */ 701 AcpiExExitInterpreter (); 702 (void) AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); 703 AcpiExEnterInterpreter (); 704 return_ACPI_STATUS (AE_OK); 705 } 706 } 707 708 /* This node does not have the handler we need; Pop up one level */ 709 710 Node = Node->Parent; 711 } 712 713 /* 714 * If we get here, there is no handler for this region. This is not 715 * fatal because many regions get created before a handler is installed 716 * for said region. 717 */ 718 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 719 "No handler for RegionType %s(%X) (RegionObj %p)\n", 720 AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); 721 722 return_ACPI_STATUS (AE_OK); 723 } 724