1 /****************************************************************************** 2 * 3 * Module Name: aslresource - Resource template/descriptor utilities 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2023, 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 "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "amlcode.h" 47 48 49 #define _COMPONENT ACPI_COMPILER 50 ACPI_MODULE_NAME ("aslresource") 51 52 53 /******************************************************************************* 54 * 55 * FUNCTION: RsSmallAddressCheck 56 * 57 * PARAMETERS: Minimum - Address Min value 58 * Maximum - Address Max value 59 * Length - Address range value 60 * Alignment - Address alignment value 61 * MinOp - Original Op for Address Min 62 * MaxOp - Original Op for Address Max 63 * LengthOp - Original Op for address range 64 * AlignOp - Original Op for address alignment. If 65 * NULL, means "zero value for alignment is 66 * OK, and means 64K alignment" (for 67 * Memory24 descriptor) 68 * Op - Parent Op for entire construct 69 * 70 * RETURN: None. Adds error messages to error log if necessary 71 * 72 * DESCRIPTION: Perform common value checks for "small" address descriptors. 73 * Currently: 74 * Io, Memory24, Memory32 75 * 76 ******************************************************************************/ 77 78 void 79 RsSmallAddressCheck ( 80 UINT8 Type, 81 UINT32 Minimum, 82 UINT32 Maximum, 83 UINT32 Length, 84 UINT32 Alignment, 85 ACPI_PARSE_OBJECT *MinOp, 86 ACPI_PARSE_OBJECT *MaxOp, 87 ACPI_PARSE_OBJECT *LengthOp, 88 ACPI_PARSE_OBJECT *AlignOp, 89 ACPI_PARSE_OBJECT *Op) 90 { 91 92 if (AslGbl_NoResourceChecking) 93 { 94 return; 95 } 96 97 /* 98 * Check for a so-called "null descriptor". These are descriptors that are 99 * created with most fields set to zero. The intent is that the descriptor 100 * will be updated/completed at runtime via a BufferField. 101 * 102 * If the descriptor does NOT have a resource tag, it cannot be referenced 103 * by a BufferField and we will flag this as an error. Conversely, if 104 * the descriptor has a resource tag, we will assume that a BufferField 105 * will be used to dynamically update it, so no error. 106 * 107 * A possible enhancement to this check would be to verify that in fact 108 * a BufferField is created using the resource tag, and perhaps even 109 * verify that a Store is performed to the BufferField. 110 * 111 * Note: for these descriptors, Alignment is allowed to be zero 112 */ 113 if (!Minimum && !Maximum && !Length) 114 { 115 if (!Op->Asl.ExternalName) 116 { 117 /* No resource tag. Descriptor is fixed and is also illegal */ 118 119 AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL); 120 } 121 122 return; 123 } 124 125 /* 126 * Range checks for Memory24 and Memory32. 127 * IO descriptor has different definition of min/max, don't check. 128 */ 129 if (Type != ACPI_RESOURCE_NAME_IO) 130 { 131 /* Basic checks on Min/Max/Length */ 132 133 if (Minimum > Maximum) 134 { 135 AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); 136 } 137 else if (Length > (Maximum - Minimum + 1)) 138 { 139 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); 140 } 141 142 /* Special case for Memory24, min/max values are compressed */ 143 144 if (Type == ACPI_RESOURCE_NAME_MEMORY24) 145 { 146 if (!Alignment) /* Alignment==0 means 64K alignment */ 147 { 148 Alignment = ACPI_UINT16_MAX + 1; 149 } 150 151 Minimum <<= 8; 152 Maximum <<= 8; 153 } 154 } 155 156 /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */ 157 158 if (!Alignment) 159 { 160 Alignment = 1; 161 } 162 163 /* Addresses must be an exact multiple of the alignment value */ 164 165 if (Minimum % Alignment) 166 { 167 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); 168 } 169 if (Maximum % Alignment) 170 { 171 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL); 172 } 173 } 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: RsLargeAddressCheck 179 * 180 * PARAMETERS: Minimum - Address Min value 181 * Maximum - Address Max value 182 * Length - Address range value 183 * Granularity - Address granularity value 184 * Flags - General flags for address descriptors: 185 * _MIF, _MAF, _DEC 186 * MinOp - Original Op for Address Min 187 * MaxOp - Original Op for Address Max 188 * LengthOp - Original Op for address range 189 * GranOp - Original Op for address granularity 190 * Op - Parent Op for entire construct 191 * 192 * RETURN: None. Adds error messages to error log if necessary 193 * 194 * DESCRIPTION: Perform common value checks for "large" address descriptors. 195 * Currently: 196 * WordIo, WordBusNumber, WordSpace 197 * DWordIo, DWordMemory, DWordSpace 198 * QWordIo, QWordMemory, QWordSpace 199 * ExtendedIo, ExtendedMemory, ExtendedSpace 200 * 201 * _MIF flag set means that the minimum address is fixed and is not relocatable 202 * _MAF flag set means that the maximum address is fixed and is not relocatable 203 * Length of zero means that the record size is variable 204 * 205 * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40 206 * of the ACPI 4.0a specification. Added 04/2010. 207 * 208 ******************************************************************************/ 209 210 void 211 RsLargeAddressCheck ( 212 UINT64 Minimum, 213 UINT64 Maximum, 214 UINT64 Length, 215 UINT64 Granularity, 216 UINT8 Flags, 217 ACPI_PARSE_OBJECT *MinOp, 218 ACPI_PARSE_OBJECT *MaxOp, 219 ACPI_PARSE_OBJECT *LengthOp, 220 ACPI_PARSE_OBJECT *GranOp, 221 ACPI_PARSE_OBJECT *Op) 222 { 223 224 if (AslGbl_NoResourceChecking) 225 { 226 return; 227 } 228 229 /* 230 * Check for a so-called "null descriptor". These are descriptors that are 231 * created with most fields set to zero. The intent is that the descriptor 232 * will be updated/completed at runtime via a BufferField. 233 * 234 * If the descriptor does NOT have a resource tag, it cannot be referenced 235 * by a BufferField and we will flag this as an error. Conversely, if 236 * the descriptor has a resource tag, we will assume that a BufferField 237 * will be used to dynamically update it, so no error. 238 * 239 * A possible enhancement to this check would be to verify that in fact 240 * a BufferField is created using the resource tag, and perhaps even 241 * verify that a Store is performed to the BufferField. 242 */ 243 if (!Minimum && !Maximum && !Length && !Granularity) 244 { 245 if (!Op->Asl.ExternalName) 246 { 247 /* No resource tag. Descriptor is fixed and is also illegal */ 248 249 AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL); 250 } 251 252 return; 253 } 254 255 /* Basic checks on Min/Max/Length */ 256 257 if (Minimum > Maximum) 258 { 259 AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); 260 return; 261 } 262 else if (Length > (Maximum - Minimum + 1)) 263 { 264 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); 265 return; 266 } 267 268 /* If specified (non-zero), ensure granularity is a power-of-two minus one */ 269 270 if (Granularity) 271 { 272 if ((Granularity + 1) & 273 Granularity) 274 { 275 AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL); 276 return; 277 } 278 } 279 280 /* 281 * Check the various combinations of Length, MinFixed, and MaxFixed 282 */ 283 if (Length) 284 { 285 /* Fixed non-zero length */ 286 287 switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) 288 { 289 case 0: 290 /* 291 * Fixed length, variable locations (both _MIN and _MAX). 292 * Length must be a multiple of granularity 293 */ 294 if (Granularity & Length) 295 { 296 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL); 297 } 298 break; 299 300 case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): 301 302 /* Fixed length, fixed location. Granularity must be zero */ 303 304 if (Granularity != 0) 305 { 306 AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL); 307 } 308 309 /* Length must be exactly the size of the min/max window */ 310 311 if (Length != (Maximum - Minimum + 1)) 312 { 313 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL); 314 } 315 break; 316 317 /* All other combinations are invalid */ 318 319 case ACPI_RESOURCE_FLAG_MIF: 320 case ACPI_RESOURCE_FLAG_MAF: 321 default: 322 323 AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); 324 } 325 } 326 else 327 { 328 /* Variable length (length==0) */ 329 330 switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) 331 { 332 case 0: 333 /* 334 * Both _MIN and _MAX are variable. 335 * No additional requirements, just exit 336 */ 337 break; 338 339 case ACPI_RESOURCE_FLAG_MIF: 340 341 /* _MIN is fixed. _MIN must be multiple of _GRA */ 342 343 /* 344 * The granularity is defined by the ACPI specification to be a 345 * power-of-two minus one, therefore the granularity is a 346 * bitmask which can be used to easily validate the addresses. 347 */ 348 if (Granularity & Minimum) 349 { 350 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); 351 } 352 break; 353 354 case ACPI_RESOURCE_FLAG_MAF: 355 356 /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */ 357 358 if (Granularity & (Maximum + 1)) 359 { 360 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1"); 361 } 362 break; 363 364 /* Both MIF/MAF set is invalid if length is zero */ 365 366 case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): 367 default: 368 369 AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); 370 } 371 } 372 } 373 374 375 /******************************************************************************* 376 * 377 * FUNCTION: RsGetStringDataLength 378 * 379 * PARAMETERS: InitializerOp - Start of a subtree of init nodes 380 * 381 * RETURN: Valid string length if a string node is found (otherwise 0) 382 * 383 * DESCRIPTION: In a list of peer nodes, find the first one that contains a 384 * string and return the length of the string. 385 * 386 ******************************************************************************/ 387 388 UINT16 389 RsGetStringDataLength ( 390 ACPI_PARSE_OBJECT *InitializerOp) 391 { 392 393 while (InitializerOp) 394 { 395 if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) 396 { 397 return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1)); 398 } 399 400 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 401 } 402 403 return (0); 404 } 405 406 407 /******************************************************************************* 408 * 409 * FUNCTION: RsAllocateResourceNode 410 * 411 * PARAMETERS: Size - Size of node in bytes 412 * 413 * RETURN: The allocated node - aborts on allocation failure 414 * 415 * DESCRIPTION: Allocate a resource description node and the resource 416 * descriptor itself (the nodes are used to link descriptors). 417 * 418 ******************************************************************************/ 419 420 ASL_RESOURCE_NODE * 421 RsAllocateResourceNode ( 422 UINT32 Size) 423 { 424 ASL_RESOURCE_NODE *Rnode; 425 426 427 /* Allocate the node */ 428 429 Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE)); 430 431 /* Allocate the resource descriptor itself */ 432 433 Rnode->Buffer = UtLocalCalloc (Size); 434 Rnode->BufferLength = Size; 435 return (Rnode); 436 } 437 438 439 /******************************************************************************* 440 * 441 * FUNCTION: RsCreateResourceField 442 * 443 * PARAMETERS: Op - Resource field node 444 * Name - Name of the field (Used only to reference 445 * the field in the ASL, not in the AML) 446 * ByteOffset - Offset from the field start 447 * BitOffset - Additional bit offset 448 * BitLength - Number of bits in the field 449 * 450 * RETURN: None, sets fields within the input node 451 * 452 * DESCRIPTION: Utility function to generate a named bit field within a 453 * resource descriptor. Mark a node as 1) a field in a resource 454 * descriptor, and 2) set the value to be a BIT offset 455 * 456 ******************************************************************************/ 457 458 void 459 RsCreateResourceField ( 460 ACPI_PARSE_OBJECT *Op, 461 char *Name, 462 UINT32 ByteOffset, 463 UINT32 BitOffset, 464 UINT32 BitLength) 465 { 466 467 Op->Asl.ExternalName = Name; 468 Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD; 469 470 Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset; 471 Op->Asl.Value.Tag.BitLength = BitLength; 472 } 473 474 475 /******************************************************************************* 476 * 477 * FUNCTION: RsSetFlagBits 478 * 479 * PARAMETERS: *Flags - Pointer to the flag byte 480 * Op - Flag initialization node 481 * Position - Bit position within the flag byte 482 * Default - Used if the node is DEFAULT. 483 * 484 * RETURN: Sets bits within the *Flags output byte. 485 * 486 * DESCRIPTION: Set a bit in a cumulative flags word from an initialization 487 * node. Will use a default value if the node is DEFAULT, meaning 488 * that no value was specified in the ASL. Used to merge multiple 489 * keywords into a single flags byte. 490 * 491 ******************************************************************************/ 492 493 void 494 RsSetFlagBits ( 495 UINT8 *Flags, 496 ACPI_PARSE_OBJECT *Op, 497 UINT8 Position, 498 UINT8 DefaultBit) 499 { 500 501 if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 502 { 503 /* Use the default bit */ 504 505 *Flags |= (DefaultBit << Position); 506 } 507 else 508 { 509 /* Use the bit specified in the initialization node */ 510 511 *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position); 512 } 513 } 514 515 516 void 517 RsSetFlagBits16 ( 518 UINT16 *Flags, 519 ACPI_PARSE_OBJECT *Op, 520 UINT8 Position, 521 UINT8 DefaultBit) 522 { 523 524 if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 525 { 526 /* Use the default bit */ 527 528 *Flags |= (DefaultBit << Position); 529 } 530 else 531 { 532 /* Use the bit specified in the initialization node */ 533 534 *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position); 535 } 536 } 537 538 539 /******************************************************************************* 540 * 541 * FUNCTION: RsCompleteNodeAndGetNext 542 * 543 * PARAMETERS: Op - Resource node to be completed 544 * 545 * RETURN: The next peer to the input node. 546 * 547 * DESCRIPTION: Mark the current node completed and return the next peer. 548 * The node ParseOpcode is set to DEFAULT_ARG, meaning that 549 * this node is to be ignored from now on. 550 * 551 ******************************************************************************/ 552 553 ACPI_PARSE_OBJECT * 554 RsCompleteNodeAndGetNext ( 555 ACPI_PARSE_OBJECT *Op) 556 { 557 558 /* Mark this node unused */ 559 560 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 561 562 /* Move on to the next peer node in the initializer list */ 563 564 return (ASL_GET_PEER_NODE (Op)); 565 } 566 567 568 /******************************************************************************* 569 * 570 * FUNCTION: RsCheckListForDuplicates 571 * 572 * PARAMETERS: Op - First op in the initializer list 573 * 574 * RETURN: None 575 * 576 * DESCRIPTION: Check an initializer list for duplicate values. Emits an error 577 * if any duplicates are found. 578 * 579 ******************************************************************************/ 580 581 void 582 RsCheckListForDuplicates ( 583 ACPI_PARSE_OBJECT *Op) 584 { 585 ACPI_PARSE_OBJECT *NextValueOp = Op; 586 ACPI_PARSE_OBJECT *NextOp; 587 UINT32 Value; 588 589 590 if (!Op) 591 { 592 return; 593 } 594 595 /* Search list once for each value in the list */ 596 597 while (NextValueOp) 598 { 599 Value = (UINT32) NextValueOp->Asl.Value.Integer; 600 601 /* Compare this value to all remaining values in the list */ 602 603 NextOp = ASL_GET_PEER_NODE (NextValueOp); 604 while (NextOp) 605 { 606 if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 607 { 608 /* Compare values */ 609 610 if (Value == (UINT32) NextOp->Asl.Value.Integer) 611 { 612 /* Emit error only once per duplicate node */ 613 614 if (!(NextOp->Asl.CompileFlags & OP_IS_DUPLICATE)) 615 { 616 NextOp->Asl.CompileFlags |= OP_IS_DUPLICATE; 617 AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM, 618 NextOp, NULL); 619 } 620 } 621 } 622 623 NextOp = ASL_GET_PEER_NODE (NextOp); 624 } 625 626 NextValueOp = ASL_GET_PEER_NODE (NextValueOp); 627 } 628 } 629 630 631 /******************************************************************************* 632 * 633 * FUNCTION: RsDoOneResourceDescriptor 634 * 635 * PARAMETERS: DescriptorTypeOp - Parent parse node of the descriptor 636 * CurrentByteOffset - Offset in the resource descriptor 637 * buffer. 638 * 639 * RETURN: A valid resource node for the descriptor 640 * 641 * DESCRIPTION: Dispatches the processing of one resource descriptor 642 * 643 ******************************************************************************/ 644 645 ASL_RESOURCE_NODE * 646 RsDoOneResourceDescriptor ( 647 ASL_RESOURCE_INFO *Info, 648 UINT8 *State) 649 { 650 ASL_RESOURCE_NODE *Rnode = NULL; 651 652 653 /* Construct the resource */ 654 655 switch (Info->DescriptorTypeOp->Asl.ParseOpcode) 656 { 657 658 case PARSEOP_CLOCKINPUT: 659 660 Rnode = RsDoClockInputDescriptor(Info); 661 break; 662 663 case PARSEOP_DMA: 664 665 Rnode = RsDoDmaDescriptor (Info); 666 break; 667 668 case PARSEOP_FIXEDDMA: 669 670 Rnode = RsDoFixedDmaDescriptor (Info); 671 break; 672 673 case PARSEOP_DWORDIO: 674 675 Rnode = RsDoDwordIoDescriptor (Info); 676 break; 677 678 case PARSEOP_DWORDMEMORY: 679 680 Rnode = RsDoDwordMemoryDescriptor (Info); 681 break; 682 683 case PARSEOP_DWORDPCC: 684 685 Rnode = RsDoDwordPccDescriptor (Info); 686 break; 687 688 case PARSEOP_DWORDSPACE: 689 690 Rnode = RsDoDwordSpaceDescriptor (Info); 691 break; 692 693 case PARSEOP_ENDDEPENDENTFN: 694 695 switch (*State) 696 { 697 case ACPI_RSTATE_NORMAL: 698 699 AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT, 700 Info->DescriptorTypeOp, NULL); 701 break; 702 703 case ACPI_RSTATE_START_DEPENDENT: 704 705 AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, 706 Info->DescriptorTypeOp, NULL); 707 break; 708 709 case ACPI_RSTATE_DEPENDENT_LIST: 710 default: 711 712 break; 713 } 714 715 *State = ACPI_RSTATE_NORMAL; 716 Rnode = RsDoEndDependentDescriptor (Info); 717 break; 718 719 case PARSEOP_ENDTAG: 720 721 Rnode = RsDoEndTagDescriptor (Info); 722 break; 723 724 case PARSEOP_EXTENDEDIO: 725 726 Rnode = RsDoExtendedIoDescriptor (Info); 727 break; 728 729 case PARSEOP_EXTENDEDMEMORY: 730 731 Rnode = RsDoExtendedMemoryDescriptor (Info); 732 break; 733 734 case PARSEOP_EXTENDEDSPACE: 735 736 Rnode = RsDoExtendedSpaceDescriptor (Info); 737 break; 738 739 case PARSEOP_FIXEDIO: 740 741 Rnode = RsDoFixedIoDescriptor (Info); 742 break; 743 744 case PARSEOP_INTERRUPT: 745 746 Rnode = RsDoInterruptDescriptor (Info); 747 break; 748 749 case PARSEOP_IO: 750 751 Rnode = RsDoIoDescriptor (Info); 752 break; 753 754 case PARSEOP_IRQ: 755 756 Rnode = RsDoIrqDescriptor (Info); 757 break; 758 759 case PARSEOP_IRQNOFLAGS: 760 761 Rnode = RsDoIrqNoFlagsDescriptor (Info); 762 break; 763 764 case PARSEOP_MEMORY24: 765 766 Rnode = RsDoMemory24Descriptor (Info); 767 break; 768 769 case PARSEOP_MEMORY32: 770 771 Rnode = RsDoMemory32Descriptor (Info); 772 break; 773 774 case PARSEOP_MEMORY32FIXED: 775 776 Rnode = RsDoMemory32FixedDescriptor (Info); 777 break; 778 779 case PARSEOP_QWORDIO: 780 781 Rnode = RsDoQwordIoDescriptor (Info); 782 break; 783 784 case PARSEOP_QWORDMEMORY: 785 786 Rnode = RsDoQwordMemoryDescriptor (Info); 787 break; 788 789 case PARSEOP_QWORDPCC: 790 791 Rnode = RsDoQwordPccDescriptor (Info); 792 break; 793 794 case PARSEOP_QWORDSPACE: 795 796 Rnode = RsDoQwordSpaceDescriptor (Info); 797 break; 798 799 case PARSEOP_REGISTER: 800 801 Rnode = RsDoGeneralRegisterDescriptor (Info); 802 break; 803 804 case PARSEOP_STARTDEPENDENTFN: 805 806 switch (*State) 807 { 808 case ACPI_RSTATE_START_DEPENDENT: 809 810 AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, 811 Info->DescriptorTypeOp, NULL); 812 break; 813 814 case ACPI_RSTATE_NORMAL: 815 case ACPI_RSTATE_DEPENDENT_LIST: 816 default: 817 818 break; 819 } 820 821 *State = ACPI_RSTATE_START_DEPENDENT; 822 Rnode = RsDoStartDependentDescriptor (Info); 823 *State = ACPI_RSTATE_DEPENDENT_LIST; 824 break; 825 826 case PARSEOP_STARTDEPENDENTFN_NOPRI: 827 828 switch (*State) 829 { 830 case ACPI_RSTATE_START_DEPENDENT: 831 832 AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, 833 Info->DescriptorTypeOp, NULL); 834 break; 835 836 case ACPI_RSTATE_NORMAL: 837 case ACPI_RSTATE_DEPENDENT_LIST: 838 default: 839 840 break; 841 } 842 843 *State = ACPI_RSTATE_START_DEPENDENT; 844 Rnode = RsDoStartDependentNoPriDescriptor (Info); 845 *State = ACPI_RSTATE_DEPENDENT_LIST; 846 break; 847 848 case PARSEOP_VENDORLONG: 849 850 Rnode = RsDoVendorLargeDescriptor (Info); 851 break; 852 853 case PARSEOP_VENDORSHORT: 854 855 Rnode = RsDoVendorSmallDescriptor (Info); 856 break; 857 858 case PARSEOP_WORDBUSNUMBER: 859 860 Rnode = RsDoWordBusNumberDescriptor (Info); 861 break; 862 863 case PARSEOP_WORDIO: 864 865 Rnode = RsDoWordIoDescriptor (Info); 866 break; 867 868 case PARSEOP_WORDPCC: 869 870 Rnode = RsDoWordPccDescriptor (Info); 871 break; 872 873 case PARSEOP_WORDSPACE: 874 875 Rnode = RsDoWordSpaceDescriptor (Info); 876 break; 877 878 case PARSEOP_GPIO_INT: 879 880 Rnode = RsDoGpioIntDescriptor (Info); 881 break; 882 883 case PARSEOP_GPIO_IO: 884 885 Rnode = RsDoGpioIoDescriptor (Info); 886 break; 887 888 case PARSEOP_I2C_SERIALBUS: 889 case PARSEOP_I2C_SERIALBUS_V2: 890 891 Rnode = RsDoI2cSerialBusDescriptor (Info); 892 break; 893 894 case PARSEOP_SPI_SERIALBUS: 895 case PARSEOP_SPI_SERIALBUS_V2: 896 897 Rnode = RsDoSpiSerialBusDescriptor (Info); 898 break; 899 900 case PARSEOP_UART_SERIALBUS: 901 case PARSEOP_UART_SERIALBUS_V2: 902 903 Rnode = RsDoUartSerialBusDescriptor (Info); 904 break; 905 906 case PARSEOP_CSI2_SERIALBUS: 907 908 Rnode = RsDoCsi2SerialBusDescriptor (Info); 909 break; 910 911 case PARSEOP_PINCONFIG: 912 913 Rnode = RsDoPinConfigDescriptor (Info); 914 break; 915 916 case PARSEOP_PINFUNCTION: 917 918 Rnode = RsDoPinFunctionDescriptor (Info); 919 break; 920 921 case PARSEOP_PINGROUP: 922 923 Rnode = RsDoPinGroupDescriptor (Info); 924 break; 925 926 case PARSEOP_PINGROUPFUNCTION: 927 928 Rnode = RsDoPinGroupFunctionDescriptor (Info); 929 break; 930 931 case PARSEOP_PINGROUPCONFIG: 932 933 Rnode = RsDoPinGroupConfigDescriptor (Info); 934 break; 935 936 case PARSEOP_DEFAULT_ARG: 937 938 /* Just ignore any of these, they are used as fillers/placeholders */ 939 break; 940 941 default: 942 943 printf ("Unknown resource descriptor type [%s]\n", 944 Info->DescriptorTypeOp->Asl.ParseOpName); 945 break; 946 } 947 948 /* 949 * Mark original node as unused, but head of a resource descriptor. 950 * This allows the resource to be installed in the namespace so that 951 * references to the descriptor can be resolved. 952 */ 953 Info->DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 954 Info->DescriptorTypeOp->Asl.CompileFlags = OP_IS_RESOURCE_DESC; 955 Info->DescriptorTypeOp->Asl.Value.Integer = Info->CurrentByteOffset; 956 957 if (Rnode) 958 { 959 Info->DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength; 960 Info->DescriptorTypeOp->Asl.Extra = 961 ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType; 962 } 963 964 return (Rnode); 965 } 966 967 968 /******************************************************************************* 969 * 970 * FUNCTION: RsLinkDescriptorChain 971 * 972 * PARAMETERS: PreviousRnode - Pointer to the node that will be previous 973 * to the linked node, At exit, set to the 974 * last node in the new chain. 975 * Rnode - Resource node to link into the list 976 * 977 * RETURN: Cumulative buffer byte offset of the new segment of chain 978 * 979 * DESCRIPTION: Link a descriptor chain at the end of an existing chain. 980 * 981 ******************************************************************************/ 982 983 UINT32 984 RsLinkDescriptorChain ( 985 ASL_RESOURCE_NODE **PreviousRnode, 986 ASL_RESOURCE_NODE *Rnode) 987 { 988 ASL_RESOURCE_NODE *LastRnode; 989 UINT32 CurrentByteOffset; 990 991 992 /* Anything to do? */ 993 994 if (!Rnode) 995 { 996 return (0); 997 } 998 999 /* Point the previous node to the new node */ 1000 1001 (*PreviousRnode)->Next = Rnode; 1002 CurrentByteOffset = Rnode->BufferLength; 1003 1004 /* Walk to the end of the chain headed by Rnode */ 1005 1006 LastRnode = Rnode; 1007 while (LastRnode->Next) 1008 { 1009 LastRnode = LastRnode->Next; 1010 CurrentByteOffset += LastRnode->BufferLength; 1011 } 1012 1013 /* Previous node becomes the last node in the chain */ 1014 1015 *PreviousRnode = LastRnode; 1016 return (CurrentByteOffset); 1017 } 1018 1019 1020 /******************************************************************************* 1021 * 1022 * FUNCTION: RsDoResourceTemplate 1023 * 1024 * PARAMETERS: Op - Parent of a resource template list 1025 * 1026 * RETURN: None. Sets input node to point to a list of AML code 1027 * 1028 * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer, 1029 * in preparation for output to the AML output file. 1030 * 1031 ******************************************************************************/ 1032 1033 void 1034 RsDoResourceTemplate ( 1035 ACPI_PARSE_OBJECT *Op) 1036 { 1037 ACPI_PARSE_OBJECT *BufferLengthOp; 1038 ACPI_PARSE_OBJECT *BufferOp; 1039 ACPI_PARSE_OBJECT *DescriptorTypeOp; 1040 ACPI_PARSE_OBJECT *LastOp = NULL; 1041 UINT32 CurrentByteOffset = 0; 1042 ASL_RESOURCE_NODE HeadRnode; 1043 ASL_RESOURCE_NODE *PreviousRnode; 1044 ASL_RESOURCE_NODE *Rnode; 1045 ASL_RESOURCE_INFO Info; 1046 UINT8 State; 1047 1048 1049 /* Mark parent as containing a resource template */ 1050 1051 if (Op->Asl.Parent) 1052 { 1053 Op->Asl.Parent->Asl.CompileFlags |= OP_IS_RESOURCE_DESC; 1054 } 1055 1056 /* ResourceTemplate Opcode is first (Op) */ 1057 /* Buffer Length node is first child */ 1058 1059 BufferLengthOp = ASL_GET_CHILD_NODE (Op); 1060 1061 /* Buffer Op is first peer */ 1062 1063 BufferOp = ASL_GET_PEER_NODE (BufferLengthOp); 1064 1065 /* First Descriptor type is next */ 1066 1067 DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp); 1068 1069 /* DEFAULT_ARG indicates null template - ResourceTemplate(){} */ 1070 1071 if (DescriptorTypeOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 1072 { 1073 AslError (ASL_WARNING, ASL_MSG_NULL_RESOURCE_TEMPLATE, 1074 DescriptorTypeOp, DescriptorTypeOp->Asl.Value.String); 1075 } 1076 1077 /* 1078 * Process all resource descriptors in the list 1079 * Note: It is assumed that the EndTag node has been automatically 1080 * inserted at the end of the template by the parser. 1081 */ 1082 State = ACPI_RSTATE_NORMAL; 1083 PreviousRnode = &HeadRnode; 1084 while (DescriptorTypeOp) 1085 { 1086 /* Save information for optional mapfile */ 1087 1088 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION) 1089 { 1090 Info.MappingOp = Op->Asl.Parent; 1091 } 1092 else 1093 { 1094 Info.MappingOp = DescriptorTypeOp; 1095 } 1096 1097 Info.DescriptorTypeOp = DescriptorTypeOp; 1098 Info.CurrentByteOffset = CurrentByteOffset; 1099 1100 DescriptorTypeOp->Asl.CompileFlags |= OP_IS_RESOURCE_DESC; 1101 Rnode = RsDoOneResourceDescriptor (&Info, &State); 1102 1103 /* 1104 * Update current byte offset to indicate the number of bytes from the 1105 * start of the buffer. Buffer can include multiple descriptors, we 1106 * must keep track of the offset of not only each descriptor, but each 1107 * element (field) within each descriptor as well. 1108 */ 1109 CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode); 1110 1111 /* Get the next descriptor in the list */ 1112 1113 LastOp = DescriptorTypeOp; 1114 DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp); 1115 } 1116 1117 if (State == ACPI_RSTATE_DEPENDENT_LIST) 1118 { 1119 if (LastOp) 1120 { 1121 LastOp = LastOp->Asl.Parent; 1122 } 1123 AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL); 1124 } 1125 1126 /* 1127 * Transform the nodes into the following 1128 * 1129 * Op -> AML_BUFFER_OP 1130 * First Child -> BufferLength 1131 * Second Child -> Descriptor Buffer (raw byte data) 1132 */ 1133 Op->Asl.ParseOpcode = PARSEOP_BUFFER; 1134 Op->Asl.AmlOpcode = AML_BUFFER_OP; 1135 Op->Asl.CompileFlags = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC; 1136 UtSetParseOpName (Op); 1137 1138 BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; 1139 BufferLengthOp->Asl.Value.Integer = CurrentByteOffset; 1140 (void) OpcSetOptimalIntegerSize (BufferLengthOp); 1141 UtSetParseOpName (BufferLengthOp); 1142 1143 BufferOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 1144 BufferOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN; 1145 BufferOp->Asl.AmlOpcodeLength = 0; 1146 BufferOp->Asl.AmlLength = CurrentByteOffset; 1147 BufferOp->Asl.Value.Buffer = ACPI_CAST_PTR (UINT8, HeadRnode.Next); 1148 BufferOp->Asl.CompileFlags |= OP_IS_RESOURCE_DATA; 1149 UtSetParseOpName (BufferOp); 1150 1151 return; 1152 } 1153