1 /****************************************************************************** 2 * 3 * Module Name: aeregion - Operation region support for acpiexec 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include "aecommon.h" 153 154 #define _COMPONENT ACPI_TOOLS 155 ACPI_MODULE_NAME ("aeregion") 156 157 158 /* Local prototypes */ 159 160 static ACPI_STATUS 161 AeRegionInit ( 162 ACPI_HANDLE RegionHandle, 163 UINT32 Function, 164 void *HandlerContext, 165 void **RegionContext); 166 167 static ACPI_STATUS 168 AeInstallEcHandler ( 169 ACPI_HANDLE ObjHandle, 170 UINT32 Level, 171 void *Context, 172 void **ReturnValue); 173 174 static ACPI_STATUS 175 AeInstallPciHandler ( 176 ACPI_HANDLE ObjHandle, 177 UINT32 Level, 178 void *Context, 179 void **ReturnValue); 180 181 182 static AE_DEBUG_REGIONS AeRegions; 183 BOOLEAN AcpiGbl_DisplayRegionAccess = FALSE; 184 ACPI_CONNECTION_INFO AeMyContext; 185 186 187 /* 188 * We will override some of the default region handlers, especially 189 * the SystemMemory handler, which must be implemented locally. 190 * These handlers are installed "early" - before any _REG methods 191 * are executed - since they are special in the sense that the ACPI spec 192 * declares that they must "always be available". Cannot override the 193 * DataTable region handler either -- needed for test execution. 194 * 195 * NOTE: The local region handler will simulate access to these address 196 * spaces by creating a memory buffer behind each operation region. 197 */ 198 static ACPI_ADR_SPACE_TYPE DefaultSpaceIdList[] = 199 { 200 ACPI_ADR_SPACE_SYSTEM_MEMORY, 201 ACPI_ADR_SPACE_SYSTEM_IO, 202 ACPI_ADR_SPACE_PCI_CONFIG, 203 ACPI_ADR_SPACE_EC 204 }; 205 206 /* 207 * We will install handlers for some of the various address space IDs. 208 * Test one user-defined address space (used by aslts). 209 */ 210 #define ACPI_ADR_SPACE_USER_DEFINED1 0x80 211 #define ACPI_ADR_SPACE_USER_DEFINED2 0xE4 212 213 static ACPI_ADR_SPACE_TYPE SpaceIdList[] = 214 { 215 ACPI_ADR_SPACE_SMBUS, 216 ACPI_ADR_SPACE_CMOS, 217 ACPI_ADR_SPACE_PCI_BAR_TARGET, 218 ACPI_ADR_SPACE_IPMI, 219 ACPI_ADR_SPACE_GPIO, 220 ACPI_ADR_SPACE_GSBUS, 221 ACPI_ADR_SPACE_FIXED_HARDWARE, 222 ACPI_ADR_SPACE_USER_DEFINED1, 223 ACPI_ADR_SPACE_USER_DEFINED2 224 }; 225 226 227 /****************************************************************************** 228 * 229 * FUNCTION: AeRegionInit 230 * 231 * PARAMETERS: Region init handler 232 * 233 * RETURN: Status 234 * 235 * DESCRIPTION: Opregion init function. 236 * 237 *****************************************************************************/ 238 239 static ACPI_STATUS 240 AeRegionInit ( 241 ACPI_HANDLE RegionHandle, 242 UINT32 Function, 243 void *HandlerContext, 244 void **RegionContext) 245 { 246 247 if (Function == ACPI_REGION_DEACTIVATE) 248 { 249 *RegionContext = NULL; 250 } 251 else 252 { 253 *RegionContext = RegionHandle; 254 } 255 256 return (AE_OK); 257 } 258 259 260 /****************************************************************************** 261 * 262 * FUNCTION: AeOverrideRegionHandlers 263 * 264 * PARAMETERS: None 265 * 266 * RETURN: None 267 * 268 * DESCRIPTION: Override the default region handlers for memory, i/o, and 269 * pci_config. Also install a handler for EC. This is part of 270 * the "install early handlers" functionality. 271 * 272 *****************************************************************************/ 273 274 void 275 AeOverrideRegionHandlers ( 276 void) 277 { 278 UINT32 i; 279 ACPI_STATUS Status; 280 281 /* 282 * Install handlers that will override the default handlers for some of 283 * the space IDs. 284 */ 285 for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++) 286 { 287 /* Install handler at the root object */ 288 289 Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT, 290 DefaultSpaceIdList[i], AeRegionHandler, 291 AeRegionInit, &AeMyContext); 292 293 if (ACPI_FAILURE (Status)) 294 { 295 ACPI_EXCEPTION ((AE_INFO, Status, 296 "Could not install an OpRegion handler for %s space(%u)", 297 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]), 298 DefaultSpaceIdList[i])); 299 } 300 } 301 } 302 303 304 /****************************************************************************** 305 * 306 * FUNCTION: AeInstallRegionHandlers 307 * 308 * PARAMETERS: None 309 * 310 * RETURN: None 311 * 312 * DESCRIPTION: Install handlers for the address spaces other than memory, 313 * i/o, and pci_config. 314 * 315 *****************************************************************************/ 316 317 void 318 AeInstallRegionHandlers ( 319 void) 320 { 321 UINT32 i; 322 ACPI_STATUS Status; 323 324 /* 325 * Install handlers for some of the "device driver" address spaces 326 * such as SMBus, etc. 327 */ 328 for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++) 329 { 330 /* Install handler at the root object */ 331 332 Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT, 333 SpaceIdList[i], AeRegionHandler, 334 AeRegionInit, &AeMyContext); 335 336 if (ACPI_FAILURE (Status)) 337 { 338 ACPI_EXCEPTION ((AE_INFO, Status, 339 "Could not install an OpRegion handler for %s space(%u)", 340 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i])); 341 return; 342 } 343 } 344 } 345 346 347 /******************************************************************************* 348 * 349 * FUNCTION: AeInstallDeviceHandlers, 350 * AeInstallEcHandler, 351 * AeInstallPciHandler 352 * 353 * PARAMETERS: ACPI_WALK_NAMESPACE callback 354 * 355 * RETURN: Status 356 * 357 * DESCRIPTION: Walk entire namespace, install a handler for every EC 358 * and PCI device found. 359 * 360 ******************************************************************************/ 361 362 static ACPI_STATUS 363 AeInstallEcHandler ( 364 ACPI_HANDLE ObjHandle, 365 UINT32 Level, 366 void *Context, 367 void **ReturnValue) 368 { 369 ACPI_STATUS Status; 370 371 372 /* Install the handler for this EC device */ 373 374 Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_EC, 375 AeRegionHandler, AeRegionInit, &AeMyContext); 376 if (ACPI_FAILURE (Status)) 377 { 378 ACPI_EXCEPTION ((AE_INFO, Status, 379 "Could not install an OpRegion handler for EC device (%p)", 380 ObjHandle)); 381 } 382 383 return (Status); 384 } 385 386 387 static ACPI_STATUS 388 AeInstallPciHandler ( 389 ACPI_HANDLE ObjHandle, 390 UINT32 Level, 391 void *Context, 392 void **ReturnValue) 393 { 394 ACPI_STATUS Status; 395 396 397 /* Install memory and I/O handlers for the PCI device */ 398 399 Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_IO, 400 AeRegionHandler, AeRegionInit, &AeMyContext); 401 if (ACPI_FAILURE (Status)) 402 { 403 ACPI_EXCEPTION ((AE_INFO, Status, 404 "Could not install an OpRegion handler for PCI device (%p)", 405 ObjHandle)); 406 } 407 408 Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_MEMORY, 409 AeRegionHandler, AeRegionInit, &AeMyContext); 410 if (ACPI_FAILURE (Status)) 411 { 412 ACPI_EXCEPTION ((AE_INFO, Status, 413 "Could not install an OpRegion handler for PCI device (%p)", 414 ObjHandle)); 415 } 416 417 return (AE_CTRL_TERMINATE); 418 } 419 420 421 ACPI_STATUS 422 AeInstallDeviceHandlers ( 423 void) 424 { 425 426 /* Find all Embedded Controller devices */ 427 428 AcpiGetDevices ("PNP0C09", AeInstallEcHandler, NULL, NULL); 429 430 /* Install a PCI handler */ 431 432 AcpiGetDevices ("PNP0A08", AeInstallPciHandler, NULL, NULL); 433 return (AE_OK); 434 } 435 436 437 /****************************************************************************** 438 * 439 * FUNCTION: AeRegionHandler 440 * 441 * PARAMETERS: Standard region handler parameters 442 * 443 * RETURN: Status 444 * 445 * DESCRIPTION: Test handler - Handles some dummy regions via memory that can 446 * be manipulated in Ring 3. Simulates actual reads and writes. 447 * 448 *****************************************************************************/ 449 450 ACPI_STATUS 451 AeRegionHandler ( 452 UINT32 Function, 453 ACPI_PHYSICAL_ADDRESS Address, 454 UINT32 BitWidth, 455 UINT64 *Value, 456 void *HandlerContext, 457 void *RegionContext) 458 { 459 460 ACPI_OPERAND_OBJECT *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext); 461 UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Value); 462 UINT8 *OldBuffer; 463 UINT8 *NewBuffer; 464 ACPI_PHYSICAL_ADDRESS BaseAddress; 465 ACPI_PHYSICAL_ADDRESS BaseAddressEnd; 466 ACPI_PHYSICAL_ADDRESS RegionAddress; 467 ACPI_PHYSICAL_ADDRESS RegionAddressEnd; 468 ACPI_SIZE Length; 469 BOOLEAN BufferExists; 470 BOOLEAN BufferResize; 471 AE_REGION *RegionElement; 472 void *BufferValue; 473 ACPI_STATUS Status; 474 UINT32 ByteWidth; 475 UINT32 RegionLength; 476 UINT32 i; 477 UINT8 SpaceId; 478 ACPI_CONNECTION_INFO *MyContext; 479 UINT32 Value1; 480 UINT32 Value2; 481 ACPI_RESOURCE *Resource; 482 483 484 ACPI_FUNCTION_NAME (AeRegionHandler); 485 486 /* 487 * If the object is not a region, simply return 488 */ 489 if (RegionObject->Region.Type != ACPI_TYPE_REGION) 490 { 491 return (AE_OK); 492 } 493 494 /* Check that we actually got back our context parameter */ 495 496 if (HandlerContext != &AeMyContext) 497 { 498 printf ("Region handler received incorrect context %p, should be %p\n", 499 HandlerContext, &AeMyContext); 500 } 501 502 MyContext = ACPI_CAST_PTR (ACPI_CONNECTION_INFO, HandlerContext); 503 504 /* 505 * Find the region's address space and length before searching 506 * the linked list. 507 */ 508 BaseAddress = RegionObject->Region.Address; 509 Length = (ACPI_SIZE) RegionObject->Region.Length; 510 SpaceId = RegionObject->Region.SpaceId; 511 512 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 513 "Operation Region request on %s at 0x%X\n", 514 AcpiUtGetRegionName (RegionObject->Region.SpaceId), 515 (UINT32) Address)); 516 517 /* 518 * Region support can be disabled with the -do option. 519 * We use this to support dynamically loaded tables where we pass a valid 520 * address to the AML. 521 */ 522 if (AcpiGbl_DbOpt_NoRegionSupport) 523 { 524 BufferValue = ACPI_TO_POINTER (Address); 525 ByteWidth = (BitWidth / 8); 526 527 if (BitWidth % 8) 528 { 529 ByteWidth += 1; 530 } 531 goto DoFunction; 532 } 533 534 switch (SpaceId) 535 { 536 case ACPI_ADR_SPACE_SYSTEM_IO: 537 /* 538 * For I/O space, exercise the port validation 539 * Note: ReadPort currently always returns all ones, length=BitLength 540 */ 541 switch (Function & ACPI_IO_MASK) 542 { 543 case ACPI_READ: 544 545 if (BitWidth == 64) 546 { 547 /* Split the 64-bit request into two 32-bit requests */ 548 549 Status = AcpiHwReadPort (Address, &Value1, 32); 550 ACPI_CHECK_OK (AcpiHwReadPort, Status); 551 Status = AcpiHwReadPort (Address+4, &Value2, 32); 552 ACPI_CHECK_OK (AcpiHwReadPort, Status); 553 554 *Value = Value1 | ((UINT64) Value2 << 32); 555 } 556 else 557 { 558 Status = AcpiHwReadPort (Address, &Value1, BitWidth); 559 ACPI_CHECK_OK (AcpiHwReadPort, Status); 560 *Value = (UINT64) Value1; 561 } 562 break; 563 564 case ACPI_WRITE: 565 566 if (BitWidth == 64) 567 { 568 /* Split the 64-bit request into two 32-bit requests */ 569 570 Status = AcpiHwWritePort (Address, ACPI_LODWORD (*Value), 32); 571 ACPI_CHECK_OK (AcpiHwWritePort, Status); 572 Status = AcpiHwWritePort (Address+4, ACPI_HIDWORD (*Value), 32); 573 ACPI_CHECK_OK (AcpiHwWritePort, Status); 574 } 575 else 576 { 577 Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth); 578 ACPI_CHECK_OK (AcpiHwWritePort, Status); 579 } 580 break; 581 582 default: 583 584 Status = AE_BAD_PARAMETER; 585 break; 586 } 587 588 if (ACPI_FAILURE (Status)) 589 { 590 return (Status); 591 } 592 593 /* Now go ahead and simulate the hardware */ 594 break; 595 596 /* 597 * SMBus and GenericSerialBus support the various bidirectional 598 * protocols. 599 */ 600 case ACPI_ADR_SPACE_SMBUS: 601 case ACPI_ADR_SPACE_GSBUS: /* ACPI 5.0 */ 602 603 Length = 0; 604 605 switch (Function & ACPI_IO_MASK) 606 { 607 case ACPI_READ: 608 609 switch (Function >> 16) 610 { 611 case AML_FIELD_ATTRIB_QUICK: 612 613 Length = 0; 614 break; 615 616 case AML_FIELD_ATTRIB_SEND_RCV: 617 case AML_FIELD_ATTRIB_BYTE: 618 619 Length = 1; 620 break; 621 622 case AML_FIELD_ATTRIB_WORD: 623 case AML_FIELD_ATTRIB_WORD_CALL: 624 625 Length = 2; 626 break; 627 628 case AML_FIELD_ATTRIB_BLOCK: 629 case AML_FIELD_ATTRIB_BLOCK_CALL: 630 631 Length = 32; 632 break; 633 634 case AML_FIELD_ATTRIB_MULTIBYTE: 635 case AML_FIELD_ATTRIB_RAW_BYTES: 636 case AML_FIELD_ATTRIB_RAW_PROCESS: 637 638 Length = MyContext->AccessLength; 639 break; 640 641 default: 642 643 break; 644 } 645 break; 646 647 case ACPI_WRITE: 648 649 switch (Function >> 16) 650 { 651 case AML_FIELD_ATTRIB_QUICK: 652 case AML_FIELD_ATTRIB_SEND_RCV: 653 case AML_FIELD_ATTRIB_BYTE: 654 case AML_FIELD_ATTRIB_WORD: 655 case AML_FIELD_ATTRIB_BLOCK: 656 657 Length = 0; 658 break; 659 660 case AML_FIELD_ATTRIB_WORD_CALL: 661 Length = 2; 662 break; 663 664 case AML_FIELD_ATTRIB_BLOCK_CALL: 665 Length = 32; 666 break; 667 668 case AML_FIELD_ATTRIB_MULTIBYTE: 669 case AML_FIELD_ATTRIB_RAW_BYTES: 670 case AML_FIELD_ATTRIB_RAW_PROCESS: 671 672 Length = MyContext->AccessLength; 673 break; 674 675 default: 676 677 break; 678 } 679 break; 680 681 default: 682 683 break; 684 } 685 686 if (AcpiGbl_DisplayRegionAccess) 687 { 688 AcpiOsPrintf ("AcpiExec: %s " 689 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X", 690 AcpiUtGetRegionName (SpaceId), 691 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 692 (UINT32) (Function >> 16), 693 (UINT32) Address, (UINT32) BaseAddress, 694 Length, BitWidth, Buffer[1]); 695 696 /* GenericSerialBus has a Connection() parameter */ 697 698 if (SpaceId == ACPI_ADR_SPACE_GSBUS) 699 { 700 Status = AcpiBufferToResource (MyContext->Connection, 701 MyContext->Length, &Resource); 702 703 AcpiOsPrintf (" [AccLen %.2X Conn %p]", 704 MyContext->AccessLength, MyContext->Connection); 705 } 706 AcpiOsPrintf ("\n"); 707 } 708 709 /* Setup the return buffer. Note: ASLTS depends on these fill values */ 710 711 for (i = 0; i < Length; i++) 712 { 713 Buffer[i+2] = (UINT8) (0xA0 + i); 714 } 715 716 Buffer[0] = 0x7A; 717 Buffer[1] = (UINT8) Length; 718 return (AE_OK); 719 720 721 case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */ 722 723 if (AcpiGbl_DisplayRegionAccess) 724 { 725 AcpiOsPrintf ("AcpiExec: IPMI " 726 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X\n", 727 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 728 (UINT32) (Function >> 16), (UINT32) Address, (UINT32) BaseAddress, 729 Length, BitWidth, Buffer[1]); 730 } 731 732 /* 733 * Regardless of a READ or WRITE, this handler is passed a 66-byte 734 * buffer in which to return the IPMI status/length/data. 735 * 736 * Return some example data to show use of the bidirectional buffer 737 */ 738 Buffer[0] = 0; /* Status byte */ 739 Buffer[1] = 64; /* Return buffer data length */ 740 Buffer[2] = 0; /* Completion code */ 741 Buffer[3] = 0; /* Reserved */ 742 743 /* 744 * Fill the 66-byte buffer with the return data. 745 * Note: ASLTS depends on these fill values. 746 */ 747 for (i = 4; i < 66; i++) 748 { 749 Buffer[i] = (UINT8) (i); 750 } 751 return (AE_OK); 752 753 /* 754 * GPIO has some special semantics: 755 * 1) Address is the pin number index into the Connection() pin list 756 * 2) BitWidth is the actual number of bits (pins) defined by the field 757 */ 758 case ACPI_ADR_SPACE_GPIO: /* ACPI 5.0 */ 759 760 if (AcpiGbl_DisplayRegionAccess) 761 { 762 AcpiOsPrintf ("AcpiExec: GPIO " 763 "%s: Addr %.4X Width %X Conn %p\n", 764 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 765 (UINT32) Address, BitWidth, MyContext->Connection); 766 } 767 return (AE_OK); 768 769 default: 770 break; 771 } 772 773 /* 774 * Search through the linked list for this region's buffer 775 */ 776 BufferExists = FALSE; 777 BufferResize = FALSE; 778 RegionElement = AeRegions.RegionList; 779 780 if (AeRegions.NumberOfRegions) 781 { 782 BaseAddressEnd = BaseAddress + Length - 1; 783 while (!BufferExists && RegionElement) 784 { 785 RegionAddress = RegionElement->Address; 786 RegionAddressEnd = RegionElement->Address + RegionElement->Length - 1; 787 RegionLength = RegionElement->Length; 788 789 /* 790 * Overlapping Region Support 791 * 792 * While searching through the region buffer list, determine if an 793 * overlap exists between the requested buffer space and the current 794 * RegionElement space. If there is an overlap then replace the old 795 * buffer with a new buffer of increased size before continuing to 796 * do the read or write 797 */ 798 if (RegionElement->SpaceId != SpaceId || 799 BaseAddressEnd < RegionAddress || 800 BaseAddress > RegionAddressEnd) 801 { 802 /* 803 * Requested buffer is outside of the current RegionElement 804 * bounds 805 */ 806 RegionElement = RegionElement->NextRegion; 807 } 808 else 809 { 810 /* 811 * Some amount of buffer space sharing exists. There are 4 cases 812 * to consider: 813 * 814 * 1. Right overlap 815 * 2. Left overlap 816 * 3. Left and right overlap 817 * 4. Fully contained - no resizing required 818 */ 819 BufferExists = TRUE; 820 821 if ((BaseAddress >= RegionAddress) && 822 (BaseAddress <= RegionAddressEnd) && 823 (BaseAddressEnd > RegionAddressEnd)) 824 { 825 /* Right overlap */ 826 827 RegionElement->Length = (UINT32) (BaseAddress - 828 RegionAddress + Length); 829 BufferResize = TRUE; 830 } 831 832 else if ((BaseAddressEnd >= RegionAddress) && 833 (BaseAddressEnd <= RegionAddressEnd) && 834 (BaseAddress < RegionAddress)) 835 { 836 /* Left overlap */ 837 838 RegionElement->Address = BaseAddress; 839 RegionElement->Length = (UINT32) (RegionAddress - 840 BaseAddress + RegionElement->Length); 841 BufferResize = TRUE; 842 } 843 844 else if ((BaseAddress < RegionAddress) && 845 (BaseAddressEnd > RegionAddressEnd)) 846 { 847 /* Left and right overlap */ 848 849 RegionElement->Address = BaseAddress; 850 RegionElement->Length = Length; 851 BufferResize = TRUE; 852 } 853 854 /* 855 * only remaining case is fully contained for which we don't 856 * need to do anything 857 */ 858 if (BufferResize) 859 { 860 NewBuffer = AcpiOsAllocate (RegionElement->Length); 861 if (!NewBuffer) 862 { 863 return (AE_NO_MEMORY); 864 } 865 866 OldBuffer = RegionElement->Buffer; 867 RegionElement->Buffer = NewBuffer; 868 NewBuffer = NULL; 869 870 /* Initialize the region with the default fill value */ 871 872 memset (RegionElement->Buffer, 873 AcpiGbl_RegionFillValue, RegionElement->Length); 874 875 /* 876 * Get BufferValue to point (within the new buffer) to the 877 * base address of the old buffer 878 */ 879 BufferValue = (UINT8 *) RegionElement->Buffer + 880 (UINT64) RegionAddress - 881 (UINT64) RegionElement->Address; 882 883 /* 884 * Copy the old buffer to its same location within the new 885 * buffer 886 */ 887 memcpy (BufferValue, OldBuffer, RegionLength); 888 AcpiOsFree (OldBuffer); 889 } 890 } 891 } 892 } 893 894 /* 895 * If the Region buffer does not exist, create it now 896 */ 897 if (!BufferExists) 898 { 899 /* Do the memory allocations first */ 900 901 RegionElement = AcpiOsAllocate (sizeof (AE_REGION)); 902 if (!RegionElement) 903 { 904 return (AE_NO_MEMORY); 905 } 906 907 RegionElement->Buffer = AcpiOsAllocate (Length); 908 if (!RegionElement->Buffer) 909 { 910 AcpiOsFree (RegionElement); 911 return (AE_NO_MEMORY); 912 } 913 914 /* Initialize the region with the default fill value */ 915 916 memset (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length); 917 918 RegionElement->Address = BaseAddress; 919 RegionElement->Length = Length; 920 RegionElement->SpaceId = SpaceId; 921 RegionElement->NextRegion = NULL; 922 923 /* 924 * Increment the number of regions and put this one 925 * at the head of the list as it will probably get accessed 926 * more often anyway. 927 */ 928 AeRegions.NumberOfRegions += 1; 929 930 if (AeRegions.RegionList) 931 { 932 RegionElement->NextRegion = AeRegions.RegionList; 933 } 934 935 AeRegions.RegionList = RegionElement; 936 } 937 938 /* Calculate the size of the memory copy */ 939 940 ByteWidth = (BitWidth / 8); 941 942 if (BitWidth % 8) 943 { 944 ByteWidth += 1; 945 } 946 947 /* 948 * The buffer exists and is pointed to by RegionElement. 949 * We now need to verify the request is valid and perform the operation. 950 * 951 * NOTE: RegionElement->Length is in bytes, therefore it we compare against 952 * ByteWidth (see above) 953 */ 954 if ((RegionObject->Region.SpaceId != ACPI_ADR_SPACE_GPIO) && 955 ((UINT64) Address + ByteWidth) > 956 ((UINT64)(RegionElement->Address) + RegionElement->Length)) 957 { 958 ACPI_WARNING ((AE_INFO, 959 "Request on [%4.4s] is beyond region limit " 960 "Req-0x%X+0x%X, Base=0x%X, Len-0x%X", 961 (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address, 962 ByteWidth, (UINT32)(RegionElement->Address), 963 RegionElement->Length)); 964 965 return (AE_AML_REGION_LIMIT); 966 } 967 968 /* 969 * Get BufferValue to point to the "address" in the buffer 970 */ 971 BufferValue = ((UINT8 *) RegionElement->Buffer + 972 ((UINT64) Address - (UINT64) RegionElement->Address)); 973 974 DoFunction: 975 /* 976 * Perform a read or write to the buffer space 977 */ 978 switch (Function) 979 { 980 case ACPI_READ: 981 /* 982 * Set the pointer Value to whatever is in the buffer 983 */ 984 memcpy (Value, BufferValue, ByteWidth); 985 break; 986 987 case ACPI_WRITE: 988 /* 989 * Write the contents of Value to the buffer 990 */ 991 memcpy (BufferValue, Value, ByteWidth); 992 break; 993 994 default: 995 996 return (AE_BAD_PARAMETER); 997 } 998 999 if (AcpiGbl_DisplayRegionAccess) 1000 { 1001 switch (SpaceId) 1002 { 1003 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 1004 1005 AcpiOsPrintf ("AcpiExec: SystemMemory " 1006 "%s: Val %.8X Addr %.4X Width %X [REGION: BaseAddr %.4X Len %.2X]\n", 1007 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 1008 (UINT32) *Value, (UINT32) Address, BitWidth, (UINT32) BaseAddress, Length); 1009 break; 1010 1011 case ACPI_ADR_SPACE_GPIO: /* ACPI 5.0 */ 1012 1013 /* This space is required to always be ByteAcc */ 1014 1015 Status = AcpiBufferToResource (MyContext->Connection, 1016 MyContext->Length, &Resource); 1017 1018 AcpiOsPrintf ("AcpiExec: GeneralPurposeIo " 1019 "%s: Val %.8X Addr %.4X BaseAddr %.4X Len %.2X Width %X AccLen %.2X Conn %p\n", 1020 (Function & ACPI_IO_MASK) ? "Write" : "Read ", (UINT32) *Value, 1021 (UINT32) Address, (UINT32) BaseAddress, Length, BitWidth, 1022 MyContext->AccessLength, MyContext->Connection); 1023 break; 1024 1025 default: 1026 1027 break; 1028 } 1029 } 1030 1031 return (AE_OK); 1032 } 1033